You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ga...@apache.org on 2015/09/17 22:24:26 UTC

[1/5] jclouds git commit: JCLOUDS-217: AWS-S3: Remove special encoding.

Repository: jclouds
Updated Branches:
  refs/heads/master 4bc456490 -> f8eff7e00


JCLOUDS-217: AWS-S3: Remove special encoding.

AWS-S3 provider should not pre-encode parameters that are passed to
the jclouds request. This comes up in the AWSS3BlobRequestSigner as
the only place where a parameter is pre-encoded.


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/f8eff7e0
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/f8eff7e0
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/f8eff7e0

Branch: refs/heads/master
Commit: f8eff7e00e979dedab511bc6f1e0aa2a9d885671
Parents: 2c2b498
Author: Timur Alperovich <ti...@gmail.com>
Authored: Fri Sep 11 13:45:05 2015 -0700
Committer: Timur Alperovich <ti...@gmail.com>
Committed: Thu Sep 17 13:08:44 2015 -0700

----------------------------------------------------------------------
 .../s3/blobstore/AWSS3BlobRequestSigner.java    | 11 ----------
 .../s3/blobstore/AWSS3BlobSignerExpectTest.java | 23 ++++++++++++--------
 2 files changed, 14 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/f8eff7e0/providers/aws-s3/src/main/java/org/jclouds/aws/s3/blobstore/AWSS3BlobRequestSigner.java
----------------------------------------------------------------------
diff --git a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/blobstore/AWSS3BlobRequestSigner.java b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/blobstore/AWSS3BlobRequestSigner.java
index b719bab..39649af 100644
--- a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/blobstore/AWSS3BlobRequestSigner.java
+++ b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/blobstore/AWSS3BlobRequestSigner.java
@@ -19,8 +19,6 @@ package org.jclouds.aws.s3.blobstore;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.jclouds.blobstore.util.BlobStoreUtils.cleanRequest;
 
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
 import java.util.Date;
 import java.util.concurrent.TimeUnit;
 
@@ -37,7 +35,6 @@ import org.jclouds.s3.blobstore.S3BlobRequestSigner;
 import org.jclouds.s3.blobstore.functions.BlobToObject;
 import org.jclouds.s3.filters.RequestAuthorizeSignature;
 
-import com.google.common.base.Charsets;
 import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableList;
 import com.google.common.net.HttpHeaders;
@@ -92,15 +89,7 @@ public class AWSS3BlobRequestSigner extends S3BlobRequestSigner<AWSS3Client> {
       String expiration = String.valueOf(TimeUnit.MILLISECONDS.toSeconds(date.getTime()) + timeInSeconds);
       HttpRequest.Builder<?> builder = request.toBuilder().replaceHeader(HttpHeaders.DATE, expiration);
       String stringToSign = authSigner.createStringToSign(builder.build());
-      // We MUST encode the signature because addQueryParam internally _always_ decodes values
-      // and if we don't encode the signature here, the decoding may change the signature. For e.g.
-      // any '+' characters in the signature will be converted to space ' ' on decoding.
       String signature = authSigner.sign(stringToSign);
-      try {
-         signature = URLEncoder.encode(signature, Charsets.UTF_8.name());
-      } catch (UnsupportedEncodingException e) {
-         throw new IllegalStateException("Bad encoding on input: " + signature, e);
-      }
       HttpRequest ret = builder.addQueryParam(HttpHeaders.EXPIRES, expiration)
          .addQueryParam("AWSAccessKeyId", identity)
          // Signature MUST be the last parameter because if it isn't, even encoded '+' values in the

http://git-wip-us.apache.org/repos/asf/jclouds/blob/f8eff7e0/providers/aws-s3/src/test/java/org/jclouds/aws/s3/blobstore/AWSS3BlobSignerExpectTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-s3/src/test/java/org/jclouds/aws/s3/blobstore/AWSS3BlobSignerExpectTest.java b/providers/aws-s3/src/test/java/org/jclouds/aws/s3/blobstore/AWSS3BlobSignerExpectTest.java
index aed33d6..a9bca53 100644
--- a/providers/aws-s3/src/test/java/org/jclouds/aws/s3/blobstore/AWSS3BlobSignerExpectTest.java
+++ b/providers/aws-s3/src/test/java/org/jclouds/aws/s3/blobstore/AWSS3BlobSignerExpectTest.java
@@ -51,10 +51,12 @@ public class AWSS3BlobSignerExpectTest extends S3BlobSignerExpectTest {
    @Override
    protected HttpRequest getBlobWithTime() {
       return HttpRequest.builder().method("GET")
-         .endpoint("https://container.s3.amazonaws.com/name" +
-            "?Expires=1212683902&AWSAccessKeyId=identity&Signature=Y4Ac4sZfBemGZmgfG78F7IX%2BIFg%3D")
-         .addHeader("Host", "container.s3.amazonaws.com")
-         .addHeader("Date", DATE).build();
+            .endpoint("https://container.s3.amazonaws.com/name")
+            .addQueryParam("Expires", "1212683902")
+            .addQueryParam("AWSAccessKeyId", "identity")
+            .addQueryParam("Signature", "Y4Ac4sZfBemGZmgfG78F7IX+IFg=")
+            .addHeader("Host", "container.s3.amazonaws.com")
+            .addHeader("Date", DATE).build();
    }
 
    @Override
@@ -88,11 +90,14 @@ public class AWSS3BlobSignerExpectTest extends S3BlobSignerExpectTest {
    @Override
    protected HttpRequest putBlobWithTime() {
       return HttpRequest.builder().method("PUT")
-         .endpoint("https://container.s3.amazonaws.com/name" +
-            "?Expires=1212683902&AWSAccessKeyId=identity&Signature=genkB2vLxe3AWV/bPvRTMqQts7E%3D")
-         .addHeader("Expect", "100-continue")
-         .addHeader("Host", "container.s3.amazonaws.com")
-         .addHeader("Date", DATE).build();
+            .endpoint("https://container.s3.amazonaws.com/name")
+            .addQueryParam("Expires", "1212683902")
+            .addQueryParam("AWSAccessKeyId", "identity")
+            .addQueryParam("Signature", "genkB2vLxe3AWV/bPvRTMqQts7E=")
+            .addHeader("Expect", "100-continue")
+            .addHeader("Host", "container.s3.amazonaws.com")
+            .addHeader("Date", DATE)
+            .build();
    }
 
    @Override


[2/5] jclouds git commit: JCLOUDS-217: Cloudstack: avoid encoded strings.

Posted by ga...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds/blob/7151a387/apis/cloudstack/src/test/java/org/jclouds/cloudstack/internal/BaseCloudStackComputeServiceContextExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/internal/BaseCloudStackComputeServiceContextExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/internal/BaseCloudStackComputeServiceContextExpectTest.java
index 4a971b2..ed51520 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/internal/BaseCloudStackComputeServiceContextExpectTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/internal/BaseCloudStackComputeServiceContextExpectTest.java
@@ -38,7 +38,7 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest<T> extends B
       .addQueryParam("listAll", "true")
       .addQueryParam("templatefilter", "executable")
       .addQueryParam("apiKey", "APIKEY")
-      .addQueryParam("signature", "Xk6lF/v3SbhrxTKqaC2IWoBPKHo%3D")
+      .addQueryParam("signature", "Xk6lF/v3SbhrxTKqaC2IWoBPKHo=")
       .addHeader("Accept", "application/json")
       .build();
 
@@ -55,7 +55,7 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest<T> extends B
            .addQueryParam("account", "jclouds")
            .addQueryParam("domainid", "457")
            .addQueryParam("apiKey", "APIKEY")
-           .addQueryParam("signature", "yAx1XbtjeEhdBQCNP0OLyWWAFCw%3D")
+           .addQueryParam("signature", "yAx1XbtjeEhdBQCNP0OLyWWAFCw=")
            .addHeader("Accept", "application/json")
            .build();
 
@@ -68,7 +68,7 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest<T> extends B
       .addQueryParam("command", "listOsTypes")
       .addQueryParam("listAll", "true")
       .addQueryParam("apiKey", "APIKEY")
-      .addQueryParam("signature", "8BsE8MsOAhUzo1Q4Y3UD/e96u84%3D")
+      .addQueryParam("signature", "8BsE8MsOAhUzo1Q4Y3UD/e96u84=")
       .addHeader("Accept", "application/json")
       .build();
 
@@ -82,7 +82,7 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest<T> extends B
       .addQueryParam("command", "listOsCategories")
       .addQueryParam("listAll", "true")
       .addQueryParam("apiKey", "APIKEY")
-      .addQueryParam("signature", "OojW4ssh/RQ3CubAzXue4svlofM%3D")
+      .addQueryParam("signature", "OojW4ssh/RQ3CubAzXue4svlofM=")
 //      .addHeader("Accept", "application/json") //TODO: why are we not passing this?
       .build();
 
@@ -96,7 +96,7 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest<T> extends B
       .addQueryParam("command", "listZones")
       .addQueryParam("listAll", "true")
       .addQueryParam("apiKey", "APIKEY")
-      .addQueryParam("signature", "GTUgn/LHDioJRq48kurOdCAYueo%3D")
+      .addQueryParam("signature", "GTUgn/LHDioJRq48kurOdCAYueo=")
       .addHeader("Accept", "application/json")
       .build();
 
@@ -110,7 +110,7 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest<T> extends B
       .addQueryParam("command", "listServiceOfferings")
       .addQueryParam("listAll", "true")
       .addQueryParam("apiKey", "APIKEY")
-      .addQueryParam("signature", "jUien8oeEan7bjKKQbBlzvFuMjw%3D")
+      .addQueryParam("signature", "jUien8oeEan7bjKKQbBlzvFuMjw=")
       .addHeader("Accept", "application/json")
       .build();
 
@@ -124,7 +124,7 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest<T> extends B
       .addQueryParam("command", "listAccounts")
       .addQueryParam("listAll", "true")
       .addQueryParam("apiKey", "APIKEY")
-      .addQueryParam("signature", "E4wuKXCkioaNIiL8hL8FD9K5K2c%3D")
+      .addQueryParam("signature", "E4wuKXCkioaNIiL8hL8FD9K5K2c=")
       .addHeader("Accept", "application/json")
       .build();
 
@@ -140,7 +140,7 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest<T> extends B
       .addQueryParam("account", "jclouds") // account and domain came from above
       .addQueryParam("domainid", "457")
       .addQueryParam("apiKey", "APIKEY")
-      .addQueryParam("signature", "FDiGGBiG/sVj0k6DmZIgMNU8SqI%3D")
+      .addQueryParam("signature", "FDiGGBiG/sVj0k6DmZIgMNU8SqI=")
       .addHeader("Accept", "application/json")
       .build();
 
@@ -159,7 +159,7 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest<T> extends B
       .addQueryParam("listAll", "true")
       .addQueryParam("id", "1")
       .addQueryParam("apiKey", "APIKEY")
-      .addQueryParam("signature", "q5GMO9iUYIFs5S58DdAuYAy8yu0%3D")
+      .addQueryParam("signature", "q5GMO9iUYIFs5S58DdAuYAy8yu0=")
       .addHeader("Accept", "application/json")
       .build();
 
@@ -174,7 +174,7 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest<T> extends B
       .addQueryParam("listAll", "true")
       .addQueryParam("id", "2")
       .addQueryParam("apiKey", "APIKEY")
-      .addQueryParam("signature", "FnYX25207fVLLRz5GhOfRrWuUek%3D")
+      .addQueryParam("signature", "FnYX25207fVLLRz5GhOfRrWuUek=")
       .addHeader("Accept", "application/json")
       .build();
 
@@ -185,10 +185,10 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest<T> extends B
    protected final HttpRequest listCapabilities = HttpRequest.builder().method("GET")
       .endpoint("http://localhost:8080/client/api")
       .addQueryParam("response", "json")
-      .addQueryParam("listAll", "true")      
+      .addQueryParam("listAll", "true")
       .addQueryParam("command", "listCapabilities")
-      .addQueryParam("apiKey", "APIKEY")      
-      .addQueryParam("signature", "vVdhtet/zG59FXgkYkAzEQQ4q1o%3D")
+      .addQueryParam("apiKey", "APIKEY")
+      .addQueryParam("signature", "vVdhtet/zG59FXgkYkAzEQQ4q1o=")
       .addHeader("Accept", "application/json")
       .build();
 
@@ -200,10 +200,10 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest<T> extends B
       .endpoint("http://localhost:8080/client/api")
       .addQueryParam("response", "json")
       .addQueryParam("command", "listSecurityGroups")
-      .addQueryParam("listAll", "true")      
-      .addQueryParam("securitygroupname", "jclouds-test")      
-      .addQueryParam("apiKey", "APIKEY")      
-      .addQueryParam("signature", "zGp2rfHY6fBIGkgODRxyNzFfPFI%3D")
+      .addQueryParam("listAll", "true")
+      .addQueryParam("securitygroupname", "jclouds-test")
+      .addQueryParam("apiKey", "APIKEY")
+      .addQueryParam("signature", "zGp2rfHY6fBIGkgODRxyNzFfPFI=")
       .addHeader("Accept", "application/json")
       .build();
 
@@ -215,9 +215,9 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest<T> extends B
       .endpoint("http://localhost:8080/client/api")
       .addQueryParam("response", "json")
       .addQueryParam("command", "createSecurityGroup")
-      .addQueryParam("name", "jclouds-test")      
-      .addQueryParam("apiKey", "APIKEY")      
-      .addQueryParam("signature", "BdgmqGsvjPmP4PxsEKEpq6buwuA%3D")
+      .addQueryParam("name", "jclouds-test")
+      .addQueryParam("apiKey", "APIKEY")
+      .addQueryParam("signature", "BdgmqGsvjPmP4PxsEKEpq6buwuA=")
       .addHeader("Accept", "application/json")
       .build();
 
@@ -229,13 +229,13 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest<T> extends B
       .endpoint("http://localhost:8080/client/api")
       .addQueryParam("response", "json")
       .addQueryParam("command", "authorizeSecurityGroupIngress")
-      .addQueryParam("securitygroupid", "30")      
+      .addQueryParam("securitygroupid", "30")
       .addQueryParam("protocol", "TCP")
       .addQueryParam("startport", "22")
       .addQueryParam("endport", "22")
       .addQueryParam("cidrlist", "0.0.0.0/0")
-      .addQueryParam("apiKey", "APIKEY")      
-      .addQueryParam("signature", "GVtXzAl/Q7z4wnvKEHtdV0lxv2o%3D")
+      .addQueryParam("apiKey", "APIKEY")
+      .addQueryParam("signature", "GVtXzAl/Q7z4wnvKEHtdV0lxv2o=")
       .addHeader("Accept", "application/json")
       .build();
 
@@ -247,9 +247,9 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest<T> extends B
       .endpoint("http://localhost:8080/client/api")
       .addQueryParam("response", "json")
       .addQueryParam("command", "createSSHKeyPair")
-      .addQueryParam("name", "jclouds-test")      
-      .addQueryParam("apiKey", "APIKEY")      
-      .addQueryParam("signature", "er6YjvUjPFwxy/x/aAVNW9Z8yo8%3D")
+      .addQueryParam("name", "jclouds-test")
+      .addQueryParam("apiKey", "APIKEY")
+      .addQueryParam("signature", "er6YjvUjPFwxy/x/aAVNW9Z8yo8=")
       .addHeader("Accept", "application/json")
       .build();
 


[4/5] jclouds git commit: JCLOUDS-217: Old Swift should encode blob names.

Posted by ga...@apache.org.
JCLOUDS-217: Old Swift should encode blob names.

When constructing the URI from the blob names, the deprecated Swift
provider should encode the blob names.


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/2c2b4980
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/2c2b4980
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/2c2b4980

Branch: refs/heads/master
Commit: 2c2b498066b44f49c4f41064aa9f80ecb2a0ac84
Parents: 7151a38
Author: Timur Alperovich <ti...@gmail.com>
Authored: Fri Sep 11 13:43:35 2015 -0700
Committer: Timur Alperovich <ti...@gmail.com>
Committed: Thu Sep 17 13:08:44 2015 -0700

----------------------------------------------------------------------
 .../swift/functions/ParseObjectInfoListFromJsonResponse.java    | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/2c2b4980/apis/swift/src/main/java/org/jclouds/openstack/swift/functions/ParseObjectInfoListFromJsonResponse.java
----------------------------------------------------------------------
diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/functions/ParseObjectInfoListFromJsonResponse.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/functions/ParseObjectInfoListFromJsonResponse.java
index b2e65a3..485408a 100644
--- a/apis/swift/src/main/java/org/jclouds/openstack/swift/functions/ParseObjectInfoListFromJsonResponse.java
+++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/functions/ParseObjectInfoListFromJsonResponse.java
@@ -38,6 +38,7 @@ import org.jclouds.openstack.swift.domain.internal.ObjectInfoImpl;
 import org.jclouds.openstack.swift.options.ListContainerOptions;
 import org.jclouds.rest.InvocationContext;
 import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.jclouds.util.Strings2;
 
 import com.google.common.base.Function;
 import com.google.common.collect.Iterables;
@@ -72,8 +73,10 @@ public class ParseObjectInfoListFromJsonResponse extends ParseJson<PageSet<Objec
          SortedSet<ObjectInfo> returnVal = Sets.newTreeSet(Iterables.transform(list,
                new Function<ObjectInfoImpl, ObjectInfo>() {
                   public ObjectInfo apply(ObjectInfoImpl from) {
+                     // appendPath decodes the argument and we should pass an encoded string
                      return from.toBuilder().container(container)
-                           .uri(uriBuilder(request.getEndpoint()).clearQuery().appendPath(from.getName()).build())
+                           .uri(uriBuilder(request.getEndpoint()).clearQuery().appendPath(
+                                 Strings2.urlEncode(from.getName())).build())
                            .build();
                   }
                }));


[5/5] jclouds git commit: JCLOUDS-217: Do not decode query strings.

Posted by ga...@apache.org.
JCLOUDS-217: Do not decode query strings.

jclouds should not decode query strings that are passed to create HTTP
requests. This is problematic because in some cases a wrong request
may be generated. The most obvious example is if one passes the "+"
character. For example, the following query parameter: "users=me+you"
is stored by the URI builder as "me you" and subsequently appears in
the request as "users=me%20you", as opposed to "users=me%2Byou" (%2b
is percent encoding for "+").

This is not currently a problem because jclouds relies on the
isUrlEncoded() method to check if a query parameter should be decoded
and the situation above is avoided.

This PR attempts to suggest an alternative (and what I believe is
simpler) approach: on the path of crafting requests, jclouds should
only *encode*, not decode strings. Specifically, jclouds should
_never_ be in a situation where it relies on the isUrlEncoded()
method.


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/075c912d
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/075c912d
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/075c912d

Branch: refs/heads/master
Commit: 075c912d873708a7fbedfea62fae073275c41a05
Parents: 4bc4564
Author: Timur Alperovich <ti...@gmail.com>
Authored: Wed Sep 9 15:42:52 2015 -0700
Committer: Timur Alperovich <ti...@gmail.com>
Committed: Thu Sep 17 13:08:44 2015 -0700

----------------------------------------------------------------------
 core/src/main/java/org/jclouds/http/Uris.java   | 65 +++-----------------
 .../main/java/org/jclouds/util/Strings2.java    |  9 ---
 .../java/org/jclouds/http/HttpRequestTest.java  |  5 +-
 .../java/org/jclouds/util/Strings2Test.java     | 10 ---
 4 files changed, 10 insertions(+), 79 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/075c912d/core/src/main/java/org/jclouds/http/Uris.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/http/Uris.java b/core/src/main/java/org/jclouds/http/Uris.java
index abab52b..facc181 100644
--- a/core/src/main/java/org/jclouds/http/Uris.java
+++ b/core/src/main/java/org/jclouds/http/Uris.java
@@ -28,17 +28,13 @@ import static org.jclouds.util.Strings2.urlEncode;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Map;
 
 import org.jclouds.javax.annotation.Nullable;
 
 import com.google.common.annotations.Beta;
-import com.google.common.base.Function;
-import com.google.common.collect.ForwardingMultimap;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
 import com.google.common.collect.LinkedHashMultimap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Multimap;
@@ -103,7 +99,7 @@ public final class Uris {
       private String host;
       private Integer port;
       private String path;
-      private Multimap<String, Object> query = DecodingMultimap.create();
+      private Multimap<String, Object> query = LinkedHashMultimap.create();
 
       /**
        * override default of {@code / : ; =}
@@ -274,10 +270,12 @@ public final class Uris {
          this.scheme = uri.getScheme();
          this.host = uri.getHost();
          this.port = uri.getPort() == -1 ? null : uri.getPort();
-         if (uri.getPath() != null)
-            path(unescapeSpecialChars(uri.getPath()));
-         if (uri.getQuery() != null)
-            query(queryParser().apply(unescapeSpecialChars(uri.getQuery())));
+         if (uri.getRawPath() != null)
+            // path decodes the string, so we need to get at the raw (encoded) string
+            path(unescapeSpecialChars(uri.getRawPath()));
+         if (uri.getRawQuery() != null)
+            // The query parser decodes the strings that are passed to it; we should pass raw (encoded) queries
+            query(queryParser().apply(unescapeSpecialChars(uri.getRawQuery())));
       }
 
       public URI build() {
@@ -372,53 +370,4 @@ public final class Uris {
          return new StringBuilder().append('/').append(in).toString();
       return in;
    }
-
-   /**
-    * Mutable and permits null values. Url decodes all mutations except {@link Multimap#putAll(Multimap)}
-    *
-    *
-    */
-   static final class DecodingMultimap extends ForwardingMultimap<String, Object> {
-
-      private static Multimap<String, Object> create() {
-         return new DecodingMultimap();
-      }
-
-      private final Multimap<String, Object> delegate = LinkedHashMultimap.create();
-      private final Function<Object, Object> urlDecoder = new Function<Object, Object>() {
-         public Object apply(Object in) {
-            if (in == null) {
-               return null;
-            }
-            return urlDecode(in.toString());
-         }
-      };
-
-      @Override
-      public boolean put(String key, Object value) {
-         return super.put(urlDecode(key), urlDecoder.apply(value));
-      }
-
-      @Override
-      public boolean putAll(String key, Iterable<? extends Object> values) {
-         return super.putAll(urlDecode(key), Iterables.transform(values, urlDecoder));
-      }
-
-      @Override
-      public boolean putAll(Multimap<? extends String, ? extends Object> multimap) {
-         return super.putAll(multimap);
-      }
-
-      @Override
-      public Collection<Object> replaceValues(String key, Iterable<? extends Object> values) {
-         return super.replaceValues(urlDecode(key), Iterables.transform(values, urlDecoder));
-      }
-
-      @Override
-      protected Multimap<String, Object> delegate() {
-         return delegate;
-      }
-
-   }
-
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/075c912d/core/src/main/java/org/jclouds/util/Strings2.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/util/Strings2.java b/core/src/main/java/org/jclouds/util/Strings2.java
index e58e0a2..28ba26c 100644
--- a/core/src/main/java/org/jclouds/util/Strings2.java
+++ b/core/src/main/java/org/jclouds/util/Strings2.java
@@ -88,12 +88,6 @@ public class Strings2 {
    public static boolean isCidrFormat(String in) {
       return CIDR_PATTERN.matcher(in).matches();
    }
-      
-   private static final Pattern URL_ENCODED_PATTERN = Pattern.compile(".*%[a-fA-F0-9][a-fA-F0-9].*");
-
-   public static boolean isUrlEncoded(String in) {
-      return URL_ENCODED_PATTERN.matcher(in).matches();
-   }
 
    /**
     * url decodes the input param, if set.
@@ -107,9 +101,6 @@ public class Strings2 {
    public static String urlDecode(@Nullable String in) {
       if (in == null)
          return null;
-      if (!isUrlEncoded(in)) {
-         return in;
-      }
       String input = in.toString();
       try {
          return URLDecoder.decode(input, "UTF-8");

http://git-wip-us.apache.org/repos/asf/jclouds/blob/075c912d/core/src/test/java/org/jclouds/http/HttpRequestTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/jclouds/http/HttpRequestTest.java b/core/src/test/java/org/jclouds/http/HttpRequestTest.java
index 73ad8b5..ffdaadf 100644
--- a/core/src/test/java/org/jclouds/http/HttpRequestTest.java
+++ b/core/src/test/java/org/jclouds/http/HttpRequestTest.java
@@ -23,6 +23,7 @@ import java.net.URI;
 
 import org.jclouds.io.Payload;
 import org.jclouds.io.Payloads;
+import org.jclouds.util.Strings2;
 import org.testng.annotations.Test;
 
 import com.google.common.collect.ImmutableMultimap;
@@ -67,8 +68,8 @@ public class HttpRequestTest {
 
    // note that + ends up encoded as %2B (plus) and %2F converts back into slash
    public void testAddBase64AndUrlEncodedQueryParams() {
-      String base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789%2B%2F%3D";
-      URI uri = URI.create("http://goo.com:443?header1=" + base64Chars);
+      String base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+      URI uri = URI.create("http://goo.com:443?header1=" + Strings2.urlEncode(base64Chars));
       HttpRequest request = HttpRequest.builder()
             .method("GET")
             .endpoint(uri)

http://git-wip-us.apache.org/repos/asf/jclouds/blob/075c912d/core/src/test/java/org/jclouds/util/Strings2Test.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/jclouds/util/Strings2Test.java b/core/src/test/java/org/jclouds/util/Strings2Test.java
index 125e0eb..bbfbfee 100644
--- a/core/src/test/java/org/jclouds/util/Strings2Test.java
+++ b/core/src/test/java/org/jclouds/util/Strings2Test.java
@@ -27,16 +27,6 @@ import com.google.common.collect.ImmutableMap;
 @Test(groups = "unit")
 public class Strings2Test {
 
-   public void testIsEncoded() {
-      assert Strings2.isUrlEncoded("/read-tests/%73%6f%6d%65%20%66%69%6c%65");
-      assert !Strings2.isUrlEncoded("/read-tests/ tep");
-   }
-
-   public void testNoDoubleDecode() {
-      assertEquals(urlDecode("foo%20bar%2Bbaz"), "foo bar+baz");
-      assertEquals(urlDecode("foo bar+baz"), "foo bar+baz");
-   }
-
    public void testReplaceTokens() {
       assertEquals(Strings2.replaceTokens("hello {where}", ImmutableMap.of("where", "world")), "hello world");
    }


[3/5] jclouds git commit: JCLOUDS-217: Cloudstack: avoid encoded strings.

Posted by ga...@apache.org.
JCLOUDS-217: Cloudstack: avoid encoded strings.

jclouds should not use encoded strings in tests for Cloudstack.


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/7151a387
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/7151a387
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/7151a387

Branch: refs/heads/master
Commit: 7151a3875ba46e768a368d534ecbaa2bb43acb14
Parents: 075c912
Author: Timur Alperovich <ti...@gmail.com>
Authored: Fri Sep 11 13:40:29 2015 -0700
Committer: Timur Alperovich <ti...@gmail.com>
Committed: Thu Sep 17 13:08:44 2015 -0700

----------------------------------------------------------------------
 ...oudStackComputeServiceAdapterExpectTest.java |  22 +-
 .../CloudStackImageExtensionExpectTest.java     |  24 +-
 ...udStackSecurityGroupExtensionExpectTest.java |  36 +-
 .../features/FirewallApiExpectTest.java         | 380 +++++++++++--------
 .../features/GlobalHostApiExpectTest.java       |   6 +-
 .../cloudstack/features/GlobalUserApiTest.java  |   2 +-
 .../features/GlobalZoneApiExpectTest.java       |  45 ++-
 .../cloudstack/features/ISOApiExpectTest.java   |  18 +-
 .../features/SecurityGroupApiTest.java          |  24 +-
 .../cloudstack/features/SnapshotApiTest.java    |  12 +-
 .../cloudstack/features/TagApiExpectTest.java   |  40 +-
 .../cloudstack/features/TemplateApiTest.java    |   6 +-
 .../features/VirtualMachineApiExpectTest.java   |  19 +-
 .../cloudstack/features/ZoneApiExpectTest.java  |  19 +-
 ...oudStackComputeServiceContextExpectTest.java |  52 +--
 15 files changed, 389 insertions(+), 316 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/7151a387/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterExpectTest.java
index 877b0fe..1675fa4 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterExpectTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterExpectTest.java
@@ -56,7 +56,7 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom
         .addQueryParam("command", "queryAsyncJobResult")
         .addQueryParam("jobid", "50006")
         .addQueryParam("apiKey", "APIKEY")
-        .addQueryParam("signature", "v8BWKMxd%2BIzHIuTaZ9sNSzCWqFI%3D")
+        .addQueryParam("signature", "v8BWKMxd+IzHIuTaZ9sNSzCWqFI=")
         .addHeader("Accept", "application/json")
         .build();
 
@@ -74,7 +74,7 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom
         .addQueryParam("command", "queryAsyncJobResult")
         .addQueryParam("jobid", "13330fc9-8b3e-4582-aa3e-90883c041010")
         .addQueryParam("apiKey", "APIKEY")
-        .addQueryParam("signature", "y4gk3ckWAMPDNZM26LUK0gAhfiE%3D")
+        .addQueryParam("signature", "y4gk3ckWAMPDNZM26LUK0gAhfiE=")
         .addHeader("Accept", "application/json")
         .build();
 
@@ -86,8 +86,8 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom
      .endpoint("http://localhost:8080/client/api")
      .addQueryParam("response", "json")
      .addQueryParam("command", "listCapabilities")
-     .addQueryParam("apiKey", "APIKEY")      
-     .addQueryParam("signature", "l3PVoJnKK2G2gHk3HPHtpwWjlW4%3D")
+     .addQueryParam("apiKey", "APIKEY")
+     .addQueryParam("signature", "l3PVoJnKK2G2gHk3HPHtpwWjlW4=")
      .addHeader("Accept", "application/json")
      .build();
 
@@ -104,7 +104,7 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom
               .addQueryParam("networkids", "204")
               .addQueryParam("group", "test")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "M2Wx0CgOeH9vYHhbcbblwziqpwI%3D")
+              .addQueryParam("signature", "M2Wx0CgOeH9vYHhbcbblwziqpwI=")
               .addHeader("Accept", "application/json")
               .build();
   
@@ -149,7 +149,7 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom
               .addQueryParam("group", "test")
               .addQueryParam("keypair", "mykeypair")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "D3qQlTNjxrBXeG82C7YPrwU1jMc%3D")
+              .addQueryParam("signature", "D3qQlTNjxrBXeG82C7YPrwU1jMc=")
               .addHeader("Accept", "application/json")
               .build();
   
@@ -197,7 +197,7 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom
               .addQueryParam("group", "test")
               .addQueryParam("keypair", "jclouds-test")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "kfU/J/REa4DdYj0b/pSjuB3h3Qc%3D")
+              .addQueryParam("signature", "kfU/J/REa4DdYj0b/pSjuB3h3Qc=")
               .addHeader("Accept", "application/json")
               .build();
   
@@ -244,7 +244,7 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom
               .addQueryParam("group", "test")
               .addQueryParam("keypair", "mykeypair")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "5qkUSGh0y%2BP/t04/j3%2BEN9PAeFI%3D")
+              .addQueryParam("signature", "5qkUSGh0y+P/t04/j3+EN9PAeFI=")
               .addHeader("Accept", "application/json")
               .build();
   
@@ -297,7 +297,7 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom
               .addQueryParam("diskofferingid", "5678")
               .addQueryParam("size", "10")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "lDzBXtVKCktueskyI/haID9ohJU%3D")
+              .addQueryParam("signature", "lDzBXtVKCktueskyI/haID9ohJU=")
               .addHeader("Accept", "application/json")
               .build();
 
@@ -352,7 +352,7 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom
               .addQueryParam("keypair", "mykeypair")
               .addQueryParam("securitygroupids", "30")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "rz8V/tMk/UbxUhNqp7Bq3CrSg/k%3D")
+              .addQueryParam("signature", "rz8V/tMk/UbxUhNqp7Bq3CrSg/k=")
               .addHeader("Accept", "application/json")
               .build();
   
@@ -411,7 +411,7 @@ public class CloudStackComputeServiceAdapterExpectTest extends BaseCloudStackCom
               .addQueryParam("group", "test")
               .addQueryParam("keypair", "mykeypair")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "hGV6gZZakwvNKhTJurkm48%2Bzgso%3D")
+              .addQueryParam("signature", "hGV6gZZakwvNKhTJurkm48+zgso=")
               .addHeader("Accept", "application/json")
               .build();
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7151a387/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtensionExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtensionExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtensionExpectTest.java
index 8b1db02..89e6b0c 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtensionExpectTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtensionExpectTest.java
@@ -54,9 +54,9 @@ public class CloudStackImageExtensionExpectTest extends BaseCloudStackComputeSer
          .addQueryParam("listAll", "true")
          .addQueryParam("id", "3239ade9-fd25-405c-8eda-59f0313a3fb0")
          .addQueryParam("apiKey", "APIKEY")
-         .addQueryParam("signature", "Qq7Br3qNsyr5ifWZHIrLAslhwm0%3D")
+         .addQueryParam("signature", "Qq7Br3qNsyr5ifWZHIrLAslhwm0=")
          .addHeader("Accept", "application/json")
-         .build(); 
+         .build();
 
       HttpResponse listVMResponse = HttpResponse.builder().statusCode(200)
          .payload(payloadFromResource("/listvirtualmachinesresponse-imageextension.json"))
@@ -68,9 +68,9 @@ public class CloudStackImageExtensionExpectTest extends BaseCloudStackComputeSer
          .addQueryParam("command", "stopVirtualMachine")
          .addQueryParam("id", "3239ade9-fd25-405c-8eda-59f0313a3fb0")
          .addQueryParam("apiKey", "APIKEY")
-         .addQueryParam("signature", "y9vxRK61K8sDoWtvSJHIx5WO9AE%3D")
+         .addQueryParam("signature", "y9vxRK61K8sDoWtvSJHIx5WO9AE=")
          .addHeader("Accept", "application/json")
-         .build(); 
+         .build();
 
       HttpResponse stopVMResponse = HttpResponse.builder().statusCode(200)
          .payload(payloadFromResource("/stopvirtualmachineresponse-imageextension.json"))
@@ -82,7 +82,7 @@ public class CloudStackImageExtensionExpectTest extends BaseCloudStackComputeSer
          .addQueryParam("command", "queryAsyncJobResult")
          .addQueryParam("jobid", "a7d5127b-24a2-4a44-a4a7-25a6d057b453")
          .addQueryParam("apiKey", "APIKEY")
-         .addQueryParam("signature", "CVpnN%2FSbx%2FMCOOyj%2FoVAt3bn684%3D")
+         .addQueryParam("signature", "CVpnN/Sbx/MCOOyj/oVAt3bn684=")
          .addHeader("Accept", "application/json")
          .build();
 
@@ -97,9 +97,9 @@ public class CloudStackImageExtensionExpectTest extends BaseCloudStackComputeSer
          .addQueryParam("listAll", "true")
          .addQueryParam("virtualmachineid", "3239ade9-fd25-405c-8eda-59f0313a3fb0")
          .addQueryParam("apiKey", "APIKEY")
-         .addQueryParam("signature", "drLPf9NE9ROZPOfeDkASiKa50t8%3D")
+         .addQueryParam("signature", "drLPf9NE9ROZPOfeDkASiKa50t8=")
          .addHeader("Accept", "application/json")
-         .build(); 
+         .build();
 
       HttpResponse listVolumesResponse = HttpResponse.builder().statusCode(200)
          .payload(payloadFromResource("/listvolumesresponse-imageextension.json"))
@@ -115,9 +115,9 @@ public class CloudStackImageExtensionExpectTest extends BaseCloudStackComputeSer
          .addQueryParam("ostypeid", "45de18f1-87c6-4646-8099-95c61f2a300a")
          .addQueryParam("displaytext", "temp-template-ignore")
          .addQueryParam("apiKey", "APIKEY")
-         .addQueryParam("signature", "madHsBgxjYbM6JnZKYWajOlfPlY%3D")
+         .addQueryParam("signature", "madHsBgxjYbM6JnZKYWajOlfPlY=")
          .addHeader("Accept", "application/json")
-         .build(); 
+         .build();
 
       HttpResponse createTemplateResponse = HttpResponse.builder().statusCode(200)
          .payload(payloadFromResource("/createtemplateresponse-imageextension.json"))
@@ -129,7 +129,7 @@ public class CloudStackImageExtensionExpectTest extends BaseCloudStackComputeSer
          .addQueryParam("command", "queryAsyncJobResult")
          .addQueryParam("jobid", "4e345230-8fcc-48a3-8a37-c5fe960df671")
          .addQueryParam("apiKey", "APIKEY")
-         .addQueryParam("signature", "6mTKL9fjz7bn6C7tOaZBzKdZwHs%3D")
+         .addQueryParam("signature", "6mTKL9fjz7bn6C7tOaZBzKdZwHs=")
          .addHeader("Accept", "application/json")
          .build();
 
@@ -145,9 +145,9 @@ public class CloudStackImageExtensionExpectTest extends BaseCloudStackComputeSer
          .addQueryParam("templatefilter", "executable")
          .addQueryParam("id", "3dc6ce25-a6cf-4d60-a664-3499993b511b")
          .addQueryParam("apiKey", "APIKEY")
-         .addQueryParam("signature", "dXv%2Bl04EDd7hmrWv5CdW8v298RE%3D")
+         .addQueryParam("signature", "dXv+l04EDd7hmrWv5CdW8v298RE=")
          .addHeader("Accept", "application/json")
-         .build(); 
+         .build();
 
       HttpResponse getTemplateResponse = HttpResponse.builder().statusCode(200)
          .payload(payloadFromResource("/listtemplatesresponse-imageextension.json"))

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7151a387/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/extensions/CloudStackSecurityGroupExtensionExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/extensions/CloudStackSecurityGroupExtensionExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/extensions/CloudStackSecurityGroupExtensionExpectTest.java
index 07372a0..8d719be 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/extensions/CloudStackSecurityGroupExtensionExpectTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/extensions/CloudStackSecurityGroupExtensionExpectTest.java
@@ -67,7 +67,7 @@ public class CloudStackSecurityGroupExtensionExpectTest extends BaseCloudStackCo
            .addQueryParam("command", "queryAsyncJobResult")
            .addQueryParam("jobid", "13330fc9-8b3e-4582-aa3e-90883c041010")
            .addQueryParam("apiKey", "APIKEY")
-           .addQueryParam("signature", "y4gk3ckWAMPDNZM26LUK0gAhfiE%3D")
+           .addQueryParam("signature", "y4gk3ckWAMPDNZM26LUK0gAhfiE=")
            .addHeader("Accept", "application/json")
            .build();
 
@@ -82,7 +82,7 @@ public class CloudStackSecurityGroupExtensionExpectTest extends BaseCloudStackCo
            .addQueryParam("listAll", "true")
            .addQueryParam("id", "13")
            .addQueryParam("apiKey", "APIKEY")
-           .addQueryParam("signature", "TmlGaO2ICM%2BiXQr88%2BZCyWUniSw%3D")
+           .addQueryParam("signature", "TmlGaO2ICM+iXQr88+ZCyWUniSw=")
            .addHeader("Accept", "application/json")
            .build();
 
@@ -104,7 +104,7 @@ public class CloudStackSecurityGroupExtensionExpectTest extends BaseCloudStackCo
               .addQueryParam("command", "listSecurityGroups")
               .addQueryParam("listAll", "true")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "o%2Bd8xxWT1Pa%2BI57SG2caFAblBYA%3D")
+              .addQueryParam("signature", "o+d8xxWT1Pa+I57SG2caFAblBYA=")
               .addHeader("Accept", "application/json")
               .build();
 
@@ -138,7 +138,7 @@ public class CloudStackSecurityGroupExtensionExpectTest extends BaseCloudStackCo
               .addQueryParam("listAll", "true")
               .addQueryParam("virtualmachineid", "some-node")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "x4f9fGMjIHXl5biaaFK5oOEONcg%3D")
+              .addQueryParam("signature", "x4f9fGMjIHXl5biaaFK5oOEONcg=")
               .addHeader("Accept", "application/json")
               .build();
 
@@ -172,7 +172,7 @@ public class CloudStackSecurityGroupExtensionExpectTest extends BaseCloudStackCo
               .addQueryParam("listAll", "true")
               .addQueryParam("id", "13")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "TmlGaO2ICM%2BiXQr88%2BZCyWUniSw%3D")
+              .addQueryParam("signature", "TmlGaO2ICM+iXQr88+ZCyWUniSw=")
               .addHeader("Accept", "application/json")
               .build();
 
@@ -207,7 +207,7 @@ public class CloudStackSecurityGroupExtensionExpectTest extends BaseCloudStackCo
               .addQueryParam("listAll", "true")
               .addQueryParam("securitygroupname", "jclouds-test")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "zGp2rfHY6fBIGkgODRxyNzFfPFI%3D")
+              .addQueryParam("signature", "zGp2rfHY6fBIGkgODRxyNzFfPFI=")
               .addHeader("Accept", "application/json")
               .build();
 
@@ -245,7 +245,7 @@ public class CloudStackSecurityGroupExtensionExpectTest extends BaseCloudStackCo
               .addQueryParam("listAll", "true")
               .addQueryParam("securitygroupname", "jclouds-test")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "zGp2rfHY6fBIGkgODRxyNzFfPFI%3D")
+              .addQueryParam("signature", "zGp2rfHY6fBIGkgODRxyNzFfPFI=")
               .addHeader("Accept", "application/json")
               .build();
 
@@ -281,7 +281,7 @@ public class CloudStackSecurityGroupExtensionExpectTest extends BaseCloudStackCo
               .addQueryParam("listAll", "true")
               .addQueryParam("id", "13")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "TmlGaO2ICM%2BiXQr88%2BZCyWUniSw%3D")
+              .addQueryParam("signature", "TmlGaO2ICM+iXQr88+ZCyWUniSw=")
               .addHeader("Accept", "application/json")
               .build();
 
@@ -295,7 +295,7 @@ public class CloudStackSecurityGroupExtensionExpectTest extends BaseCloudStackCo
               .addQueryParam("command", "deleteSecurityGroup")
               .addQueryParam("id", "13")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "S1A2lYR/ibf4%2BHGFxVLdZvXZujQ%3D")
+              .addQueryParam("signature", "S1A2lYR/ibf4+HGFxVLdZvXZujQ=")
               .addHeader("Accept", "application/json")
               .build();
 
@@ -329,7 +329,7 @@ public class CloudStackSecurityGroupExtensionExpectTest extends BaseCloudStackCo
               .addQueryParam("listAll", "true")
               .addQueryParam("id", "14")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "pWQ30A6l5qh4eaNypGwM9FoLnUM%3D")
+              .addQueryParam("signature", "pWQ30A6l5qh4eaNypGwM9FoLnUM=")
               .addHeader("Accept", "application/json")
               .build();
 
@@ -364,7 +364,7 @@ public class CloudStackSecurityGroupExtensionExpectTest extends BaseCloudStackCo
               .addQueryParam("endport", "11")
               .addQueryParam("cidrlist", "1.1.1.1/24")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "XyokGNutHwcyU7KQVFZOTHvc4RY%3D")
+              .addQueryParam("signature", "XyokGNutHwcyU7KQVFZOTHvc4RY=")
               .addHeader("Accept", "application/json")
               .build();
 
@@ -413,7 +413,7 @@ public class CloudStackSecurityGroupExtensionExpectTest extends BaseCloudStackCo
               .addQueryParam("endport", "11")
               .addQueryParam("cidrlist", "1.1.1.1/24")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "XyokGNutHwcyU7KQVFZOTHvc4RY%3D")
+              .addQueryParam("signature", "XyokGNutHwcyU7KQVFZOTHvc4RY=")
               .addHeader("Accept", "application/json")
               .build();
 
@@ -455,7 +455,7 @@ public class CloudStackSecurityGroupExtensionExpectTest extends BaseCloudStackCo
               .addQueryParam("usersecuritygrouplist[0].account", "adrian")
               .addQueryParam("usersecuritygrouplist[0].group", "adriancole")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "v2OgKc2IftwX9pfKq2Pw/Z2xh9w%3D")
+              .addQueryParam("signature", "v2OgKc2IftwX9pfKq2Pw/Z2xh9w=")
               .addHeader("Accept", "application/json")
               .build();
 
@@ -507,7 +507,7 @@ public class CloudStackSecurityGroupExtensionExpectTest extends BaseCloudStackCo
               .addQueryParam("usersecuritygrouplist[0].account", "adrian")
               .addQueryParam("usersecuritygrouplist[0].group", "adriancole")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "v2OgKc2IftwX9pfKq2Pw/Z2xh9w%3D")
+              .addQueryParam("signature", "v2OgKc2IftwX9pfKq2Pw/Z2xh9w=")
               .addHeader("Accept", "application/json")
               .build();
 
@@ -549,7 +549,7 @@ public class CloudStackSecurityGroupExtensionExpectTest extends BaseCloudStackCo
               .addQueryParam("command", "revokeSecurityGroupIngress")
               .addQueryParam("id", "6")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "H7cY/MEYGN7df1hiz0mMAFVBfa8%3D")
+              .addQueryParam("signature", "H7cY/MEYGN7df1hiz0mMAFVBfa8=")
               .addHeader("Accept", "application/json")
               .build();
 
@@ -586,7 +586,7 @@ public class CloudStackSecurityGroupExtensionExpectTest extends BaseCloudStackCo
               .addQueryParam("command", "revokeSecurityGroupIngress")
               .addQueryParam("id", "6")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "H7cY/MEYGN7df1hiz0mMAFVBfa8%3D")
+              .addQueryParam("signature", "H7cY/MEYGN7df1hiz0mMAFVBfa8=")
               .addHeader("Accept", "application/json")
               .build();
 
@@ -616,7 +616,7 @@ public class CloudStackSecurityGroupExtensionExpectTest extends BaseCloudStackCo
               .addQueryParam("command", "revokeSecurityGroupIngress")
               .addQueryParam("id", "5")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "bEzvrLtO7aEWkIqJgUeTnd%2B0XbY%3D")
+              .addQueryParam("signature", "bEzvrLtO7aEWkIqJgUeTnd+0XbY=")
               .addHeader("Accept", "application/json")
               .build();
 
@@ -653,7 +653,7 @@ public class CloudStackSecurityGroupExtensionExpectTest extends BaseCloudStackCo
               .addQueryParam("command", "revokeSecurityGroupIngress")
               .addQueryParam("id", "5")
               .addQueryParam("apiKey", "APIKEY")
-              .addQueryParam("signature", "bEzvrLtO7aEWkIqJgUeTnd%2B0XbY%3D")
+              .addQueryParam("signature", "bEzvrLtO7aEWkIqJgUeTnd+0XbY=")
               .addHeader("Accept", "application/json")
               .build();
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7151a387/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallApiExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallApiExpectTest.java
index db6dbc5..2fd9565 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallApiExpectTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallApiExpectTest.java
@@ -19,7 +19,6 @@ package org.jclouds.cloudstack.features;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNull;
 
-import java.net.URI;
 import java.util.Set;
 
 import com.google.common.collect.ImmutableSet;
@@ -41,17 +40,20 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
 
    public void testListFirewallRulesWhenResponseIs2xx() {
       FirewallApi client = requestSendsResponse(
-         HttpRequest.builder()
-            .method("GET")
-            .endpoint(
-               URI.create("http://localhost:8080/client/api?response=json&command=listFirewallRules&listAll=true&" +
-                  "apiKey=identity&signature=9%2BtdTXe2uYLzAexPNgrMy5Tq8hE%3D"))
-            .addHeader("Accept", "application/json")
-            .build(),
-         HttpResponse.builder()
-            .statusCode(200)
-            .payload(payloadFromResource("/listfirewallrulesresponse.json"))
-            .build());
+            HttpRequest.builder()
+                  .method("GET")
+                  .endpoint("http://localhost:8080/client/api")
+                  .addQueryParam("response", "json")
+                  .addQueryParam("command", "listFirewallRules")
+                  .addQueryParam("listAll", "true")
+                  .addQueryParam("apiKey", "identity")
+                  .addQueryParam("signature", "9+tdTXe2uYLzAexPNgrMy5Tq8hE=")
+                  .addHeader("Accept", "application/json")
+                  .build(),
+            HttpResponse.builder()
+                  .statusCode(200)
+                  .payload(payloadFromResource("/listfirewallrulesresponse.json"))
+                  .build());
 
       Set<String> CIDRs  = ImmutableSet.of("0.0.0.0/0");
       assertEquals(client.listFirewallRules(),
@@ -72,15 +74,18 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
    public void testListFirewallRulesWhenReponseIs404() {
       FirewallApi client = requestSendsResponse(
          HttpRequest.builder()
-            .method("GET")
-            .endpoint(
-               URI.create("http://localhost:8080/client/api?response=json&command=listFirewallRules&listAll=true&" +
-                  "apiKey=identity&signature=9%2BtdTXe2uYLzAexPNgrMy5Tq8hE%3D"))
-            .addHeader("Accept", "application/json")
-            .build(),
+               .method("GET")
+               .endpoint("http://localhost:8080/client/api")
+               .addQueryParam("response", "json")
+               .addQueryParam("command", "listFirewallRules")
+               .addQueryParam("listAll", "true")
+               .addQueryParam("apiKey", "identity")
+               .addQueryParam("signature", "9+tdTXe2uYLzAexPNgrMy5Tq8hE=")
+               .addHeader("Accept", "application/json")
+               .build(),
          HttpResponse.builder()
-            .statusCode(404)
-            .build());
+               .statusCode(404)
+               .build());
 
       assertEquals(client.listFirewallRules(), ImmutableSet.of());
    }
@@ -88,16 +93,20 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
    public void testGetFirewallRuleWhenResponseIs2xx() {
       FirewallApi client = requestSendsResponse(
          HttpRequest.builder()
-            .method("GET")
-            .endpoint(
-               URI.create("http://localhost:8080/client/api?response=json&command=listFirewallRules&listAll=true&" +
-                  "id=2017&apiKey=identity&signature=6coh9Qdwla94TN1Dl008WlhzZUY%3D"))
-            .addHeader("Accept", "application/json")
-            .build(),
+               .method("GET")
+               .endpoint("http://localhost:8080/client/api")
+               .addQueryParam("response", "json")
+               .addQueryParam("command", "listFirewallRules")
+               .addQueryParam("listAll", "true")
+               .addQueryParam("id", "2017")
+               .addQueryParam("apiKey", "identity")
+               .addQueryParam("signature", "6coh9Qdwla94TN1Dl008WlhzZUY=")
+               .addHeader("Accept", "application/json")
+               .build(),
          HttpResponse.builder()
-            .statusCode(200)
-            .payload(payloadFromResource("/getfirewallrulesresponse.json"))
-            .build());
+               .statusCode(200)
+               .payload(payloadFromResource("/getfirewallrulesresponse.json"))
+               .build());
 
       assertEquals(client.getFirewallRule("2017"),
          FirewallRule.builder().id("2017").protocol(FirewallRule.Protocol.TCP).startPort(30)
@@ -109,15 +118,19 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
    public void testGetFirewallRuleWhenResponseIs404() {
       FirewallApi client = requestSendsResponse(
          HttpRequest.builder()
-            .method("GET")
-            .endpoint(
-               URI.create("http://localhost:8080/client/api?response=json&command=listFirewallRules&listAll=true&" +
-                  "id=4&apiKey=identity&signature=rYd8gr7ptdSZlIehBEMQEKsm07Q%3D"))
-            .addHeader("Accept", "application/json")
-            .build(),
+               .method("GET")
+               .endpoint("http://localhost:8080/client/api")
+               .addQueryParam("response", "json")
+               .addQueryParam("command", "listFirewallRules")
+               .addQueryParam("listAll", "true")
+               .addQueryParam("id", "4")
+               .addQueryParam("apiKey", "identity")
+               .addQueryParam("signature", "rYd8gr7ptdSZlIehBEMQEKsm07Q=")
+               .addHeader("Accept", "application/json")
+               .build(),
          HttpResponse.builder()
-            .statusCode(404)
-            .build());
+               .statusCode(404)
+               .build());
 
       assertNull(client.getFirewallRule("4"));
    }
@@ -125,16 +138,20 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
    public void testCreateFirewallRuleForIpAndProtocol() {
       FirewallApi client = requestSendsResponse(
          HttpRequest.builder()
-            .method("GET")
-            .endpoint(
-               URI.create("http://localhost:8080/client/api?response=json&command=createFirewallRule&" +
-                  "ipaddressid=2&protocol=TCP&apiKey=identity&signature=d0MZ/yhQPAaV%2BYQmfZsQtQL2C28%3D"))
-            .addHeader("Accept", "application/json")
-            .build(),
+               .method("GET")
+               .endpoint("http://localhost:8080/client/api")
+               .addQueryParam("response", "json")
+               .addQueryParam("command", "createFirewallRule")
+               .addQueryParam("ipaddressid", "2")
+               .addQueryParam("protocol", "TCP")
+               .addQueryParam("apiKey", "identity")
+               .addQueryParam("signature", "d0MZ/yhQPAaV+YQmfZsQtQL2C28=")
+               .addHeader("Accept", "application/json")
+               .build(),
          HttpResponse.builder()
-            .statusCode(200)
-            .payload(payloadFromResource("/createfirewallrulesresponse.json"))
-            .build());
+               .statusCode(200)
+               .payload(payloadFromResource("/createfirewallrulesresponse.json"))
+               .build());
 
       AsyncCreateResponse response = client.createFirewallRuleForIpAndProtocol("2", FirewallRule.Protocol.TCP);
       assertEquals(response.getJobId(), "2036");
@@ -144,15 +161,18 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
    public void testDeleteFirewallRule() {
       FirewallApi client = requestSendsResponse(
          HttpRequest.builder()
-            .method("GET")
-            .endpoint(
-               URI.create("http://localhost:8080/client/api?response=json&" +
-                  "command=deleteFirewallRule&id=2015&apiKey=identity&signature=/T5FAO2yGPctaPmg7TEtIEFW3EU%3D"))
-            .build(),
+               .method("GET")
+               .endpoint("http://localhost:8080/client/api")
+               .addQueryParam("response", "json")
+               .addQueryParam("command", "deleteFirewallRule")
+               .addQueryParam("id", "2015")
+               .addQueryParam("apiKey", "identity").
+               addQueryParam("signature", "/T5FAO2yGPctaPmg7TEtIEFW3EU=")
+               .build(),
          HttpResponse.builder()
-            .statusCode(200)
-            .payload(payloadFromResource("/deletefirewallrulesresponse.json"))
-            .build());
+               .statusCode(200)
+               .payload(payloadFromResource("/deletefirewallrulesresponse.json"))
+               .build());
 
       client.deleteFirewallRule("2015");
    }
@@ -160,16 +180,19 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
    public void testListPortForwardingRulesWhenResponseIs2xx() {
       FirewallApi client = requestSendsResponse(
          HttpRequest.builder()
-            .method("GET")
-            .endpoint(
-               URI.create("http://localhost:8080/client/api?response=json&" +
-                  "command=listPortForwardingRules&listAll=true&apiKey=identity&signature=8SXGJZWdcJfVz4V90Pyod12x9dM%3D"))
-            .addHeader("Accept", "application/json")
-            .build(),
+               .method("GET")
+               .endpoint("http://localhost:8080/client/api")
+               .addQueryParam("response", "json")
+               .addQueryParam("command", "listPortForwardingRules")
+               .addQueryParam("listAll", "true")
+               .addQueryParam("apiKey", "identity")
+               .addQueryParam("signature", "8SXGJZWdcJfVz4V90Pyod12x9dM=")
+               .addHeader("Accept", "application/json")
+               .build(),
          HttpResponse.builder()
-            .statusCode(200)
-            .payload(payloadFromResource("/listportforwardingrulesresponse.json"))
-            .build());
+               .statusCode(200)
+               .payload(payloadFromResource("/listportforwardingrulesresponse.json"))
+               .build());
 
       Set<String> cidrs = ImmutableSet.of("0.0.0.0/1", "128.0.0.0/1");
 
@@ -190,15 +213,18 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
    public void testListPortForwardingRulesWhenReponseIs404() {
       FirewallApi client = requestSendsResponse(
          HttpRequest.builder()
-            .method("GET")
-            .endpoint(
-               URI.create("http://localhost:8080/client/api?response=json&" +
-                  "command=listPortForwardingRules&listAll=true&apiKey=identity&signature=8SXGJZWdcJfVz4V90Pyod12x9dM%3D"))
-            .addHeader("Accept", "application/json")
-            .build(),
+               .method("GET")
+               .endpoint("http://localhost:8080/client/api")
+               .addQueryParam("response", "json")
+               .addQueryParam("command", "listPortForwardingRules")
+               .addQueryParam("listAll", "true")
+               .addQueryParam("apiKey", "identity")
+               .addQueryParam("signature", "8SXGJZWdcJfVz4V90Pyod12x9dM=")
+               .addHeader("Accept", "application/json")
+               .build(),
          HttpResponse.builder()
-            .statusCode(404)
-            .build());
+               .statusCode(404)
+               .build());
 
       assertEquals(client.listPortForwardingRules(), ImmutableSet.of());
    }
@@ -206,16 +232,19 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
    public void testGetPortForwardingRuleWhenResponseIs2xx() {
       FirewallApi client = requestSendsResponse(
          HttpRequest.builder()
-            .method("GET")
-            .endpoint(
-               URI.create("http://localhost:8080/client/api?response=json&" +
-                  "command=listPortForwardingRules&listAll=true&id=15&apiKey=identity&signature=JL63p6cJzbb9vaffeV4u60IGlWE%3D"))
-            .addHeader("Accept", "application/json")
-            .build(),
+               .method("GET")
+               .endpoint("http://localhost:8080/client/api").addQueryParam("response", "json")
+               .addQueryParam("command", "listPortForwardingRules")
+               .addQueryParam("listAll", "true")
+               .addQueryParam("id", "15")
+               .addQueryParam("apiKey", "identity")
+               .addQueryParam("signature", "JL63p6cJzbb9vaffeV4u60IGlWE=")
+               .addHeader("Accept", "application/json")
+               .build(),
          HttpResponse.builder()
-            .statusCode(200)
-            .payload(payloadFromResource("/getportforwardingrulesresponse.json"))
-            .build());
+               .statusCode(200)
+               .payload(payloadFromResource("/getportforwardingrulesresponse.json"))
+               .build());
 
       Set<String> cidrs = ImmutableSet.of("0.0.0.0/1", "128.0.0.0/1");
 
@@ -230,15 +259,18 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
    public void testGetPortForwardingRuleWhenResponseIs404() {
       FirewallApi client = requestSendsResponse(
          HttpRequest.builder()
-            .method("GET")
-            .endpoint(
-               URI.create("http://localhost:8080/client/api?response=json&" +
-                  "command=listPortForwardingRules&listAll=true&id=4&apiKey=identity&signature=4blbBVn2%2BZfF8HwoglbmtYoDAjs%3D"))
-            .addHeader("Accept", "application/json")
-            .build(),
+               .method("GET")
+               .endpoint("http://localhost:8080/client/api").addQueryParam("response", "json")
+               .addQueryParam("command", "listPortForwardingRules")
+               .addQueryParam("listAll", "true")
+               .addQueryParam("id", "4")
+               .addQueryParam("apiKey", "identity")
+               .addQueryParam("signature", "4blbBVn2+ZfF8HwoglbmtYoDAjs=")
+               .addHeader("Accept", "application/json")
+               .build(),
          HttpResponse.builder()
-            .statusCode(404)
-            .build());
+               .statusCode(404)
+               .build());
 
       assertNull(client.getPortForwardingRule("4"));
    }
@@ -246,22 +278,22 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
    public void testCreatePortForwardingRuleForVirtualMachine() {
       FirewallApi client = requestSendsResponse(
          HttpRequest.builder().method("GET")
-                    .endpoint("http://localhost:8080/client/api")
-                    .addQueryParam("response", "json")
-                    .addQueryParam("command", "createPortForwardingRule")
-                    .addQueryParam("ipaddressid", "2")
-                    .addQueryParam("protocol", "tcp")
-                    .addQueryParam("publicport", "22")
-                    .addQueryParam("virtualmachineid", "1234")
-                    .addQueryParam("privateport", "22")
-                    .addQueryParam("apiKey", "identity")
-                    .addQueryParam("signature", "84dtGzQp0G6k3z3Gkc3F/HBNS2Y%3D")
-                    .addHeader("Accept", "application/json")
-                    .build(),
+               .endpoint("http://localhost:8080/client/api")
+               .addQueryParam("response", "json")
+               .addQueryParam("command", "createPortForwardingRule")
+               .addQueryParam("ipaddressid", "2")
+               .addQueryParam("protocol", "tcp")
+               .addQueryParam("publicport", "22")
+               .addQueryParam("virtualmachineid", "1234")
+               .addQueryParam("privateport", "22")
+               .addQueryParam("apiKey", "identity")
+               .addQueryParam("signature", "84dtGzQp0G6k3z3Gkc3F/HBNS2Y=")
+               .addHeader("Accept", "application/json")
+               .build(),
          HttpResponse.builder()
-            .statusCode(200)
-            .payload(payloadFromResource("/createportforwardingrulesresponse.json"))
-            .build());
+               .statusCode(200)
+               .payload(payloadFromResource("/createportforwardingrulesresponse.json"))
+               .build());
 
       AsyncCreateResponse response = client.createPortForwardingRuleForVirtualMachine(
          "2", PortForwardingRule.Protocol.TCP, 22, "1234", 22);
@@ -272,15 +304,18 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
    public void testDeletePortForwardingRule() {
       FirewallApi client = requestSendsResponse(
          HttpRequest.builder()
-            .method("GET")
-            .endpoint(
-               URI.create("http://localhost:8080/client/api?response=json&" +
-                  "command=deletePortForwardingRule&id=2015&apiKey=identity&signature=2UE7KB3wm5ocmR%2BGMNFKPKfiDo8%3D"))
-            .build(),
+               .method("GET")
+               .endpoint("http://localhost:8080/client/api")
+               .addQueryParam("response", "json")
+               .addQueryParam("command", "deletePortForwardingRule")
+               .addQueryParam("id", "2015")
+               .addQueryParam("apiKey", "identity")
+               .addQueryParam("signature", "2UE7KB3wm5ocmR+GMNFKPKfiDo8=")
+               .build(),
          HttpResponse.builder()
-            .statusCode(200)
-            .payload(payloadFromResource("/deleteportforwardingrulesresponse.json"))
-            .build());
+               .statusCode(200)
+               .payload(payloadFromResource("/deleteportforwardingrulesresponse.json"))
+               .build());
 
       client.deletePortForwardingRule("2015");
    }
@@ -288,16 +323,19 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
    public void testListEgressFirewallRulesWhenResponseIs2xx() {
       FirewallApi client = requestSendsResponse(
               HttpRequest.builder()
-                      .method("GET")
-                      .endpoint(
-                              URI.create("http://localhost:8080/client/api?response=json&command=listEgressFirewallRules&listAll=true&" +
-                                      "apiKey=identity&signature=j3OpRXs7mEwVKs9KIb4ncRKVO9A%3D"))
-                      .addHeader("Accept", "application/json")
-                      .build(),
+                    .method("GET")
+                    .endpoint("http://localhost:8080/client/api")
+                    .addQueryParam("response", "json")
+                    .addQueryParam("command", "listEgressFirewallRules")
+                    .addQueryParam("listAll", "true")
+                    .addQueryParam("apiKey", "identity")
+                    .addQueryParam("signature", "j3OpRXs7mEwVKs9KIb4ncRKVO9A=")
+                    .addHeader("Accept", "application/json")
+                    .build(),
               HttpResponse.builder()
-                      .statusCode(200)
-                      .payload(payloadFromResource("/listegressfirewallrulesresponse.json"))
-                      .build());
+                    .statusCode(200)
+                    .payload(payloadFromResource("/listegressfirewallrulesresponse.json"))
+                    .build());
 
       Set<String> CIDRs  = ImmutableSet.of("0.0.0.0/0");
       assertEquals(client.listEgressFirewallRules(),
@@ -318,15 +356,18 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
    public void testListEgressFirewallRulesWhenReponseIs404() {
       FirewallApi client = requestSendsResponse(
               HttpRequest.builder()
-                      .method("GET")
-                      .endpoint(
-                              URI.create("http://localhost:8080/client/api?response=json&command=listEgressFirewallRules&listAll=true&" +
-                                      "apiKey=identity&signature=j3OpRXs7mEwVKs9KIb4ncRKVO9A%3D"))
-                      .addHeader("Accept", "application/json")
-                      .build(),
+                    .method("GET")
+                    .endpoint("http://localhost:8080/client/api")
+                    .addQueryParam("response", "json")
+                    .addQueryParam("command", "listEgressFirewallRules")
+                    .addQueryParam("listAll", "true")
+                    .addQueryParam("apiKey", "identity")
+                    .addQueryParam("signature", "j3OpRXs7mEwVKs9KIb4ncRKVO9A=")
+                    .addHeader("Accept", "application/json")
+                    .build(),
               HttpResponse.builder()
-                      .statusCode(404)
-                      .build());
+                    .statusCode(404)
+                    .build());
 
       assertEquals(client.listEgressFirewallRules(), ImmutableSet.of());
    }
@@ -334,16 +375,20 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
    public void testGetEgressFirewallRuleWhenResponseIs2xx() {
       FirewallApi client = requestSendsResponse(
               HttpRequest.builder()
-                      .method("GET")
-                      .endpoint(
-                              URI.create("http://localhost:8080/client/api?response=json&command=listEgressFirewallRules&listAll=true&" +
-                                      "id=2017&apiKey=identity&signature=Hi1K5VA3yd3mk0AmgJ2F6y%2BVzMo%3D"))
-                      .addHeader("Accept", "application/json")
-                      .build(),
+                    .method("GET")
+                    .endpoint("http://localhost:8080/client/api")
+                    .addQueryParam("response", "json")
+                    .addQueryParam("command", "listEgressFirewallRules")
+                    .addQueryParam("listAll", "true")
+                    .addQueryParam("id", "2017")
+                    .addQueryParam("apiKey", "identity")
+                    .addQueryParam("signature", "Hi1K5VA3yd3mk0AmgJ2F6y+VzMo=")
+                    .addHeader("Accept", "application/json")
+                    .build(),
               HttpResponse.builder()
-                      .statusCode(200)
-                      .payload(payloadFromResource("/getegressfirewallrulesresponse.json"))
-                      .build());
+                    .statusCode(200)
+                    .payload(payloadFromResource("/getegressfirewallrulesresponse.json"))
+                    .build());
 
       assertEquals(client.getEgressFirewallRule("2017"),
               FirewallRule.builder().id("2017").protocol(FirewallRule.Protocol.TCP).startPort(30)
@@ -355,15 +400,19 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
    public void testGetEgressFirewallRuleWhenResponseIs404() {
       FirewallApi client = requestSendsResponse(
               HttpRequest.builder()
-                      .method("GET")
-                      .endpoint(
-                              URI.create("http://localhost:8080/client/api?response=json&command=listEgressFirewallRules&listAll=true&" +
-                                      "id=4&apiKey=identity&signature=dzb5azKxXZsuGrNRJbRHfna7FMo%3D"))
-                      .addHeader("Accept", "application/json")
-                      .build(),
+                    .method("GET")
+                    .endpoint("http://localhost:8080/client/api")
+                    .addQueryParam("response", "json")
+                    .addQueryParam("command", "listEgressFirewallRules")
+                    .addQueryParam("listAll", "true")
+                    .addQueryParam("id", "4")
+                    .addQueryParam("apiKey", "identity")
+                    .addQueryParam("signature", "dzb5azKxXZsuGrNRJbRHfna7FMo=")
+                    .addHeader("Accept", "application/json")
+                    .build(),
               HttpResponse.builder()
-                      .statusCode(404)
-                      .build());
+                    .statusCode(404)
+                    .build());
 
       assertNull(client.getEgressFirewallRule("4"));
    }
@@ -371,16 +420,20 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
    public void testCreateEgressFirewallRuleForNetworkAndProtocol() {
       FirewallApi client = requestSendsResponse(
               HttpRequest.builder()
-                      .method("GET")
-                      .endpoint(
-                              URI.create("http://localhost:8080/client/api?response=json&command=createEgressFirewallRule&" +
-                                      "networkid=2&protocol=TCP&apiKey=identity&signature=I/OJEqiLp8ZHlZskKUiT5uTRE3M%3D"))
-                      .addHeader("Accept", "application/json")
-                      .build(),
+                    .method("GET")
+                    .endpoint("http://localhost:8080/client/api")
+                    .addQueryParam("response", "json")
+                    .addQueryParam("command", "createEgressFirewallRule")
+                    .addQueryParam("networkid", "2")
+                    .addQueryParam("protocol", "TCP")
+                    .addQueryParam("apiKey", "identity")
+                    .addQueryParam("signature", "I/OJEqiLp8ZHlZskKUiT5uTRE3M=")
+                    .addHeader("Accept", "application/json")
+                    .build(),
               HttpResponse.builder()
-                      .statusCode(200)
-                      .payload(payloadFromResource("/createegressfirewallrulesresponse.json"))
-                      .build());
+                    .statusCode(200)
+                    .payload(payloadFromResource("/createegressfirewallrulesresponse.json"))
+                    .build());
 
       AsyncCreateResponse response = client.createEgressFirewallRuleForNetworkAndProtocol("2", FirewallRule.Protocol.TCP);
       assertEquals(response.getJobId(), "2036");
@@ -390,15 +443,18 @@ public class FirewallApiExpectTest extends BaseCloudStackExpectTest<FirewallApi>
    public void testDeleteEgressFirewallRule() {
       FirewallApi client = requestSendsResponse(
               HttpRequest.builder()
-                      .method("GET")
-                      .endpoint(
-                              URI.create("http://localhost:8080/client/api?response=json&" +
-                                      "command=deleteEgressFirewallRule&id=2015&apiKey=identity&signature=S119WNmamKwc5d9qvvkIJznXytg%3D"))
-                      .build(),
+                    .method("GET")
+                    .endpoint("http://localhost:8080/client/api")
+                    .addQueryParam("response", "json")
+                    .addQueryParam("command", "deleteEgressFirewallRule")
+                    .addQueryParam("id", "2015")
+                    .addQueryParam("apiKey", "identity")
+                    .addQueryParam("signature", "S119WNmamKwc5d9qvvkIJznXytg=")
+                    .build(),
               HttpResponse.builder()
-                      .statusCode(200)
-                      .payload(payloadFromResource("/deleteegressfirewallrulesresponse.json"))
-                      .build());
+                    .statusCode(200)
+                    .payload(payloadFromResource("/deleteegressfirewallrulesresponse.json"))
+                    .build());
 
       client.deleteEgressFirewallRule("2015");
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7151a387/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostApiExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostApiExpectTest.java
index 9fd82db..a782b54 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostApiExpectTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostApiExpectTest.java
@@ -97,14 +97,14 @@ public class GlobalHostApiExpectTest extends BaseCloudStackExpectTest<GlobalHost
                                     .addQueryParam("response", "json")
                                     .addQueryParam("command", "addHost")
                                     .addQueryParam("zoneid", "1")
-                                    .addQueryParam("url", "http%3A//example.com")
+                                    .addQueryParam("url", "http://example.com")
                                     .addQueryParam("hypervisor", "XenServer")
                                     .addQueryParam("username", "fred")
                                     .addQueryParam("password", "sekrit")
                                     .addQueryParam("hosttags", "")
                                     .addQueryParam("allocationstate", "Enabled")
                                     .addQueryParam("clusterid", "1")
-                                    .addQueryParam("clustername", "Xen%20Clust%201")
+                                    .addQueryParam("clustername", "Xen Clust 1")
                                     .addQueryParam("podid", "1")
                                     .addQueryParam("apiKey", "identity")
                                     .addQueryParam("signature", "ExGaljKKQIlVbWk5hd0BnnjmBzs=")
@@ -334,7 +334,7 @@ public class GlobalHostApiExpectTest extends BaseCloudStackExpectTest<GlobalHost
                                                   .addQueryParam("username", "fred")
                                                   .addQueryParam("password", "sekrit")
                                                   .addQueryParam("apiKey", "identity")
-                                                  .addQueryParam("signature", "xwc83%2BoYK0cuAiFQAlg/7/1IVHE=")
+                                                  .addQueryParam("signature", "xwc83+oYK0cuAiFQAlg/7/1IVHE=")
                                                   .addHeader("Accept", "application/json").build();
 
    @Test

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7151a387/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalUserApiTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalUserApiTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalUserApiTest.java
index 4c8f76a..2a01125 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalUserApiTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalUserApiTest.java
@@ -42,7 +42,7 @@ public class GlobalUserApiTest extends BaseCloudStackApiTest<GlobalUserApi> {
                                        .addQueryParam("command", "createUser")
                                        .addQueryParam("username", "user")
                                        .addQueryParam("account", "account")
-                                       .addQueryParam("email", "email%40example.com")
+                                       .addQueryParam("email", "email@example.com")
                                        .addQueryParam("password", "hashed-password")
                                        .addQueryParam("firstname", "FirstName")
                                        .addQueryParam("lastname", "LastName").build();

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7151a387/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalZoneApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalZoneApiExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalZoneApiExpectTest.java
index 80364d5..92e43f3 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalZoneApiExpectTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalZoneApiExpectTest.java
@@ -20,8 +20,6 @@ import static org.jclouds.cloudstack.options.UpdateZoneOptions.Builder.name;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNull;
 
-import java.net.URI;
-
 import org.jclouds.cloudstack.CloudStackContext;
 import org.jclouds.cloudstack.domain.AllocationState;
 import org.jclouds.cloudstack.domain.NetworkType;
@@ -49,7 +47,7 @@ public class GlobalZoneApiExpectTest extends BaseCloudStackExpectTest<GlobalZone
                                        .addQueryParam("dns1", "8.8.8.8")
                                        .addQueryParam("internaldns1", "10.10.10.10")
                                        .addQueryParam("apiKey", "identity")
-                                       .addQueryParam("signature", "hWNmM2%2BTsfb5DelQa/GJLN5DVWE=")
+                                       .addQueryParam("signature", "hWNmM2+Tsfb5DelQa/GJLN5DVWE=")
                                        .addHeader("Accept", "application/json").build();
    
    public void testCreateZoneWhenResponseIs2xxAnd404() {
@@ -77,15 +75,17 @@ public class GlobalZoneApiExpectTest extends BaseCloudStackExpectTest<GlobalZone
 
    public void testUpdateZoneWhenResponseIs2xxAnd404() {
       HttpRequest request = HttpRequest.builder()
-         .method("GET")
-         .endpoint(
-            URI.create("http://localhost:8080/client/api?response=json&command=updateZone&" +
-               "id=6&name=test-zone&dns1=8.8.8.8&apiKey=identity&signature=v19FdHKHztdT0IRloYFFn0eNbWM%3D"))
-         .headers(
-            ImmutableMultimap.<String, String>builder()
-               .put("Accept", "application/json")
-               .build())
-         .build();
+            .method("GET")
+            .endpoint("http://localhost:8080/client/api")
+            .addQueryParam("response", "json")
+            .addQueryParam("command", "updateZone")
+            .addQueryParam("id", "6")
+            .addQueryParam("name", "test-zone")
+            .addQueryParam("dns1", "8.8.8.8")
+            .addQueryParam("apiKey", "identity")
+            .addQueryParam("signature", "v19FdHKHztdT0IRloYFFn0eNbWM=")
+            .headers(ImmutableMultimap.<String, String>builder().put("Accept", "application/json").build())
+            .build();
 
       GlobalZoneApi client = requestSendsResponse(request,
          HttpResponse.builder()
@@ -112,16 +112,19 @@ public class GlobalZoneApiExpectTest extends BaseCloudStackExpectTest<GlobalZone
    public void testDeleteZone() {
       GlobalZoneApi client = requestSendsResponse(
          HttpRequest.builder()
-            .method("GET")
-            .endpoint(
-               URI.create("http://localhost:8080/client/api?response=json&" +
-                  "command=deleteZone&id=6&apiKey=identity&signature=TfkzSIK8kzGJnIYo3DofECyuOII%3D"))
-            .addHeader("Accept", "application/json")
-            .build(),
+               .method("GET")
+               .endpoint("http://localhost:8080/client/api")
+               .addQueryParam("response", "json")
+               .addQueryParam("command", "deleteZone")
+               .addQueryParam("id", "6")
+               .addQueryParam("apiKey", "identity")
+               .addQueryParam("signature", "TfkzSIK8kzGJnIYo3DofECyuOII=")
+               .addHeader("Accept", "application/json")
+               .build(),
          HttpResponse.builder()
-            .statusCode(200)
-            .payload(payloadFromResource("/deletezoneresponse.json"))
-            .build());
+               .statusCode(200)
+               .payload(payloadFromResource("/deletezoneresponse.json"))
+               .build());
 
       client.deleteZone("6");
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7151a387/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOApiExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOApiExpectTest.java
index ce564a1..2366041 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOApiExpectTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOApiExpectTest.java
@@ -76,7 +76,7 @@ public class ISOApiExpectTest extends BaseCloudStackExpectTest<ISOApi> {
                                      .addQueryParam("command", "listIsos")
                                      .addQueryParam("listAll", "true")
                                      .addQueryParam("apiKey", "identity")
-                                     .addQueryParam("signature", "qUUF6hCDc57Bc/nHriS9umbZBKA%3D")
+                                     .addQueryParam("signature", "qUUF6hCDc57Bc/nHriS9umbZBKA=")
                                      .addHeader("Accept", "application/json")
                                      .build();
    
@@ -113,10 +113,10 @@ public class ISOApiExpectTest extends BaseCloudStackExpectTest<ISOApi> {
                                             .addQueryParam("ispublic", "true")
                                             .addQueryParam("isready", "true")
                                             .addQueryParam("keyword", "bob")
-                                            .addQueryParam("name", "bob%27s%20iso")
+                                            .addQueryParam("name", "bob's iso")
                                             .addQueryParam("zoneid", "7")
                                             .addQueryParam("apiKey", "identity")
-                                            .addQueryParam("signature", "4S5ustbaBErEnpymWLSj1rEJ/nk%3D")
+                                            .addQueryParam("signature", "4S5ustbaBErEnpymWLSj1rEJ/nk=")
                                             .addHeader("Accept", "application/json")
                                             .build();
    
@@ -137,7 +137,7 @@ public class ISOApiExpectTest extends BaseCloudStackExpectTest<ISOApi> {
                                      .addQueryParam("listAll", "true")
                                      .addQueryParam("id", "018e0928-8205-4d8e-9329-f731a9ccd488")
                                      .addQueryParam("apiKey", "identity")
-                                     .addQueryParam("signature", "uZyPUJt6ThMDcQSDa%2BEv5LMs%2B2U%3D")
+                                     .addQueryParam("signature", "uZyPUJt6ThMDcQSDa+Ev5LMs+2U=")
                                      .addHeader("Accept", "application/json")
                                      .build();
    
@@ -176,8 +176,8 @@ public class ISOApiExpectTest extends BaseCloudStackExpectTest<ISOApi> {
                                         .addQueryParam("ispublic", "true")
                                         .addQueryParam("ostypeid", "1234-abcd")
                                         .addQueryParam("apiKey", "identity")
-                                        .addQueryParam("signature", "YpFMYUUu0daLgwxNFubVfkV0Nw8%3D")
-                                        .addHeader("Accept", "application/json") 
+                                        .addQueryParam("signature", "YpFMYUUu0daLgwxNFubVfkV0Nw8=")
+                                        .addHeader("Accept", "application/json")
                                         .build();
    
    RegisterISOOptions registerISOOptions = RegisterISOOptions.Builder
@@ -192,8 +192,8 @@ public class ISOApiExpectTest extends BaseCloudStackExpectTest<ISOApi> {
             .statusCode(200)
             .payload(payloadFromResource("/registerisoresponse.json"))
             .build());
-      
-      assertEquals(client.registerISO("ubuntu10.10", "ubuntu 10.10 (32 bit)", "http://ubuntu/ubuntu-10.10.iso", "1e0335d9-b6cc-4805-bddf-0828e66a0d01", 
+
+      assertEquals(client.registerISO("ubuntu10.10", "ubuntu 10.10 (32 bit)", "http://ubuntu/ubuntu-10.10.iso", "1e0335d9-b6cc-4805-bddf-0828e66a0d01",
               registerISOOptions),
             ISO.builder().id("b52c509d-c6e2-452c-b6ec-aa00720ed6cd").name("ubuntu10.10").displayText("ubuntu 10.10 (32 bit)").isPublic(true)
                 .isReady(false).bootable(true).isFeatured(false).crossZones(false).osTypeId("0e0335d9-b6cc-4808-bddf-0828e66a0d03")
@@ -210,7 +210,7 @@ public class ISOApiExpectTest extends BaseCloudStackExpectTest<ISOApi> {
              .statusCode(404)
              .build());
 
-       assertNull(client.registerISO("ubuntu10.10", "ubuntu 10.10 (32 bit)", "http://ubuntu/ubuntu-10.10.iso", "1e0335d9-b6cc-4805-bddf-0828e66a0d01", 
+       assertNull(client.registerISO("ubuntu10.10", "ubuntu 10.10 (32 bit)", "http://ubuntu/ubuntu-10.10.iso", "1e0335d9-b6cc-4805-bddf-0828e66a0d01",
                registerISOOptions));
     }
    

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7151a387/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupApiTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupApiTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupApiTest.java
index 1907877..c2ebe89 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupApiTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupApiTest.java
@@ -173,12 +173,12 @@ public class SecurityGroupApiTest extends BaseCloudStackApiTest<SecurityGroupApi
                                                            .addQueryParam("protocol", "tcp")
                                                            .addQueryParam("startport", "22")
                                                            .addQueryParam("endport", "22")
-                                                           .addQueryParam("usersecuritygrouplist%5B0%5D.account", "adrian")
-                                                           .addQueryParam("usersecuritygrouplist%5B0%5D.group", "group1")
-                                                           .addQueryParam("usersecuritygrouplist%5B1%5D.account", "adrian")
-                                                           .addQueryParam("usersecuritygrouplist%5B1%5D.group", "group2")
-                                                           .addQueryParam("usersecuritygrouplist%5B2%5D.account", "bob")
-                                                           .addQueryParam("usersecuritygrouplist%5B2%5D.group", "group1").build();
+                                                           .addQueryParam("usersecuritygrouplist[0].account", "adrian")
+                                                           .addQueryParam("usersecuritygrouplist[0].group", "group1")
+                                                           .addQueryParam("usersecuritygrouplist[1].account", "adrian")
+                                                           .addQueryParam("usersecuritygrouplist[1].group", "group2")
+                                                           .addQueryParam("usersecuritygrouplist[2].account", "bob")
+                                                           .addQueryParam("usersecuritygrouplist[2].group", "group1").build();
 
    public void testAuthorizeIngressPortsToSecurityGroups() throws SecurityException, NoSuchMethodException, IOException {
       Invokable<?, ?> method = method(SecurityGroupApi.class, "authorizeIngressPortsToSecurityGroups", String.class,
@@ -233,12 +233,12 @@ public class SecurityGroupApiTest extends BaseCloudStackApiTest<SecurityGroupApi
                                                            .addQueryParam("securitygroupid", "2")
                                                            .addQueryParam("icmpcode", "22")
                                                            .addQueryParam("icmptype", "22")
-                                                           .addQueryParam("usersecuritygrouplist%5B0%5D.account", "adrian")
-                                                           .addQueryParam("usersecuritygrouplist%5B0%5D.group", "group1")
-                                                           .addQueryParam("usersecuritygrouplist%5B1%5D.account", "adrian")
-                                                           .addQueryParam("usersecuritygrouplist%5B1%5D.group", "group2")
-                                                           .addQueryParam("usersecuritygrouplist%5B2%5D.account", "bob")
-                                                           .addQueryParam("usersecuritygrouplist%5B2%5D.group", "group1").build();
+                                                           .addQueryParam("usersecuritygrouplist[0].account", "adrian")
+                                                           .addQueryParam("usersecuritygrouplist[0].group", "group1")
+                                                           .addQueryParam("usersecuritygrouplist[1].account", "adrian")
+                                                           .addQueryParam("usersecuritygrouplist[1].group", "group2")
+                                                           .addQueryParam("usersecuritygrouplist[2].account", "bob")
+                                                           .addQueryParam("usersecuritygrouplist[2].group", "group1").build();
 
    public void testAuthorizeIngressICMPToSecurityGroups() throws SecurityException, NoSuchMethodException, IOException {
       Invokable<?, ?> method = method(SecurityGroupApi.class, "authorizeIngressICMPToSecurityGroups", String.class,

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7151a387/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotApiTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotApiTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotApiTest.java
index 897bf3c..270719d 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotApiTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotApiTest.java
@@ -118,7 +118,15 @@ public class SnapshotApiTest extends BaseCloudStackApiTest<SnapshotApi> {
 
    public void testListSnapshotsOptions() throws NoSuchMethodException {
       Invokable<?, ?> method = method(SnapshotApi.class, "listSnapshots", ListSnapshotsOptions[].class);
-      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(ListSnapshotsOptions.Builder.accountInDomain("acc", "7").id("5").interval(Snapshot.Interval.MONTHLY).isRecursive(true).keyword("fred").name("fred's snapshot").snapshotType(Snapshot.Type.RECURRING).volumeId("11")));
+      GeneratedHttpRequest httpRequest = processor.createRequest(method,
+            ImmutableList.<Object> of(ListSnapshotsOptions.Builder.accountInDomain("acc", "7")
+                  .id("5")
+                  .interval(Snapshot.Interval.MONTHLY)
+                  .isRecursive(true)
+                  .keyword("fred")
+                  .name("fred's snapshot")
+                  .snapshotType(Snapshot.Type.RECURRING)
+                  .volumeId("11")));
 
       assertRequestLineEquals(httpRequest,
             "GET http://localhost:8080/client/api?response=json&command=listSnapshots&listAll=true&account=acc&domainid=7&id=5&intervaltype=MONTHLY&isrecursive=true&keyword=fred&name=fred%27s%20snapshot&snapshottype=RECURRING&volumeid=11 HTTP/1.1");
@@ -156,7 +164,7 @@ public class SnapshotApiTest extends BaseCloudStackApiTest<SnapshotApi> {
                                        .addQueryParam("timezone", "UTC")
                                        .addQueryParam("volumeid", "12")
                                        .addQueryParam("intervaltype", "MONTHLY")
-                                       .addQueryParam("schedule", "07%3A06%3A05").build();
+                                       .addQueryParam("schedule", "07:06:05").build();
 
    public void testCreateSnapshotPolicy() throws NoSuchMethodException {
       Invokable<?, ?> method = method(SnapshotApi.class, "createSnapshotPolicy", SnapshotPolicySchedule.class, String.class, String.class, String.class);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7151a387/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TagApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TagApiExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TagApiExpectTest.java
index a198579..0adcd34 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TagApiExpectTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TagApiExpectTest.java
@@ -16,10 +16,8 @@
  */
 package org.jclouds.cloudstack.features;
 
-import static org.jclouds.util.Strings2.urlEncode;
 import static org.testng.Assert.assertEquals;
 
-import java.net.URI;
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -48,7 +46,7 @@ public class TagApiExpectTest extends BaseCloudStackExpectTest<TagApi> {
                   .addQueryParam("command", "listTags")
                   .addQueryParam("listAll", "true")
                   .addQueryParam("apiKey", "identity")
-                  .addQueryParam("signature", "amvtC2a0VHzzDF5SUAIOZpXHd0A%3D")
+                  .addQueryParam("signature", "amvtC2a0VHzzDF5SUAIOZpXHd0A=")
                   .addHeader("Accept", "application/json")
                   .build(),
             HttpResponse.builder()
@@ -73,17 +71,19 @@ public class TagApiExpectTest extends BaseCloudStackExpectTest<TagApi> {
 
    public void testListTagsWhenResponseIs404() {
       TagApi client = requestSendsResponse(
-         HttpRequest.builder()
-            .method("GET")
-            .endpoint(
-                  URI.create("http://localhost:8080/client/api?response=json&" +
-                        "command=listTags&listAll=true&apiKey=identity&signature=amvtC2a0VHzzDF5SUAIOZpXHd0A%3D")
-            )
-            .addHeader("Accept", "application/json")
-            .build(),
-         HttpResponse.builder()
-            .statusCode(404)
-            .build());
+            HttpRequest.builder()
+                  .method("GET")
+                  .endpoint("http://localhost:8080/client/api")
+                  .addQueryParam("response", "json")
+                  .addQueryParam("command", "listTags")
+                  .addQueryParam("listAll", "true")
+                  .addQueryParam("apiKey", "identity")
+                  .addQueryParam("signature", "amvtC2a0VHzzDF5SUAIOZpXHd0A=")
+                  .addHeader("Accept", "application/json")
+                  .build(),
+            HttpResponse.builder()
+                  .statusCode(404)
+                  .build());
 
       assertEquals(client.listTags(), ImmutableSet.of());
    }
@@ -96,10 +96,10 @@ public class TagApiExpectTest extends BaseCloudStackExpectTest<TagApi> {
                   .addQueryParam("command", "createTags")
                   .addQueryParam("resourcetype", "Template")
                   .addQueryParam("resourceids", "52d89d5d-6070-4fd4-8131-c6c9ca4b062e")
-                  .addQueryParam(urlEncode("tags[0].key"), "some-tag")
-                  .addQueryParam(urlEncode("tags[0].value"), "some-value")
+                  .addQueryParam("tags[0].key", "some-tag")
+                  .addQueryParam("tags[0].value", "some-value")
                   .addQueryParam("apiKey", "identity")
-                  .addQueryParam("signature", "HDGTKGG9kONEwh5xlLe9R72z%2B9Q%3D")
+                  .addQueryParam("signature", "HDGTKGG9kONEwh5xlLe9R72z+9Q=")
                   .addHeader("Accept", "application/json")
                   .build(),
             HttpResponse.builder()
@@ -125,10 +125,10 @@ public class TagApiExpectTest extends BaseCloudStackExpectTest<TagApi> {
                   .addQueryParam("command", "deleteTags")
                   .addQueryParam("resourcetype", "Template")
                   .addQueryParam("resourceids", "52d89d5d-6070-4fd4-8131-c6c9ca4b062e")
-                  .addQueryParam(urlEncode("tags[0].key"), "some-tag")
-                  .addQueryParam(urlEncode("tags[0].value"), "some-value")
+                  .addQueryParam("tags[0].key", "some-tag")
+                  .addQueryParam("tags[0].value", "some-value")
                   .addQueryParam("apiKey", "identity")
-                  .addQueryParam("signature", "inAqWH/GkkGipkZFG5Wfmxa8vOE%3D")
+                  .addQueryParam("signature", "inAqWH/GkkGipkZFG5Wfmxa8vOE=")
                   .addHeader("Accept", "application/json")
                   .build(),
             HttpResponse.builder()

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7151a387/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TemplateApiTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TemplateApiTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TemplateApiTest.java
index 002d6b0..be8b0af 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TemplateApiTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/TemplateApiTest.java
@@ -92,7 +92,7 @@ public class TemplateApiTest extends BaseCloudStackApiTest<TemplateApi> {
                                              .addQueryParam("command", "registerTemplate")
                                              .addQueryParam("format", "QCOW2")
                                              .addQueryParam("hypervisor", "xen")
-                                             .addQueryParam("url", "http%3A//example.com/")
+                                             .addQueryParam("url", "http://example.com/")
                                              .addQueryParam("zoneid", "20")
                                              .addQueryParam("name", "thename")
                                              .addQueryParam("ostypeid", "10")
@@ -119,7 +119,7 @@ public class TemplateApiTest extends BaseCloudStackApiTest<TemplateApi> {
                                                     .addQueryParam("command", "registerTemplate")
                                                     .addQueryParam("format", "QCOW2")
                                                     .addQueryParam("hypervisor", "xen")
-                                                    .addQueryParam("url", "http%3A//example.com/")
+                                                    .addQueryParam("url", "http://example.com/")
                                                     .addQueryParam("zoneid", "20")
                                                     .addQueryParam("account", "mydomain")
                                                     .addQueryParam("domainid", "3")
@@ -381,7 +381,7 @@ public class TemplateApiTest extends BaseCloudStackApiTest<TemplateApi> {
                                                    .addQueryParam("id", "3")
                                                    .addQueryParam("mode", "HTTP_DOWNLOAD")
                                                    .addQueryParam("zoneid", "5")
-                                                   .addQueryParam("url", "http%3A//example.com/").build();
+                                                   .addQueryParam("url", "http://example.com/").build();
 
    public void testExtractTemplateOptions() throws NoSuchMethodException {
       Invokable<?, ?> method = method(TemplateApi.class, "extractTemplate", String.class, ExtractMode.class, String.class, ExtractTemplateOptions[].class);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7151a387/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineApiExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineApiExpectTest.java
index 3b8b043..0afa58d 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineApiExpectTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineApiExpectTest.java
@@ -56,13 +56,18 @@ public class VirtualMachineApiExpectTest extends BaseCloudStackExpectTest<Virtua
 
       VirtualMachineApi client = requestSendsResponse(
          HttpRequest.builder().method("GET")
-            .endpoint("http://localhost:8080/client/api?response=json&command=getVMPassword&id=1&apiKey=identity&signature=SVA2r1KRj4yG03rATMLPZWS%2BKnw%3D")
-            .addHeader("Accept", "application/json")
-            .build(),
+               .endpoint("http://localhost:8080/client/api")
+               .addQueryParam("response", "json")
+               .addQueryParam("command", "getVMPassword")
+               .addQueryParam("id", "1")
+               .addQueryParam("apiKey", "identity")
+               .addQueryParam("signature", "SVA2r1KRj4yG03rATMLPZWS+Knw=")
+               .addHeader("Accept", "application/json")
+               .build(),
          HttpResponse.builder()
-            .statusCode(200)
-            .payload(payloadFromResource("/getvmpasswordresponse.json"))
-            .build());
+               .statusCode(200)
+               .payload(payloadFromResource("/getvmpasswordresponse.json"))
+               .build());
 
       String actual = client.getEncryptedPasswordForVirtualMachine("1");
       String expected = "EFOwm8icZ4sEib4y6ntVHUKHZJQrGBdyPkL1L9lpFHYhs3JfAtL5E5bxBP5Er27bJyOZPjKFcInX\r\n" +
@@ -85,7 +90,7 @@ public class VirtualMachineApiExpectTest extends BaseCloudStackExpectTest<Virtua
       .addQueryParam("serviceofferingid", "serviceOffering1")
       .addQueryParam("templateid", "template1")
       .addQueryParam("apiKey", "identity")
-      .addQueryParam("signature", "pBjjnTq7/ezN94Uj0gpy2T//cJQ%3D")
+      .addQueryParam("signature", "pBjjnTq7/ezN94Uj0gpy2T//cJQ=")
       .addHeader("Accept", "application/json")
       .build();
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7151a387/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiExpectTest.java
index 6032ceb..a9d34b4 100644
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiExpectTest.java
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiExpectTest.java
@@ -18,8 +18,6 @@ package org.jclouds.cloudstack.features;
 
 import static org.testng.Assert.assertEquals;
 
-import java.net.URI;
-
 import org.jclouds.cloudstack.CloudStackContext;
 import org.jclouds.cloudstack.domain.NetworkType;
 import org.jclouds.cloudstack.domain.Tag;
@@ -46,7 +44,7 @@ public class ZoneApiExpectTest extends BaseCloudStackExpectTest<ZoneApi> {
                     .addQueryParam("command", "listZones")
                     .addQueryParam("listAll", "true")
                     .addQueryParam("apiKey", "identity")
-                    .addQueryParam("signature", "8iHCtck0qfxFTqJ8reyAObRf31I%3D")
+                    .addQueryParam("signature", "8iHCtck0qfxFTqJ8reyAObRf31I=")
                     .addHeader("Accept", "application/json")
                     .build(),
          HttpResponse.builder()
@@ -80,12 +78,15 @@ public class ZoneApiExpectTest extends BaseCloudStackExpectTest<ZoneApi> {
 
    public void testListZonesWhenResponseIs404() {
       ZoneApi client = requestSendsResponse(
-         HttpRequest.builder()
-            .method("GET")
-            .endpoint(
-               URI.create("http://localhost:8080/client/api?response=json&" +
-                  "command=listZones&listAll=true&apiKey=identity&signature=8iHCtck0qfxFTqJ8reyAObRf31I%3D"))
-            .addHeader("Accept", "application/json")
+            HttpRequest.builder()
+                  .method("GET")
+                  .endpoint("http://localhost:8080/client/api")
+                  .addQueryParam("response", "json")
+                  .addQueryParam("command", "listZones")
+                  .addQueryParam("listAll", "true")
+                  .addQueryParam("apiKey", "identity")
+                  .addQueryParam("signature", "8iHCtck0qfxFTqJ8reyAObRf31I=")
+                  .addHeader("Accept", "application/json")
             .build(),
          HttpResponse.builder()
             .statusCode(404)