diff --git a/apis/atmos/src/main/java/org/jclouds/atmos/AtmosAsyncClient.java b/apis/atmos/src/main/java/org/jclouds/atmos/AtmosAsyncClient.java index 145b9f7fcf..e16f506dd1 100644 --- a/apis/atmos/src/main/java/org/jclouds/atmos/AtmosAsyncClient.java +++ b/apis/atmos/src/main/java/org/jclouds/atmos/AtmosAsyncClient.java @@ -56,7 +56,6 @@ import org.jclouds.rest.annotations.ParamParser; import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; @@ -74,7 +73,6 @@ import com.google.inject.Provides; * @author Adrian Cole */ @RequestFilters(SignRequest.class) -@SkipEncoding('/') @Path("/rest/namespace") public interface AtmosAsyncClient { /** diff --git a/apis/atmos/src/main/java/org/jclouds/atmos/filters/ShareUrl.java b/apis/atmos/src/main/java/org/jclouds/atmos/filters/ShareUrl.java index 596235295d..5a0d0b9814 100644 --- a/apis/atmos/src/main/java/org/jclouds/atmos/filters/ShareUrl.java +++ b/apis/atmos/src/main/java/org/jclouds/atmos/filters/ShareUrl.java @@ -18,18 +18,22 @@ */ package org.jclouds.atmos.filters; +import static com.google.common.base.Throwables.propagate; import static org.jclouds.Constants.LOGGER_SIGNATURE; +import static org.jclouds.crypto.CryptoStreams.base64; +import static org.jclouds.crypto.CryptoStreams.mac; +import static org.jclouds.http.Uris.uriBuilder; +import java.io.IOException; import java.net.URI; +import java.security.InvalidKeyException; import javax.annotation.Resource; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; -import javax.ws.rs.core.UriBuilder; import org.jclouds.crypto.Crypto; -import org.jclouds.crypto.CryptoStreams; import org.jclouds.date.TimeStamp; import org.jclouds.http.HttpException; import org.jclouds.io.InputSuppliers; @@ -40,6 +44,7 @@ import org.jclouds.rest.annotations.Identity; import com.google.common.base.Function; import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableMap; /** * Signs the EMC Atmos Online Storage request. @@ -55,7 +60,6 @@ public class ShareUrl implements Function { private final byte[] key; private final Supplier provider; private final javax.inject.Provider timeStampProvider; - private final javax.inject.Provider uriBuilders; private final Crypto crypto; @Resource @@ -67,12 +71,10 @@ public class ShareUrl implements Function { @Inject public ShareUrl(@Identity String uid, @Credential String encodedKey, - @Provider Supplier provider, @TimeStamp javax.inject.Provider timeStampProvider, - javax.inject.Provider uriBuilders, Crypto crypto) { + @Provider Supplier provider, @TimeStamp javax.inject.Provider timeStampProvider, Crypto crypto) { this.uid = uid; - this.key = CryptoStreams.base64(encodedKey); + this.key = base64(encodedKey); this.provider = provider; - this.uriBuilders = uriBuilders; this.timeStampProvider = timeStampProvider; this.crypto = crypto; } @@ -80,13 +82,14 @@ public class ShareUrl implements Function { @Override public URI apply(String path) throws HttpException { String requestedResource = new StringBuilder().append("/rest/namespace/").append(path).toString(); - long expires = timeStampProvider.get(); + String expires = timeStampProvider.get().toString(); String signature = signString(createStringToSign(requestedResource, expires)); - return uriBuilders.get().uri(provider.get()).path(requestedResource).queryParam("uid", uid).queryParam("expires", - expires).queryParam("signature", signature).build(); + return uriBuilder(provider.get()) + .replaceQuery(ImmutableMap.of("uid", uid, "expires", expires, "signature", signature)) + .appendPath(requestedResource).build(); } - public String createStringToSign(String requestedResource, long expires) { + public String createStringToSign(String requestedResource, String expires) { StringBuilder toSign = new StringBuilder(); toSign.append("GET\n"); toSign.append(requestedResource.toLowerCase()).append("\n"); @@ -96,13 +99,13 @@ public class ShareUrl implements Function { } public String signString(String toSign) { - String signature; try { - signature = CryptoStreams.base64(CryptoStreams.mac(InputSuppliers.of(toSign), crypto.hmacSHA1(key))); - } catch (Exception e) { - throw new HttpException("error signing request", e); + return base64(mac(InputSuppliers.of(toSign), crypto.hmacSHA1(key))); + } catch (InvalidKeyException e) { + throw propagate(e); + } catch (IOException e) { + throw propagate(e); } - return signature; } } diff --git a/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/CloudFilesAsyncClient.java b/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/CloudFilesAsyncClient.java index 6e2ca5ab5d..7a9169b167 100644 --- a/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/CloudFilesAsyncClient.java +++ b/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/CloudFilesAsyncClient.java @@ -51,7 +51,6 @@ import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; -import org.jclouds.rest.annotations.SkipEncoding; import com.google.common.util.concurrent.ListenableFuture; @@ -66,7 +65,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @see * @author Adrian Cole */ -@SkipEncoding('/') @RequestFilters(AuthenticateRequest.class) @Endpoint(Storage.class) public interface CloudFilesAsyncClient extends CommonSwiftAsyncClient { diff --git a/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/blobstore/functions/PublicUriForObjectInfo.java b/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/blobstore/functions/PublicUriForObjectInfo.java index e78b301302..d3121b25a2 100644 --- a/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/blobstore/functions/PublicUriForObjectInfo.java +++ b/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/blobstore/functions/PublicUriForObjectInfo.java @@ -18,12 +18,12 @@ */ package org.jclouds.cloudfiles.blobstore.functions; +import static org.jclouds.http.Uris.uriBuilder; + import java.net.URI; import javax.inject.Inject; -import javax.inject.Provider; import javax.inject.Singleton; -import javax.ws.rs.core.UriBuilder; import org.jclouds.openstack.swift.domain.ObjectInfo; @@ -38,20 +38,18 @@ import com.google.common.cache.LoadingCache; public class PublicUriForObjectInfo implements Function { private final LoadingCache cdnContainer; - private final Provider uriBuilders; @Inject - public PublicUriForObjectInfo(LoadingCache cdnContainer, Provider uriBuilders) { + public PublicUriForObjectInfo(LoadingCache cdnContainer) { this.cdnContainer = cdnContainer; - this.uriBuilders = uriBuilders; } public URI apply(ObjectInfo from) { if (from == null) return null; try { - return uriBuilders.get().uri(cdnContainer.getUnchecked(from.getContainer())).path(from.getName()).replaceQuery("") - .build(); + return uriBuilder(cdnContainer.getUnchecked(from.getContainer())) + .clearQuery().appendPath(from.getName()).build(); } catch (NullPointerException e) { // nulls not permitted from cache loader return null; diff --git a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/CloudServersAsyncClient.java b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/CloudServersAsyncClient.java index 9a9f31ca40..ede78594b7 100644 --- a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/CloudServersAsyncClient.java +++ b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/CloudServersAsyncClient.java @@ -56,7 +56,6 @@ import org.jclouds.rest.annotations.Payload; import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.Unwrap; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404; @@ -76,7 +75,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @see * @author Adrian Cole */ -@SkipEncoding({ '/', '=' }) @RequestFilters({ AuthenticateRequest.class, AddTimestampQuery.class }) @Endpoint(Compute.class) public interface CloudServersAsyncClient { diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindAccountSecurityGroupPairsToIndexedQueryParams.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindAccountSecurityGroupPairsToIndexedQueryParams.java index 40ca237a9c..6760a4f14a 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindAccountSecurityGroupPairsToIndexedQueryParams.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindAccountSecurityGroupPairsToIndexedQueryParams.java @@ -20,21 +20,20 @@ package org.jclouds.cloudstack.binders; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.http.Uris.uriBuilder; +import static org.jclouds.http.utils.Queries.queryParser; +import java.net.URI; import java.util.Map.Entry; -import javax.inject.Inject; -import javax.inject.Provider; import javax.inject.Singleton; -import javax.ws.rs.core.UriBuilder; import org.jclouds.http.HttpRequest; -import org.jclouds.http.utils.Queries; import org.jclouds.rest.Binder; import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.Multimap; import com.google.common.collect.ImmutableMultimap.Builder; +import com.google.common.collect.Multimap; /** * @@ -42,12 +41,6 @@ import com.google.common.collect.ImmutableMultimap.Builder; */ @Singleton public class BindAccountSecurityGroupPairsToIndexedQueryParams implements Binder { - private final Provider uriBuilderProvider; - - @Inject - public BindAccountSecurityGroupPairsToIndexedQueryParams(Provider uriBuilderProvider) { - this.uriBuilderProvider = checkNotNull(uriBuilderProvider, "uriBuilderProvider"); - } @SuppressWarnings("unchecked") @Override @@ -55,15 +48,14 @@ public class BindAccountSecurityGroupPairsToIndexedQueryParams implements Binder checkArgument(input instanceof Multimap, "this binder is only valid for Multimaps!"); Multimap pairs = (Multimap) checkNotNull(input, "account group pairs"); checkArgument(pairs.size() > 0, "you must specify at least one account, group pair"); - UriBuilder builder = uriBuilderProvider.get(); - builder.uri(request.getEndpoint()); - Builder map = ImmutableMultimap. builder().putAll( - Queries.parseQueryToMap(request.getEndpoint().getQuery())); + + Multimap existingParams = queryParser().apply(request.getEndpoint().getQuery()); + Builder map = ImmutableMultimap. builder().putAll(existingParams); int i = 0; for (Entry entry : pairs.entries()) map.put(String.format("usersecuritygrouplist[%d].account", i), entry.getKey()).put( String.format("usersecuritygrouplist[%d].group", i++), entry.getValue()); - builder.replaceQuery(Queries.makeQueryLine(map.build(), null)); - return (R) request.toBuilder().endpoint(builder.build()).build(); + URI endpoint = uriBuilder(request.getEndpoint()).query(map.build()).build(); + return (R) request.toBuilder().endpoint(endpoint).build(); } } diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Account.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Account.java index c592cdf601..d3e032241c 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Account.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Account.java @@ -456,7 +456,6 @@ public class Account extends ForwardingSet { "templatelimit", "templatetotal", "vmavailable", "vmlimit", "vmrunning", "vmstopped", "vmtotal", "volumeavailable", "volumelimit", "volumetotal", "user" }) - @SuppressWarnings("unused") private Account(String id, @Nullable Type type, @Nullable String networkDomain, @Nullable String domain, @Nullable String domainId, @Nullable String IPsAvailable, @Nullable String IPLimit, long IPs, boolean cleanupRequired, @Nullable String name, long receivedBytes, long sentBytes, diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/FirewallRule.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/FirewallRule.java index 3ddbec09c3..8b8e98d032 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/FirewallRule.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/FirewallRule.java @@ -228,7 +228,6 @@ public class FirewallRule implements Comparable { @ConstructorProperties({ "id", "cidrlist", "startport", "endport", "icmpcode", "icmptype", "ipaddress", "ipaddressid", "protocol", "state" }) - @SuppressWarnings("unused") private FirewallRule(String id, @Nullable String CIDRs, int startPort, int endPort, @Nullable String icmpCode, @Nullable String icmpType, @Nullable String ipAddress, @Nullable String ipAddressId, @Nullable Protocol protocol, @Nullable State state) { diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/LoadBalancerRule.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/LoadBalancerRule.java index abec957dad..6da97a50ec 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/LoadBalancerRule.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/LoadBalancerRule.java @@ -267,7 +267,6 @@ public class LoadBalancerRule { "id", "account", "algorithm", "description", "domain", "domainid", "name", "privateport", "publicip", "publicipid", "publicport", "state", "cidrlist", "zoneId" }) - @SuppressWarnings("unused") private LoadBalancerRule(String id, @Nullable String account, @Nullable Algorithm algorithm, @Nullable String description, @Nullable String domain, @Nullable String domainId, @Nullable String name, int privatePort, @Nullable String publicIP, diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/PortForwardingRule.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/PortForwardingRule.java index 6aab67de7a..4526568ec3 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/PortForwardingRule.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/PortForwardingRule.java @@ -261,7 +261,6 @@ public class PortForwardingRule implements Comparable { "id", "ipaddress", "ipaddressid", "privateport", "protocol", "publicport", "state", "virtualmachinedisplayname", "virtualmachineid", "virtualmachinename", "cidrlist", "privateendport", "publicendport" }) - @SuppressWarnings("unused") private PortForwardingRule(String id, @Nullable String IPAddress, @Nullable String IPAddressId, int privatePort, @Nullable Protocol protocol, int publicPort, @Nullable State state, @Nullable String virtualMachineDisplayName, @Nullable String virtualMachineId, @Nullable String virtualMachineName, @Nullable String CIDRs, diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalStoragePoolAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalStoragePoolAsyncClient.java index afce6bf829..f6dcefa128 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalStoragePoolAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalStoragePoolAsyncClient.java @@ -30,7 +30,6 @@ import org.jclouds.cloudstack.options.ListStoragePoolsOptions; import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import com.google.common.util.concurrent.ListenableFuture; @@ -44,7 +43,6 @@ import com.google.common.util.concurrent.ListenableFuture; */ @RequestFilters(AuthenticationFilter.class) @QueryParams(keys = "response", values = "json") -@SkipEncoding({'/'}) public interface GlobalStoragePoolAsyncClient { @GET diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/ISOAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/ISOAsyncClient.java index 84a7bc526f..a8cd057ca1 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/ISOAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/ISOAsyncClient.java @@ -42,7 +42,6 @@ import org.jclouds.rest.annotations.OnlyElement; import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.Unwrap; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; @@ -59,7 +58,6 @@ import com.google.common.util.concurrent.ListenableFuture; */ @RequestFilters(AuthenticationFilter.class) @QueryParams(keys = "response", values = "json") -@SkipEncoding({'/', ','}) public interface ISOAsyncClient { /** diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SSHKeyPairAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SSHKeyPairAsyncClient.java index b1f7ea2a19..99c6e5e7ae 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SSHKeyPairAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SSHKeyPairAsyncClient.java @@ -27,7 +27,6 @@ import javax.ws.rs.core.MediaType; import org.jclouds.cloudstack.domain.SshKeyPair; import org.jclouds.cloudstack.filters.AuthenticationFilter; -import org.jclouds.cloudstack.filters.ReEncodeQueryWithDefaultURLEncoder; import org.jclouds.cloudstack.options.ListSSHKeyPairsOptions; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.OnlyElement; @@ -68,7 +67,6 @@ public interface SSHKeyPairAsyncClient { @QueryParams(keys = "command", values = "registerSSHKeyPair") @SelectJson("keypair") @Consumes(MediaType.APPLICATION_JSON) - @RequestFilters(ReEncodeQueryWithDefaultURLEncoder.class) ListenableFuture registerSSHKeyPair(@QueryParam("name") String name, @QueryParam("publickey") String publicKey); /** diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TemplateAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TemplateAsyncClient.java index f76c46881c..0785b39524 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TemplateAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/TemplateAsyncClient.java @@ -46,7 +46,6 @@ import org.jclouds.rest.annotations.OnlyElement; import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.Unwrap; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; @@ -65,7 +64,6 @@ import com.google.common.util.concurrent.ListenableFuture; */ @RequestFilters(AuthenticationFilter.class) @QueryParams(keys = "response", values = "json") -@SkipEncoding(',') public interface TemplateAsyncClient { /** diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/filters/QuerySigner.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/filters/QuerySigner.java index 0753c85db8..d44f4259e3 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/filters/QuerySigner.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/filters/QuerySigner.java @@ -19,42 +19,42 @@ package org.jclouds.cloudstack.filters; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Throwables.propagate; +import static org.jclouds.Constants.LOGGER_SIGNATURE; +import static org.jclouds.crypto.CryptoStreams.base64; +import static org.jclouds.crypto.CryptoStreams.mac; +import static org.jclouds.http.Uris.uriBuilder; +import static org.jclouds.http.utils.Queries.encodeQueryLine; +import static org.jclouds.http.utils.Queries.queryParser; +import static org.jclouds.util.Strings2.toInputStream; -import java.util.Map.Entry; +import java.io.IOException; +import java.security.InvalidKeyException; import javax.annotation.Resource; import javax.inject.Inject; import javax.inject.Named; -import javax.inject.Provider; import javax.inject.Singleton; -import javax.ws.rs.core.UriBuilder; -import org.jclouds.Constants; import org.jclouds.crypto.Crypto; -import org.jclouds.crypto.CryptoStreams; import org.jclouds.http.HttpException; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpUtils; import org.jclouds.http.internal.SignatureWire; -import org.jclouds.http.utils.Queries; import org.jclouds.io.InputSuppliers; import org.jclouds.logging.Logger; import org.jclouds.rest.RequestSigner; import org.jclouds.rest.annotations.Credential; import org.jclouds.rest.annotations.Identity; -import org.jclouds.util.Strings2; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Multimap; +import com.google.common.collect.TreeMultimap; /** * - * @see + * @see * @author Adrian Cole * */ @@ -66,35 +66,29 @@ public class QuerySigner implements AuthenticationFilter, RequestSigner { private final String secretKey; private final Crypto crypto; private final HttpUtils utils; - private final Provider builder; @Resource - @Named(Constants.LOGGER_SIGNATURE) + @Named(LOGGER_SIGNATURE) private Logger signatureLog = Logger.NULL; @Inject public QuerySigner(SignatureWire signatureWire, @Identity String accessKey, @Credential String secretKey, - Crypto crypto, HttpUtils utils, Provider builder) { + Crypto crypto, HttpUtils utils) { this.signatureWire = signatureWire; this.accessKey = accessKey; this.secretKey = secretKey; this.crypto = crypto; this.utils = utils; - this.builder = builder; } public HttpRequest filter(HttpRequest request) throws HttpException { checkNotNull(request, "request must be present"); - Multimap decodedParams = Queries.parseQueryToMap(request.getEndpoint().getRawQuery()); + Multimap decodedParams = queryParser().apply(request.getEndpoint().getRawQuery()); addSigningParams(decodedParams); String stringToSign = createStringToSign(request, decodedParams); String signature = sign(stringToSign); addSignature(decodedParams, signature); - request = request - .toBuilder() - .endpoint( - builder.get().uri(request.getEndpoint()) - .replaceQuery(Queries.makeQueryLine(decodedParams, null)).build()).build(); + request = request.toBuilder().endpoint(uriBuilder(request.getEndpoint()).query(decodedParams).build()).build(); utils.logRequest(signatureLog, request, "<<"); return request; } @@ -108,27 +102,24 @@ public class QuerySigner implements AuthenticationFilter, RequestSigner { public String sign(String stringToSign) { String signature; try { - signature = CryptoStreams.base64(CryptoStreams.mac(InputSuppliers.of(stringToSign), - crypto.hmacSHA1(secretKey.getBytes()))); + signature = base64(mac(InputSuppliers.of(stringToSign), crypto.hmacSHA1(secretKey.getBytes()))); if (signatureWire.enabled()) - signatureWire.input(Strings2.toInputStream(signature)); - } catch (Exception e) { - throw new HttpException("error signing request", e); + signatureWire.input(toInputStream(signature)); + return signature; + } catch (InvalidKeyException e) { + throw propagate(e); + } catch (IOException e) { + throw propagate(e); } - return signature; } @VisibleForTesting public String createStringToSign(HttpRequest request, Multimap decodedParams) { utils.logRequest(signatureLog, request, ">>"); - - // encode each parameter value first, - ImmutableSortedSet.Builder builder = ImmutableSortedSet.naturalOrder(); - for (Entry entry : decodedParams.entries()) - builder.add(entry.getKey() + "=" + Strings2.urlEncode(entry.getValue())); - + // like aws, percent encode the canonicalized string without skipping '/' and '?' + String queryLine = encodeQueryLine(TreeMultimap.create(decodedParams), ImmutableList. of()); // then, lower case the entire query string - String stringToSign = Joiner.on('&').join(builder.build()).toLowerCase(); + String stringToSign = queryLine.toLowerCase(); if (signatureWire.enabled()) signatureWire.output(stringToSign); @@ -142,7 +133,7 @@ public class QuerySigner implements AuthenticationFilter, RequestSigner { } public String createStringToSign(HttpRequest input) { - Multimap decodedParams = Queries.parseQueryToMap(input.getEndpoint().getQuery()); + Multimap decodedParams = queryParser().apply(input.getEndpoint().getQuery()); addSigningParams(decodedParams); return createStringToSign(input, decodedParams); } diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/filters/ReEncodeQueryWithDefaultURLEncoder.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/filters/ReEncodeQueryWithDefaultURLEncoder.java deleted file mode 100644 index 16f102d0c5..0000000000 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/filters/ReEncodeQueryWithDefaultURLEncoder.java +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Licensed to jclouds, Inc. (jclouds) under one or more - * contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. jclouds licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.jclouds.cloudstack.filters; - -import static com.google.common.collect.Iterables.getOnlyElement; - -import javax.ws.rs.core.UriBuilder; - -import org.jclouds.http.HttpException; -import org.jclouds.http.HttpRequest; -import org.jclouds.http.HttpRequestFilter; -import org.jclouds.http.utils.Queries; - -import com.google.common.collect.Multimap; -import com.google.inject.Inject; -import com.google.inject.Provider; - -/** - * By default, jclouds controls encoding based on rules which are different - * - * @author Adrian Cole - */ -public class ReEncodeQueryWithDefaultURLEncoder implements HttpRequestFilter { - private final Provider builders; - - @Inject - public ReEncodeQueryWithDefaultURLEncoder(Provider builders) { - this.builders = builders; - } - - @Override - public HttpRequest filter(HttpRequest request) throws HttpException { - UriBuilder builder = builders.get(); - builder.uri(request.getEndpoint()); - Multimap map = Queries.parseQueryToMap(request.getEndpoint().getRawQuery()); - builder.replaceQuery(""); - for (String key : map.keySet()) - builder.queryParam(key, getOnlyElement(map.get(key))); - return request.toBuilder().endpoint(builder.build()).build(); - } - -} \ No newline at end of file diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/PasswordAuthenticationExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/PasswordAuthenticationExpectTest.java index 95a1e70684..f4c125436d 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/PasswordAuthenticationExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/PasswordAuthenticationExpectTest.java @@ -56,7 +56,7 @@ public class PasswordAuthenticationExpectTest extends BaseCloudStackExpectTestbuilder() .put("Accept", "application/json") diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalZoneClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalZoneClientExpectTest.java index d3ed7c1fb5..a660734c2d 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalZoneClientExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalZoneClientExpectTest.java @@ -50,7 +50,7 @@ public class GlobalZoneClientExpectTest extends BaseCloudStackExpectTestbuilder() .put("Accept", "application/json") diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOAsyncClientTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOAsyncClientTest.java index 014f95d207..09ba8f9383 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOAsyncClientTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOAsyncClientTest.java @@ -26,10 +26,8 @@ import org.jclouds.cloudstack.internal.BaseCloudStackAsyncClientTest; import org.jclouds.cloudstack.options.AccountInDomainOptions; import org.jclouds.cloudstack.options.DeleteISOOptions; import org.jclouds.cloudstack.options.ExtractISOOptions; -import org.jclouds.cloudstack.options.RegisterISOOptions; import org.jclouds.cloudstack.options.UpdateISOOptions; import org.jclouds.cloudstack.options.UpdateISOPermissionsOptions; -import org.jclouds.functions.IdentityFunction; import org.jclouds.http.HttpRequest; import org.jclouds.http.functions.ParseFirstJsonValueNamed; import org.jclouds.http.functions.ReleasePayloadAndReturn; @@ -38,7 +36,6 @@ import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions; import org.jclouds.rest.internal.RestAnnotationProcessor; import org.testng.annotations.Test; -import com.google.common.base.Functions; import com.google.common.collect.ImmutableSet; import com.google.inject.TypeLiteral; /** @@ -47,8 +44,7 @@ import com.google.inject.TypeLiteral; * @see ISOAsyncClient * @author Richard Downer */ -// NOTE:without testName, this will not call @Before* and fail w/NPE during -// surefire +// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire @Test(groups = "unit", testName = "ISOAsyncClientTest") public class ISOAsyncClientTest extends BaseCloudStackAsyncClientTest { diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOClientExpectTest.java index 8de56ccd74..6b5c6ac26e 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOClientExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ISOClientExpectTest.java @@ -81,7 +81,7 @@ public class ISOClientExpectTest extends BaseCloudStackExpectTest { .addQueryParam("command", "listIsos") .addQueryParam("listAll", "true") .addQueryParam("apiKey", "identity") - .addQueryParam("signature", "qUUF6hCDc57Bc%2FnHriS9umbZBKA%3D") + .addQueryParam("signature", "qUUF6hCDc57Bc/nHriS9umbZBKA%3D") .addHeader("Accept", "application/json") .build(); @@ -121,7 +121,7 @@ public class ISOClientExpectTest extends BaseCloudStackExpectTest { .addQueryParam("name", "bob%27s%20iso") .addQueryParam("zoneid", "7") .addQueryParam("apiKey", "identity") - .addQueryParam("signature", "4S5ustbaBErEnpymWLSj1rEJ%2Fnk%3D") + .addQueryParam("signature", "4S5ustbaBErEnpymWLSj1rEJ/nk%3D") .addHeader("Accept", "application/json") .build(); diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SSHKeyPairAsyncClientTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SSHKeyPairAsyncClientTest.java index d34739ea65..f73585be34 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SSHKeyPairAsyncClientTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SSHKeyPairAsyncClientTest.java @@ -117,7 +117,7 @@ public class SSHKeyPairAsyncClientTest extends BaseCloudStackAsyncClientTestbuilder() diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupAsyncClientTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupAsyncClientTest.java index 5e24efdf58..c1f8753449 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupAsyncClientTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupAsyncClientTest.java @@ -130,7 +130,7 @@ public class SecurityGroupAsyncClientTest extends BaseCloudStackAsyncClientTest< assertRequestLineEquals( httpRequest, - "GET http://localhost:8080/client/api?response=json&command=authorizeSecurityGroupIngress&securitygroupid=2&startport=22&protocol=tcp&endport=22&cidrlist=1.1.1.1%2F24%2C1.2.2.2%2F16 HTTP/1.1"); + "GET http://localhost:8080/client/api?response=json&command=authorizeSecurityGroupIngress&securitygroupid=2&startport=22&protocol=tcp&endport=22&cidrlist=1.1.1.1/24,1.2.2.2/16 HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); assertPayloadEquals(httpRequest, null, null, false); @@ -169,7 +169,7 @@ public class SecurityGroupAsyncClientTest extends BaseCloudStackAsyncClientTest< assertRequestLineEquals( httpRequest, - "GET http://localhost:8080/client/api?response=json&command=authorizeSecurityGroupIngress&protocol=ICMP&securitygroupid=2&icmptype=22&icmpcode=22&cidrlist=1.1.1.1%2F24%2C1.2.2.2%2F16 HTTP/1.1"); + "GET http://localhost:8080/client/api?response=json&command=authorizeSecurityGroupIngress&protocol=ICMP&securitygroupid=2&icmptype=22&icmpcode=22&cidrlist=1.1.1.1/24,1.2.2.2/16 HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); assertPayloadEquals(httpRequest, null, null, false); diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SessionClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SessionClientExpectTest.java index 7abc4eb248..bdcff81c53 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SessionClientExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SessionClientExpectTest.java @@ -23,7 +23,6 @@ import static org.testng.Assert.assertEquals; import java.io.IOException; import java.net.URI; -import java.net.URLEncoder; import org.jclouds.cloudstack.CloudStackContext; import org.jclouds.cloudstack.domain.Account; @@ -43,7 +42,6 @@ import com.google.common.collect.ImmutableMultimap; @Test(groups = "live", singleThreaded = true, testName = "SessionClientExpectTest") public class SessionClientExpectTest extends BaseCloudStackExpectTest { - @SuppressWarnings("deprecation") public void testLoginWhenResponseIs2xxIncludesJSessionId() throws IOException { String domain = "Partners/jCloud"; String user = "jcloud"; @@ -54,7 +52,7 @@ public class SessionClientExpectTest extends BaseCloudStackExpectTest extends B .addQueryParam("command", "listOsTypes") .addQueryParam("listAll", "true") .addQueryParam("apiKey", "APIKEY") - .addQueryParam("signature", "8BsE8MsOAhUzo1Q4Y3UD%2Fe96u84%3D") + .addQueryParam("signature", "8BsE8MsOAhUzo1Q4Y3UD/e96u84%3D") .addHeader("Accept", "application/json") .build(); @@ -70,7 +70,7 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest extends B .addQueryParam("command", "listOsCategories") .addQueryParam("listAll", "true") .addQueryParam("apiKey", "APIKEY") - .addQueryParam("signature", "OojW4ssh%2FRQ3CubAzXue4svlofM%3D") + .addQueryParam("signature", "OojW4ssh/RQ3CubAzXue4svlofM%3D") // .addHeader("Accept", "application/json") //TODO: why are we not passing this? .build(); @@ -84,7 +84,7 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest extends B .addQueryParam("command", "listZones") .addQueryParam("listAll", "true") .addQueryParam("apiKey", "APIKEY") - .addQueryParam("signature", "GTUgn%2FLHDioJRq48kurOdCAYueo%3D") + .addQueryParam("signature", "GTUgn/LHDioJRq48kurOdCAYueo%3D") .addHeader("Accept", "application/json") .build(); @@ -128,7 +128,7 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest extends B .addQueryParam("account", "jclouds") // account and domain came from above .addQueryParam("domainid", "457") .addQueryParam("apiKey", "APIKEY") - .addQueryParam("signature", "FDiGGBiG%2FsVj0k6DmZIgMNU8SqI%3D") + .addQueryParam("signature", "FDiGGBiG/sVj0k6DmZIgMNU8SqI%3D") .addHeader("Accept", "application/json") .build(); @@ -157,7 +157,7 @@ public abstract class BaseCloudStackComputeServiceContextExpectTest extends B .addQueryParam("listAll", "true") .addQueryParam("command", "listCapabilities") .addQueryParam("apiKey", "APIKEY") - .addQueryParam("signature", "vVdhtet%2FzG59FXgkYkAzEQQ4q1o%3D") + .addQueryParam("signature", "vVdhtet/zG59FXgkYkAzEQQ4q1o%3D") .addHeader("Accept", "application/json") .build(); diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchAsyncApiTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchAsyncApiTest.java index c800dcb9a4..e134e7d36b 100644 --- a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchAsyncApiTest.java +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchAsyncApiTest.java @@ -72,7 +72,7 @@ public class CloudWatchAsyncApiTest extends BaseAsyncApiTest assertNonPayloadHeadersEqual(request, "Host: monitoring.us-east-1.amazonaws.com\n"); assertPayloadEquals( request, - "Action=GetMetricStatistics&Statistics.member.1=Average&Period=60&Namespace=AWS%2FEC2&MetricName=CPUUtilization&StartTime=1970-01-01T02%3A46%3A40Z&EndTime=1970-01-01T02%3A46%3A40Z&Dimensions.member.1.Name=InstanceId&Dimensions.member.1.Value=i-12312313", + "Action=GetMetricStatistics&Statistics.member.1=Average&Period=60&Namespace=AWS/EC2&MetricName=CPUUtilization&StartTime=1970-01-01T02%3A46%3A40Z&EndTime=1970-01-01T02%3A46%3A40Z&Dimensions.member.1.Name=InstanceId&Dimensions.member.1.Value=i-12312313", "application/x-www-form-urlencoded", false); assertResponseParserClassEquals(method, request, ParseSax.class); diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricApiExpectTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricApiExpectTest.java index 90ff95865c..fc2271f82f 100644 --- a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricApiExpectTest.java +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricApiExpectTest.java @@ -56,7 +56,7 @@ public class MetricApiExpectTest extends BaseCloudWatchApiExpectTest { .payload( payloadFromStringWithContentType( "Action=ListMetrics" + - "&Signature=KSh9oQydCR0HMAV6QPYwDzqwQIpxs8I%2Fig7brYgHVZU%3D" + + "&Signature=KSh9oQydCR0HMAV6QPYwDzqwQIpxs8I/ig7brYgHVZU%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -100,7 +100,7 @@ public class MetricApiExpectTest extends BaseCloudWatchApiExpectTest { payloadFromStringWithContentType( "Action=ListMetrics" + "&NextToken=MARKER" + - "&Signature=RpBdQydXD1jQhEUnXoqT60NEuCP%2FZgdvO6Hf3uf%2Fwy0%3D" + + "&Signature=RpBdQydXD1jQhEUnXoqT60NEuCP/ZgdvO6Hf3uf/wy0%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -132,8 +132,8 @@ public class MetricApiExpectTest extends BaseCloudWatchApiExpectTest { "&Dimensions.member.1.Value=SOMEINSTANCEID" + "&MetricName=CPUUtilization" + "&Namespace=SOMENEXTTOKEN" + - "&NextToken=AWS%2FEC2" + - "&Signature=G05HKEx9FJpGZBk02OVYwt3u4g%2FilAY9nU5hJI9LDXA%3D" + + "&NextToken=AWS/EC2" + + "&Signature=G05HKEx9FJpGZBk02OVYwt3u4g/ilAY9nU5hJI9LDXA%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -178,9 +178,9 @@ public class MetricApiExpectTest extends BaseCloudWatchApiExpectTest { "Action=GetMetricStatistics" + "&EndTime=1970-01-01T02%3A46%3A40Z" + "&MetricName=CPUUtilization" + - "&Namespace=AWS%2FEC2" + + "&Namespace=AWS/EC2" + "&Period=60" + - "&Signature=rmg8%2Ba7w4ycy%2FKfO8rnuj6rDL0jNE96m8GKfjh3SWcw%3D" + + "&Signature=rmg8%2Ba7w4ycy/KfO8rnuj6rDL0jNE96m8GKfjh3SWcw%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&StartTime=1970-01-01T02%3A46%3A40Z" + @@ -235,9 +235,9 @@ public class MetricApiExpectTest extends BaseCloudWatchApiExpectTest { "&Dimensions.member.2.Value=t1.micro" + "&EndTime=1970-01-01T02%3A46%3A40Z" + "&MetricName=CPUUtilization" + - "&Namespace=AWS%2FEC2" + + "&Namespace=AWS/EC2" + "&Period=60" + - "&Signature=e0WyI%2FNm4hN2%2BMEm1mjRUzsvgvMCdFXbVJWi4ORpwic%3D" + + "&Signature=e0WyI/Nm4hN2%2BMEm1mjRUzsvgvMCdFXbVJWi4ORpwic%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&StartTime=1970-01-01T02%3A46%3A40Z" + diff --git a/apis/deltacloud/src/main/java/org/jclouds/deltacloud/handlers/DeltacloudRedirectionRetryHandler.java b/apis/deltacloud/src/main/java/org/jclouds/deltacloud/handlers/DeltacloudRedirectionRetryHandler.java index 2104a0d3c7..9d72a44a3c 100644 --- a/apis/deltacloud/src/main/java/org/jclouds/deltacloud/handlers/DeltacloudRedirectionRetryHandler.java +++ b/apis/deltacloud/src/main/java/org/jclouds/deltacloud/handlers/DeltacloudRedirectionRetryHandler.java @@ -19,9 +19,7 @@ package org.jclouds.deltacloud.handlers; import javax.inject.Inject; -import javax.inject.Provider; import javax.inject.Singleton; -import javax.ws.rs.core.UriBuilder; import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpResponse; @@ -37,9 +35,8 @@ import org.jclouds.http.handlers.RedirectionRetryHandler; public class DeltacloudRedirectionRetryHandler extends RedirectionRetryHandler { @Inject - public DeltacloudRedirectionRetryHandler(Provider uriBuilderProvider, - BackoffLimitedRetryHandler backoffHandler) { - super(uriBuilderProvider, backoffHandler); + public DeltacloudRedirectionRetryHandler(BackoffLimitedRetryHandler backoffHandler) { + super(backoffHandler); } @Override diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/compute/predicates/GetImageWhenStatusAvailablePredicateWithResultExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/compute/predicates/GetImageWhenStatusAvailablePredicateWithResultExpectTest.java index d70eeebcce..e7f6f6dbcb 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/compute/predicates/GetImageWhenStatusAvailablePredicateWithResultExpectTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/compute/predicates/GetImageWhenStatusAvailablePredicateWithResultExpectTest.java @@ -57,7 +57,7 @@ public class GetImageWhenStatusAvailablePredicateWithResultExpectTest extends Ba .endpoint("https://ec2.us-east-1.amazonaws.com/") .addHeader("Host", "ec2.us-east-1.amazonaws.com") .payload(payloadFromStringWithContentType( - "Action=DescribeImages&ImageId.1=ami-0&Signature=k9douTXFWkAZecPiZfBLUm3LIS3bTLanMV%2F%2BWrB1jFA%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2010-06-15&AWSAccessKeyId=identity", + "Action=DescribeImages&ImageId.1=ami-0&Signature=k9douTXFWkAZecPiZfBLUm3LIS3bTLanMV/%2BWrB1jFA%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2010-06-15&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(); protected HttpRequest describeImagesRequest1 = HttpRequest.builder() diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/TagApiExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/TagApiExpectTest.java index 4f084b4696..f451581ea2 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/features/TagApiExpectTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/TagApiExpectTest.java @@ -102,7 +102,7 @@ public class TagApiExpectTest extends BaseEC2ApiExpectTest { payloadFromStringWithContentType( "Action=CreateTags" + "&ResourceId.1=i-43532" + - "&Signature=jwCQr50j%2BvGkav4t0BN0G8RmNJ7VaFK6%2F7N%2FHKUmHL8%3D" + + "&Signature=jwCQr50j%2BvGkav4t0BN0G8RmNJ7VaFK6/7N/HKUmHL8%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Tag.1.Key=tag" + @@ -180,7 +180,7 @@ public class TagApiExpectTest extends BaseEC2ApiExpectTest { "&Filter.1.Value.1=instance" + "&Filter.2.Name=key" + "&Filter.2.Value.1=stack" + - "&Signature=doNEEZHEzXV%2FSD2eSZ6PpB1PADcsAF99lXGvsh3MbS4%3D" + + "&Signature=doNEEZHEzXV/SD2eSZ6PpB1PADcsAF99lXGvsh3MbS4%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2012-04-16T15%3A54%3A08.897Z" + @@ -223,7 +223,7 @@ public class TagApiExpectTest extends BaseEC2ApiExpectTest { payloadFromStringWithContentType( "Action=DeleteTags" + "&ResourceId.1=i-43532" + - "&Signature=ytM605menR00re60wXMgBDpozrQCi0lVupf755%2FMpck%3D" + + "&Signature=ytM605menR00re60wXMgBDpozrQCi0lVupf755/Mpck%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Tag.1.Key=tag" + @@ -261,7 +261,7 @@ public class TagApiExpectTest extends BaseEC2ApiExpectTest { payloadFromStringWithContentType( "Action=DeleteTags" + "&ResourceId.1=i-43532" + - "&Signature=vRvgPegVDDjIEKudZ5Tpck0GQrVts%2F%2F1jzk4W5RgI9k%3D" + + "&Signature=vRvgPegVDDjIEKudZ5Tpck0GQrVts//1jzk4W5RgI9k%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Tag.1.Key=tag" + diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiExpectTest.java index f34a0b5fe1..3a2de63247 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiExpectTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiExpectTest.java @@ -48,7 +48,7 @@ public class WindowsApiExpectTest extends BaseEC2ApiExpectTest { payloadFromStringWithContentType( "Action=GetPasswordData" + "&InstanceId=i-2574e22a" + - "&Signature=vX1Tskc4VuBUWPqsJ%2BzcjEj6%2F2iMCKzqjWnKFXRkDdA%3D" + + "&Signature=vX1Tskc4VuBUWPqsJ%2BzcjEj6/2iMCKzqjWnKFXRkDdA%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2012-04-16T15%3A54%3A08.897Z" + diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/AMIAsyncClientTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/AMIAsyncClientTest.java index ac52311db2..c026801282 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/services/AMIAsyncClientTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/services/AMIAsyncClientTest.java @@ -99,7 +99,7 @@ public class AMIAsyncClientTest extends BaseEC2AsyncClientTest { filter.filter(request); assertPayloadEquals( request, - "Action=DescribeImages&Signature=qE4vexSFJqS0UWK%2BccV3s%2BP9woL3M5HI5bTBoM7s%2FLY%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2009-11-08T15%3A54%3A08.897Z&Version=2010-06-15&AWSAccessKeyId=identity", + "Action=DescribeImages&Signature=qE4vexSFJqS0UWK%2BccV3s%2BP9woL3M5HI5bTBoM7s/LY%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2009-11-08T15%3A54%3A08.897Z&Version=2010-06-15&AWSAccessKeyId=identity", "application/x-www-form-urlencoded", false); assertResponseParserClassEquals(method, request, ParseSax.class); @@ -190,7 +190,7 @@ public class AMIAsyncClientTest extends BaseEC2AsyncClientTest { assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n"); assertPayloadEquals( request, - "Action=RegisterImage&RootDeviceName=%2Fdev%2Fsda1&BlockDeviceMapping.0.DeviceName=%2Fdev%2Fsda1&BlockDeviceMapping.0.Ebs.SnapshotId=snapshotId&Name=imageName", + "Action=RegisterImage&RootDeviceName=/dev/sda1&BlockDeviceMapping.0.DeviceName=/dev/sda1&BlockDeviceMapping.0.Ebs.SnapshotId=snapshotId&Name=imageName", "application/x-www-form-urlencoded", false); assertResponseParserClassEquals(method, request, ParseSax.class); assertSaxResponseParserClassEquals(method, ImageIdHandler.class); @@ -210,7 +210,7 @@ public class AMIAsyncClientTest extends BaseEC2AsyncClientTest { assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n"); assertPayloadEquals( request, - "Action=RegisterImage&RootDeviceName=%2Fdev%2Fsda1&BlockDeviceMapping.0.DeviceName=%2Fdev%2Fsda1&BlockDeviceMapping.0.Ebs.SnapshotId=snapshotId&Name=imageName&Description=description&BlockDeviceMapping.1.Ebs.DeleteOnTermination=false&BlockDeviceMapping.1.DeviceName=%2Fdev%2Fdevice&BlockDeviceMapping.1.Ebs.SnapshotId=snapshot&BlockDeviceMapping.2.Ebs.DeleteOnTermination=false&BlockDeviceMapping.2.DeviceName=%2Fdev%2Fnewdevice&BlockDeviceMapping.2.VirtualName=newblock&BlockDeviceMapping.2.Ebs.VolumeSize=100", + "Action=RegisterImage&RootDeviceName=/dev/sda1&BlockDeviceMapping.0.DeviceName=/dev/sda1&BlockDeviceMapping.0.Ebs.SnapshotId=snapshotId&Name=imageName&Description=description&BlockDeviceMapping.1.Ebs.DeleteOnTermination=false&BlockDeviceMapping.1.DeviceName=/dev/device&BlockDeviceMapping.1.Ebs.SnapshotId=snapshot&BlockDeviceMapping.2.Ebs.DeleteOnTermination=false&BlockDeviceMapping.2.DeviceName=/dev/newdevice&BlockDeviceMapping.2.VirtualName=newblock&BlockDeviceMapping.2.Ebs.VolumeSize=100", "application/x-www-form-urlencoded", false); assertResponseParserClassEquals(method, request, ParseSax.class); diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticBlockStoreAsyncClientTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticBlockStoreAsyncClientTest.java index c36fb6833a..3a9ca6d4bc 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticBlockStoreAsyncClientTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticBlockStoreAsyncClientTest.java @@ -111,7 +111,7 @@ public class ElasticBlockStoreAsyncClientTest extends BaseEC2AsyncClientTest extends BaseRestClientExpectTe .endpoint("http://partnercloud.eucalyptus.com:8773/services/Eucalyptus/") .addHeader("Host", "partnercloud.eucalyptus.com:8773") .payload(payloadFromStringWithContentType( - "Action=DescribeRegions&Signature=tp9WpT8503JdxIXYu6Eu2Dmu%2Bd%2FpqviST7N7Fvr%2FyQo%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2010-06-15&AWSAccessKeyId=identity", + "Action=DescribeRegions&Signature=tp9WpT8503JdxIXYu6Eu2Dmu%2Bd/pqviST7N7Fvr/yQo%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2010-06-15&AWSAccessKeyId=identity", MediaType.APPLICATION_FORM_URLENCODED)).build(); protected HttpResponse describeRegionsResponse = HttpResponse.builder().statusCode(200) @@ -60,7 +60,7 @@ public abstract class BaseEucalyptusExpectTest extends BaseRestClientExpectTe .endpoint("http://eucalyptus.partner.eucalyptus.com:8773/services/Eucalyptus/") .addHeader("Host", "eucalyptus.partner.eucalyptus.com:8773") .payload(payloadFromStringWithContentType( - "Action=DescribeAvailabilityZones&Signature=i4OkMed1sqQV7hlF%2Fl1KdbQwmwJ4Fh4o9W32eVGayPk%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2010-06-15&AWSAccessKeyId=identity", + "Action=DescribeAvailabilityZones&Signature=i4OkMed1sqQV7hlF/l1KdbQwmwJ4Fh4o9W32eVGayPk%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2010-06-15&AWSAccessKeyId=identity", MediaType.APPLICATION_FORM_URLENCODED)).build(); protected HttpResponse describeAZResponse = HttpResponse.builder().statusCode(200) diff --git a/apis/nova/src/main/java/org/jclouds/openstack/nova/NovaAsyncClient.java b/apis/nova/src/main/java/org/jclouds/openstack/nova/NovaAsyncClient.java index 3b05db1eb7..7836fbae7d 100644 --- a/apis/nova/src/main/java/org/jclouds/openstack/nova/NovaAsyncClient.java +++ b/apis/nova/src/main/java/org/jclouds/openstack/nova/NovaAsyncClient.java @@ -50,7 +50,6 @@ import org.jclouds.rest.annotations.Payload; import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.Unwrap; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404; @@ -69,7 +68,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @see NovaClient * @see */ -@SkipEncoding({'/', '='}) @RequestFilters({AuthenticateRequest.class, AddTimestampQuery.class}) @Endpoint(ServerManagement.class) public interface NovaAsyncClient { diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/PaginatedCollection.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/PaginatedCollection.java index 2d8758025d..e53ce36e2e 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/PaginatedCollection.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/PaginatedCollection.java @@ -18,7 +18,7 @@ */ package org.jclouds.openstack.keystone.v2_0.domain; -import static org.jclouds.http.utils.Queries.parseQueryToMap; +import static org.jclouds.http.utils.Queries.queryParser; import java.util.Collection; import java.util.Iterator; @@ -78,7 +78,7 @@ public class PaginatedCollection extends IterableWithMarker { }).transform(new Function>() { @Override public Optional apply(Link link) { - Collection markers = parseQueryToMap(link.getHref().getRawQuery()).get("marker"); + Collection markers = queryParser().apply(link.getHref().getRawQuery()).get("marker"); return Optional. fromNullable(markers == null ? null : Iterables.get(markers, 0)); } }).first().or(Optional.absent()); diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/ServiceAsyncApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/ServiceAsyncApi.java index c890d35b10..0e0ff9b2aa 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/ServiceAsyncApi.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/ServiceAsyncApi.java @@ -30,7 +30,6 @@ import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import com.google.common.util.concurrent.ListenableFuture; @@ -45,7 +44,6 @@ import com.google.common.util.concurrent.ListenableFuture; * /> * @author Adam Lowe */ -@SkipEncoding( { '/', '=' }) public interface ServiceAsyncApi { /** diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantAsyncApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantAsyncApi.java index b2476cebe9..aa3f1955cb 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantAsyncApi.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantAsyncApi.java @@ -38,7 +38,6 @@ import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.Transform; import org.jclouds.rest.functions.ReturnEmptyPagedIterableOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; @@ -56,7 +55,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @author Adam Lowe */ @org.jclouds.rest.annotations.Endpoint(Identity.class) -@SkipEncoding( { '/', '=' }) public interface TenantAsyncApi { /** diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TokenAsyncApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TokenAsyncApi.java index 2473400a78..7a8b2a7e94 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TokenAsyncApi.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TokenAsyncApi.java @@ -35,7 +35,6 @@ import org.jclouds.openstack.v2_0.services.Identity; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; @@ -52,7 +51,6 @@ import com.google.common.util.concurrent.ListenableFuture; * /> * @author Adam Lowe */ -@SkipEncoding({ '/', '=' }) @org.jclouds.rest.annotations.Endpoint(Identity.class) public interface TokenAsyncApi { diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserAsyncApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserAsyncApi.java index f91d61f3b1..68a46efbd5 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserAsyncApi.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserAsyncApi.java @@ -41,7 +41,6 @@ import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.Transform; import org.jclouds.rest.functions.ReturnEmptyPagedIterableOnNotFoundOr404; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; @@ -60,7 +59,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @author Adam Lowe */ @org.jclouds.rest.annotations.Endpoint(Identity.class) -@SkipEncoding({ '/', '=' }) public interface UserAsyncApi { /** diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/features/ExtensionAsyncApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/features/ExtensionAsyncApi.java index ef88c60272..11d423ce7c 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/features/ExtensionAsyncApi.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/features/ExtensionAsyncApi.java @@ -31,7 +31,6 @@ import org.jclouds.openstack.v2_0.domain.Extension; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; @@ -47,7 +46,6 @@ import com.google.common.util.concurrent.ListenableFuture; * /> * @author Adrian Cole */ -@SkipEncoding({ '/', '=' }) @RequestFilters(AuthenticateRequest.class) public interface ExtensionAsyncApi { diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/functions/ExtensionToNameSpace.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/functions/ExtensionToNameSpace.java index 5174ae9fc2..4f750258d8 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/functions/ExtensionToNameSpace.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/v2_0/functions/ExtensionToNameSpace.java @@ -18,12 +18,11 @@ */ package org.jclouds.openstack.v2_0.functions; +import static org.jclouds.http.Uris.uriBuilder; + import java.net.URI; -import javax.inject.Inject; -import javax.inject.Provider; import javax.inject.Singleton; -import javax.ws.rs.core.UriBuilder; import org.jclouds.openstack.v2_0.domain.Extension; @@ -31,20 +30,14 @@ import com.google.common.base.Function; @Singleton public class ExtensionToNameSpace implements Function { - private final Provider uriBuilders; - - @Inject - public ExtensionToNameSpace(Provider uriBuilders) { - this.uriBuilders = uriBuilders; - } @Override public URI apply(Extension input) { - return uriBuilders.get().uri(input.getNamespace()).scheme("http").build(); + return uriBuilder(input.getNamespace()).scheme("http").build(); } public String toString() { - return "extensionToURI()"; + return "changeSchemeToHttp()"; } } diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/v2_0/functions/ExtensionToNameSpaceTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/v2_0/functions/ExtensionToNameSpaceTest.java index 2518e69492..000c86af5f 100644 --- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/v2_0/functions/ExtensionToNameSpaceTest.java +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/v2_0/functions/ExtensionToNameSpaceTest.java @@ -4,28 +4,16 @@ import static org.testng.Assert.assertEquals; import java.net.URI; -import javax.inject.Provider; -import javax.ws.rs.core.UriBuilder; - import org.jclouds.date.internal.SimpleDateFormatDateService; import org.jclouds.openstack.v2_0.domain.Extension; import org.testng.annotations.Test; -import com.sun.jersey.api.uri.UriBuilderImpl; - /** * @author Adrian Cole */ @Test(groups = "unit", testName = "ExtensionToNameSpaceTest") public class ExtensionToNameSpaceTest { - private final ExtensionToNameSpace fn = new ExtensionToNameSpace(new Provider() { - - @Override - public UriBuilder get() { - return new UriBuilderImpl(); - } - - }); + private final ExtensionToNameSpace fn = new ExtensionToNameSpace(); public void testReturnsNamespace() { URI ns = URI.create("http://docs.openstack.org/ext/keypairs/api/v1.1"); diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2AMIClientExpectTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2AMIClientExpectTest.java index 1f3adb3b91..8ce460896a 100644 --- a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2AMIClientExpectTest.java +++ b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2AMIClientExpectTest.java @@ -42,7 +42,7 @@ public class NovaEC2AMIClientExpectTest extends BaseNovaEC2RestClientExpectTest HttpRequest.builder().method("POST") .endpoint("http://localhost:8773/services/Cloud/") .addHeader("Host", "localhost:8773") - .payload(payloadFromStringWithContentType("Action=DescribeImages&Signature=Z3q3jSutwlfgvbcINT0Ed3AjrjxM4WMvQloXu%2F1kd40%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2009-04-04&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(), + .payload(payloadFromStringWithContentType("Action=DescribeImages&Signature=Z3q3jSutwlfgvbcINT0Ed3AjrjxM4WMvQloXu/1kd40%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2009-04-04&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(), HttpResponse.builder().statusCode(200).payload(payloadFromResource("/nova_ec2_images_with_ramdisk.xml")).build() ).getAMIServices(); diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/binders/BindKeyPairToJsonPayload.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/binders/BindKeyPairToJsonPayload.java new file mode 100644 index 0000000000..ec9f5cd2ec --- /dev/null +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/binders/BindKeyPairToJsonPayload.java @@ -0,0 +1,49 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.openstack.nova.v2_0.binders; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.http.HttpRequest; +import org.jclouds.json.Json; +import org.jclouds.rest.binders.BindToJsonPayload; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSortedMap; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class BindKeyPairToJsonPayload extends BindToJsonPayload { + + @Inject + public BindKeyPairToJsonPayload(Json jsonBinder) { + super(jsonBinder); + } + + @Override + public R bindToRequest(R request, Map postParams) { + return bindToRequest(request, (Object) ImmutableMap.of("keypair", ImmutableSortedMap.copyOf(postParams))); + } +} \ No newline at end of file diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/FloatingIPAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/FloatingIPAsyncApi.java index 391de9fdd2..b2cd6d7b38 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/FloatingIPAsyncApi.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/FloatingIPAsyncApi.java @@ -37,7 +37,6 @@ import org.jclouds.rest.annotations.Payload; import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnEmptyFluentIterableOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; @@ -59,7 +58,6 @@ import com.google.common.util.concurrent.ListenableFuture; */ @Beta @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.FLOATING_IPS) -@SkipEncoding( { '/', '=' }) @RequestFilters(AuthenticateRequest.class) public interface FloatingIPAsyncApi { diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationAsyncApi.java index dcf9f9f6aa..3a76ef1468 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationAsyncApi.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationAsyncApi.java @@ -43,7 +43,6 @@ import org.jclouds.rest.annotations.Payload; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnEmptyFluentIterableOnNotFoundOr404; import com.google.common.annotations.Beta; @@ -62,7 +61,6 @@ import com.google.common.util.concurrent.ListenableFuture; */ @Beta @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.HOSTS) -@SkipEncoding({'/', '='}) @RequestFilters(AuthenticateRequest.class) @Path("/os-hosts") @Consumes(MediaType.APPLICATION_JSON) diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairAsyncApi.java index c5b0f69fda..6b1b6fcefa 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairAsyncApi.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairAsyncApi.java @@ -28,18 +28,19 @@ import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; +import org.jclouds.openstack.nova.v2_0.binders.BindKeyPairToJsonPayload; import org.jclouds.openstack.nova.v2_0.domain.KeyPair; import org.jclouds.openstack.nova.v2_0.functions.internal.ParseKeyPairs; import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.openstack.v2_0.features.ExtensionAsyncApi; import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.MapBinder; import org.jclouds.rest.annotations.Payload; import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnEmptyFluentIterableOnNotFoundOr404; import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404; @@ -62,7 +63,6 @@ import com.google.common.util.concurrent.ListenableFuture; */ @Beta @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.KEYPAIRS) -@SkipEncoding({ '/', '=' }) @RequestFilters(AuthenticateRequest.class) public interface KeyPairAsyncApi { @@ -86,9 +86,9 @@ public interface KeyPairAsyncApi { @SelectJson("keypair") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - @Payload("%7B\"keypair\":%7B\"name\":\"{name}\",\"public_key\":\"{publicKey}\"%7D%7D") + @MapBinder(BindKeyPairToJsonPayload.class) ListenableFuture createWithPublicKey(@PayloadParam("name") String name, - @PayloadParam("publicKey") String publicKey); + @PayloadParam("public_key") String publicKey); @DELETE @Path("/os-keypairs/{name}") diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SecurityGroupAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SecurityGroupAsyncApi.java index 0303ff8270..600bbfed3f 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SecurityGroupAsyncApi.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SecurityGroupAsyncApi.java @@ -40,7 +40,6 @@ import org.jclouds.rest.annotations.Payload; import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnEmptyFluentIterableOnNotFoundOr404; import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; @@ -62,7 +61,6 @@ import com.google.common.util.concurrent.ListenableFuture; */ @Beta @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.SECURITY_GROUPS) -@SkipEncoding( { '/', '=' }) @RequestFilters(AuthenticateRequest.class) public interface SecurityGroupAsyncApi { diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/ServerAdminAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/ServerAdminAsyncApi.java index f6ce679b30..dc4a5dfc3b 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/ServerAdminAsyncApi.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/ServerAdminAsyncApi.java @@ -36,7 +36,6 @@ import org.jclouds.rest.annotations.Payload; import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.WrapWith; import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions; import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404; @@ -52,7 +51,6 @@ import com.google.common.util.concurrent.ListenableFuture; */ @Beta @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.ADMIN_ACTIONS) -@SkipEncoding( { '/', '=' }) @RequestFilters(AuthenticateRequest.class) @Path("/servers/{id}/action") public interface ServerAdminAsyncApi { diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/ServerWithSecurityGroupsAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/ServerWithSecurityGroupsAsyncApi.java index 9585b309ed..b96f4cd6cf 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/ServerWithSecurityGroupsAsyncApi.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/ServerWithSecurityGroupsAsyncApi.java @@ -31,7 +31,6 @@ import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; import com.google.common.annotations.Beta; @@ -47,7 +46,6 @@ import com.google.common.util.concurrent.ListenableFuture; */ @Beta @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.CREATESERVEREXT) -@SkipEncoding({'/', '='}) @RequestFilters(AuthenticateRequest.class) public interface ServerWithSecurityGroupsAsyncApi { diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageAsyncApi.java index ea14d37d7b..e2fc199805 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageAsyncApi.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageAsyncApi.java @@ -31,7 +31,6 @@ import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnEmptyFluentIterableOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; @@ -51,7 +50,6 @@ import com.google.common.util.concurrent.ListenableFuture; */ @Beta @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.SIMPLE_TENANT_USAGE) -@SkipEncoding({'/', '='}) @RequestFilters(AuthenticateRequest.class) public interface SimpleTenantUsageAsyncApi { diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VirtualInterfaceAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VirtualInterfaceAsyncApi.java index de94545adf..6096ae6b3f 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VirtualInterfaceAsyncApi.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VirtualInterfaceAsyncApi.java @@ -31,7 +31,6 @@ import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnEmptyFluentIterableOnNotFoundOr404; import com.google.common.annotations.Beta; @@ -46,7 +45,6 @@ import com.google.common.util.concurrent.ListenableFuture; */ @Beta @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VIRTUAL_INTERFACES) -@SkipEncoding({'/', '='}) @RequestFilters(AuthenticateRequest.class) public interface VirtualInterfaceAsyncApi { /** diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeAsyncApi.java index 83aaf22e6e..a8c928cf8b 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeAsyncApi.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeAsyncApi.java @@ -40,7 +40,6 @@ import org.jclouds.rest.annotations.MapBinder; import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.WrapWith; import org.jclouds.rest.functions.ReturnEmptyFluentIterableOnNotFoundOr404; import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404; @@ -59,7 +58,6 @@ import com.google.common.util.concurrent.ListenableFuture; */ @Beta @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VOLUMES) -@SkipEncoding({'/', '='}) @RequestFilters(AuthenticateRequest.class) public interface VolumeAsyncApi { /** diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeAttachmentAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeAttachmentAsyncApi.java index 495ee8bba7..85693d9e86 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeAttachmentAsyncApi.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeAttachmentAsyncApi.java @@ -35,7 +35,6 @@ import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.WrapWith; import org.jclouds.rest.functions.ReturnEmptyFluentIterableOnNotFoundOr404; import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404; @@ -53,7 +52,6 @@ import com.google.common.util.concurrent.ListenableFuture; */ @Beta @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VOLUMES) -@SkipEncoding({'/', '='}) @RequestFilters(AuthenticateRequest.class) public interface VolumeAttachmentAsyncApi { /** @@ -103,4 +101,4 @@ public interface VolumeAttachmentAsyncApi { ListenableFuture detachVolumeFromServer( @PathParam("id") String volumeId, @PathParam("server_id") String serverId); -} \ No newline at end of file +} diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeAsyncApi.java index 8dc6061ecf..c15fccfaed 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeAsyncApi.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeAsyncApi.java @@ -41,7 +41,6 @@ import org.jclouds.rest.annotations.Payload; import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.Unwrap; import org.jclouds.rest.annotations.WrapWith; import org.jclouds.rest.binders.BindToJsonPayload; @@ -62,7 +61,6 @@ import com.google.common.util.concurrent.ListenableFuture; */ @Beta @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VOLUME_TYPES) -@SkipEncoding({'/', '='}) @RequestFilters(AuthenticateRequest.class) @Path("/os-volume-types") @Consumes(MediaType.APPLICATION_JSON) diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/FlavorAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/FlavorAsyncApi.java index 411acb5cd8..415e9fb4c4 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/FlavorAsyncApi.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/FlavorAsyncApi.java @@ -37,7 +37,6 @@ import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.Transform; import org.jclouds.rest.functions.ReturnEmptyPagedIterableOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; @@ -55,7 +54,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @author Jeremy Daggett TODO: Need a ListFlavorOptions class minDisk=minDiskInGB& * minRam=minRamInMB& marker=markerID&limit=int */ -@SkipEncoding({ '/', '=' }) @RequestFilters(AuthenticateRequest.class) public interface FlavorAsyncApi { diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ImageAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ImageAsyncApi.java index 0d69ab3402..dbd0aed705 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ImageAsyncApi.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ImageAsyncApi.java @@ -47,7 +47,6 @@ import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.Transform; import org.jclouds.rest.binders.BindToJsonPayload; import org.jclouds.rest.functions.ReturnEmptyMapOnNotFoundOr404; @@ -64,7 +63,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @see ImageApi * @author Jeremy Daggett */ -@SkipEncoding({ '/', '=' }) @RequestFilters(AuthenticateRequest.class) public interface ImageAsyncApi { diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ServerAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ServerAsyncApi.java index a01485026e..07bc61bd60 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ServerAsyncApi.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ServerAsyncApi.java @@ -54,7 +54,6 @@ import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.Transform; import org.jclouds.rest.annotations.Unwrap; import org.jclouds.rest.binders.BindToJsonPayload; @@ -78,7 +77,6 @@ import org.jclouds.openstack.nova.v2_0.functions.internal.*; * /> * @author Adrian Cole */ -@SkipEncoding({ '/', '=' }) @RequestFilters(AuthenticateRequest.class) public interface ServerAsyncApi { diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/LoadBalancerAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/LoadBalancerAsyncApi.java index a38aaa5dee..25d46e8ff0 100644 --- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/LoadBalancerAsyncApi.java +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/LoadBalancerAsyncApi.java @@ -40,7 +40,6 @@ import org.jclouds.rackspace.cloudloadbalancers.functions.ParseLoadBalancers; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.Transform; import org.jclouds.rest.annotations.WrapWith; import org.jclouds.rest.functions.ReturnEmptyPagedIterableOnNotFoundOr404; @@ -56,7 +55,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @see LoadBalancerApi * @author Everett Toews */ -@SkipEncoding('/') @RequestFilters(AuthenticateRequest.class) public interface LoadBalancerAsyncApi { diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/NodeAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/NodeAsyncApi.java index 82ae99c5ae..96fa286b85 100644 --- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/NodeAsyncApi.java +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/NodeAsyncApi.java @@ -44,7 +44,6 @@ import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.Transform; import org.jclouds.rest.annotations.WrapWith; import org.jclouds.rest.functions.ReturnEmptyPagedIterableOnNotFoundOr404; @@ -60,7 +59,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @see NodeAsyncApi * @author Everett Toews */ -@SkipEncoding('/') @RequestFilters(AuthenticateRequest.class) public interface NodeAsyncApi { diff --git a/apis/s3/src/main/java/org/jclouds/s3/S3AsyncClient.java b/apis/s3/src/main/java/org/jclouds/s3/S3AsyncClient.java index fcc0998c49..fde752385c 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/S3AsyncClient.java +++ b/apis/s3/src/main/java/org/jclouds/s3/S3AsyncClient.java @@ -52,7 +52,6 @@ import org.jclouds.rest.annotations.ParamValidators; import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.XMLResponseParser; import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; @@ -106,7 +105,6 @@ import com.google.inject.Provides; * @see S3Client * @see */ -@SkipEncoding('/') @RequestFilters(RequestAuthorizeSignature.class) @BlobScope(CONTAINER) public interface S3AsyncClient { diff --git a/apis/s3/src/main/java/org/jclouds/s3/filters/RequestAuthorizeSignature.java b/apis/s3/src/main/java/org/jclouds/s3/filters/RequestAuthorizeSignature.java index f04ca0442c..3a71c48a5b 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/filters/RequestAuthorizeSignature.java +++ b/apis/s3/src/main/java/org/jclouds/s3/filters/RequestAuthorizeSignature.java @@ -21,7 +21,7 @@ package org.jclouds.s3.filters; import static com.google.common.collect.Iterables.get; import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG; import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG; -import static org.jclouds.http.utils.Queries.parseQueryToMap; +import static org.jclouds.http.utils.Queries.queryParser; import static org.jclouds.s3.reference.S3Constants.PROPERTY_S3_SERVICE_PATH; import static org.jclouds.s3.reference.S3Constants.PROPERTY_S3_VIRTUAL_HOST_BUCKETS; import static org.jclouds.util.Strings2.toInputStream; @@ -238,7 +238,7 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign // ...however, there are a few exceptions that must be included in the // signed URI. if (request.getEndpoint().getQuery() != null) { - Multimap params = parseQueryToMap(request.getEndpoint().getQuery()); + Multimap params = queryParser().apply(request.getEndpoint().getQuery()); char separator = '?'; for (String paramName : Ordering.natural().sortedCopy(params.keySet())) { // Skip any parameters that aren't part of the canonical signed string diff --git a/apis/s3/src/main/java/org/jclouds/s3/handlers/S3RedirectionRetryHandler.java b/apis/s3/src/main/java/org/jclouds/s3/handlers/S3RedirectionRetryHandler.java index 88712153e4..1d74731085 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/handlers/S3RedirectionRetryHandler.java +++ b/apis/s3/src/main/java/org/jclouds/s3/handlers/S3RedirectionRetryHandler.java @@ -19,13 +19,14 @@ package org.jclouds.s3.handlers; import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream; +import static org.jclouds.http.Uris.uriBuilder; + +import java.net.URI; import javax.inject.Inject; -import javax.inject.Provider; import javax.inject.Singleton; import javax.ws.rs.HttpMethod; import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.UriBuilder; import org.jclouds.aws.domain.AWSError; import org.jclouds.aws.util.AWSUtils; @@ -44,9 +45,8 @@ public class S3RedirectionRetryHandler extends RedirectionRetryHandler { private final AWSUtils utils; @Inject - public S3RedirectionRetryHandler(Provider uriBuilderProvider, - BackoffLimitedRetryHandler backoffHandler, AWSUtils utils) { - super(uriBuilderProvider, backoffHandler); + public S3RedirectionRetryHandler(BackoffLimitedRetryHandler backoffHandler, AWSUtils utils) { + super(backoffHandler); this.utils = utils; } @@ -69,9 +69,8 @@ public class S3RedirectionRetryHandler extends RedirectionRetryHandler { // http://developer.amazonwebservices.com/connect/thread.jspa?messageID=72287𑩟 return backoffHandler.shouldRetryRequest(command, response); } else { - UriBuilder builder = uriBuilderProvider.get().uri(command.getCurrentRequest().getEndpoint()); - builder.host(host); - command.setCurrentRequest(command.getCurrentRequest().toBuilder().endpoint(builder.build()).build()); + URI newHost = uriBuilder(command.getCurrentRequest().getEndpoint()).host(host).build(); + command.setCurrentRequest(command.getCurrentRequest().toBuilder().endpoint(newHost).build()); } return true; } else { diff --git a/apis/s3/src/main/java/org/jclouds/s3/xml/ListBucketHandler.java b/apis/s3/src/main/java/org/jclouds/s3/xml/ListBucketHandler.java index ef902bd055..bb2b574c3b 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/xml/ListBucketHandler.java +++ b/apis/s3/src/main/java/org/jclouds/s3/xml/ListBucketHandler.java @@ -18,11 +18,10 @@ */ package org.jclouds.s3.xml; +import static org.jclouds.http.Uris.uriBuilder; import static org.jclouds.util.SaxUtils.currentOrNull; import javax.inject.Inject; -import javax.inject.Provider; -import javax.ws.rs.core.UriBuilder; import org.jclouds.crypto.CryptoStreams; import org.jclouds.date.DateService; @@ -56,7 +55,6 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult uriBuilders; private final DateService dateParser; private String bucketName; @@ -67,9 +65,8 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult uriBuilders) { + public ListBucketHandler(DateService dateParser) { this.dateParser = dateParser; - this.uriBuilders = uriBuilders; } public ListBucketResponse getResult() { @@ -96,7 +93,7 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult uriBuilderProvider = new Provider() { - - @Override - public UriBuilder get() { - return new UriBuilderImpl(); - } - - }; public void testWhenNoBucketRegionMappingInCache() { diff --git a/apis/s3/src/test/java/org/jclouds/s3/xml/S3ParserTest.java b/apis/s3/src/test/java/org/jclouds/s3/xml/S3ParserTest.java index 7fe3b3183c..44e24fc4a7 100644 --- a/apis/s3/src/test/java/org/jclouds/s3/xml/S3ParserTest.java +++ b/apis/s3/src/test/java/org/jclouds/s3/xml/S3ParserTest.java @@ -28,8 +28,6 @@ import java.util.concurrent.CompletionService; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorCompletionService; -import javax.ws.rs.core.UriBuilder; - import org.jclouds.PerformanceTest; import org.jclouds.date.internal.SimpleDateFormatDateService; import org.jclouds.http.HttpException; @@ -50,7 +48,6 @@ import org.xml.sax.SAXException; import com.google.common.collect.Iterables; import com.google.inject.Guice; import com.google.inject.Injector; -import com.sun.jersey.api.uri.UriBuilderImpl; /** * Tests parsing of S3 responses @@ -65,12 +62,7 @@ public class S3ParserTest extends PerformanceTest { @BeforeTest protected void setUpInjector() { - injector = Guice.createInjector(new SaxParserModule() { - public void configure() { - super.configure(); - bind(UriBuilder.class).to(UriBuilderImpl.class); - } - }); + injector = Guice.createInjector(new SaxParserModule()); factory = injector.getInstance(ParseSax.Factory.class); assert factory != null; } diff --git a/apis/sqs/src/test/java/org/jclouds/sqs/features/MessageApiExpectTest.java b/apis/sqs/src/test/java/org/jclouds/sqs/features/MessageApiExpectTest.java index da2fa1b138..13d354e1e5 100644 --- a/apis/sqs/src/test/java/org/jclouds/sqs/features/MessageApiExpectTest.java +++ b/apis/sqs/src/test/java/org/jclouds/sqs/features/MessageApiExpectTest.java @@ -103,7 +103,7 @@ public class MessageApiExpectTest extends BaseSQSApiExpectTest { .addFormParam("SendMessageBatchRequestEntry.1.MessageBody", "payload1") .addFormParam("SendMessageBatchRequestEntry.2.Id", "foo2") .addFormParam("SendMessageBatchRequestEntry.2.MessageBody", "payload2") - .addFormParam("Signature", "f9v8e%2FrPXTI3zhBYMhg7U8yCfvPqHjAV8bFjhGL6%2BXc%3D") + .addFormParam("Signature", "f9v8e/rPXTI3zhBYMhg7U8yCfvPqHjAV8bFjhGL6%2BXc%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") @@ -135,7 +135,7 @@ public class MessageApiExpectTest extends BaseSQSApiExpectTest { .addFormParam("SendMessageBatchRequestEntry.2.DelaySeconds", "10") .addFormParam("SendMessageBatchRequestEntry.2.Id", "foo2") .addFormParam("SendMessageBatchRequestEntry.2.MessageBody", "payload2") - .addFormParam("Signature", "COjjEaJ76EwziEFtkT2FuSRSbrCIu%2FhlJf1Zmu7cYoU%3D") + .addFormParam("Signature", "COjjEaJ76EwziEFtkT2FuSRSbrCIu/hlJf1Zmu7cYoU%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") @@ -168,7 +168,7 @@ public class MessageApiExpectTest extends BaseSQSApiExpectTest { .addFormParam("SendMessageBatchRequestEntry.2.DelaySeconds", "10") .addFormParam("SendMessageBatchRequestEntry.2.Id", "2") .addFormParam("SendMessageBatchRequestEntry.2.MessageBody", "payload2") - .addFormParam("Signature", "8AVNvSVXPSnoXjJAc6h1rysMBBZPnSycbnmD2%2FqpdV8%3D") + .addFormParam("Signature", "8AVNvSVXPSnoXjJAc6h1rysMBBZPnSycbnmD2/qpdV8%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") @@ -231,7 +231,7 @@ public class MessageApiExpectTest extends BaseSQSApiExpectTest { .addFormParam("SendMessageBatchRequestEntry.2.DelaySeconds", "10") .addFormParam("SendMessageBatchRequestEntry.2.Id", "2") .addFormParam("SendMessageBatchRequestEntry.2.MessageBody", "payload2") - .addFormParam("Signature", "nbA4UnKDAuQCiCcvQHH%2F1UjMMeo2s3d94A27Q3t9SlI%3D") + .addFormParam("Signature", "nbA4UnKDAuQCiCcvQHH/1UjMMeo2s3d94A27Q3t9SlI%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") @@ -281,7 +281,7 @@ public class MessageApiExpectTest extends BaseSQSApiExpectTest { .addHeader("Host", "sqs.us-east-1.amazonaws.com") .addFormParam("Action", "ReceiveMessage") .addFormParam("MaxNumberOfMessages", "10") - .addFormParam("Signature", "pZ9B4%2BTBvQA4n0joP4t8ue5x0xmKMd9prpVLVoT%2F7qU%3D") + .addFormParam("Signature", "pZ9B4%2BTBvQA4n0joP4t8ue5x0xmKMd9prpVLVoT/7qU%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") @@ -305,7 +305,7 @@ public class MessageApiExpectTest extends BaseSQSApiExpectTest { .addHeader("Host", "sqs.us-east-1.amazonaws.com") .addFormParam("Action", "DeleteMessage") .addFormParam("ReceiptHandle", "eXJYhj5rDr9cAe") - .addFormParam("Signature", "9%2FkuCc2i78gMsmul%2BRsOPcdQ1OLUKrItqgGIRRBJb8M%3D") + .addFormParam("Signature", "9/kuCc2i78gMsmul%2BRsOPcdQ1OLUKrItqgGIRRBJb8M%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") @@ -335,7 +335,7 @@ public class MessageApiExpectTest extends BaseSQSApiExpectTest { .addFormParam("DeleteMessageBatchRequestEntry.1.ReceiptHandle", "eXJYhj5rDr9cAe") .addFormParam("DeleteMessageBatchRequestEntry.2.Id", "2") .addFormParam("DeleteMessageBatchRequestEntry.2.ReceiptHandle", "fffeeerrr") - .addFormParam("Signature", "S4xIobjm3LOkJvibeI2X54nxKJw9r1a5zj%2FdvHlfDMY%3D") + .addFormParam("Signature", "S4xIobjm3LOkJvibeI2X54nxKJw9r1a5zj/dvHlfDMY%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") @@ -487,7 +487,7 @@ public class MessageApiExpectTest extends BaseSQSApiExpectTest { .addFormParam("ChangeMessageVisibilityBatchRequestEntry.2.Id", "foo2") .addFormParam("ChangeMessageVisibilityBatchRequestEntry.2.ReceiptHandle", "bbbbbbbbb") .addFormParam("ChangeMessageVisibilityBatchRequestEntry.2.VisibilityTimeout", "10") - .addFormParam("Signature", "y%2FgaaxoE5wrG2P7NIAyfDo7DTgRx2PLJUi9%2FzNnWQ6A%3D") + .addFormParam("Signature", "y/gaaxoE5wrG2P7NIAyfDo7DTgRx2PLJUi9/zNnWQ6A%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") diff --git a/apis/sqs/src/test/java/org/jclouds/sqs/features/PermissionApiExpectTest.java b/apis/sqs/src/test/java/org/jclouds/sqs/features/PermissionApiExpectTest.java index 037de11b3a..81f3164647 100644 --- a/apis/sqs/src/test/java/org/jclouds/sqs/features/PermissionApiExpectTest.java +++ b/apis/sqs/src/test/java/org/jclouds/sqs/features/PermissionApiExpectTest.java @@ -36,8 +36,8 @@ public class PermissionApiExpectTest extends BaseSQSApiExpectTest { .endpoint("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/") .addHeader("Host", "sqs.us-east-1.amazonaws.com") .addFormParam("Action", "AddPermission") - .addFormParam("ActionName.1", "ReceiveMessage") .addFormParam("AWSAccountId.1", "125074342641") + .addFormParam("ActionName.1", "ReceiveMessage") .addFormParam("Label", "testLabel") .addFormParam("Signature", "J9sV4q1rJ7dWYJDQp9JxsfEKNXQhpQBYIwBYi1IeXV0%3D") .addFormParam("SignatureMethod", "HmacSHA256") diff --git a/apis/sqs/src/test/java/org/jclouds/sqs/features/QueueApiExpectTest.java b/apis/sqs/src/test/java/org/jclouds/sqs/features/QueueApiExpectTest.java index c17691ce9a..34da7d03b6 100644 --- a/apis/sqs/src/test/java/org/jclouds/sqs/features/QueueApiExpectTest.java +++ b/apis/sqs/src/test/java/org/jclouds/sqs/features/QueueApiExpectTest.java @@ -71,7 +71,7 @@ public class QueueApiExpectTest extends BaseSQSApiExpectTest { .addFormParam("Action", "GetQueueUrl") .addFormParam("QueueName", "queueName") .addFormParam("QueueOwnerAWSAccountId", "120908098979") - .addFormParam("Signature", "O0E%2B3jh2vN6bKqmb4%2FXPTHUmPO1iat9o8YnIFH463g8%3D") + .addFormParam("Signature", "O0E%2B3jh2vN6bKqmb4/XPTHUmPO1iat9o8YnIFH463g8%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") @@ -213,7 +213,7 @@ public class QueueApiExpectTest extends BaseSQSApiExpectTest { .addFormParam("Action", "SetQueueAttributes") .addFormParam("Attribute.Name", "MaximumMessageSize") .addFormParam("Attribute.Value", "1") - .addFormParam("Signature", "ktBkQ3c%2FrwGcBSec0fkckfo73xmcoTuub5fxudM1qh0%3D") + .addFormParam("Signature", "ktBkQ3c/rwGcBSec0fkckfo73xmcoTuub5fxudM1qh0%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/CommonSwiftAsyncClient.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/CommonSwiftAsyncClient.java index 18bf1ff1e9..1e7b431a6d 100644 --- a/apis/swift/src/main/java/org/jclouds/openstack/swift/CommonSwiftAsyncClient.java +++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/CommonSwiftAsyncClient.java @@ -66,7 +66,6 @@ import org.jclouds.rest.annotations.ParamParser; import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; import com.google.common.annotations.Beta; @@ -80,7 +79,6 @@ import com.google.inject.Provides; * @see * @author Adrian Cole */ -@SkipEncoding('/') @RequestFilters(AuthenticateRequest.class) @Endpoint(Storage.class) public interface CommonSwiftAsyncClient { diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftAsyncClient.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftAsyncClient.java index fd8aefd8bc..a870308818 100644 --- a/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftAsyncClient.java +++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftAsyncClient.java @@ -21,14 +21,12 @@ package org.jclouds.openstack.swift; import org.jclouds.openstack.filters.AuthenticateRequest; import org.jclouds.rest.annotations.Endpoint; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; /** * Functionality that's in Swift, and not in CloudFiles. * * @author Adrian Cole */ -@SkipEncoding('/') @RequestFilters(AuthenticateRequest.class) @Endpoint(Storage.class) public interface SwiftAsyncClient extends CommonSwiftAsyncClient { diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftKeystoneAsyncClient.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftKeystoneAsyncClient.java index 069682f048..65304a5615 100644 --- a/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftKeystoneAsyncClient.java +++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftKeystoneAsyncClient.java @@ -21,14 +21,12 @@ package org.jclouds.openstack.swift; import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; import org.jclouds.rest.annotations.Endpoint; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; /** * Functionality that's in Swift, and not in CloudFiles. * * @author Adrian Cole */ -@SkipEncoding('/') @RequestFilters(AuthenticateRequest.class) @Endpoint(Storage.class) public interface SwiftKeystoneAsyncClient extends CommonSwiftAsyncClient { diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/extensions/KeystoneTemporaryUrlKeyAsyncApi.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/extensions/KeystoneTemporaryUrlKeyAsyncApi.java index 7fb51d8dc2..a790103d7c 100644 --- a/apis/swift/src/main/java/org/jclouds/openstack/swift/extensions/KeystoneTemporaryUrlKeyAsyncApi.java +++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/extensions/KeystoneTemporaryUrlKeyAsyncApi.java @@ -22,7 +22,6 @@ import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; import org.jclouds.openstack.swift.Storage; import org.jclouds.rest.annotations.Endpoint; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; /** * Only purpose is to override the auth filter with one that works in keystone @@ -30,7 +29,6 @@ import org.jclouds.rest.annotations.SkipEncoding; * @author Adrian Cole * @see TemporaryUrlKeyApi */ -@SkipEncoding('/') @RequestFilters(AuthenticateRequest.class) @Endpoint(Storage.class) public interface KeystoneTemporaryUrlKeyAsyncApi extends TemporaryUrlKeyAsyncApi { diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/extensions/TemporaryUrlKeyAsyncApi.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/extensions/TemporaryUrlKeyAsyncApi.java index fafca1ba8f..8737680b5d 100644 --- a/apis/swift/src/main/java/org/jclouds/openstack/swift/extensions/TemporaryUrlKeyAsyncApi.java +++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/extensions/TemporaryUrlKeyAsyncApi.java @@ -26,7 +26,6 @@ import org.jclouds.openstack.swift.reference.SwiftHeaders; import org.jclouds.rest.annotations.Endpoint; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; -import org.jclouds.rest.annotations.SkipEncoding; import javax.ws.rs.Consumes; import javax.ws.rs.HEAD; @@ -39,7 +38,6 @@ import javax.ws.rs.core.MediaType; * @author Andrei Savu * @see TemporaryUrlKeyApi */ -@SkipEncoding('/') @RequestFilters(AuthenticateRequest.class) @Endpoint(Storage.class) public interface TemporaryUrlKeyAsyncApi { 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 676193b022..fe60a776d9 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 @@ -20,6 +20,7 @@ package org.jclouds.openstack.swift.functions; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; +import static org.jclouds.http.Uris.uriBuilder; import java.io.IOException; import java.io.InputStream; @@ -27,8 +28,6 @@ import java.lang.reflect.Type; import java.util.SortedSet; import javax.inject.Inject; -import javax.inject.Provider; -import javax.ws.rs.core.UriBuilder; import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.internal.PageSetImpl; @@ -54,16 +53,14 @@ import com.google.inject.TypeLiteral; */ public class ParseObjectInfoListFromJsonResponse extends ParseJson> implements InvocationContext { - private final Provider uriBuilders; private GeneratedHttpRequest request; private String container; @Inject - public ParseObjectInfoListFromJsonResponse(Json json, Provider uriBuilders) { + public ParseObjectInfoListFromJsonResponse(Json json) { super(json, new TypeLiteral>() { }); - this.uriBuilders = uriBuilders; } public PageSet apply(InputStream stream) { @@ -82,9 +79,9 @@ public class ParseObjectInfoListFromJsonResponse extends ParseJson returnVal = Sets.newTreeSet(Iterables.transform(list, new Function() { public ObjectInfo apply(ObjectInfoImpl from) { - return from.toBuilder().container(container).uri( - uriBuilders.get().uri(request.getEndpoint()).path(from.getName()).replaceQuery("") - .build()).build(); + return from.toBuilder().container(container) + .uri(uriBuilder(request.getEndpoint()).clearQuery().appendPath(from.getName()).build()) + .build(); } })); boolean truncated = options.getMaxResults() == returnVal.size(); diff --git a/apis/swift/src/test/java/org/jclouds/openstack/functions/ParseAuthenticationResponseFromHeadersTest.java b/apis/swift/src/test/java/org/jclouds/openstack/functions/ParseAuthenticationResponseFromHeadersTest.java index 2e92e93d4a..dc161466a6 100644 --- a/apis/swift/src/test/java/org/jclouds/openstack/functions/ParseAuthenticationResponseFromHeadersTest.java +++ b/apis/swift/src/test/java/org/jclouds/openstack/functions/ParseAuthenticationResponseFromHeadersTest.java @@ -22,8 +22,6 @@ import static org.testng.Assert.assertEquals; import java.net.URI; -import javax.ws.rs.core.UriBuilder; - import org.jclouds.Constants; import org.jclouds.blobstore.reference.BlobStoreConstants; import org.jclouds.http.HttpResponse; @@ -35,7 +33,6 @@ import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.name.Names; -import com.sun.jersey.api.uri.UriBuilderImpl; /** * Tests behavior of {@code ParseContainerListFromJsonResponse} @@ -51,7 +48,6 @@ public class ParseAuthenticationResponseFromHeadersTest { protected void configure() { bindConstant().annotatedWith(Names.named(BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX)).to("sdf"); bindConstant().annotatedWith(Names.named(Constants.PROPERTY_API_VERSION)).to("1"); - bind(UriBuilder.class).to(UriBuilderImpl.class); } }); diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/domain/internal/ParseObjectInfoListFromJsonResponseTest.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/domain/internal/ParseObjectInfoListFromJsonResponseTest.java index 8df85a2326..c5f2fa0037 100644 --- a/apis/swift/src/test/java/org/jclouds/openstack/swift/domain/internal/ParseObjectInfoListFromJsonResponseTest.java +++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/domain/internal/ParseObjectInfoListFromJsonResponseTest.java @@ -27,8 +27,6 @@ import java.io.InputStream; import java.net.URI; import java.util.Set; -import javax.ws.rs.core.UriBuilder; - import org.jclouds.crypto.CryptoStreams; import org.jclouds.date.internal.SimpleDateFormatDateService; import org.jclouds.json.config.GsonModule; @@ -45,7 +43,6 @@ import com.google.common.collect.ImmutableSet; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; -import com.sun.jersey.api.uri.UriBuilderImpl; /** * Tests behavior of {@code ParseObjectInfoListFromJsonResponse} @@ -60,7 +57,6 @@ public class ParseObjectInfoListFromJsonResponseTest { @Override protected void configure() { bind(DateAdapter.class).to(Iso8601DateAdapter.class); - bind(UriBuilder.class).to(UriBuilderImpl.class); } }, new GsonModule()); diff --git a/apis/vcloud/src/test/java/org/jclouds/vcloud/binders/BindCloneVAppParamsToXmlPayloadTest.java b/apis/vcloud/src/test/java/org/jclouds/vcloud/binders/BindCloneVAppParamsToXmlPayloadTest.java index b9900ef019..2c239e6924 100644 --- a/apis/vcloud/src/test/java/org/jclouds/vcloud/binders/BindCloneVAppParamsToXmlPayloadTest.java +++ b/apis/vcloud/src/test/java/org/jclouds/vcloud/binders/BindCloneVAppParamsToXmlPayloadTest.java @@ -18,13 +18,8 @@ */ package org.jclouds.vcloud.binders; -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.verify; +import static org.testng.Assert.assertEquals; -import java.io.IOException; -import java.net.URI; import java.util.Properties; import org.jclouds.rest.internal.GeneratedHttpRequest; @@ -33,7 +28,6 @@ import org.jclouds.vcloud.VCloudApiMetadata; import org.jclouds.vcloud.options.CloneVAppOptions; import org.testng.annotations.Test; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap.Builder; import com.google.inject.AbstractModule; @@ -59,36 +53,30 @@ public class BindCloneVAppParamsToXmlPayloadTest { } }); - public void testWithDescriptionDeployOn() throws IOException { + public void testWithDescriptionDeployOn() throws Exception { String expected = Strings2.toStringAndClose(getClass().getResourceAsStream("/copyVApp.xml")); CloneVAppOptions options = new CloneVAppOptions().deploy().powerOn().description( "The description of the new vApp"); - GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class); - expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes(); - expect(request.getArgs()).andReturn(ImmutableList. of(options)).atLeastOnce(); - request.setPayload(expected); - replay(request); + GeneratedHttpRequest request = GeneratedHttpRequest.builder().method("POST").endpoint("http://localhost/key") + .declaring(String.class).javaMethod(String.class.getDeclaredMethod("toString")).arg(options).build(); BindCloneVAppParamsToXmlPayload binder = injector.getInstance(BindCloneVAppParamsToXmlPayload.class); Builder map = ImmutableMap.builder(); map.put("name", "new-linux-server"); map.put("Source", "https://vcenterprise.bluelock.com/api/v1.0/vapp/201"); - binder.bindToRequest(request, map.build()); - verify(request); + assertEquals(binder.bindToRequest(request, map.build()).getPayload().getRawContent(), expected); } - public void testWithDescriptionDeployOnSourceDelete() throws IOException { + public void testWithDescriptionDeployOnSourceDelete() throws Exception { String expected = Strings2.toStringAndClose(getClass().getResourceAsStream("/moveVApp.xml")); CloneVAppOptions options = new CloneVAppOptions().deploy().powerOn().description( "The description of the new vApp"); - GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class); - expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes(); - expect(request.getArgs()).andReturn(ImmutableList. of(options)).atLeastOnce(); - request.setPayload(expected); - replay(request); + GeneratedHttpRequest request = GeneratedHttpRequest.builder().method("POST").endpoint("http://localhost/key") + .declaring(String.class).javaMethod(String.class.getDeclaredMethod("toString")).arg(options).build(); + BindCloneVAppParamsToXmlPayload binder = injector.getInstance(BindCloneVAppParamsToXmlPayload.class); @@ -96,25 +84,21 @@ public class BindCloneVAppParamsToXmlPayloadTest { map.put("name", "new-linux-server"); map.put("Source", "https://vcenterprise.bluelock.com/api/v1.0/vapp/201"); map.put("IsSourceDelete", "true"); - binder.bindToRequest(request, map.build()); - verify(request); + assertEquals(binder.bindToRequest(request, map.build()).getPayload().getRawContent(), expected); } - public void testDefault() throws IOException { + public void testDefault() throws Exception { String expected = Strings2.toStringAndClose(getClass().getResourceAsStream("/copyVApp-default.xml")); - GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class); - expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes(); - expect(request.getArgs()).andReturn(ImmutableList. of()).atLeastOnce(); - request.setPayload(expected); - replay(request); + GeneratedHttpRequest request = GeneratedHttpRequest.builder().method("POST").endpoint("http://localhost/key") + .declaring(String.class).javaMethod(String.class.getDeclaredMethod("toString")).build(); + BindCloneVAppParamsToXmlPayload binder = injector.getInstance(BindCloneVAppParamsToXmlPayload.class); Builder map = ImmutableMap.builder(); map.put("name", "my-vapp"); map.put("Source", "https://vcenterprise.bluelock.com/api/v1.0/vapp/4181"); - binder.bindToRequest(request, map.build()); - verify(request); + assertEquals(binder.bindToRequest(request, map.build()).getPayload().getRawContent(), expected); } } diff --git a/apis/walrus/src/main/java/org/jclouds/walrus/WalrusAsyncClient.java b/apis/walrus/src/main/java/org/jclouds/walrus/WalrusAsyncClient.java index 8b90f49cd5..35e1f19db2 100644 --- a/apis/walrus/src/main/java/org/jclouds/walrus/WalrusAsyncClient.java +++ b/apis/walrus/src/main/java/org/jclouds/walrus/WalrusAsyncClient.java @@ -31,7 +31,6 @@ import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.ParamValidators; import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.s3.Bucket; import org.jclouds.s3.S3AsyncClient; import org.jclouds.s3.S3Client; @@ -45,7 +44,6 @@ import com.google.common.util.concurrent.ListenableFuture; * * @author Adrian Cole */ -@SkipEncoding('/') @RequestFilters(RequestAuthorizeSignature.class) @BlobScope(CONTAINER) public interface WalrusAsyncClient extends S3AsyncClient { diff --git a/archetypes/rest-client-archetype/src/main/resources/archetype-resources/src/main/java/features/KeyAsyncApi.java b/archetypes/rest-client-archetype/src/main/resources/archetype-resources/src/main/java/features/KeyAsyncApi.java index b572292607..7528b9e241 100644 --- a/archetypes/rest-client-archetype/src/main/resources/archetype-resources/src/main/java/features/KeyAsyncApi.java +++ b/archetypes/rest-client-archetype/src/main/resources/archetype-resources/src/main/java/features/KeyAsyncApi.java @@ -37,7 +37,6 @@ import org.jclouds.rest.annotations.BinderParam; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.binders.BindToJsonPayload; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; @@ -50,7 +49,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @see KeyApi * @see api doc */ -@SkipEncoding({ '/', '=' }) @Headers(keys = "X-Api-Version", values = "{jclouds.api-version}") @RequestFilters(BasicAuthentication.class) public interface KeyAsyncApi { diff --git a/blobstore/src/main/java/org/jclouds/blobstore/TransientStorageStrategy.java b/blobstore/src/main/java/org/jclouds/blobstore/TransientStorageStrategy.java index a4506fc217..7ff3b5a4d1 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/TransientStorageStrategy.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/TransientStorageStrategy.java @@ -27,15 +27,9 @@ import java.util.Date; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import javax.inject.Provider; + import javax.inject.Inject; import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.UriBuilder; - -import com.google.common.base.Preconditions; -import com.google.common.base.Supplier; -import com.google.common.base.Throwables; -import com.google.common.collect.Multimaps; import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob.Factory; @@ -47,6 +41,7 @@ import org.jclouds.crypto.CryptoStreams; import org.jclouds.date.DateService; import org.jclouds.domain.Location; import org.jclouds.http.HttpUtils; +import static org.jclouds.http.Uris.*; import org.jclouds.io.ContentMetadataCodec; import org.jclouds.io.MutableContentMetadata; import org.jclouds.io.Payload; @@ -54,6 +49,11 @@ import org.jclouds.io.Payloads; import org.jclouds.io.payloads.ByteArrayPayload; import org.jclouds.io.payloads.DelegatingPayload; +import com.google.common.base.Supplier; +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Multimaps; + public class TransientStorageStrategy implements LocalStorageStrategy { private final ConcurrentMap> containerToBlobs = new ConcurrentHashMap>(); private final ConcurrentMap containerToLocation = new ConcurrentHashMap(); @@ -62,19 +62,15 @@ public class TransientStorageStrategy implements LocalStorageStrategy { private final Factory blobFactory; private final Crypto crypto; private final ContentMetadataCodec contentMetadataCodec; - private final Provider uriBuilders; @Inject - TransientStorageStrategy(final Supplier defaultLocation, - DateService dateService, Factory blobFactory, Crypto crypto, - ContentMetadataCodec contentMetadataCodec, - Provider uriBuilders) { + TransientStorageStrategy(Supplier defaultLocation, DateService dateService, Factory blobFactory, + Crypto crypto, ContentMetadataCodec contentMetadataCodec) { this.defaultLocation = defaultLocation; this.dateService = dateService; this.blobFactory = blobFactory; this.crypto = crypto; this.contentMetadataCodec = contentMetadataCodec; - this.uriBuilders = uriBuilders; } @Override @@ -185,7 +181,7 @@ public class TransientStorageStrategy implements LocalStorageStrategy { blob.setPayload(payload); blob.getMetadata().setContainer(containerName); blob.getMetadata().setUri( - uriBuilders.get().scheme("mem").host(containerName).path(in.getMetadata().getName()).build()); + uriBuilder(new StringBuilder("mem://").append(containerName)).path(in.getMetadata().getName()).build()); blob.getMetadata().setLastModified(new Date()); String eTag = CryptoStreams.hex(payload.getContentMetadata().getContentMD5()); blob.getMetadata().setETag(eTag); diff --git a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobIntegrationTest.java b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobIntegrationTest.java index 2026bf8d0d..5c162ecb06 100644 --- a/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobIntegrationTest.java +++ b/blobstore/src/test/java/org/jclouds/blobstore/integration/internal/BaseBlobIntegrationTest.java @@ -363,51 +363,6 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { } } - // @Test(groups = { "integration", "live" }) - // public void testGetTail() throws InterruptedException, ExecutionException, - // TimeoutException, - // IOException { - // String container = getContainerName(); - // try { - // - // String name = "apples"; - // - // addObjectAndValidateContent(container, name); - // Blob blob = context.getBlobStore().getBlob(container, name, - // tail(5)).get(30, - // TimeUnit.SECONDS); - // assertEquals(BlobStoreUtils.getContentAsStringAndClose(blob), TEST_STRING - // .substring(TEST_STRING.length() - 5)); - // assertEquals(blob.getContentLength(), 5); - // assertEquals(blob.getMetadata().getSize(), TEST_STRING.length()); - // } finally { - // returnContainer(container); - // } - // } - - // @Test(groups = { "integration", "live" }) - // public void testGetStartAt() throws InterruptedException, - // ExecutionException, - // TimeoutException, - // IOException { - // String container = getContainerName(); - // try { - // String name = "apples"; - // - // addObjectAndValidateContent(container, name); - // Blob blob = context.getBlobStore().getBlob(container, name, - // startAt(5)).get(30, - // TimeUnit.SECONDS); - // assertEquals(BlobStoreUtils.getContentAsStringAndClose(blob), - // TEST_STRING.substring(5, - // TEST_STRING.length())); - // assertEquals(blob.getContentLength(), TEST_STRING.length() - 5); - // assertEquals(blob.getMetadata().getSize(), TEST_STRING.length()); - // } finally { - // returnContainer(container); - // } - // } - private String addObjectAndValidateContent(String sourcecontainer, String sourceKey) throws InterruptedException { String eTag = addBlobToContainer(sourcecontainer, sourceKey); validateContent(sourcecontainer, sourceKey); @@ -646,4 +601,4 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest { assertEquals(metadata.getContentMetadata().getContentMD5(), CryptoStreams.md5(InputSuppliers.of(TEST_STRING))); } -} \ No newline at end of file +} diff --git a/common/aws/src/main/java/org/jclouds/aws/filters/FormSigner.java b/common/aws/src/main/java/org/jclouds/aws/filters/FormSigner.java index 072a7f0f8c..2cc05c9923 100644 --- a/common/aws/src/main/java/org/jclouds/aws/filters/FormSigner.java +++ b/common/aws/src/main/java/org/jclouds/aws/filters/FormSigner.java @@ -20,6 +20,7 @@ package org.jclouds.aws.filters; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; +import static com.google.common.collect.Ordering.natural; import static org.jclouds.aws.reference.FormParameters.ACTION; import static org.jclouds.aws.reference.FormParameters.AWS_ACCESS_KEY_ID; import static org.jclouds.aws.reference.FormParameters.SIGNATURE; @@ -27,11 +28,14 @@ import static org.jclouds.aws.reference.FormParameters.SIGNATURE_METHOD; import static org.jclouds.aws.reference.FormParameters.SIGNATURE_VERSION; import static org.jclouds.aws.reference.FormParameters.TIMESTAMP; import static org.jclouds.aws.reference.FormParameters.VERSION; +import static org.jclouds.crypto.CryptoStreams.base64; +import static org.jclouds.crypto.CryptoStreams.mac; +import static org.jclouds.http.utils.Queries.encodeQueryLine; +import static org.jclouds.http.utils.Queries.queryParser; +import static org.jclouds.util.Strings2.toInputStream; -import java.util.Arrays; import java.util.Comparator; -import java.util.Map; -import java.util.Map.Entry; +import java.util.Set; import javax.annotation.Resource; import javax.inject.Inject; @@ -42,31 +46,29 @@ import javax.ws.rs.core.HttpHeaders; import org.jclouds.Constants; import org.jclouds.crypto.Crypto; -import org.jclouds.crypto.CryptoStreams; import org.jclouds.date.TimeStamp; import org.jclouds.http.HttpException; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpUtils; import org.jclouds.http.internal.SignatureWire; -import org.jclouds.http.utils.Queries; import org.jclouds.io.InputSuppliers; import org.jclouds.logging.Logger; import org.jclouds.rest.RequestSigner; import org.jclouds.rest.annotations.ApiVersion; import org.jclouds.rest.annotations.Credential; import org.jclouds.rest.annotations.Identity; -import org.jclouds.util.Strings2; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; +import com.google.common.collect.TreeMultimap; /** * * @see * @author Adrian Cole * @@ -74,8 +76,9 @@ import com.google.common.collect.Multimap; @Singleton public class FormSigner implements HttpRequestFilter, RequestSigner { - public static String[] mandatoryParametersForSignature = new String[] { ACTION, SIGNATURE_METHOD, SIGNATURE_VERSION, - VERSION }; + public static final Set mandatoryParametersForSignature = ImmutableSet.of(ACTION, SIGNATURE_METHOD, + SIGNATURE_VERSION, VERSION); + private final SignatureWire signatureWire; private final String apiVersion; private final String accessKey; @@ -103,8 +106,7 @@ public class FormSigner implements HttpRequestFilter, RequestSigner { public HttpRequest filter(HttpRequest request) throws HttpException { checkNotNull(request.getFirstHeaderOrNull(HttpHeaders.HOST), "request is not ready to sign; host not present"); - Multimap decodedParams = Queries.parseQueryToMap(request.getPayload().getRawContent() - .toString()); + Multimap decodedParams = queryParser().apply(request.getPayload().getRawContent().toString()); decodedParams.replaceValues(VERSION, ImmutableSet.of(apiVersion)); addSigningParams(decodedParams); validateParams(decodedParams); @@ -115,36 +117,39 @@ public class FormSigner implements HttpRequestFilter, RequestSigner { utils.logRequest(signatureLog, request, "<<"); return request; } - - String[] sortForSigning(String queryLine) { - String[] parts = queryLine.split("&"); - // 1. Sort the UTF-8 query string components by parameter name with natural byte ordering. - Arrays.sort(parts, new Comparator() { - - public int compare(String o1, String o2) { - if (o1.startsWith("AWSAccessKeyId")) - return -1; - return o1.compareTo(o2); - } - - }); - return parts; - } - + HttpRequest setPayload(HttpRequest request, Multimap decodedParams) { - request.setPayload(Queries.makeQueryLine(decodedParams, new Comparator>() { - public int compare(Entry o1, Entry o2) { - if (o1.getKey().startsWith("Action") || o2.getKey().startsWith("AWSAccessKeyId")) - return -1; - if (o1.getKey().startsWith("AWSAccessKeyId") || o2.getKey().startsWith("Action")) - return 1; - return o1.getKey().compareTo(o2.getKey()); - } - })); + String queryLine = buildQueryLine(decodedParams); + request.setPayload(queryLine); request.getPayload().getContentMetadata().setContentType("application/x-www-form-urlencoded"); return request; } + private static final Comparator actionFirstAccessKeyLast = new Comparator() { + static final int LEFT_IS_GREATER = 1; + static final int RIGHT_IS_GREATER = -1; + + @Override + public int compare(String left, String right) { + if (left == right) { + return 0; + } + if ("Action".equals(right) || "AWSAccessKeyId".equals(left)) { + return LEFT_IS_GREATER; + } + if ("Action".equals(left) || "AWSAccessKeyId".equals(right)) { + return RIGHT_IS_GREATER; + } + return natural().compare(left, right); + } + }; + + private static String buildQueryLine(Multimap decodedParams) { + Multimap sortedParams = TreeMultimap.create(actionFirstAccessKeyLast, natural()); + sortedParams.putAll(decodedParams); + return encodeQueryLine(sortedParams); + } + @VisibleForTesting void validateParams(Multimap params) { for (String parameter : mandatoryParametersForSignature) { @@ -161,10 +166,9 @@ public class FormSigner implements HttpRequestFilter, RequestSigner { public String sign(String stringToSign) { String signature; try { - signature = CryptoStreams.base64(CryptoStreams.mac(InputSuppliers.of(stringToSign), crypto - .hmacSHA256(secretKey.getBytes()))); + signature = base64(mac(InputSuppliers.of(stringToSign), crypto.hmacSHA256(secretKey.getBytes()))); if (signatureWire.enabled()) - signatureWire.input(Strings2.toInputStream(signature)); + signatureWire.input(toInputStream(signature)); } catch (Exception e) { throw new HttpException("error signing request", e); } @@ -190,16 +194,10 @@ public class FormSigner implements HttpRequestFilter, RequestSigner { @VisibleForTesting String buildCanonicalizedString(Multimap decodedParams) { - return Queries.makeQueryLine(decodedParams, sortAWSFirst); + // note that aws wants to percent encode the canonicalized string without skipping '/' and '?' + return encodeQueryLine(TreeMultimap.create(decodedParams), ImmutableList. of()); } - public static final Comparator> sortAWSFirst = new Comparator>() { - public int compare(Map.Entry o1, Map.Entry o2) { - if (o1.getKey().startsWith("AWSAccessKeyId")) - return -1; - return o1.getKey().compareTo(o2.getKey()); - } - }; @VisibleForTesting void addSigningParams(Multimap params) { @@ -211,7 +209,7 @@ public class FormSigner implements HttpRequestFilter, RequestSigner { } public String createStringToSign(HttpRequest input) { - return createStringToSign(input, Queries.parseQueryToMap(input.getPayload().getRawContent().toString())); + return createStringToSign(input, queryParser().apply(input.getPayload().getRawContent().toString())); } } diff --git a/common/aws/src/test/java/org/jclouds/aws/filters/FormSignerTest.java b/common/aws/src/test/java/org/jclouds/aws/filters/FormSignerTest.java index cc03882ed8..6f7d551470 100644 --- a/common/aws/src/test/java/org/jclouds/aws/filters/FormSignerTest.java +++ b/common/aws/src/test/java/org/jclouds/aws/filters/FormSignerTest.java @@ -77,7 +77,7 @@ public class FormSignerTest { .addHeader(HttpHeaders.HOST, "localhost") .payload("Action=DescribeImages&ImageId.1=ami-2bb65342").build()) .getPayload().getRawContent(), - "Action=DescribeImages&ImageId.1=ami-2bb65342&Signature=ugnt4m2eHE7Ka%2FvXTr9EhKZq7bhxOfvW0y4pAEqF97w%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2009-11-08T15%3A54%3A08.897Z&Version=apiVersion&AWSAccessKeyId=identity"); + "Action=DescribeImages&ImageId.1=ami-2bb65342&Signature=ugnt4m2eHE7Ka/vXTr9EhKZq7bhxOfvW0y4pAEqF97w%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2009-11-08T15%3A54%3A08.897Z&Version=apiVersion&AWSAccessKeyId=identity"); } @Test @@ -90,4 +90,4 @@ public class FormSignerTest { "AWSAccessKeyId=foo&Action=DescribeImages&Expires=2008-02-10T12%3A00%3A00Z&ImageId.1=ami-2bb65342&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2010-06-15"); } -} \ No newline at end of file +} diff --git a/common/openstack/src/main/java/org/jclouds/openstack/functions/ParseAuthenticationResponseFromHeaders.java b/common/openstack/src/main/java/org/jclouds/openstack/functions/ParseAuthenticationResponseFromHeaders.java index 9b68139a8d..60bcfebafa 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/functions/ParseAuthenticationResponseFromHeaders.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/functions/ParseAuthenticationResponseFromHeaders.java @@ -20,6 +20,7 @@ package org.jclouds.openstack.functions; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.http.HttpUtils.releasePayload; +import static org.jclouds.http.Uris.uriBuilder; import static org.jclouds.openstack.reference.AuthHeaders.AUTH_TOKEN; import static org.jclouds.openstack.reference.AuthHeaders.URL_SUFFIX; @@ -27,9 +28,6 @@ import java.net.URI; import java.util.Map.Entry; import javax.annotation.Resource; -import javax.inject.Inject; -import javax.inject.Provider; -import javax.ws.rs.core.UriBuilder; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; @@ -53,14 +51,8 @@ public class ParseAuthenticationResponseFromHeaders implements Function uriBuilderProvider; private String hostToReplace; - @Inject - public ParseAuthenticationResponseFromHeaders(Provider uriBuilderProvider) { - this.uriBuilderProvider = uriBuilderProvider; - } - /** * parses the http response headers to create a new {@link AuthenticationResponse} object. */ @@ -84,7 +76,7 @@ public class ParseAuthenticationResponseFromHeaders implements Function of(options)).atLeastOnce(); - request.setPayload(expected); - replay(request); + GeneratedHttpRequest request = GeneratedHttpRequest.builder().method("POST").endpoint("http://localhost/key") + .declaring(String.class).javaMethod(String.class.getDeclaredMethod("toString")).arg(options).build(); + BindCloneVAppParamsToXmlPayload binder = injector.getInstance(BindCloneVAppParamsToXmlPayload.class); Map map = Maps.newHashMap(); map.put("newName", "new-linux-server"); map.put("vApp", "https://vcloud.safesecureweb.com/api/v0.8/vapp/201"); - binder.bindToRequest(request, map); - verify(request); + assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected); } - public void testDefault() throws IOException { + public void testDefault() throws Exception { String expected = Strings2.toStringAndClose(getClass().getResourceAsStream("/cloneVApp-default.xml")); - GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class); - expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes(); - expect(request.getArgs()).andReturn(ImmutableList. of()).atLeastOnce(); - request.setPayload(expected); - replay(request); + GeneratedHttpRequest request = GeneratedHttpRequest.builder().method("POST").endpoint("http://localhost/key") + .declaring(String.class).javaMethod(String.class.getDeclaredMethod("toString")).build(); BindCloneVAppParamsToXmlPayload binder = injector.getInstance(BindCloneVAppParamsToXmlPayload.class); Map map = Maps.newHashMap(); map.put("newName", "my-vapp"); map.put("vApp", "https://vcloud.safesecureweb.com/api/v0.8/vapp/4181"); - binder.bindToRequest(request, map); - verify(request); + assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected); } } diff --git a/core/pom.xml b/core/pom.xml index 06f5e23654..a7280b78f3 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -53,9 +53,9 @@ 1.46 - com.sun.jersey - jersey-core - 1.12 + javax.ws.rs + jsr311-api + 1.1.1 com.google.inject.extensions diff --git a/core/src/main/java/org/jclouds/http/HttpRequest.java b/core/src/main/java/org/jclouds/http/HttpRequest.java index cc14b31893..1b03a51065 100644 --- a/core/src/main/java/org/jclouds/http/HttpRequest.java +++ b/core/src/main/java/org/jclouds/http/HttpRequest.java @@ -20,14 +20,14 @@ package org.jclouds.http; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import static org.jclouds.http.utils.Queries.makeQueryLine; -import static org.jclouds.http.utils.Queries.parseQueryToMap; +import static org.jclouds.http.Uris.uriBuilder; +import static org.jclouds.http.utils.Queries.queryParser; import static org.jclouds.io.Payloads.newUrlEncodedFormPayload; -import static org.jclouds.util.Multimaps2.replaceEntries; import java.net.URI; import java.util.Collections; import java.util.List; +import java.util.Map; import org.jclouds.io.Payload; import org.jclouds.javax.annotation.Nullable; @@ -36,10 +36,9 @@ import com.google.common.base.Objects; import com.google.common.base.Objects.ToStringHelper; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.Iterables; +import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Multimap; -import com.google.common.primitives.Chars; -import com.sun.jersey.api.uri.UriBuilderImpl; +import com.google.common.collect.Multimaps; /** * Represents a request that can be executed within {@link HttpCommandExecutorService} @@ -59,7 +58,6 @@ public class HttpRequest extends HttpMessage { public static abstract class Builder> extends HttpMessage.Builder { protected String method; protected URI endpoint; - protected ImmutableList.Builder skips = ImmutableList.builder(); protected ImmutableList.Builder filters = ImmutableList.builder(); /** @@ -89,68 +87,64 @@ public class HttpRequest extends HttpMessage { * @see HttpRequest#getEndpoint() */ public T addQueryParam(String name, Iterable values) { - return addQueryParam(name, Iterables.toArray(checkNotNull(values, "values of %s", name), String.class)); + endpoint = uriBuilder(endpoint).addQuery(name, values).build(); + return self(); } /** * @see HttpRequest#getEndpoint() */ public T addQueryParam(String name, String... values) { - return addQueryParams(ImmutableMultimap. builder() - .putAll(checkNotNull(name, "name"), checkNotNull(values, "values of %s", name)).build()); - } - - /** - * @see HttpRequest#getEndpoint() - */ - public T addQueryParams(Multimap parameters) { - checkNotNull(endpoint, "endpoint"); - Multimap map = parseQueryToMap(endpoint.getQuery()); - map = ImmutableMultimap.builder().putAll(map).putAll(parameters).build(); - return replaceQuery(map); - } - - /** - * @see HttpRequest#getEndpoint() - */ - public T replaceQueryParam(String name, Iterable values) { - return replaceQueryParam(name, Iterables.toArray(checkNotNull(values, "values of %s", name), String.class)); - } - - /** - * @see HttpRequest#getEndpoint() - */ - public T replaceQueryParam(String name, String... values) { - return replaceQueryParams(ImmutableMultimap. builder() - .putAll(checkNotNull(name, "name"), checkNotNull(values, "values of %s", name)).build()); - } - - /** - * @see HttpRequest#getEndpoint() - */ - public T replaceQueryParams(Multimap parameters) { - checkNotNull(endpoint, "endpoint"); - Multimap map = replaceEntries(parseQueryToMap(endpoint.getRawQuery()), parameters); - return replaceQuery(map); - } - - @SuppressWarnings("unchecked") - private T replaceQuery(Multimap map) { - URI oldURI = endpoint; - String query = makeQueryLine(map, null, Chars.toArray(skips.build())); - endpoint = new UriBuilderImpl().uri(oldURI).replaceQuery(query).buildFromEncodedMap(Collections.EMPTY_MAP); + endpoint = uriBuilder(endpoint).addQuery(name, values).build(); + return self(); + } + + /** + * @see HttpRequest#getEndpoint() + */ + public T addQueryParams(Multimap parameters) { + endpoint = uriBuilder(endpoint).addQuery(parameters).build(); + return self(); + } + + /** + * @see HttpRequest#getEndpoint() + */ + public T replaceQueryParam(String name, Iterable values) { + endpoint = uriBuilder(endpoint).replaceQuery(name, values).build(); + return self(); + } + + /** + * @see HttpRequest#getEndpoint() + */ + public T replaceQueryParam(String name, String... values) { + endpoint = uriBuilder(endpoint).replaceQuery(name, values).build(); + return self(); + } + + /** + * @see HttpRequest#getEndpoint() + */ + public T replaceQueryParams(Map parameters) { + return replaceQueryParams(Multimaps.forMap(parameters)); + } + + /** + * @see HttpRequest#getEndpoint() + */ + public T replaceQueryParams(Multimap parameters) { + endpoint = uriBuilder(endpoint).replaceQuery(parameters).build(); return self(); } /** * @see HttpRequest#getEndpoint() */ - @SuppressWarnings("unchecked") public T replacePath(String path) { checkNotNull(endpoint, "endpoint"); checkNotNull(path, "path"); - URI oldURI = endpoint; - endpoint = new UriBuilderImpl().uri(oldURI).replacePath(path).buildFromEncodedMap(Collections.EMPTY_MAP); + endpoint = uriBuilder(endpoint).path(path).build(); return self(); } @@ -170,9 +164,9 @@ public class HttpRequest extends HttpMessage { */ public T addFormParams(Multimap parameters) { checkNotNull(endpoint, "endpoint"); - Multimap map = payload != null ? parseQueryToMap(payload.getRawContent() - .toString()) : ImmutableMultimap. of(); - map = ImmutableMultimap.builder().putAll(map).putAll(parameters).build(); + Multimap map = payload != null ? queryParser().apply(payload.getRawContent().toString()) + : LinkedHashMultimap. create(); + map.putAll(parameters); payload = newUrlEncodedFormPayload(map); return self(); } @@ -193,21 +187,15 @@ public class HttpRequest extends HttpMessage { */ public T replaceFormParams(Multimap parameters) { checkNotNull(endpoint, "endpoint"); - Multimap map = replaceEntries(payload != null ? parseQueryToMap(payload.getRawContent() - .toString()) : ImmutableMultimap. of(), parameters); + Multimap map = payload != null ? queryParser().apply(payload.getRawContent().toString()) + : LinkedHashMultimap. create(); + for (String key : parameters.keySet()) { + map.replaceValues(key, parameters.get(key)); + } payload = newUrlEncodedFormPayload(map); return self(); } - /** - * @see HttpRequest#getSkips() - */ - public T skips(char[] skips) { - this.skips = ImmutableList.builder(); - this.skips.addAll(Chars.asList(checkNotNull(skips, "skips"))); - return self(); - } - /** * @see HttpRequest#getFilters() */ @@ -226,14 +214,13 @@ public class HttpRequest extends HttpMessage { } public HttpRequest build() { - return new HttpRequest(method, endpoint, headers.build(), payload, skips.build(), filters.build()); + return new HttpRequest(method, endpoint, headers.build(), payload, filters.build()); } public T fromHttpRequest(HttpRequest in) { return super.fromHttpMessage(in) .method(in.getMethod()) .endpoint(in.getEndpoint()) - .skips(in.getSkips()) .filters(in.getFilters()); } } @@ -247,16 +234,14 @@ public class HttpRequest extends HttpMessage { private final String method; private final URI endpoint; - private final List skips; private final List filters; protected HttpRequest(String method, URI endpoint, Multimap headers, @Nullable Payload payload, - Iterable skips, Iterable filters) { + Iterable filters) { super(headers, payload); this.method = checkNotNull(method, "method"); this.endpoint = checkNotNull(endpoint, "endpoint"); checkArgument(endpoint.getHost() != null, String.format("endpoint.getHost() is null for %s", endpoint)); - this.skips = ImmutableList. copyOf(checkNotNull(skips, "skips")); this.filters = ImmutableList. copyOf(checkNotNull(filters, "filters")); } @@ -278,13 +263,6 @@ public class HttpRequest extends HttpMessage { return endpoint; } - /** - * characters to skip encoding on. - */ - public char[] getSkips() { - return Chars.toArray(skips); - } - public List getFilters() { return filters; } diff --git a/core/src/main/java/org/jclouds/http/HttpUtils.java b/core/src/main/java/org/jclouds/http/HttpUtils.java index 43d1de5605..114f1a321c 100644 --- a/core/src/main/java/org/jclouds/http/HttpUtils.java +++ b/core/src/main/java/org/jclouds/http/HttpUtils.java @@ -19,30 +19,25 @@ package org.jclouds.http; import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Throwables.getCausalChain; import static com.google.common.base.Throwables.propagate; import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Iterables.get; import static com.google.common.collect.Iterables.size; -import static com.google.common.collect.Lists.newArrayList; import static com.google.common.io.ByteStreams.toByteArray; import static com.google.common.io.Closeables.closeQuietly; -import static javax.ws.rs.core.HttpHeaders.CONTENT_ENCODING; -import static javax.ws.rs.core.HttpHeaders.CONTENT_LANGUAGE; -import static javax.ws.rs.core.HttpHeaders.CONTENT_LENGTH; -import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE; -import static javax.ws.rs.core.HttpHeaders.EXPIRES; -import static org.jclouds.util.Patterns.PATTERN_THAT_BREAKS_URI; -import static org.jclouds.util.Patterns.URI_PATTERN; +import static com.google.common.net.HttpHeaders.CONTENT_DISPOSITION; +import static com.google.common.net.HttpHeaders.CONTENT_ENCODING; +import static com.google.common.net.HttpHeaders.CONTENT_LANGUAGE; +import static com.google.common.net.HttpHeaders.CONTENT_LENGTH; +import static com.google.common.net.HttpHeaders.CONTENT_MD5; +import static com.google.common.net.HttpHeaders.CONTENT_TYPE; +import static com.google.common.net.HttpHeaders.EXPIRES; import java.io.IOException; import java.io.InputStream; -import java.net.URI; import java.util.Collection; -import java.util.List; import java.util.Map.Entry; -import java.util.regex.Matcher; import javax.inject.Named; import javax.inject.Singleton; @@ -57,14 +52,8 @@ import org.jclouds.io.PayloadEnclosing; import org.jclouds.io.Payloads; import org.jclouds.logging.Logger; import org.jclouds.logging.internal.Wire; -import org.jclouds.util.Strings2; -import com.google.common.base.Joiner; import com.google.common.base.Predicate; -import com.google.common.base.Splitter; -import com.google.common.collect.Multimap; -import com.google.common.collect.SortedSetMultimap; -import com.google.common.collect.TreeMultimap; import com.google.inject.Inject; /** @@ -169,18 +158,6 @@ public class HttpUtils { return globalMaxConnectionsPerHost; } - /** - * keys to the map are only used for socket information, not path. In this case, you should - * remove any path or query details from the URI. - */ - public static URI createBaseEndpointFor(URI endpoint) { - if (endpoint.getPort() == -1) { - return URI.create(String.format("%s://%s", endpoint.getScheme(), endpoint.getHost())); - } else { - return URI.create(String.format("%s://%s:%d", endpoint.getScheme(), endpoint.getHost(), endpoint.getPort())); - } - } - public static byte[] toByteArrayOrNull(PayloadEnclosing response) { if (response.getPayload() != null) { InputStream input = response.getPayload().getInput(); @@ -222,70 +199,6 @@ public class HttpUtils { toMd.setExpires(fromMd.getExpires()); } - public static URI parseEndPoint(String hostHeader) { - URI redirectURI = URI.create(hostHeader); - String scheme = redirectURI.getScheme(); - - checkState(redirectURI.getScheme().startsWith("http"), - String.format("header %s didn't parse an http scheme: [%s]", hostHeader, scheme)); - int port = redirectURI.getPort() > 0 ? redirectURI.getPort() : redirectURI.getScheme().equals("https") ? 443 : 80; - String host = redirectURI.getHost(); - checkState(host.indexOf('/') == -1, - String.format("header %s didn't parse an http host correctly: [%s]", hostHeader, host)); - URI endPoint = URI.create(String.format("%s://%s:%d", scheme, host, port)); - return endPoint; - } - - public static URI replaceHostInEndPoint(URI endPoint, String host) { - return URI.create(endPoint.toString().replace(endPoint.getHost(), host)); - } - - /** - * Used to extract the URI and authentication data from a String. Note that the java URI class - * breaks, if there are special characters like '/' present. Otherwise, we wouldn't need this - * class, and we could simply use URI.create("uri").getUserData(); Also, URI breaks if there are - * curly braces. - * - */ - public static URI createUri(String uriPath) { - List onQuery = newArrayList(Splitter.on('?').split(uriPath)); - if (onQuery.size() == 2) { - onQuery.add(Strings2.urlEncode(onQuery.remove(1), '=', '&')); - uriPath = Joiner.on('?').join(onQuery); - } - if (uriPath.indexOf('@') != 1) { - List parts = newArrayList(Splitter.on('@').split(uriPath)); - String path = parts.remove(parts.size() - 1); - if (parts.size() > 1) { - parts = newArrayList(Strings2.urlEncode(Joiner.on('@').join(parts), '/', ':')); - } - parts.add(Strings2.urlEncode(path, '/', ':')); - uriPath = Joiner.on('@').join(parts); - } else { - List parts = newArrayList(Splitter.on('/').split(uriPath)); - String path = parts.remove(parts.size() - 1); - parts.add(Strings2.urlEncode(path, ':')); - uriPath = Joiner.on('/').join(parts); - } - - if (PATTERN_THAT_BREAKS_URI.matcher(uriPath).matches()) { - // Compile and use regular expression - Matcher matcher = URI_PATTERN.matcher(uriPath); - if (matcher.find()) { - String scheme = matcher.group(1); - String rest = matcher.group(4); - String identity = matcher.group(2); - String key = matcher.group(3); - return URI.create(String.format("%s://%s:%s@%s", scheme, Strings2.urlEncode(identity), - Strings2.urlEncode(key), rest)); - } else { - throw new IllegalArgumentException("bad syntax"); - } - } else { - return URI.create(uriPath); - } - } - public void logRequest(Logger logger, HttpRequest request, String prefix) { if (logger.isDebugEnabled()) { logger.debug("%s %s", prefix, request.getRequestLine().toString()); @@ -304,19 +217,11 @@ public class HttpUtils { if (message.getPayload().getContentMetadata().getContentLength() != null) logger.debug("%s %s: %s", prefix, CONTENT_LENGTH, message.getPayload().getContentMetadata() .getContentLength()); - if (message.getPayload().getContentMetadata().getContentMD5() != null) - try { - logger.debug( - "%s %s: %s", - prefix, - "Content-MD5", - CryptoStreams.base64Encode(InputSuppliers.of(message.getPayload().getContentMetadata() - .getContentMD5()))); - } catch (IOException e) { - logger.warn(e, " error getting md5 for %s", message); - } + byte[] md5 = message.getPayload().getContentMetadata().getContentMD5(); + if (md5 != null) + logger.debug("%s %s: %s", prefix, CONTENT_MD5, CryptoStreams.base64(md5)); if (message.getPayload().getContentMetadata().getContentDisposition() != null) - logger.debug("%s %s: %s", prefix, "Content-Disposition", message.getPayload().getContentMetadata() + logger.debug("%s %s: %s", prefix, CONTENT_DISPOSITION, message.getPayload().getContentMetadata() .getContentDisposition()); if (message.getPayload().getContentMetadata().getContentEncoding() != null) logger.debug("%s %s: %s", prefix, CONTENT_ENCODING, message.getPayload().getContentMetadata() @@ -337,17 +242,6 @@ public class HttpUtils { } } - public static String sortAndConcatHeadersIntoString(Multimap headers) { - StringBuilder buffer = new StringBuilder(); - SortedSetMultimap sortedMap = TreeMultimap.create(); - sortedMap.putAll(headers); - for (Entry header : sortedMap.entries()) { - if (header.getKey() != null) - buffer.append(String.format("%s: %s\n", header.getKey(), header.getValue())); - } - return buffer.toString(); - } - public void checkRequestHasRequiredProperties(HttpRequest message) { checkArgument( message.getPayload() == null || message.getFirstHeaderOrNull(CONTENT_TYPE) == null, diff --git a/core/src/main/java/org/jclouds/http/UriTemplates.java b/core/src/main/java/org/jclouds/http/UriTemplates.java new file mode 100644 index 0000000000..7e554400e6 --- /dev/null +++ b/core/src/main/java/org/jclouds/http/UriTemplates.java @@ -0,0 +1,75 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.http; + +import static com.google.common.base.Preconditions.*; + +import java.util.Map; + +import com.google.common.collect.Lists; + +/** + * + * @author Adrian Cole + * + */ +public class UriTemplates { + + /** + * + * @param template + * URI template that can be in level 1 RFC6570 form. + * + * @param variables + * to the URI template + * @return expanded template, leaving any unresolved parameters literal + */ + public static String expand(String template, Map variables) { + if (checkNotNull(template, "template").length() < 3) + return template.toString(); // skip expansion if there's no valid variables set. ex. {a} is the first valid + checkNotNull(variables, "variables for %s", template); + + boolean inVar = false; + StringBuilder var = new StringBuilder(); + StringBuilder builder = new StringBuilder(); + for (char c : Lists.charactersOf(template)) { + switch (c) { + case '{': + inVar = true; + break; + case '}': + inVar = false; + String key = var.toString(); + Object value = variables.get(var.toString()); + if (value != null) + builder.append(value); + else + builder.append('{').append(key).append('}'); + var = new StringBuilder(); + break; + default: + if (inVar) + var.append(c); + else + builder.append(c); + } + } + return builder.toString(); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/http/Uris.java b/core/src/main/java/org/jclouds/http/Uris.java new file mode 100644 index 0000000000..f8a66bf378 --- /dev/null +++ b/core/src/main/java/org/jclouds/http/Uris.java @@ -0,0 +1,441 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.http; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Strings.emptyToNull; +import static com.google.common.collect.Multimaps.forMap; +import static org.jclouds.http.utils.Queries.buildQueryLine; +import static org.jclouds.http.utils.Queries.encodeQueryLine; +import static org.jclouds.http.utils.Queries.queryParser; +import static org.jclouds.util.Strings2.urlDecode; +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; + +/** + * Functions on {@code String}s and {@link URI}s. Strings can be level 1 RFC6570 form. + * + * ex. + * + *
+ *  https://api.github.com/repos/{user}
+ * 
+ * + *

Reminder

+ * + * Unresolved RFC6570 templates are not supported by + * {@link URI#create(String)} and result in an {@link IllegalArgumentException}. + * + *

Limitations

+ * + * In order to reduce complexity not needed in jclouds, this doesn't support {@link URI#getUserInfo()}, + * {@link URI#getFragment()}, or {@code matrix} params. Matrix params can be achieved via adding {@code ;} refs in the + * http path directly. Moreover, since jclouds only uses level 1 templates, this doesn't support the additional forms + * noted in the RFC. + * + * @since 1.6 + * + * @author Adrian Cole + * + */ +@Beta +public final class Uris { + + /** + * @param template + * URI string that can be in level 1 RFC6570 form. + */ + public static UriBuilder uriBuilder(CharSequence template) { + return new UriBuilder(template); + } + + /** + * @param in + * uri + */ + public static UriBuilder uriBuilder(URI uri) { + return new UriBuilder(uri); + } + + /** + * Mutable URI builder that can be in level 1 RFC6570 template form. + * + * ex. + * + *
+    *  https://api.github.com/repos/{user}
+    * 
+ * + */ + public static final class UriBuilder { + // colon for urns, semicolon & equals for matrix params + private Iterable skipPathEncoding = Lists.charactersOf("/:;="); + private String scheme; + private String host; + private Integer port; + private String path; + private Multimap query = DecodingMultimap.create(); + + /** + * override default of {@code / : ; =} + * @param scheme + * scheme to set or replace + */ + public UriBuilder skipPathEncoding(Iterable skipPathEncoding) { + this.skipPathEncoding = ImmutableSet.copyOf(checkNotNull(skipPathEncoding, "skipPathEncoding")); + return this; + } + + /** + * @param scheme + * scheme to set or replace + */ + public UriBuilder scheme(String scheme) { + this.scheme = checkNotNull(scheme, "scheme"); + return this; + } + + /** + * @param host + * host to set or replace + * @return replaced value + */ + public UriBuilder host(String host) { + this.host = checkNotNull(host, "host"); + return this; + } + + public UriBuilder clearPath() { + path = null; + return this; + } + + public UriBuilder path(@Nullable String path) { + path = emptyToNull(path); + if (path == null) + this.path = null; + else + this.path = prefixIfNeeded(urlDecode(path)); + return this; + } + + public UriBuilder appendPath(String path) { + path = urlDecode(checkNotNull(path, "path")); + if (this.path == null) { + path(path); + } else { + path(slash(this.path, path)); + } + return this; + } + + public UriBuilder query(Map parameters) { + return query(forMap(parameters)); + } + + public UriBuilder query(@Nullable String queryLine) { + if (query == null) + return clearQuery(); + return query(queryParser().apply(queryLine)); + } + + public UriBuilder clearQuery() { + query.clear(); + return this; + } + + public UriBuilder query(Multimap parameters) { + checkNotNull(parameters, "parameters"); + query.clear(); + query.putAll(parameters); + return this; + } + + public UriBuilder addQuery(String name, Iterable values) { + query.putAll(checkNotNull(name, "name"), checkNotNull(values, "values of %s", name)); + return this; + } + + public UriBuilder addQuery(String name, String... values) { + return addQuery(name, Arrays.asList(checkNotNull(values, "values of %s", name))); + } + + public UriBuilder addQuery(Map parameters) { + return addQuery(forMap(parameters)); + } + + public UriBuilder addQuery(Multimap parameters) { + query.putAll(checkNotNull(parameters, "parameters")); + return this; + } + + public UriBuilder replaceQuery(String name, Iterable values) { + query.replaceValues(checkNotNull(name, "name"), checkNotNull(values, "values of %s", name)); + return this; + } + + public UriBuilder replaceQuery(String name, String... values) { + return replaceQuery(name, Arrays.asList(checkNotNull(values, "values of %s", name))); + } + + public UriBuilder replaceQuery(Map parameters) { + return replaceQuery(forMap(parameters)); + } + + public UriBuilder replaceQuery(Multimap parameters) { + for (String key : checkNotNull(parameters, "parameters").keySet()) + replaceQuery(key, parameters.get(key)); + return this; + } + + /** + * RFC6570 templates have variables defined in curly braces. + * Curly brace characters are unparsable via {@link URI#create} and result in an {@link IllegalArgumentException}. + * + * This implementation temporarily replaces curly braces with double parenthesis so that it can reuse + * {@link URI#create}. + * + * @param uri + * template which may have template parameters inside + */ + private UriBuilder(CharSequence uri) { + this(URI.create(escapeSpecialChars(checkNotNull(uri, "uri")))); + } + + private static String escapeSpecialChars(CharSequence uri) { + // skip encoding if there's no valid variables set. ex. {a} is the left valid + if (uri.length() < 3) + return uri.toString(); + + // duplicates memory even if there are no special characters, however only requires a single scan. + StringBuilder builder = new StringBuilder(); + for (char c : Lists.charactersOf(uri)) { + switch (c) { + case '{': + builder.append("(("); + break; + case '}': + builder.append("))"); + break; + default: + builder.append(c); + } + } + return builder.toString(); + } + + private static String unescapeSpecialChars(CharSequence uri) { + if (uri.length() < 5) // skip encoding if there's no valid variables set. ex. ((a)) is the left valid + return uri.toString(); + + char last = uri.charAt(0);// duplicates even if there are no special characters, but only requires 1 scan + StringBuilder builder = new StringBuilder(); + for (char c : Lists.charactersOf(uri)) { + switch (c) { + case '(': + if (last == '(') { + builder.setCharAt(builder.length() - 1, '{'); + } else { + builder.append('('); + } + break; + case ')': + if (last == ')') { + builder.setCharAt(builder.length() - 1, '}'); + } else { + builder.append(')'); + } + break; + default: + builder.append(c); + } + last = c; + } + return builder.toString(); + } + + private UriBuilder(URI uri) { + checkNotNull(uri, "uri"); + 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()))); + } + + public URI build() { + return build(ImmutableMap. of()); + } + + /** + * @throws IllegalArgumentException + * if there's a problem parsing the URI + */ + public URI build(Map variables) { + try { + return new URI(expand(variables)); + } catch (URISyntaxException e) { + throw new IllegalArgumentException(e); + } + } + + public String expand(Map variables) { + StringBuilder b = new StringBuilder(); + if (scheme != null) + b.append(scheme).append("://"); + if (host != null) + b.append(UriTemplates.expand(host, variables)); + if (port != null) + b.append(':').append(port); + if (path != null) + b.append(urlEncode(UriTemplates.expand(path, variables), skipPathEncoding)); + if (query.size() > 0) + b.append('?').append(encodeQueryLine(query)); + return b.toString(); + } + + /** + * returns template expression without url encoding + */ + @Override + public String toString() { + StringBuilder b = new StringBuilder(); + if (scheme != null) + b.append(scheme).append("://"); + if (host != null) + b.append(host); + if (port != null) + b.append(':').append(port); + if (path != null) + b.append(path); + if (query.size() > 0) + b.append('?').append(buildQueryLine(query)); + return b.toString(); + } + } + + private static String slash(CharSequence left, CharSequence right) { + return delimit(left, right, '/'); + } + + private static String delimit(CharSequence left, CharSequence right, char token) { + if (left.length() == 0) + return right.toString(); + if (right.length() == 0) + return left.toString(); + StringBuilder builder = new StringBuilder(left); + if (lastChar(left) == token) { + if (firstChar(right) == token) // left/ + /right + return builder.append(right.subSequence(1, right.length())).toString(); + return builder.append(right).toString(); // left/ + right + } else if (firstChar(right) == token) { + return builder.append(right).toString(); // left + /right + } // left + / + right + return new StringBuilder(left).append(token).append(right).toString(); + } + + public static boolean lastCharIsToken(CharSequence left, char token) { + return lastChar(left) == token; + } + + public static char lastChar(CharSequence in) { + return in.charAt(in.length() - 1); + } + + public static char firstChar(CharSequence in) { + return in.charAt(0); + } + + public static boolean isToken(CharSequence right, char token) { + return right.length() == 1 && right.charAt(0) == token; + } + + private static String prefixIfNeeded(String in) { + if (in != null && in.charAt(0) != '/') + return new StringBuilder().append('/').append(in).toString(); + return in; + } + + /** + * Mutable and permits null values. Url decodes all mutations except {@link Multimap#putAll(Multimap)} + * + * @author Adrian Cole + * + */ + static final class DecodingMultimap extends ForwardingMultimap { + + private static Multimap create() { + return new DecodingMultimap(); + } + + private final Multimap delegate = LinkedHashMultimap.create(); + private final Function urlDecoder = new Function() { + public Object apply(Object in) { + return urlDecode(in); + } + }; + + @Override + public boolean put(String key, Object value) { + return super.put(urlDecode(key), urlDecode(value)); + } + + @Override + public boolean putAll(String key, Iterable values) { + return super.putAll(urlDecode(key), Iterables.transform(values, urlDecoder)); + } + + @Override + public boolean putAll(Multimap multimap) { + return super.putAll(multimap); + } + + @Override + public Collection replaceValues(String key, Iterable values) { + return super.replaceValues(urlDecode(key), Iterables.transform(values, urlDecoder)); + } + + @Override + protected Multimap delegate() { + return delegate; + } + + } + +} diff --git a/core/src/main/java/org/jclouds/http/filters/BasicAuthentication.java b/core/src/main/java/org/jclouds/http/filters/BasicAuthentication.java index a9b75acea9..b931df117b 100644 --- a/core/src/main/java/org/jclouds/http/filters/BasicAuthentication.java +++ b/core/src/main/java/org/jclouds/http/filters/BasicAuthentication.java @@ -17,12 +17,11 @@ * under the License. */ package org.jclouds.http.filters; - import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.net.HttpHeaders.AUTHORIZATION; import javax.inject.Inject; import javax.inject.Singleton; -import javax.ws.rs.core.HttpHeaders; import org.jclouds.crypto.Crypto; import org.jclouds.crypto.CryptoStreams; @@ -53,6 +52,6 @@ public class BasicAuthentication implements HttpRequestFilter { @Override public HttpRequest filter(HttpRequest request) throws HttpException { - return request.toBuilder().replaceHeader(HttpHeaders.AUTHORIZATION, header).build(); + return request.toBuilder().replaceHeader(AUTHORIZATION, header).build(); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/jclouds/http/functions/ParseETagHeader.java b/core/src/main/java/org/jclouds/http/functions/ParseETagHeader.java index d2f628fa28..def4d05a2d 100644 --- a/core/src/main/java/org/jclouds/http/functions/ParseETagHeader.java +++ b/core/src/main/java/org/jclouds/http/functions/ParseETagHeader.java @@ -18,10 +18,10 @@ */ package org.jclouds.http.functions; +import static com.google.common.net.HttpHeaders.ETAG; import static org.jclouds.http.HttpUtils.releasePayload; import javax.inject.Singleton; -import javax.ws.rs.core.HttpHeaders; import org.jclouds.http.HttpException; import org.jclouds.http.HttpResponse; @@ -29,7 +29,7 @@ import org.jclouds.http.HttpResponse; import com.google.common.base.Function; /** - * Parses an MD5 checksum from the header {@link HttpHeaders#ETAG}. + * Parses an MD5 checksum from the header {@link com.google.common.net.HttpHeaders.HttpHeaders#ETAG}. * * @author Adrian Cole */ @@ -38,7 +38,7 @@ public class ParseETagHeader implements Function { public String apply(HttpResponse from) { releasePayload(from); - String eTag = from.getFirstHeaderOrNull(HttpHeaders.ETAG); + String eTag = from.getFirstHeaderOrNull(ETAG); if (eTag == null) { // TODO: Cloud Files sends incorrectly cased ETag header... Remove this when fixed. eTag = from.getFirstHeaderOrNull("Etag"); @@ -49,4 +49,4 @@ public class ParseETagHeader implements Function { throw new HttpException("did not receive ETag"); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/jclouds/http/functions/ParseURIFromListOrLocationHeaderIf20x.java b/core/src/main/java/org/jclouds/http/functions/ParseURIFromListOrLocationHeaderIf20x.java index de47f00a68..454344328f 100644 --- a/core/src/main/java/org/jclouds/http/functions/ParseURIFromListOrLocationHeaderIf20x.java +++ b/core/src/main/java/org/jclouds/http/functions/ParseURIFromListOrLocationHeaderIf20x.java @@ -19,20 +19,18 @@ package org.jclouds.http.functions; import static com.google.common.base.Preconditions.checkState; +import static com.google.common.net.HttpHeaders.CONTENT_TYPE; +import static com.google.common.net.HttpHeaders.LOCATION; import static org.jclouds.http.HttpUtils.releasePayload; import java.io.IOException; import java.net.URI; -import javax.inject.Inject; -import javax.inject.Provider; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.UriBuilder; - import org.jclouds.http.HttpException; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponseException; +import org.jclouds.http.Uris; import org.jclouds.rest.InvocationContext; import org.jclouds.util.Strings2; @@ -45,19 +43,13 @@ import com.google.common.base.Function; */ public class ParseURIFromListOrLocationHeaderIf20x implements Function, InvocationContext { - private final Provider uriBuilderProvider; - - @Inject - ParseURIFromListOrLocationHeaderIf20x(Provider uriBuilderProvider) { - this.uriBuilderProvider = uriBuilderProvider; - } private HttpRequest request; public URI apply(HttpResponse from) { if (from.getStatusCode() > 206) throw new HttpException(String.format("Unhandled status code - %1$s", from)); - if ("text/uri-list".equals(from.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE))) { + if ("text/uri-list".equals(from.getFirstHeaderOrNull(CONTENT_TYPE))) { try { if (from.getPayload().getInput() == null) throw new HttpResponseException("no content", null, from); @@ -70,7 +62,7 @@ public class ParseURIFromListOrLocationHeaderIf20x implements Function uriBuilderProvider; @Inject - protected RedirectionRetryHandler(Provider uriBuilderProvider, BackoffLimitedRetryHandler backoffHandler) { + protected RedirectionRetryHandler(BackoffLimitedRetryHandler backoffHandler) { this.backoffHandler = backoffHandler; - this.uriBuilderProvider = uriBuilderProvider; } public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) { closeClientButKeepContentStream(response); - String hostHeader = response.getFirstHeaderOrNull(HttpHeaders.LOCATION); + String hostHeader = response.getFirstHeaderOrNull(LOCATION); if (command.incrementRedirectCount() < retryCountLimit && hostHeader != null) { URI redirectionUrl = URI.create(hostHeader); @@ -77,11 +74,8 @@ public class RedirectionRetryHandler implements HttpRetryHandler { assert redirectionUrl.getPath() != null : "no path in redirect header from: " + response; if (!redirectionUrl.isAbsolute()) { - UriBuilder builder = uriBuilderProvider.get().uri(currentRequest.getEndpoint()); - builder.replacePath(redirectionUrl.getPath()); - if (redirectionUrl.getQuery() != null) - builder.replaceQuery(redirectionUrl.getQuery()); - redirectionUrl = builder.build(); + redirectionUrl = uriBuilder(currentRequest.getEndpoint()).path(redirectionUrl.getPath()) + .query(redirectionUrl.getQuery()).build(); } if (currentRequest.getFirstHeaderOrNull(HOST) != null && redirectionUrl.getHost() != null) { @@ -100,4 +94,4 @@ public class RedirectionRetryHandler implements HttpRetryHandler { } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java b/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java index c4e0136656..bf851ca768 100644 --- a/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java +++ b/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java @@ -17,13 +17,15 @@ * under the License. */ package org.jclouds.http.internal; - import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Throwables.propagate; import static com.google.common.collect.Iterables.getLast; import static com.google.common.io.ByteStreams.toByteArray; import static com.google.common.io.Closeables.closeQuietly; +import static com.google.common.net.HttpHeaders.CONTENT_LENGTH; +import static com.google.common.net.HttpHeaders.HOST; +import static com.google.common.net.HttpHeaders.USER_AGENT; import static org.jclouds.io.Payloads.newInputStreamPayload; import java.io.ByteArrayInputStream; @@ -49,7 +51,6 @@ import javax.inject.Singleton; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; -import javax.ws.rs.core.HttpHeaders; import org.jclouds.Constants; import org.jclouds.JcloudsVersion; @@ -80,7 +81,7 @@ import com.google.inject.Inject; @Singleton public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorService { - public static final String USER_AGENT = String.format("jclouds/%s java/%s", JcloudsVersion.get(), System + public static final String DEFAULT_USER_AGENT = String.format("jclouds/%s java/%s", JcloudsVersion.get(), System .getProperty("java.version")); @Resource @@ -109,7 +110,7 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe @Override protected HttpResponse invoke(HttpURLConnection connection) throws IOException, InterruptedException { - HttpResponse.Builder builder = HttpResponse.builder(); + HttpResponse.Builder builder = HttpResponse.builder(); InputStream in = null; try { in = consumeOnClose(connection.getInputStream()); @@ -221,9 +222,9 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe if(request.getEndpoint().getPort() != -1) { host += ":" + request.getEndpoint().getPort(); } - connection.setRequestProperty(HttpHeaders.HOST, host); - if (connection.getRequestProperty(HttpHeaders.USER_AGENT) == null) { - connection.setRequestProperty(HttpHeaders.USER_AGENT, USER_AGENT); + connection.setRequestProperty(HOST, host); + if (connection.getRequestProperty(USER_AGENT) == null) { + connection.setRequestProperty(USER_AGENT, DEFAULT_USER_AGENT); } if (request.getPayload() != null) { @@ -235,7 +236,7 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe connection.setChunkedStreamingMode(8196); } else { Long length = checkNotNull(md.getContentLength(), "payload.getContentLength"); - connection.setRequestProperty(HttpHeaders.CONTENT_LENGTH, length.toString()); + connection.setRequestProperty(CONTENT_LENGTH, length.toString()); // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6755625 checkArgument(length < Integer.MAX_VALUE, "JDK 1.6 does not support >2GB chunks. Use chunked encoding, if possible."); @@ -252,7 +253,7 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe .getContentLength(), request.getRequestLine()), e); } } else { - connection.setRequestProperty(HttpHeaders.CONTENT_LENGTH, "0"); + connection.setRequestProperty(CONTENT_LENGTH, "0"); // for some reason POST/PUT undoes the content length header above. if (connection.getRequestMethod().equals("POST") || connection.getRequestMethod().equals("PUT")) connection.setFixedLengthStreamingMode(0); diff --git a/core/src/main/java/org/jclouds/http/options/GetOptions.java b/core/src/main/java/org/jclouds/http/options/GetOptions.java index ee4d8a635b..b992382de6 100644 --- a/core/src/main/java/org/jclouds/http/options/GetOptions.java +++ b/core/src/main/java/org/jclouds/http/options/GetOptions.java @@ -17,16 +17,18 @@ * under the License. */ package org.jclouds.http.options; - import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.net.HttpHeaders.IF_MATCH; +import static com.google.common.net.HttpHeaders.IF_MODIFIED_SINCE; +import static com.google.common.net.HttpHeaders.IF_NONE_MATCH; +import static com.google.common.net.HttpHeaders.IF_UNMODIFIED_SINCE; +import static com.google.common.net.HttpHeaders.RANGE; import java.util.ArrayList; import java.util.Date; import java.util.List; -import javax.ws.rs.core.HttpHeaders; - import org.jclouds.date.DateService; import org.jclouds.date.internal.SimpleDateFormatDateService; @@ -60,7 +62,7 @@ public class GetOptions extends BaseHttpRequestOptions { Multimap headers = super.buildRequestHeaders(); String range = getRange(); if (range != null) - headers.put("Range", this.getRange()); + headers.put(RANGE, this.getRange()); return headers; } @@ -110,7 +112,7 @@ public class GetOptions extends BaseHttpRequestOptions { public GetOptions ifModifiedSince(Date ifModifiedSince) { checkArgument(getIfMatch() == null, "ifETagMatches() is not compatible with ifModifiedSince()"); checkArgument(getIfUnmodifiedSince() == null, "ifUnmodifiedSince() is not compatible with ifModifiedSince()"); - this.headers.put(HttpHeaders.IF_MODIFIED_SINCE, + this.headers.put(IF_MODIFIED_SINCE, dateService.rfc822DateFormat(checkNotNull(ifModifiedSince, "ifModifiedSince"))); return this; } @@ -124,7 +126,7 @@ public class GetOptions extends BaseHttpRequestOptions { * @see #ifModifiedSince(Date) */ public String getIfModifiedSince() { - return this.getFirstHeaderOrNull(HttpHeaders.IF_MODIFIED_SINCE); + return this.getFirstHeaderOrNull(IF_MODIFIED_SINCE); } /** @@ -135,7 +137,7 @@ public class GetOptions extends BaseHttpRequestOptions { public GetOptions ifUnmodifiedSince(Date ifUnmodifiedSince) { checkArgument(getIfNoneMatch() == null, "ifETagDoesntMatch() is not compatible with ifUnmodifiedSince()"); checkArgument(getIfModifiedSince() == null, "ifModifiedSince() is not compatible with ifUnmodifiedSince()"); - this.headers.put(HttpHeaders.IF_UNMODIFIED_SINCE, + this.headers.put(IF_UNMODIFIED_SINCE, dateService.rfc822DateFormat(checkNotNull(ifUnmodifiedSince, "ifUnmodifiedSince"))); return this; } @@ -149,7 +151,7 @@ public class GetOptions extends BaseHttpRequestOptions { * @see #ifUnmodifiedSince(Date) */ public String getIfUnmodifiedSince() { - return this.getFirstHeaderOrNull(HttpHeaders.IF_UNMODIFIED_SINCE); + return this.getFirstHeaderOrNull(IF_UNMODIFIED_SINCE); } /** @@ -164,7 +166,7 @@ public class GetOptions extends BaseHttpRequestOptions { public GetOptions ifETagMatches(String eTag) { checkArgument(getIfNoneMatch() == null, "ifETagDoesntMatch() is not compatible with ifETagMatches()"); checkArgument(getIfModifiedSince() == null, "ifModifiedSince() is not compatible with ifETagMatches()"); - this.headers.put(HttpHeaders.IF_MATCH, String.format("\"%1$s\"", checkNotNull(eTag, "eTag"))); + this.headers.put(IF_MATCH, String.format("\"%1$s\"", checkNotNull(eTag, "eTag"))); return this; } @@ -177,7 +179,7 @@ public class GetOptions extends BaseHttpRequestOptions { * @see #ifETagMatches(String) */ public String getIfMatch() { - return this.getFirstHeaderOrNull(HttpHeaders.IF_MATCH); + return this.getFirstHeaderOrNull(IF_MATCH); } /** @@ -191,7 +193,7 @@ public class GetOptions extends BaseHttpRequestOptions { public GetOptions ifETagDoesntMatch(String eTag) { checkArgument(getIfMatch() == null, "ifETagMatches() is not compatible with ifETagDoesntMatch()"); checkArgument(getIfUnmodifiedSince() == null, "ifUnmodifiedSince() is not compatible with ifETagDoesntMatch()"); - this.headers.put(HttpHeaders.IF_NONE_MATCH, String.format("\"%1$s\"", checkNotNull(eTag, "ifETagDoesntMatch"))); + this.headers.put(IF_NONE_MATCH, String.format("\"%1$s\"", checkNotNull(eTag, "ifETagDoesntMatch"))); return this; } @@ -204,7 +206,7 @@ public class GetOptions extends BaseHttpRequestOptions { * @see #ifETagDoesntMatch(String) */ public String getIfNoneMatch() { - return this.getFirstHeaderOrNull(HttpHeaders.IF_NONE_MATCH); + return this.getFirstHeaderOrNull(IF_NONE_MATCH); } public List getRanges() { diff --git a/core/src/main/java/org/jclouds/http/utils/Queries.java b/core/src/main/java/org/jclouds/http/utils/Queries.java index b3e71803f6..1057a6e0b4 100644 --- a/core/src/main/java/org/jclouds/http/utils/Queries.java +++ b/core/src/main/java/org/jclouds/http/utils/Queries.java @@ -18,14 +18,14 @@ */ package org.jclouds.http.utils; -import java.util.Comparator; -import java.util.Iterator; -import java.util.Map; +import static org.jclouds.util.Strings2.urlDecode; +import static org.jclouds.util.Strings2.urlEncode; -import org.jclouds.javax.annotation.Nullable; -import org.jclouds.util.Strings2; +import java.util.Map.Entry; -import com.google.common.collect.ImmutableSortedSet; +import com.google.common.base.Function; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableList; import com.google.common.collect.LinkedListMultimap; import com.google.common.collect.Multimap; @@ -35,47 +35,118 @@ import com.google.common.collect.Multimap; */ public class Queries { - public static Multimap parseQueryToMap(String in) { - Multimap map = LinkedListMultimap.create(); - if (in == null) { - } else if (in.indexOf('&') == -1) { - if (in.contains("=")) - parseKeyValueFromStringToMap(in, map); - else - map.put(in, null); - } else { - String[] parts = in.split("&"); - for (String part : parts) { - parseKeyValueFromStringToMap(part, map); + private static final Function> parseQueryToDecodedMap = new Function>() { + @Override + public Multimap apply(String in) { + // some query values are null, which aren't permitted by Immutable* + Multimap map = LinkedListMultimap.create(); + if (in == null) { + } else if (in.indexOf('&') == -1) { + if (in.indexOf('=') != -1) + parseKeyValueFromStringToDecodedMap(in, map); + else + map.put(in, null); + } else { + for (String part : Splitter.on('&').split(in)) { + parseKeyValueFromStringToDecodedMap(part, map); + } } + return map; } - return map; + }; + + public static Function> queryParser() { + return parseQueryToDecodedMap; } - public static void parseKeyValueFromStringToMap(String stringToParse, Multimap map) { + private static void parseKeyValueFromStringToDecodedMap(String stringToParse, Multimap map) { // note that '=' can be a valid part of the value int indexOfFirstEquals = stringToParse.indexOf('='); String key = indexOfFirstEquals == -1 ? stringToParse : stringToParse.substring(0, indexOfFirstEquals); String value = indexOfFirstEquals == -1 ? null : stringToParse.substring(indexOfFirstEquals + 1); - map.put(Strings2.urlDecode(key), Strings2.urlDecode(value)); + map.put(urlDecode(key), urlDecode(value)); } - public static String makeQueryLine(Multimap params, - @Nullable Comparator> sorter, char... skips) { - Iterator> pairs = ((sorter == null) ? params.entries() : ImmutableSortedSet.copyOf( - sorter, params.entries())).iterator(); - StringBuilder formBuilder = new StringBuilder(); - while (pairs.hasNext()) { - Map.Entry pair = pairs.next(); - formBuilder.append(Strings2.urlEncode(pair.getKey(), skips)); - if (pair.getValue() != null) - formBuilder.append("="); - if (pair.getValue() != null && !pair.getValue().equals("")) { - formBuilder.append(Strings2.urlEncode(pair.getValue(), skips)); - } - if (pairs.hasNext()) - formBuilder.append("&"); - } - return formBuilder.toString(); + /** + * percent encodes the query parameters, excep {@code /} and {@code ,} characters. + * + * @param queryParams + * @return percent encoded line or null if no queryParams present + */ + public static String encodeQueryLine(Multimap queryParams) { + if (queryParams.isEmpty()) + return null; + return buildQueryLine(queryParams, new EncodeAndAppendParam()); } + + /** + * percent encodes the query parameters according except characters specified in the {@code skips} argument. + * + * @param queryParams + * @return percent encoded line or null if no queryParams present + */ + public static String encodeQueryLine(Multimap queryParams, Iterable skips) { + if (queryParams.isEmpty()) + return null; + return buildQueryLine(queryParams, new EncodeAndAppendParam(skips)); + } + + public static String buildQueryLine(Multimap queryParams) { + if (queryParams.isEmpty()) + return null; + return buildQueryLine(queryParams, new AppendParam()); + } + + private static String buildQueryLine(Multimap queryParams, AppendParam appendParam) { + StringBuilder queryBuilder = appendParam.b; + for (Entry pair : queryParams.entries()) { + queryBuilder.append('&'); + appendParam.appendKey(pair.getKey()); + if (pair.getValue() != null) + queryBuilder.append('='); + if (pair.getValue() != null && !pair.getValue().equals("")) { + appendParam.appendValue(pair.getValue()); + } + } + queryBuilder.deleteCharAt(0); + return queryBuilder.toString(); + } + + private static class AppendParam { + final StringBuilder b; + + private AppendParam() { + this.b = new StringBuilder(); + } + + private void appendKey(String key) { + append(key); + } + + private void appendValue(Object val) { + append(val); + } + + void append(Object in) { + b.append(in.toString()); + } + } + + private static class EncodeAndAppendParam extends AppendParam { + private Iterable skips; + + private EncodeAndAppendParam() { + this(ImmutableList.of('/', ',')); + } + + private EncodeAndAppendParam(Iterable skips) { + this.skips = skips; + } + + @Override + void append(Object in) { + super.append(urlEncode(in.toString(), skips)); + } + } + } diff --git a/core/src/main/java/org/jclouds/io/ContentMetadata.java b/core/src/main/java/org/jclouds/io/ContentMetadata.java index e9b9b25c8a..6dbfc0772c 100644 --- a/core/src/main/java/org/jclouds/io/ContentMetadata.java +++ b/core/src/main/java/org/jclouds/io/ContentMetadata.java @@ -17,10 +17,13 @@ * under the License. */ package org.jclouds.io; - -import static javax.ws.rs.core.HttpHeaders.CONTENT_LENGTH; -import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE; -import static javax.ws.rs.core.HttpHeaders.EXPIRES; +import static com.google.common.net.HttpHeaders.CONTENT_DISPOSITION; +import static com.google.common.net.HttpHeaders.CONTENT_ENCODING; +import static com.google.common.net.HttpHeaders.CONTENT_LANGUAGE; +import static com.google.common.net.HttpHeaders.CONTENT_LENGTH; +import static com.google.common.net.HttpHeaders.CONTENT_MD5; +import static com.google.common.net.HttpHeaders.CONTENT_TYPE; +import static com.google.common.net.HttpHeaders.EXPIRES; import java.util.Date; import java.util.Set; @@ -33,8 +36,8 @@ import com.google.common.collect.ImmutableSet; * @author Adrian Cole */ public interface ContentMetadata { - public static final Set HTTP_HEADERS = ImmutableSet.of(CONTENT_LENGTH, "Content-MD5", CONTENT_TYPE, - "Content-Disposition", "Content-Encoding", "Content-Language", EXPIRES); + public static final Set HTTP_HEADERS = ImmutableSet.of(CONTENT_LENGTH, CONTENT_MD5, CONTENT_TYPE, + CONTENT_DISPOSITION, CONTENT_ENCODING, CONTENT_LANGUAGE, EXPIRES); // See http://stackoverflow.com/questions/10584647/simpledateformat-parse-is-one-hour-out-using-rfc-1123-gmt-in-summer // for why not using "zzz" @@ -104,4 +107,4 @@ public interface ContentMetadata { ContentMetadataBuilder toBuilder(); -} \ No newline at end of file +} diff --git a/core/src/main/java/org/jclouds/io/ContentMetadataCodec.java b/core/src/main/java/org/jclouds/io/ContentMetadataCodec.java index cb13f946c9..33ae84b02a 100644 --- a/core/src/main/java/org/jclouds/io/ContentMetadataCodec.java +++ b/core/src/main/java/org/jclouds/io/ContentMetadataCodec.java @@ -1,15 +1,18 @@ package org.jclouds.io; import static com.google.common.collect.Iterables.any; -import static javax.ws.rs.core.HttpHeaders.CONTENT_LENGTH; -import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE; -import static javax.ws.rs.core.HttpHeaders.EXPIRES; +import static com.google.common.net.HttpHeaders.CONTENT_DISPOSITION; +import static com.google.common.net.HttpHeaders.CONTENT_ENCODING; +import static com.google.common.net.HttpHeaders.CONTENT_LANGUAGE; +import static com.google.common.net.HttpHeaders.CONTENT_LENGTH; +import static com.google.common.net.HttpHeaders.CONTENT_MD5; +import static com.google.common.net.HttpHeaders.CONTENT_TYPE; +import static com.google.common.net.HttpHeaders.EXPIRES; import java.util.Date; import java.util.Map.Entry; import javax.annotation.Resource; -import javax.ws.rs.core.HttpHeaders; import org.jclouds.crypto.CryptoStreams; import org.jclouds.date.DateCodec; @@ -68,19 +71,19 @@ public interface ContentMetadataCodec { public Multimap toHeaders(ContentMetadata md) { Builder builder = ImmutableMultimap.builder(); if (md.getContentType() != null) - builder.put(HttpHeaders.CONTENT_TYPE, md.getContentType()); + builder.put(CONTENT_TYPE, md.getContentType()); if (md.getContentDisposition() != null) - builder.put("Content-Disposition", md.getContentDisposition()); + builder.put(CONTENT_DISPOSITION, md.getContentDisposition()); if (md.getContentEncoding() != null) - builder.put(HttpHeaders.CONTENT_ENCODING, md.getContentEncoding()); + builder.put(CONTENT_ENCODING, md.getContentEncoding()); if (md.getContentLanguage() != null) - builder.put(HttpHeaders.CONTENT_LANGUAGE, md.getContentLanguage()); + builder.put(CONTENT_LANGUAGE, md.getContentLanguage()); if (md.getContentLength() != null) - builder.put(HttpHeaders.CONTENT_LENGTH, md.getContentLength() + ""); + builder.put(CONTENT_LENGTH, md.getContentLength() + ""); if (md.getContentMD5() != null) - builder.put("Content-MD5", CryptoStreams.base64(md.getContentMD5())); + builder.put(CONTENT_MD5, CryptoStreams.base64(md.getContentMD5())); if (md.getExpires() != null) - builder.put(HttpHeaders.EXPIRES, getExpiresDateCodec().toString(md.getExpires())); + builder.put(EXPIRES, getExpiresDateCodec().toString(md.getExpires())); return builder.build(); } @@ -95,15 +98,15 @@ public interface ContentMetadataCodec { for (Entry header : headers.entries()) { if (!chunked && CONTENT_LENGTH.equalsIgnoreCase(header.getKey())) { contentMetadata.setContentLength(Long.valueOf(header.getValue())); - } else if ("Content-MD5".equalsIgnoreCase(header.getKey())) { + } else if (CONTENT_MD5.equalsIgnoreCase(header.getKey())) { contentMetadata.setContentMD5(CryptoStreams.base64(header.getValue())); } else if (CONTENT_TYPE.equalsIgnoreCase(header.getKey())) { contentMetadata.setContentType(header.getValue()); - } else if ("Content-Disposition".equalsIgnoreCase(header.getKey())) { + } else if (CONTENT_DISPOSITION.equalsIgnoreCase(header.getKey())) { contentMetadata.setContentDisposition(header.getValue()); - } else if ("Content-Encoding".equalsIgnoreCase(header.getKey())) { + } else if (CONTENT_ENCODING.equalsIgnoreCase(header.getKey())) { contentMetadata.setContentEncoding(header.getValue()); - } else if ("Content-Language".equalsIgnoreCase(header.getKey())) { + } else if (CONTENT_LANGUAGE.equalsIgnoreCase(header.getKey())) { contentMetadata.setContentLanguage(header.getValue()); } else if (EXPIRES.equalsIgnoreCase(header.getKey())) { contentMetadata.setExpires(parseExpires(header.getValue())); diff --git a/core/src/main/java/org/jclouds/io/Payloads.java b/core/src/main/java/org/jclouds/io/Payloads.java index 0fe038fb74..e573818a9e 100644 --- a/core/src/main/java/org/jclouds/io/Payloads.java +++ b/core/src/main/java/org/jclouds/io/Payloads.java @@ -26,8 +26,6 @@ import java.io.IOException; import java.io.InputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.Comparator; -import java.util.Map; import org.jclouds.crypto.CryptoStreams; import org.jclouds.io.payloads.ByteArrayPayload; @@ -35,7 +33,6 @@ import org.jclouds.io.payloads.FilePayload; import org.jclouds.io.payloads.InputStreamPayload; import org.jclouds.io.payloads.StringPayload; import org.jclouds.io.payloads.UrlEncodedFormPayload; -import org.jclouds.javax.annotation.Nullable; import com.google.common.base.Throwables; import com.google.common.collect.Multimap; @@ -81,15 +78,10 @@ public class Payloads { return new FilePayload(checkNotNull(data, "data")); } - public static UrlEncodedFormPayload newUrlEncodedFormPayload(Multimap formParams, char... skips) { - return new UrlEncodedFormPayload(formParams, skips); + public static UrlEncodedFormPayload newUrlEncodedFormPayload(Multimap formParams) { + return new UrlEncodedFormPayload(formParams); } - - public static UrlEncodedFormPayload newUrlEncodedFormPayload(Multimap formParams, - @Nullable Comparator> sorter, char... skips) { - return new UrlEncodedFormPayload(formParams, sorter, skips); - } - + /** * Calculates and sets {@link Payload#setContentMD5} on the payload. * diff --git a/core/src/main/java/org/jclouds/io/payloads/Part.java b/core/src/main/java/org/jclouds/io/payloads/Part.java index 93fab7af51..cb5625dfdb 100644 --- a/core/src/main/java/org/jclouds/io/payloads/Part.java +++ b/core/src/main/java/org/jclouds/io/payloads/Part.java @@ -19,9 +19,6 @@ package org.jclouds.io.payloads; import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.collect.Multimaps.forMap; - -import java.util.LinkedHashMap; import javax.ws.rs.core.HttpHeaders; @@ -40,7 +37,7 @@ public class Part extends DelegatingPayload { final String name; final Multimap headers; - private static class PartMap extends LinkedHashMap { + private static class PartMap extends ImmutableMultimap.Builder { /** The serialVersionUID */ private static final long serialVersionUID = -287387556008320212L; @@ -81,7 +78,7 @@ public class Part extends DelegatingPayload { private Part(String name, Part.PartMap map, Payload delegate) { super(delegate); this.name = name; - this.headers = ImmutableMultimap.copyOf(forMap((checkNotNull(map, "headers")))); + this.headers = checkNotNull(map, "headers").build(); } public static class PartOptions { @@ -132,4 +129,4 @@ public class Part extends DelegatingPayload { public String getName() { return name; } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/jclouds/io/payloads/UrlEncodedFormPayload.java b/core/src/main/java/org/jclouds/io/payloads/UrlEncodedFormPayload.java index 857e8939d0..8fdcf5cf03 100644 --- a/core/src/main/java/org/jclouds/io/payloads/UrlEncodedFormPayload.java +++ b/core/src/main/java/org/jclouds/io/payloads/UrlEncodedFormPayload.java @@ -17,16 +17,11 @@ * under the License. */ package org.jclouds.io.payloads; +import static com.google.common.net.MediaType.FORM_DATA; +import static org.jclouds.http.utils.Queries.encodeQueryLine; +import static org.jclouds.util.Strings2.toInputStream; import java.io.InputStream; -import java.util.Comparator; -import java.util.Map; - -import javax.ws.rs.core.MediaType; - -import org.jclouds.http.utils.Queries; -import org.jclouds.javax.annotation.Nullable; -import org.jclouds.util.Strings2; import com.google.common.collect.Multimap; @@ -34,15 +29,10 @@ import com.google.common.collect.Multimap; * @author Adrian Cole */ public class UrlEncodedFormPayload extends BasePayload { - public UrlEncodedFormPayload(Multimap formParams, char... skips) { - this(formParams, null, skips); - } - - public UrlEncodedFormPayload(Multimap formParams, - @Nullable Comparator> sorter, char... skips) { - super(Queries.makeQueryLine(formParams, sorter, skips)); + public UrlEncodedFormPayload(Multimap formParams) { + super(encodeQueryLine(formParams)); getContentMetadata().setContentLength((long) content.length()); - getContentMetadata().setContentType(MediaType.APPLICATION_FORM_URLENCODED); + getContentMetadata().setContentType(FORM_DATA.toString()); } /** @@ -50,7 +40,7 @@ public class UrlEncodedFormPayload extends BasePayload { */ @Override public InputStream getInput() { - return Strings2.toInputStream(content); + return toInputStream(content); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/jclouds/rest/annotations/SkipEncoding.java b/core/src/main/java/org/jclouds/rest/annotations/SkipEncoding.java index 6f9d565027..b99d06117c 100644 --- a/core/src/main/java/org/jclouds/rest/annotations/SkipEncoding.java +++ b/core/src/main/java/org/jclouds/rest/annotations/SkipEncoding.java @@ -19,6 +19,7 @@ package org.jclouds.rest.annotations; import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; @@ -29,7 +30,7 @@ import java.lang.annotation.Target; * * @author Adrian Cole */ -@Target(TYPE) +@Target({ TYPE, METHOD }) @Retention(RUNTIME) public @interface SkipEncoding { char[] value(); diff --git a/core/src/main/java/org/jclouds/rest/binders/BindAsHostPrefix.java b/core/src/main/java/org/jclouds/rest/binders/BindAsHostPrefix.java index b8a38e3793..08230c9526 100644 --- a/core/src/main/java/org/jclouds/rest/binders/BindAsHostPrefix.java +++ b/core/src/main/java/org/jclouds/rest/binders/BindAsHostPrefix.java @@ -22,11 +22,9 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.net.InternetDomainName.from; import static com.google.common.net.InternetDomainName.isValid; +import static org.jclouds.http.Uris.uriBuilder; -import javax.inject.Inject; -import javax.inject.Provider; import javax.inject.Singleton; -import javax.ws.rs.core.UriBuilder; import org.jclouds.http.HttpRequest; import org.jclouds.rest.Binder; @@ -40,21 +38,12 @@ import com.google.common.net.InternetDomainName; @Singleton public class BindAsHostPrefix implements Binder { - private final Provider uriBuilderProvider; - - @Inject - public BindAsHostPrefix(Provider uriBuilderProvider) { - this.uriBuilderProvider = checkNotNull(uriBuilderProvider, "uriBuilderProvider"); - } - @Override @SuppressWarnings("unchecked") public R bindToRequest(R request, Object payload) { checkNotNull(payload, "hostprefix"); checkArgument(isValid(request.getEndpoint().getHost()), "this is only valid for hostnames: " + request); - UriBuilder builder = uriBuilderProvider.get().uri(request.getEndpoint()); InternetDomainName name = from(request.getEndpoint().getHost()).child(payload.toString()); - builder.host(name.name()); - return (R) request.toBuilder().endpoint(builder.build()).build(); + return (R) request.toBuilder().endpoint(uriBuilder(request.getEndpoint()).host(name.name()).build()).build(); } } diff --git a/core/src/main/java/org/jclouds/rest/binders/BindMapToStringPayload.java b/core/src/main/java/org/jclouds/rest/binders/BindMapToStringPayload.java index 8f450fdb59..98b22130e3 100644 --- a/core/src/main/java/org/jclouds/rest/binders/BindMapToStringPayload.java +++ b/core/src/main/java/org/jclouds/rest/binders/BindMapToStringPayload.java @@ -20,14 +20,12 @@ package org.jclouds.rest.binders; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.http.UriTemplates.expand; +import static org.jclouds.util.Strings2.urlDecode; -import java.net.URI; import java.util.Map; -import javax.inject.Inject; -import javax.inject.Provider; import javax.inject.Singleton; -import javax.ws.rs.core.UriBuilder; import org.jclouds.http.HttpRequest; import org.jclouds.rest.MapBinder; @@ -40,13 +38,7 @@ import org.jclouds.rest.internal.GeneratedHttpRequest; */ @Singleton public class BindMapToStringPayload implements MapBinder { - protected final Provider uriBuilders; - - @Inject - public BindMapToStringPayload(Provider uriBuilders) { - this.uriBuilders = checkNotNull(uriBuilders, "uriBuilders"); - } - + @SuppressWarnings("unchecked") @Override public R bindToRequest(R request, Map postParams) { @@ -56,11 +48,7 @@ public class BindMapToStringPayload implements MapBinder { "method %s must have @Payload annotation to use this binder", r.getJavaMethod()); String payload = r.getJavaMethod().getAnnotation(Payload.class).value(); if (postParams.size() > 0) { - UriBuilder builder = uriBuilders.get(); - builder.uri(URI.create("http://fake/")); - builder.path(payload); - URI fake = builder.buildFromMap(postParams); - payload = fake.getPath().substring(1); + payload = urlDecode(expand(payload, postParams)); } return (R) request.toBuilder().payload(payload).build(); } @@ -70,4 +58,4 @@ public class BindMapToStringPayload implements MapBinder { throw new IllegalArgumentException("this is a map binder"); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/jclouds/rest/binders/BindToJsonPayload.java b/core/src/main/java/org/jclouds/rest/binders/BindToJsonPayload.java index 4b53743ba6..7a4a6f5b29 100644 --- a/core/src/main/java/org/jclouds/rest/binders/BindToJsonPayload.java +++ b/core/src/main/java/org/jclouds/rest/binders/BindToJsonPayload.java @@ -23,7 +23,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import java.util.Map; import javax.inject.Inject; -import javax.ws.rs.core.MediaType; import org.jclouds.http.HttpRequest; import org.jclouds.json.Json; @@ -52,8 +51,8 @@ public class BindToJsonPayload implements MapBinder { public R bindToRequest(R request, Object payload) { String json = jsonBinder.toJson(checkNotNull(payload, "payload")); request.setPayload(json); - request.getPayload().getContentMetadata().setContentType(MediaType.APPLICATION_JSON); + request.getPayload().getContentMetadata().setContentType("application/json"); return request; } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/jclouds/rest/binders/BindToXMLPayload.java b/core/src/main/java/org/jclouds/rest/binders/BindToXMLPayload.java index 87a31fe869..a9714cdb72 100644 --- a/core/src/main/java/org/jclouds/rest/binders/BindToXMLPayload.java +++ b/core/src/main/java/org/jclouds/rest/binders/BindToXMLPayload.java @@ -24,7 +24,6 @@ import java.io.IOException; import javax.inject.Inject; import javax.inject.Singleton; -import javax.ws.rs.core.MediaType; import org.jclouds.http.HttpRequest; import org.jclouds.io.MutableContentMetadata; @@ -54,7 +53,7 @@ public class BindToXMLPayload implements Binder { request.setPayload(xml); MutableContentMetadata metadata = request.getPayload().getContentMetadata(); if (contentTypeMustBeAdded(metadata)) { - metadata.setContentType(MediaType.APPLICATION_XML); + metadata.setContentType("application/xml"); } return request; } catch (IOException ex) { diff --git a/core/src/main/java/org/jclouds/rest/config/RestModule.java b/core/src/main/java/org/jclouds/rest/config/RestModule.java index d7c0fa9090..d6bfe61685 100644 --- a/core/src/main/java/org/jclouds/rest/config/RestModule.java +++ b/core/src/main/java/org/jclouds/rest/config/RestModule.java @@ -27,7 +27,6 @@ import java.util.concurrent.atomic.AtomicReference; import javax.inject.Named; import javax.inject.Singleton; -import javax.ws.rs.core.UriBuilder; import org.jclouds.functions.IdentityFunction; import org.jclouds.http.HttpRequest; @@ -71,7 +70,6 @@ import com.google.inject.TypeLiteral; import com.google.inject.assistedinject.FactoryModuleBuilder; import com.google.inject.name.Names; import com.google.inject.util.Types; -import com.sun.jersey.api.uri.UriBuilderImpl; public class RestModule extends AbstractModule { @@ -98,7 +96,6 @@ public class RestModule extends AbstractModule { install(new GsonModule()); install(new FactoryModuleBuilder().build(BindToJsonPayloadWrappedWith.Factory.class)); bind(IdentityFunction.class).toInstance(IdentityFunction.INSTANCE); - bind(UriBuilder.class).to(UriBuilderImpl.class); bind(AsyncRestClientProxy.Factory.class).to(Factory.class).in(Scopes.SINGLETON); BinderUtils.bindAsyncClient(binder(), HttpAsyncClient.class); BinderUtils.bindClient(binder(), HttpClient.class, HttpAsyncClient.class, ImmutableMap., Class> of( @@ -209,4 +206,4 @@ public class RestModule extends AbstractModule { return CacheBuilder.newBuilder().build(createClientForCaller); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/jclouds/rest/internal/AsyncRestClientProxy.java b/core/src/main/java/org/jclouds/rest/internal/AsyncRestClientProxy.java index 5732010210..9a332a89a8 100644 --- a/core/src/main/java/org/jclouds/rest/internal/AsyncRestClientProxy.java +++ b/core/src/main/java/org/jclouds/rest/internal/AsyncRestClientProxy.java @@ -28,7 +28,6 @@ import javax.annotation.Resource; import javax.inject.Named; import javax.inject.Qualifier; import javax.inject.Singleton; -import javax.ws.rs.Path; import org.jclouds.Constants; import org.jclouds.concurrent.ExceptionParsingListenableFuture; @@ -75,8 +74,8 @@ import com.google.inject.util.Types; * instance of interface set in returnVal, adding the current JAXrs annotations * to whatever are on that class. *
    - *
  • ex. if the method with {@link Delegate} has a {@link Path} annotation, - * and the returnval interface also has {@link Path}, these values are combined. + *
  • ex. if the method with {@link Delegate} has a {@code Path} annotation, + * and the returnval interface also has {@code Path}, these values are combined. *
  • *
*
  • if {@link RestAnnotationProcessor#delegationMap} contains a mapping for @@ -300,4 +299,4 @@ public class AsyncRestClientProxy implements InvocationHandler { public String toString() { return "Client Proxy for :" + declaring.getName(); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/jclouds/rest/internal/GeneratedHttpRequest.java b/core/src/main/java/org/jclouds/rest/internal/GeneratedHttpRequest.java index 1ee8266618..cb0ae42886 100644 --- a/core/src/main/java/org/jclouds/rest/internal/GeneratedHttpRequest.java +++ b/core/src/main/java/org/jclouds/rest/internal/GeneratedHttpRequest.java @@ -41,16 +41,17 @@ import com.google.common.collect.Multimap; * * @author Adrian Cole */ +// TODO: get rid of all the mock tests so that this can be made final public class GeneratedHttpRequest extends HttpRequest { - public static Builder builder() { - return new ConcreteBuilder(); + public static Builder builder() { + return new Builder(); } - public Builder toBuilder() { - return new ConcreteBuilder().fromGeneratedHttpRequest(this); + public Builder toBuilder() { + return new Builder().fromGeneratedHttpRequest(this); } - public static abstract class Builder> extends HttpRequest.Builder { + public static class Builder extends HttpRequest.Builder { protected Class declaring; protected Method javaMethod; // args can be null, so cannot use immutable list @@ -60,67 +61,65 @@ public class GeneratedHttpRequest extends HttpRequest { /** * @see GeneratedHttpRequest#getDeclaring() */ - public T declaring(Class declaring) { + public Builder declaring(Class declaring) { this.declaring = checkNotNull(declaring, "declaring"); - return self(); + return this; } /** * @see GeneratedHttpRequest#getJavaMethod() */ - public T javaMethod(Method javaMethod) { + public Builder javaMethod(Method javaMethod) { this.javaMethod = checkNotNull(javaMethod, "javaMethod"); - return self(); + return this; } /** * @see GeneratedHttpRequest#getArgs() */ - public T args(Iterable args) { + public Builder args(Iterable args) { this.args = Lists.newArrayList(checkNotNull(args, "args")); - return self(); + return this; } /** * @see GeneratedHttpRequest#getArgs() */ - public T args(@Nullable Object[] args) { + public Builder args(@Nullable Object[] args) { return args(Arrays.asList(args != null ? args : new Object[] {})); } /** * @see GeneratedHttpRequest#getArgs() */ - public T arg(@Nullable Object arg) { + public Builder arg(@Nullable Object arg) { this.args.add(arg); - return self(); + return this; } /** * @see GeneratedHttpRequest#getCaller() */ - public T caller(@Nullable ClassMethodArgs caller) { + public Builder caller(@Nullable ClassMethodArgs caller) { this.caller = Optional.fromNullable(caller); - return self(); + return this; } public GeneratedHttpRequest build() { return new GeneratedHttpRequest(method, endpoint, headers.build(), payload, declaring, javaMethod, - args, skips.build(), filters.build(), caller); + args, filters.build(), caller); } - public T fromGeneratedHttpRequest(GeneratedHttpRequest in) { + public Builder fromGeneratedHttpRequest(GeneratedHttpRequest in) { return super.fromHttpRequest(in) .declaring(in.getDeclaring()) .javaMethod(in.getJavaMethod()) .args(in.getArgs()) .caller(in.getCaller().orNull()); } - } - - private static class ConcreteBuilder extends Builder { + @Override - protected ConcreteBuilder self() { + protected Builder self() { return this; } } @@ -130,10 +129,10 @@ public class GeneratedHttpRequest extends HttpRequest { private final List args; private final Optional caller; - protected GeneratedHttpRequest(String method, URI endpoint, Multimap headers, @Nullable Payload payload, - Class declaring, Method javaMethod, Iterable args, Iterable skips, - Iterable filters, Optional caller) { - super(method, endpoint, headers, payload, skips, filters); + protected GeneratedHttpRequest(String method, URI endpoint, Multimap headers, + @Nullable Payload payload, Class declaring, Method javaMethod, Iterable args, + Iterable filters, Optional caller) { + super(method, endpoint, headers, payload, filters); this.declaring = checkNotNull(declaring, "declaring"); this.javaMethod = checkNotNull(javaMethod, "javaMethod"); // TODO make immutable. ImmutableList.of() doesn't accept nulls diff --git a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java index 84110c848b..b608ea8c57 100644 --- a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java +++ b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java @@ -18,22 +18,37 @@ */ package org.jclouds.rest.internal; +import static com.google.common.base.Functions.compose; import static com.google.common.base.Functions.toStringFunction; +import static com.google.common.base.Objects.equal; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Predicates.and; +import static com.google.common.base.Predicates.in; +import static com.google.common.base.Predicates.not; +import static com.google.common.base.Predicates.notNull; import static com.google.common.collect.Collections2.filter; +import static com.google.common.collect.Iterables.any; import static com.google.common.collect.Iterables.concat; import static com.google.common.collect.Iterables.get; import static com.google.common.collect.Iterables.transform; +import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Lists.newLinkedList; import static com.google.common.collect.Maps.filterValues; import static com.google.common.collect.Maps.newHashMap; +import static com.google.common.collect.Multimaps.filterKeys; +import static com.google.common.collect.Multimaps.transformValues; import static com.google.common.collect.Sets.newTreeSet; +import static com.google.common.net.HttpHeaders.ACCEPT; +import static com.google.common.net.HttpHeaders.CONTENT_TYPE; +import static com.google.common.net.HttpHeaders.HOST; import static java.util.Arrays.asList; -import static javax.ws.rs.core.HttpHeaders.ACCEPT; -import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE; -import static javax.ws.rs.core.HttpHeaders.HOST; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static javax.ws.rs.core.MediaType.APPLICATION_XML; +import static org.jclouds.http.Uris.uriBuilder; import static org.jclouds.io.Payloads.newPayload; +import static org.jclouds.util.Maps2.convertUnsafe; +import static org.jclouds.util.Strings2.replaceTokens; import java.io.InputStream; import java.lang.annotation.Annotation; @@ -43,9 +58,6 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.WildcardType; import java.net.URI; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -54,19 +66,14 @@ import java.util.Set; import java.util.SortedSet; import javax.annotation.Resource; -import javax.inject.Provider; import javax.ws.rs.Consumes; import javax.ws.rs.FormParam; import javax.ws.rs.HeaderParam; import javax.ws.rs.HttpMethod; -import javax.ws.rs.MatrixParam; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriBuilderException; import org.jclouds.Constants; import org.jclouds.functions.IdentityFunction; @@ -75,6 +82,7 @@ import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpUtils; +import org.jclouds.http.Uris.UriBuilder; import org.jclouds.http.functions.ParseFirstJsonValueNamed; import org.jclouds.http.functions.ParseJson; import org.jclouds.http.functions.ParseSax; @@ -87,7 +95,6 @@ import org.jclouds.http.functions.ReturnStringIf2xx; import org.jclouds.http.functions.ReturnTrueIf2xx; import org.jclouds.http.functions.UnwrapOnlyJsonValue; import org.jclouds.http.options.HttpRequestOptions; -import org.jclouds.http.utils.Queries; import org.jclouds.internal.ClassMethodArgs; import org.jclouds.io.ContentMetadata; import org.jclouds.io.ContentMetadataCodec; @@ -113,7 +120,6 @@ import org.jclouds.rest.annotations.FormParams; import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.JAXBResponseParser; import org.jclouds.rest.annotations.MapBinder; -import org.jclouds.rest.annotations.MatrixParams; import org.jclouds.rest.annotations.OnlyElement; import org.jclouds.rest.annotations.OverrideRequestFilters; import org.jclouds.rest.annotations.ParamParser; @@ -133,17 +139,12 @@ import org.jclouds.rest.annotations.XMLResponseParser; import org.jclouds.rest.binders.BindMapToStringPayload; import org.jclouds.rest.binders.BindToJsonPayloadWrappedWith; import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions; -import org.jclouds.util.Maps2; -import org.jclouds.util.Strings2; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; -import com.google.common.base.Functions; import com.google.common.base.Objects; import com.google.common.base.Optional; -import com.google.common.base.Preconditions; import com.google.common.base.Predicate; -import com.google.common.base.Predicates; import com.google.common.base.Supplier; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; @@ -153,12 +154,10 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet.Builder; -import com.google.common.collect.Iterables; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.LinkedListMultimap; -import com.google.common.collect.Lists; import com.google.common.collect.Multimap; -import com.google.common.collect.Multimaps; +import com.google.common.primitives.Chars; import com.google.common.util.concurrent.ListenableFuture; import com.google.inject.Inject; import com.google.inject.Injector; @@ -184,7 +183,6 @@ public class RestAnnotationProcessor { static final LoadingCache>> methodToIndexOfParamToHeaderParamAnnotations = createMethodToIndexOfParamToAnnotation(HeaderParam.class); static final LoadingCache>> methodToIndexOfParamToEndpointAnnotations = createMethodToIndexOfParamToAnnotation(Endpoint.class); static final LoadingCache>> methodToIndexOfParamToEndpointParamAnnotations = createMethodToIndexOfParamToAnnotation(EndpointParam.class); - static final LoadingCache>> methodToIndexOfParamToMatrixParamAnnotations = createMethodToIndexOfParamToAnnotation(MatrixParam.class); static final LoadingCache>> methodToIndexOfParamToFormParamAnnotations = createMethodToIndexOfParamToAnnotation(FormParam.class); static final LoadingCache>> methodToIndexOfParamToQueryParamAnnotations = createMethodToIndexOfParamToAnnotation(QueryParam.class); static final LoadingCache>> methodToIndexOfParamToPathParamAnnotations = createMethodToIndexOfParamToAnnotation(PathParam.class); @@ -223,11 +221,11 @@ public class RestAnnotationProcessor { } - private static final Function, ? extends Part> ENTRY_TO_PART = new Function, Part>() { + private static final Function, ? extends Part> ENTRY_TO_PART = new Function, Part>() { @Override - public Part apply(Entry from) { - return Part.create(from.getKey(), from.getValue()); + public Part apply(Entry from) { + return Part.create(from.getKey(), from.getValue().toString()); } }; @@ -249,11 +247,9 @@ public class RestAnnotationProcessor { private final ParseSax.Factory parserFactory; private final HttpUtils utils; private final ContentMetadataCodec contentMetadataCodec; - private final Provider uriBuilderProvider; private final LoadingCache, Boolean> seedAnnotationCache; private final String apiVersion; private final String buildVersion; - private char[] skips; @Inject private InputParamValidator inputParamValidator; @@ -282,7 +278,7 @@ public class RestAnnotationProcessor { if (wrappingTransformer instanceof InvocationContext) { ((InvocationContext) wrappingTransformer).setContext(request); } - transformer = Functions.compose(Function.class.cast(wrappingTransformer), transformer); + transformer = compose(Function.class.cast(wrappingTransformer), transformer); } return transformer; } @@ -297,7 +293,7 @@ public class RestAnnotationProcessor { transformer = new ParseFirstJsonValueNamed(injector.getInstance(GsonWrapper.class), TypeLiteral.get(returnVal), method.getAnnotation(SelectJson.class).value()); if (method.isAnnotationPresent(OnlyElement.class)) - transformer = Functions.compose(new OnlyElementOrNull(), transformer); + transformer = compose(new OnlyElementOrNull(), transformer); } else { transformer = injector.getInstance(getParserOrThrowException(method)); } @@ -329,15 +325,9 @@ public class RestAnnotationProcessor { this.parserFactory = parserFactory; this.utils = utils; this.contentMetadataCodec = contentMetadataCodec; - this.uriBuilderProvider = injector.getProvider(UriBuilder.class); this.seedAnnotationCache = seedAnnotationCache; seedAnnotationCache.getUnchecked(declaring); this.delegationMap = delegationMap; - if (declaring.isAnnotationPresent(SkipEncoding.class)) { - skips = declaring.getAnnotation(SkipEncoding.class).value(); - } else { - skips = new char[] {}; - } this.apiVersion = apiVersion; this.buildVersion = buildVersion; } @@ -359,9 +349,9 @@ public class RestAnnotationProcessor { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; MethodKey that = MethodKey.class.cast(obj); - return Objects.equal(this.declaringClass, that.declaringClass) - && Objects.equal(this.name, that.name) - && Objects.equal(this.parametersTypeHashCode, that.parametersTypeHashCode); + return equal(this.declaringClass, that.declaringClass) + && equal(this.name, that.name) + && equal(this.parametersTypeHashCode, that.parametersTypeHashCode); } private final String name; @@ -399,7 +389,7 @@ public class RestAnnotationProcessor { new ClassMethodArgs(method.getDeclaringClass(), method, args))); } - GeneratedHttpRequest.Builder requestBuilder = GeneratedHttpRequest.builder(); + GeneratedHttpRequest.Builder requestBuilder = GeneratedHttpRequest.builder(); HttpRequest r = RestAnnotationProcessor.findHttpRequestInArgs(args); if (r != null) { requestBuilder.fromHttpRequest(r); @@ -407,16 +397,18 @@ public class RestAnnotationProcessor { requestBuilder.method(getHttpMethodOrConstantOrThrowException(method)); } + // URI template in rfc6570 form + UriBuilder uriBuilder = uriBuilder(endpoint.get().toString()); + + overridePathEncoding(uriBuilder, method); + requestBuilder.declaring(declaring) .javaMethod(method) .args(args) .caller(caller) - .skips(skips) .filters(getFiltersIfAnnotated(method)); - - UriBuilder builder = uriBuilderProvider.get().uri(endpoint.get()); - Multimap tokenValues = LinkedHashMultimap.create(); + Multimap tokenValues = LinkedHashMultimap.create(); tokenValues.put(Constants.PROPERTY_API_VERSION, apiVersion); tokenValues.put(Constants.PROPERTY_BUILD_VERSION, buildVersion); @@ -424,15 +416,15 @@ public class RestAnnotationProcessor { // make sure any path from the caller is a prefix if (caller != null) { tokenValues.putAll(addPathAndGetTokens(caller.getMethod().getDeclaringClass(), caller.getMethod(), - caller.getArgs(), builder)); + caller.getArgs(), uriBuilder)); } - tokenValues.putAll(addPathAndGetTokens(declaring, method, args, builder)); + tokenValues.putAll(addPathAndGetTokens(declaring, method, args, uriBuilder)); - Multimap formParams = addFormParams(tokenValues.entries(), method, args); - Multimap queryParams = addQueryParams(tokenValues.entries(), method, args); - Multimap matrixParams = addMatrixParams(tokenValues.entries(), method, args); - Multimap headers = buildHeaders(tokenValues.entries(), method, args); + Multimap formParams = addFormParams(tokenValues, method, args); + Multimap queryParams = addQueryParams(tokenValues, method, args); + Multimap headers = buildHeaders(tokenValues, method, args); + if (r != null) headers.putAll(r.getHeaders()); @@ -447,60 +439,50 @@ public class RestAnnotationProcessor { for(HttpRequestOptions options : findOptionsIn(method, args)) { injector.injectMembers(options);// TODO test case for (Entry header : options.buildRequestHeaders().entries()) { - headers.put(header.getKey(), Strings2.replaceTokens(header.getValue(), tokenValues.entries())); - } - for (Entry matrix : options.buildMatrixParameters().entries()) { - matrixParams.put(matrix.getKey(), Strings2.replaceTokens(matrix.getValue(), tokenValues.entries())); + headers.put(header.getKey(), replaceTokens(header.getValue(), tokenValues)); } for (Entry query : options.buildQueryParameters().entries()) { - queryParams.put(query.getKey(), Strings2.replaceTokens(query.getValue(), tokenValues.entries())); + queryParams.put(query.getKey(), replaceTokens(query.getValue(), tokenValues)); } for (Entry form : options.buildFormParameters().entries()) { - formParams.put(form.getKey(), Strings2.replaceTokens(form.getValue(), tokenValues.entries())); + formParams.put(form.getKey(), replaceTokens(form.getValue(), tokenValues)); } String pathSuffix = options.buildPathSuffix(); if (pathSuffix != null) { - builder.path(pathSuffix); + uriBuilder.appendPath(pathSuffix); } String stringPayload = options.buildStringPayload(); if (stringPayload != null) payload = Payloads.newStringPayload(stringPayload); } - - if (matrixParams.size() > 0) { - for (String key : matrixParams.keySet()) - builder.matrixParam(key, Lists.newArrayList(matrixParams.get(key)).toArray()); - } - + if (queryParams.size() > 0) { - builder.replaceQuery(Queries.makeQueryLine(queryParams, null, skips)); + uriBuilder.query(queryParams); } requestBuilder.headers(filterOutContentHeaders(headers)); - try { - requestBuilder.endpoint(builder.buildFromEncodedMap(Maps2.convertUnsafe(tokenValues))); - } catch (IllegalArgumentException e) { - throw new IllegalStateException(e); - } catch (UriBuilderException e) { - throw new IllegalStateException(e); - } - + requestBuilder.endpoint(uriBuilder.build(convertUnsafe(tokenValues))); + if (payload == null) payload = findPayloadInArgs(args); - List parts = getParts(method, args, concat(tokenValues.entries(), formParams.entries())); + + List parts = getParts(method, args, ImmutableMultimap. builder() + .putAll(tokenValues) + .putAll(formParams).build()); + if (parts.size() > 0) { if (formParams.size() > 0) { parts = newLinkedList(concat(transform(formParams.entries(), ENTRY_TO_PART), parts)); } payload = new MultipartForm(BOUNDARY, parts); } else if (formParams.size() > 0) { - payload = Payloads.newUrlEncodedFormPayload(formParams, skips); + payload = Payloads.newUrlEncodedFormPayload(transformValues(formParams, NullableToStringFunction.INSTANCE)); } else if (headers.containsKey(CONTENT_TYPE)) { if (payload == null) payload = Payloads.newByteArrayPayload(new byte[] {}); - payload.getContentMetadata().setContentType(Iterables.get(headers.get(CONTENT_TYPE), 0)); + payload.getContentMetadata().setContentType(get(headers.get(CONTENT_TYPE), 0)); } if (payload != null) { requestBuilder.payload(payload); @@ -512,7 +494,7 @@ public class RestAnnotationProcessor { Map mapParams = buildPostParams(method, args); if (method.isAnnotationPresent(PayloadParams.class)) { PayloadParams params = method.getAnnotation(PayloadParams.class); - addMapPayload(mapParams, params, headers.entries()); + addMapPayload(mapParams, params, headers); } request = mapBinder.bindToRequest(request, mapParams); } else { @@ -526,6 +508,33 @@ public class RestAnnotationProcessor { return request; } + // TODO cache + private void overridePathEncoding(UriBuilder uriBuilder, Method method) { + if (declaring.isAnnotationPresent(SkipEncoding.class)) { + uriBuilder.skipPathEncoding(Chars.asList(declaring.getAnnotation(SkipEncoding.class).value())); + } + if (method.isAnnotationPresent(SkipEncoding.class)) { + uriBuilder.skipPathEncoding(Chars.asList(method.getAnnotation(SkipEncoding.class).value())); + } + } + + // different than guava as accepts null + private static enum NullableToStringFunction implements Function { + INSTANCE; + + @Override + public String apply(Object o) { + if (o == null) + return null; + return o.toString(); + } + + @Override + public String toString() { + return "toString"; + } + } + private Optional findEndpoint(Method method, Object... args) { ClassMethodArgs cma = logger.isTraceEnabled() ? new ClassMethodArgs(method.getDeclaringClass(), method, args) : null; @@ -560,57 +569,22 @@ public class RestAnnotationProcessor { } public static Multimap filterOutContentHeaders(Multimap headers) { - // http message usually comes in as a null key header, let's filter it - // out. - return ImmutableMultimap.copyOf(Multimaps.filterKeys(headers, - Predicates.and( - Predicates.notNull(), - Predicates.not(Predicates.in(ContentMetadata.HTTP_HEADERS))))); + // http message usually comes in as a null key header, let's filter it out. + return ImmutableMultimap.copyOf(filterKeys(headers, and(notNull(), not(in(ContentMetadata.HTTP_HEADERS))))); } public static final String BOUNDARY = "--JCLOUDS--"; - private Multimap addPathAndGetTokens(Class clazz, Method method, Object[] args, UriBuilder builder) { + private Multimap addPathAndGetTokens(Class clazz, Method method, Object[] args, UriBuilder uriBuilder) { if (clazz.isAnnotationPresent(Path.class)) - builder.path(clazz); + uriBuilder.appendPath(clazz.getAnnotation(Path.class).value()); if (method.isAnnotationPresent(Path.class)) - builder.path(method); - return encodeValues(getPathParamKeyValues(method, args), skips); + uriBuilder.appendPath(method.getAnnotation(Path.class).value()); + return getPathParamKeyValues(method, args); } - public URI replaceQuery(URI in, String newQuery, @Nullable Comparator> sorter) { - return replaceQuery(uriBuilderProvider, in, newQuery, sorter, skips); - } - - public static URI replaceQuery(Provider uriBuilderProvider, URI in, String newQuery, - @Nullable Comparator> sorter, char... skips) { - UriBuilder builder = uriBuilderProvider.get().uri(in); - builder.replaceQuery(Queries.makeQueryLine(Queries.parseQueryToMap(newQuery), sorter, skips)); - return builder.build(); - } - - private Multimap addMatrixParams(Collection> tokenValues, Method method, - Object... args) { - Multimap matrixMap = LinkedListMultimap.create(); - if (declaring.isAnnotationPresent(MatrixParams.class)) { - MatrixParams matrix = declaring.getAnnotation(MatrixParams.class); - addMatrix(matrixMap, matrix, tokenValues); - } - - if (method.isAnnotationPresent(MatrixParams.class)) { - MatrixParams matrix = method.getAnnotation(MatrixParams.class); - addMatrix(matrixMap, matrix, tokenValues); - } - - for (Entry matrix : getMatrixParamKeyValues(method, args).entries()) { - matrixMap.put(matrix.getKey(), Strings2.replaceTokens(matrix.getValue(), tokenValues)); - } - return matrixMap; - } - - private Multimap addFormParams(Collection> tokenValues, Method method, - Object... args) { - Multimap formMap = LinkedListMultimap.create(); + private Multimap addFormParams(Multimap tokenValues, Method method, Object... args) { + Multimap formMap = LinkedListMultimap.create(); if (declaring.isAnnotationPresent(FormParams.class)) { FormParams form = declaring.getAnnotation(FormParams.class); addForm(formMap, form, tokenValues); @@ -621,15 +595,15 @@ public class RestAnnotationProcessor { addForm(formMap, form, tokenValues); } - for (Entry form : getFormParamKeyValues(method, args).entries()) { - formMap.put(form.getKey(), Strings2.replaceTokens(form.getValue(), tokenValues)); + for (Entry form : getFormParamKeyValues(method, args).entries()) { + formMap.put(form.getKey(), replaceTokens(form.getValue().toString(), tokenValues)); } return formMap; } - private Multimap addQueryParams(Collection> tokenValues, Method method, + private Multimap addQueryParams(Multimap tokenValues, Method method, Object... args) { - Multimap queryMap = LinkedListMultimap.create(); + Multimap queryMap = LinkedListMultimap.create(); if (declaring.isAnnotationPresent(QueryParams.class)) { QueryParams query = declaring.getAnnotation(QueryParams.class); addQuery(queryMap, query, tokenValues); @@ -640,55 +614,41 @@ public class RestAnnotationProcessor { addQuery(queryMap, query, tokenValues); } - for (Entry query : getQueryParamKeyValues(method, args).entries()) { - queryMap.put(query.getKey(), Strings2.replaceTokens(query.getValue(), tokenValues)); + for (Entry query : getQueryParamKeyValues(method, args).entries()) { + queryMap.put(query.getKey(), replaceTokens(query.getValue().toString(), tokenValues)); } return queryMap; } - private void addForm(Multimap formParams, FormParams form, - Collection> tokenValues) { + private void addForm(Multimap formParams, FormParams form, Multimap tokenValues) { for (int i = 0; i < form.keys().length; i++) { if (form.values()[i].equals(FormParams.NULL)) { formParams.removeAll(form.keys()[i]); formParams.put(form.keys()[i], null); } else { - formParams.put(form.keys()[i], Strings2.replaceTokens(form.values()[i], tokenValues)); + formParams.put(form.keys()[i], replaceTokens(form.values()[i], tokenValues)); } } } - private void addQuery(Multimap queryParams, QueryParams query, - Collection> tokenValues) { + private void addQuery(Multimap queryParams, QueryParams query, Multimap tokenValues) { for (int i = 0; i < query.keys().length; i++) { if (query.values()[i].equals(QueryParams.NULL)) { queryParams.removeAll(query.keys()[i]); queryParams.put(query.keys()[i], null); } else { - queryParams.put(query.keys()[i], Strings2.replaceTokens(query.values()[i], tokenValues)); - } - } - } - - private void addMatrix(Multimap matrixParams, MatrixParams matrix, - Collection> tokenValues) { - for (int i = 0; i < matrix.keys().length; i++) { - if (matrix.values()[i].equals(MatrixParams.NULL)) { - matrixParams.removeAll(matrix.keys()[i]); - matrixParams.put(matrix.keys()[i], null); - } else { - matrixParams.put(matrix.keys()[i], Strings2.replaceTokens(matrix.values()[i], tokenValues)); + queryParams.put(query.keys()[i], replaceTokens(query.values()[i], tokenValues)); } } } private void addMapPayload(Map postParams, PayloadParams mapDefaults, - Collection> tokenValues) { + Multimap headers) { for (int i = 0; i < mapDefaults.keys().length; i++) { if (mapDefaults.values()[i].equals(PayloadParams.NULL)) { postParams.put(mapDefaults.keys()[i], null); } else { - postParams.put(mapDefaults.keys()[i], Strings2.replaceTokens(mapDefaults.values()[i], tokenValues)); + postParams.put(mapDefaults.keys()[i], replaceTokens(mapDefaults.values()[i], headers)); } } } @@ -696,7 +656,7 @@ public class RestAnnotationProcessor { //TODO: change to LoadingCache> and move this logic to the CacheLoader. @VisibleForTesting List getFiltersIfAnnotated(Method method) { - List filters = Lists.newArrayList(); + List filters = newArrayList(); if (declaring.isAnnotationPresent(RequestFilters.class)) { for (Class clazz : declaring.getAnnotation(RequestFilters.class).value()) { HttpRequestFilter instance = injector.getInstance(clazz); @@ -760,7 +720,7 @@ public class RestAnnotationProcessor { return null; } - private final static TypeLiteral> uriSupplierLiteral = new TypeLiteral>() { + private static final TypeLiteral> uriSupplierLiteral = new TypeLiteral>() { }; // TODO: change to LoadingCache and move this logic to the CacheLoader. @@ -825,9 +785,9 @@ public class RestAnnotationProcessor { } else if (method.getReturnType().equals(HttpResponse.class) || TypeLiteral.get(method.getGenericReturnType()).equals(futureHttpResponseLiteral)) { return Key.get(Class.class.cast(IdentityFunction.class)); - } else if (getAcceptHeadersOrNull(method).contains(MediaType.APPLICATION_JSON)) { + } else if (getAcceptHeadersOrNull(method).contains(APPLICATION_JSON)) { return getJsonParserKeyForMethod(method); - } else if (getAcceptHeadersOrNull(method).contains(MediaType.APPLICATION_XML) + } else if (getAcceptHeadersOrNull(method).contains(APPLICATION_XML) || method.isAnnotationPresent(JAXBResponseParser.class)) { return getJAXBParserKeyForMethod(method); } else if (method.getReturnType().equals(String.class) @@ -860,7 +820,7 @@ public class RestAnnotationProcessor { if (method.getReturnType().getTypeParameters().length == 0) { returnVal = method.getReturnType(); } else if (method.getReturnType().equals(ListenableFuture.class)) { - ParameterizedType futureType = ((ParameterizedType) method.getGenericReturnType()); + ParameterizedType futureType = (ParameterizedType) method.getGenericReturnType(); returnVal = futureType.getActualTypeArguments()[0]; if (returnVal instanceof WildcardType) returnVal = WildcardType.class.cast(returnVal).getUpperBounds()[0]; @@ -968,7 +928,7 @@ public class RestAnnotationProcessor { notEmpty).entrySet()); OUTER: for (Entry> entry : binderOrWrapWith) { boolean shouldBreak = false; - Annotation annotation = Iterables.get(entry.getValue(), 0); + Annotation annotation = get(entry.getValue(), 0); Binder binder; if (annotation instanceof BinderParam) binder = injector.getInstance(BinderParam.class.cast(annotation).value()); @@ -1020,7 +980,7 @@ public class RestAnnotationProcessor { if (NULLABLE.apply(a)) continue OUTER; } - Preconditions.checkNotNull(null, request.getJavaMethod().getName() + " parameter " + (entry.getKey() + 1)); + checkNotNull(null, request.getJavaMethod().getName() + " parameter " + (entry.getKey() + 1)); } } @@ -1072,8 +1032,7 @@ public class RestAnnotationProcessor { return result.build(); } - public Multimap buildHeaders(Collection> tokenValues, Method method, - final Object... args) { + public Multimap buildHeaders(Multimap tokenValues, Method method, Object... args) { Multimap headers = LinkedHashMultimap.create(); addHeaderIfAnnotationPresentOnMethod(headers, method, tokenValues); LoadingCache> indexToHeaderParam = methodToIndexOfParamToHeaderParamAnnotations @@ -1081,7 +1040,7 @@ public class RestAnnotationProcessor { for (Entry> entry : indexToHeaderParam.asMap().entrySet()) { for (Annotation key : entry.getValue()) { String value = args[entry.getKey()].toString(); - value = Strings2.replaceTokens(value, tokenValues); + value = replaceTokens(value, tokenValues); headers.put(((HeaderParam) key).value(), value); } } @@ -1097,7 +1056,7 @@ public class RestAnnotationProcessor { } private static List getAcceptHeadersOrNull(Method method) { - List accept = Collections.emptyList(); + List accept = ImmutableList.of(); if (method.getDeclaringClass().isAnnotationPresent(Consumes.class)) { Consumes header = method.getDeclaringClass().getAnnotation(Consumes.class); accept = asList(header.value()); @@ -1121,7 +1080,7 @@ public class RestAnnotationProcessor { } public void addHeaderIfAnnotationPresentOnMethod(Multimap headers, Method method, - Collection> tokenValues) { + Multimap tokenValues) { if (declaring.isAnnotationPresent(Headers.class)) { Headers header = declaring.getAnnotation(Headers.class); addHeader(headers, header, tokenValues); @@ -1132,18 +1091,17 @@ public class RestAnnotationProcessor { } } - private void addHeader(Multimap headers, Headers header, - Collection> tokenValues) { + private void addHeader(Multimap headers, Headers header, Multimap tokenValues) { for (int i = 0; i < header.keys().length; i++) { String value = header.values()[i]; - value = Strings2.replaceTokens(value, tokenValues); + value = replaceTokens(value, tokenValues); headers.put(header.keys()[i], value); } } - List getParts(Method method, Object[] args, Iterable> iterable) { - List parts = newLinkedList(); + private List getParts(Method method, Object[] args, Multimap tokenValues) { + ImmutableList.Builder parts = ImmutableList. builder(); LoadingCache> indexToPartParam = methodToIndexOfParamToPartParamAnnotations .getUnchecked(method); for (Entry> entry : indexToPartParam.asMap().entrySet()) { @@ -1153,14 +1111,14 @@ public class RestAnnotationProcessor { if (!PartParam.NO_CONTENT_TYPE.equals(param.contentType())) options.contentType(param.contentType()); if (!PartParam.NO_FILENAME.equals(param.filename())) - options.filename(Strings2.replaceTokens(param.filename(), iterable)); + options.filename(replaceTokens(param.filename(), tokenValues)); Object arg = args[entry.getKey()]; - Preconditions.checkNotNull(arg, param.name()); + checkNotNull(arg, param.name()); Part part = Part.create(param.name(), newPayload(arg), options); parts.add(part); } } - return parts; + return parts.build(); } public static HttpRequest findHttpRequestInArgs(Object[] args) { @@ -1184,8 +1142,8 @@ public class RestAnnotationProcessor { } //TODO: change to LoadingCache and move this logic to the CacheLoader. - private Multimap getPathParamKeyValues(Method method, Object... args) { - Multimap pathParamValues = LinkedHashMultimap.create(); + private Multimap getPathParamKeyValues(Method method, Object... args) { + Multimap pathParamValues = LinkedHashMultimap.create(); LoadingCache> indexToPathParam = methodToIndexOfParamToPathParamAnnotations.getUnchecked(method); LoadingCache> indexToParamExtractor = methodToIndexOfParamToParamParserAnnotations.getUnchecked(method); @@ -1240,48 +1198,14 @@ public class RestAnnotationProcessor { }; private static boolean containsNullable(Annotation[] annotations) { - return Iterables.any(ImmutableSet.copyOf(annotations), NULLABLE); + return any(ImmutableSet.copyOf(annotations), NULLABLE); } - private Multimap encodeValues(Multimap unencoded, char... skips) { - Multimap encoded = LinkedHashMultimap.create(); - for (Entry entry : unencoded.entries()) { - encoded.put(entry.getKey(), Strings2.urlEncode(entry.getValue(), skips)); - } - return encoded; - } - - //TODO: change to LoadingCache and move this logic to the CacheLoader. - private Multimap getMatrixParamKeyValues(Method method, Object... args) { - Multimap matrixParamValues = LinkedHashMultimap.create(); - LoadingCache> indexToMatrixParam = methodToIndexOfParamToMatrixParamAnnotations - .getUnchecked(method); - - LoadingCache> indexToParamExtractor = methodToIndexOfParamToParamParserAnnotations - .getUnchecked(method); - for (Entry> entry : indexToMatrixParam.asMap().entrySet()) { - for (Annotation key : entry.getValue()) { - Set extractors = indexToParamExtractor.getUnchecked(entry.getKey()); - String paramKey = ((MatrixParam) key).value(); - Optional paramValue = getParamValue(method, args, extractors, entry, paramKey); - if (paramValue.isPresent()) - matrixParamValues.put(paramKey, paramValue.get().toString()); - } - } - - if (method.isAnnotationPresent(MatrixParam.class) && method.isAnnotationPresent(ParamParser.class)) { - String paramKey = method.getAnnotation(MatrixParam.class).value(); - String paramValue = injector.getInstance(method.getAnnotation(ParamParser.class).value()).apply(args); - matrixParamValues.put(paramKey, paramValue); - - } - return matrixParamValues; - } //TODO: change to LoadingCache and move this logic to the CacheLoader. //take care to manage size of this cache - private Multimap getFormParamKeyValues(Method method, Object... args) { - Multimap formParamValues = LinkedHashMultimap.create(); + private Multimap getFormParamKeyValues(Method method, Object... args) { + Multimap formParamValues = LinkedHashMultimap.create(); LoadingCache> indexToFormParam = methodToIndexOfParamToFormParamAnnotations .getUnchecked(method); @@ -1307,8 +1231,8 @@ public class RestAnnotationProcessor { } //TODO: change to LoadingCache and move this logic to the CacheLoader. - private Multimap getQueryParamKeyValues(Method method, Object... args) { - Multimap queryParamValues = LinkedHashMultimap.create(); + private Multimap getQueryParamKeyValues(Method method, Object... args) { + Multimap queryParamValues = LinkedHashMultimap.create(); LoadingCache> indexToQueryParam = methodToIndexOfParamToQueryParamAnnotations .getUnchecked(method); diff --git a/core/src/main/java/org/jclouds/rest/internal/SeedAnnotationCache.java b/core/src/main/java/org/jclouds/rest/internal/SeedAnnotationCache.java index 6318c24bcc..2dbc3ad642 100644 --- a/core/src/main/java/org/jclouds/rest/internal/SeedAnnotationCache.java +++ b/core/src/main/java/org/jclouds/rest/internal/SeedAnnotationCache.java @@ -25,7 +25,6 @@ import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfP import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfParamToEndpointParamAnnotations; import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfParamToFormParamAnnotations; import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfParamToHeaderParamAnnotations; -import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfParamToMatrixParamAnnotations; import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfParamToParamParserAnnotations; import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfParamToPartParamAnnotations; import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfParamToPathParamAnnotations; @@ -43,7 +42,6 @@ import javax.ws.rs.Path; import org.jclouds.http.HttpRequest; import org.jclouds.logging.Logger; -import org.jclouds.rest.RestContext; import org.jclouds.rest.annotations.Delegate; import org.jclouds.rest.internal.RestAnnotationProcessor.MethodKey; @@ -85,7 +83,6 @@ public class SeedAnnotationCache extends CacheLoader, Boolean> { methodToIndexOfParamToBinderParamAnnotation.get(method).get(index); methodToIndexOfParamToWrapWithAnnotation.get(method).get(index); methodToIndexOfParamToHeaderParamAnnotations.get(method).get(index); - methodToIndexOfParamToMatrixParamAnnotations.get(method).get(index); methodToIndexOfParamToFormParamAnnotations.get(method).get(index); methodToIndexOfParamToQueryParamAnnotations.get(method).get(index); methodToIndexOfParamToEndpointAnnotations.get(method).get(index); @@ -113,4 +110,4 @@ public class SeedAnnotationCache extends CacheLoader, Boolean> { || ImmutableSet.copyOf(method.getParameterTypes()).contains(HttpRequest.class); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/jclouds/util/Patterns.java b/core/src/main/java/org/jclouds/util/Patterns.java index 22d5fd620f..1f479f3ce8 100644 --- a/core/src/main/java/org/jclouds/util/Patterns.java +++ b/core/src/main/java/org/jclouds/util/Patterns.java @@ -51,18 +51,25 @@ public class Patterns { public static final Pattern TRAILING_SLASHES = Pattern.compile("[/]*$"); public static final Pattern REST_CONTEXT_BUILDER = Pattern.compile("(.*ContextBuilder)<([^,]+), ?([^>]+)>"); - public final static LoadingCache CHAR_TO_ENCODED_PATTERN = CacheBuilder.newBuilder() - . build(new CacheLoader() { + public static final LoadingCache CHAR_TO_ENCODED = CacheBuilder.newBuilder() + . build(new CacheLoader() { @Override - public Pattern load(Character plain) throws ExecutionException { + public String load(Character plain) throws ExecutionException { try { - String encoded = URLEncoder.encode(plain + "", "UTF-8"); - return Pattern.compile(encoded); + return URLEncoder.encode(plain + "", "UTF-8"); } catch (UnsupportedEncodingException e) { throw new ExecutionException("Bad encoding on input: " + plain, e); } } }); + + public static final LoadingCache CHAR_TO_ENCODED_PATTERN = CacheBuilder.newBuilder() + . build(new CacheLoader() { + @Override + public Pattern load(Character plain) throws ExecutionException { + return Pattern.compile(CHAR_TO_ENCODED.get(plain)); + } + }); public final static LoadingCache CHAR_TO_PATTERN = CacheBuilder.newBuilder() . build(new CacheLoader() { diff --git a/core/src/main/java/org/jclouds/util/Strings2.java b/core/src/main/java/org/jclouds/util/Strings2.java index 49fd1d657e..886015e2e0 100644 --- a/core/src/main/java/org/jclouds/util/Strings2.java +++ b/core/src/main/java/org/jclouds/util/Strings2.java @@ -21,13 +21,10 @@ package org.jclouds.util; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.io.ByteStreams.toByteArray; import static com.google.common.io.Closeables.closeQuietly; -import static org.jclouds.util.Patterns.CHAR_TO_ENCODED_PATTERN; +import static org.jclouds.util.Patterns.CHAR_TO_ENCODED; import static org.jclouds.util.Patterns.CHAR_TO_PATTERN; -import static org.jclouds.util.Patterns.PLUS_PATTERN; -import static org.jclouds.util.Patterns.STAR_PATTERN; import static org.jclouds.util.Patterns.TOKEN_TO_PATTERN; import static org.jclouds.util.Patterns.URL_ENCODED_PATTERN; -import static org.jclouds.util.Patterns._7E_PATTERN; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -41,13 +38,13 @@ import java.util.concurrent.ExecutionException; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.annotation.Resource; - -import org.jclouds.logging.Logger; +import org.jclouds.javax.annotation.Nullable; import com.google.common.base.Charsets; +import com.google.common.collect.Multimap; import com.google.common.io.CharStreams; import com.google.common.io.InputSupplier; +import com.google.common.primitives.Chars; /** * @@ -60,15 +57,18 @@ public class Strings2 { * Web browsers do not always handle '+' characters well, use the well-supported '%20' instead. */ public static String urlEncode(String in, char... skipEncode) { + return urlEncode(in, Chars.asList(skipEncode)); + } + + public static String urlEncode(String in, Iterable skipEncode) { if (isUrlEncoded(in)) return in; try { String returnVal = URLEncoder.encode(in, "UTF-8"); - returnVal = Strings2.replaceAll(returnVal, '+', PLUS_PATTERN, "%20"); - returnVal = Strings2.replaceAll(returnVal, '*', STAR_PATTERN, "%2A"); - returnVal = Strings2.replaceAll(returnVal, _7E_PATTERN, "~"); + returnVal = returnVal.replace("+", "%20"); + returnVal = returnVal.replace("*", "%2A"); for (char c : skipEncode) { - returnVal = Strings2.replaceAll(returnVal, CHAR_TO_ENCODED_PATTERN.get(c), c + ""); + returnVal = returnVal.replace(CHAR_TO_ENCODED.get(c), c + ""); } return returnVal; } catch (UnsupportedEncodingException e) { @@ -77,30 +77,29 @@ public class Strings2 { throw new IllegalStateException("error creating pattern: " + in, e); } } - public static boolean isUrlEncoded(String in) { return URL_ENCODED_PATTERN.matcher(in).matches(); } - public static String urlDecode(String in) { + /** + * url decodes the input param, if set. + * + * @param in + * nullable + * @return null if input was null + * @throws IllegalStateException + * if encoding isn't {@code UTF-8} + */ + public static String urlDecode(@Nullable Object in) { + if (in == null) + return null; try { - return URLDecoder.decode(in, "UTF-8"); + return URLDecoder.decode(in.toString(), "UTF-8"); } catch (UnsupportedEncodingException e) { throw new IllegalStateException("Bad encoding on input: " + in, e); } } - public static String replaceTokens(String value, Iterable> tokenValues) { - for (Entry tokenValue : tokenValues) { - try { - value = Strings2.replaceAll(value, TOKEN_TO_PATTERN.get(tokenValue.getKey()), tokenValue.getValue()); - } catch (ExecutionException e) { - throw new IllegalStateException("error creating pattern: " + tokenValue.getKey(), e); - } - } - return value; - } - public static String replaceAll(String returnVal, Pattern pattern, String replace) { Matcher m = pattern.matcher(returnVal); returnVal = m.replaceAll(replace); @@ -135,11 +134,6 @@ public class Strings2 { checkNotNull(input, "input"); try { return new String(toByteArray(input), Charsets.UTF_8); - } catch (IOException e) { - logger.warn(e, "Failed to read from stream"); - return null; - } catch (NullPointerException e) { - return null; } finally { closeQuietly(input); } @@ -149,9 +143,6 @@ public class Strings2 { return new ByteArrayInputStream(in.getBytes(Charsets.UTF_8)); } - @Resource - private static Logger logger = Logger.NULL; - /** * replaces tokens that are expressed as {token} * @@ -182,4 +173,11 @@ public class Strings2 { return builder.toString(); } + public static String replaceTokens(String input, Multimap tokenValues) { + for (Entry tokenValue : tokenValues.entries()) { + Pattern pattern = TOKEN_TO_PATTERN.getUnchecked(tokenValue.getKey()); + input = replaceAll(input, pattern, tokenValue.getValue().toString()); + } + return input; + } } diff --git a/core/src/test/java/org/jclouds/http/BaseJettyTest.java b/core/src/test/java/org/jclouds/http/BaseJettyTest.java index 68055e507a..8dcbc6c425 100644 --- a/core/src/test/java/org/jclouds/http/BaseJettyTest.java +++ b/core/src/test/java/org/jclouds/http/BaseJettyTest.java @@ -25,7 +25,16 @@ import static com.google.common.io.ByteStreams.join; import static com.google.common.io.ByteStreams.newInputStreamSupplier; import static com.google.common.io.ByteStreams.toByteArray; import static com.google.common.io.Closeables.closeQuietly; -import static javax.ws.rs.core.HttpHeaders.CONTENT_LENGTH; +import static com.google.common.net.HttpHeaders.CONTENT_DISPOSITION; +import static com.google.common.net.HttpHeaders.CONTENT_ENCODING; +import static com.google.common.net.HttpHeaders.CONTENT_LANGUAGE; +import static com.google.common.net.HttpHeaders.CONTENT_LENGTH; +import static com.google.common.util.concurrent.Uninterruptibles.sleepUninterruptibly; +import static javax.servlet.http.HttpServletResponse.SC_OK; +import static org.jclouds.Constants.PROPERTY_RELAX_HOSTNAME; +import static org.jclouds.Constants.PROPERTY_TRUST_ALL_CERTS; +import static org.jclouds.crypto.CryptoStreams.md5Base64; +import static org.jclouds.util.Strings2.toStringAndClose; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -196,8 +205,7 @@ public abstract class BaseJettyTest { String responseString = (request.getContentLength() < 10240) ? Strings2.toStringAndClose(body) + "POST" : "POST"; body = null; - for (String header : new String[] { "Content-Disposition", HttpHeaders.CONTENT_LANGUAGE, - HttpHeaders.CONTENT_ENCODING }) + for (String header : new String[] { CONTENT_DISPOSITION, CONTENT_LANGUAGE, CONTENT_ENCODING }) if (request.getHeader(header) != null) { response.addHeader("x-" + header, request.getHeader(header)); } diff --git a/core/src/test/java/org/jclouds/http/HttpRequestTest.java b/core/src/test/java/org/jclouds/http/HttpRequestTest.java index 041ee16eef..5388f73f1d 100644 --- a/core/src/test/java/org/jclouds/http/HttpRequestTest.java +++ b/core/src/test/java/org/jclouds/http/HttpRequestTest.java @@ -18,12 +18,11 @@ */ package org.jclouds.http; +import static com.google.common.net.MediaType.FORM_DATA; import static org.testng.Assert.assertEquals; import java.net.URI; -import javax.ws.rs.core.MediaType; - import org.jclouds.io.Payload; import org.jclouds.io.Payloads; import org.testng.annotations.Test; @@ -51,21 +50,21 @@ public class HttpRequestTest { assertEquals(request.toBuilder().replaceQueryParam("header", "foo").build(), HttpRequest.builder().method("GET") .endpoint("http://goo.com:443?header=foo").build()); } - + // it is easy to accidentally encode twice. make sure this always works! public void testEncodesOnlyOnce() throws Exception { URI uri = URI.create("http://goo.com:443?header=value1"); HttpRequest request = HttpRequest.builder().method("GET").endpoint(uri).build(); - assertEquals(request.toBuilder().replaceQueryParam("header", "1.1.1.1/24,1.1.1.2/24").build(), HttpRequest.builder().method("GET") - .endpoint("http://goo.com:443?header=1.1.1.1%2F24%2C1.1.1.2%2F24").build()); + assertEquals(request.toBuilder().replaceQueryParam("header", "hello?").build(), + HttpRequest.builder().method("GET").endpoint("http://goo.com:443?header=hello%3F").build()); } public void testAddFormParamAddsAnotherValue() { HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://foo") .payload("foo=bar").build(); Payload payload = Payloads.newStringPayload("foo=bar&foo=baz"); - payload.getContentMetadata().setContentType(MediaType.APPLICATION_FORM_URLENCODED); + payload.getContentMetadata().setContentType(FORM_DATA.toString()); assertEquals(request.toBuilder().addFormParams(ImmutableMultimap.of("foo", "baz")).build(), HttpRequest .builder().method("GET").endpoint("http://foo").payload(payload).build()); } diff --git a/core/src/test/java/org/jclouds/http/UriTemplatesTest.java b/core/src/test/java/org/jclouds/http/UriTemplatesTest.java new file mode 100644 index 0000000000..e04682f640 --- /dev/null +++ b/core/src/test/java/org/jclouds/http/UriTemplatesTest.java @@ -0,0 +1,60 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.http; + +import static org.jclouds.http.UriTemplates.expand; +import static org.testng.Assert.assertEquals; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; + +/** + * + * @author Adrian Cole + */ +@Test +public class UriTemplatesTest { + + @DataProvider(name = "strings") + public Object[][] createData() { + return new Object[][] { { "apples" }, { "sp ace" }, { "unic₪de" }, { "qu?stion" } }; + } + + @Test(dataProvider = "strings") + public void testExpandNotUrlEncoded(String val) { + assertEquals(expand("/repos/{user}", ImmutableMap.of("user", val)), "/repos/" + val); + } + + public void testMultipleParams() { + assertEquals(expand("/repos/{user}/{repo}", ImmutableMap.of("user", "unic₪de", "repo", "foo")), + "/repos/unic₪de/foo"); + } + + // jclouds params often include hyphens + public void testParamKeyHyphen() { + assertEquals(expand("/{user-dir}", ImmutableMap.of("user-dir", "foo")), "/foo"); + } + + // sometimes the user intends to have a curly brace in the url + public void testMissingParamProceeds() { + assertEquals(expand("/{user-dir}", ImmutableMap.of("user_dir", "foo")), "/{user-dir}"); + } +} diff --git a/core/src/test/java/org/jclouds/http/UrisTest.java b/core/src/test/java/org/jclouds/http/UrisTest.java new file mode 100644 index 0000000000..db7ef6f53d --- /dev/null +++ b/core/src/test/java/org/jclouds/http/UrisTest.java @@ -0,0 +1,156 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.http; + +import static org.jclouds.http.Uris.uriBuilder; +import static org.jclouds.util.Strings2.urlEncode; +import static org.testng.Assert.assertEquals; + +import java.net.URI; +import java.util.Map; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; + +/** + * + * @author Adrian Cole + */ +@Test +public class UrisTest { + + private static final ImmutableMap templateParams = ImmutableMap.of("user", "bob"); + + public void testScheme() { + assertEquals(uriBuilder("https://foo.com:8080").scheme("http").toString(), "http://foo.com:8080"); + assertEquals(uriBuilder("https://foo.com:8080").scheme("http").build().toString(), "http://foo.com:8080"); + assertEquals(uriBuilder("https://api.github.com/repos/user?foo=bar&kung=fu").scheme("http").toString(), + "http://api.github.com/repos/user?foo=bar&kung=fu"); + assertEquals(uriBuilder("https://api.github.com/repos/user?foo=bar&kung=fu").scheme("http").build().toString(), + "http://api.github.com/repos/user?foo=bar&kung=fu"); + assertEquals(uriBuilder("https://api.github.com/repos/{user}").scheme("http").toString(), + "http://api.github.com/repos/{user}"); + assertEquals(uriBuilder("https://api.github.com/repos/{user}").scheme("http").build(templateParams) + .toASCIIString(), "http://api.github.com/repos/bob"); + + } + + public void testHost() { + assertEquals(uriBuilder("https://foo.com:8080").host("robots").toString(), "https://robots:8080"); + assertEquals(uriBuilder("https://foo.com:8080").host("robots").build().toString(), "https://robots:8080"); + assertEquals(uriBuilder("https://api.github.com/repos/user?foo=bar&kung=fu").host("robots").toString(), + "https://robots/repos/user?foo=bar&kung=fu"); + assertEquals(uriBuilder("https://api.github.com/repos/user?foo=bar&kung=fu").host("robots").build().toString(), + "https://robots/repos/user?foo=bar&kung=fu"); + assertEquals(uriBuilder("https://api.github.com/repos/{user}").host("robots").toString(), + "https://robots/repos/{user}"); + assertEquals(uriBuilder("https://api.github.com/repos/{user}").host("robots").build(templateParams) + .toASCIIString(), "https://robots/repos/bob"); + } + + @DataProvider(name = "strings") + public Object[][] createData() { + return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, { "path/foo" }, { "colon:" }, + { "asteri*k" }, { "quote\"" }, { "greaten" }, { "p|pe" } }; + } + + @Test(dataProvider = "strings") + public void testQuery(String val) { + Map query = ImmutableMap.of("moo", val); + assertEquals(uriBuilder("https://foo.com:8080").query(query).toString(), "https://foo.com:8080?moo=" + val); + assertEquals(uriBuilder("https://foo.com:8080").query(query).build().toString(), "https://foo.com:8080?moo=" + + urlEncode(val, '/', ',')); + assertEquals(uriBuilder("https://api.github.com/repos/user?foo=bar&kung=fu").query(query).toString(), + "https://api.github.com/repos/user?moo=" + val); + assertEquals(uriBuilder("https://api.github.com/repos/user?foo=bar&kung=fu").query(query).build().toString(), + "https://api.github.com/repos/user?moo=" + urlEncode(val, '/', ',')); + assertEquals(uriBuilder("https://api.github.com/repos/{user}").query(query).toString(), + "https://api.github.com/repos/{user}?moo=" + val); + assertEquals( + uriBuilder("https://api.github.com/repos/{user}").query(query).build(templateParams).toASCIIString(), + "https://api.github.com/repos/bob?moo=" + urlEncode(val, '/', ',')); + } + + @Test(dataProvider = "strings") + public void testPath(String path) { + assertEquals(uriBuilder("https://foo.com:8080").path(path).toString(), "https://foo.com:8080/" + path); + assertEquals(uriBuilder("https://foo.com:8080").path(path).build().toString(), "https://foo.com:8080/" + + urlEncode(path, '/', ':', ';', '=')); + assertEquals(uriBuilder("https://api.github.com/repos/user?foo=bar&kung=fu").path(path).toString(), + "https://api.github.com/" + path + "?foo=bar&kung=fu"); + assertEquals(uriBuilder("https://api.github.com/repos/user?foo=bar&kung=fu").path(path).build().toString(), + "https://api.github.com/" + urlEncode(path, '/', ':', ';', '=') + "?foo=bar&kung=fu"); + assertEquals(uriBuilder("https://api.github.com/repos/{user}").path(path).toString(), "https://api.github.com/" + + path); + assertEquals(uriBuilder("https://api.github.com/repos/{user}").path(path).build(templateParams).toASCIIString(), + "https://api.github.com/" + urlEncode(path, '/', ':', ';', '=')); + } + + @Test(dataProvider = "strings") + public void testAppendPath(String path) { + assertEquals(uriBuilder("https://foo.com:8080").appendPath(path).toString(), "https://foo.com:8080/" + path); + assertEquals(uriBuilder("https://foo.com:8080").appendPath(path).build().toString(), "https://foo.com:8080/" + + urlEncode(path, '/', ':', ';', '=')); + assertEquals(uriBuilder("https://api.github.com/repos/user?foo=bar&kung=fu").appendPath(path).toString(), + "https://api.github.com/repos/user/" + path + "?foo=bar&kung=fu"); + assertEquals(uriBuilder("https://api.github.com/repos/user?foo=bar&kung=fu").appendPath(path).build().toString(), + "https://api.github.com/repos/user/" + urlEncode(path, '/', ':', ';', '=') + "?foo=bar&kung=fu"); + assertEquals(uriBuilder("https://api.github.com/repos/{user}").appendPath(path).toString(), + "https://api.github.com/repos/{user}/" + path); + assertEquals(uriBuilder("https://api.github.com/repos/{user}").appendPath(path).build(templateParams) + .toASCIIString(), "https://api.github.com/repos/bob/" + urlEncode(path, '/', ':', ';', '=')); + } + + @Test + public void testNoDoubleSlashInPath() { + assertEquals(uriBuilder("https://vcloud/api/").appendPath("/").build().toASCIIString(), "https://vcloud/api/"); + } + + @Test + public void testWhenUrnInPath() { + assertEquals(uriBuilder("https://vcloud/api").appendPath("urn::acme:foo").build(templateParams).toASCIIString(), + "https://vcloud/api/urn::acme:foo"); + } + + @Test + public void testWhenMatrixOnPath() { + assertEquals( + uriBuilder("https://api.rimuhosting.com/r").appendPath("orders;include_inactive=N").build(templateParams) + .toASCIIString(), "https://api.rimuhosting.com/r/orders;include_inactive=N"); + } + + @Test(dataProvider = "strings") + public void testReplaceQueryIsEncoded(String key) { + assertEquals(uriBuilder("/redirect").addQuery("foo", key).toString(), "/redirect?foo=" + key); + assertEquals(uriBuilder("/redirect").addQuery("foo", key).build().toString(), + "/redirect?foo=" + urlEncode(key, '/', ',')); + } + + public void testAddQuery() { + assertEquals(uriBuilder("http://localhost:8080/client/api").addQuery("response", "json").toString(), + "http://localhost:8080/client/api?response=json"); + + assertEquals( + uriBuilder(URI.create("http://localhost:8080/client/api")).addQuery("response", "json") + .addQuery("command", "queryAsyncJobResult").build().toString(), + "http://localhost:8080/client/api?response=json&command=queryAsyncJobResult"); + } +} diff --git a/core/src/test/java/org/jclouds/http/filters/BasicAuthenticationTest.java b/core/src/test/java/org/jclouds/http/filters/BasicAuthenticationTest.java index 6576789252..4d7e2dfdd8 100644 --- a/core/src/test/java/org/jclouds/http/filters/BasicAuthenticationTest.java +++ b/core/src/test/java/org/jclouds/http/filters/BasicAuthenticationTest.java @@ -18,14 +18,13 @@ */ package org.jclouds.http.filters; +import static com.google.common.net.HttpHeaders.AUTHORIZATION; import static org.testng.Assert.assertEquals; import java.io.UnsupportedEncodingException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; -import javax.ws.rs.core.HttpHeaders; - import org.jclouds.encryption.internal.JCECrypto; import org.jclouds.http.HttpRequest; import org.testng.annotations.Test; @@ -44,7 +43,7 @@ public class BasicAuthenticationTest { BasicAuthentication filter = new BasicAuthentication(USER, PASSWORD, new JCECrypto(null)); HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://localhost").build(); request = filter.filter(request); - assertEquals(request.getFirstHeaderOrNull(HttpHeaders.AUTHORIZATION), "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="); + assertEquals(request.getFirstHeaderOrNull(AUTHORIZATION), "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="); } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/jclouds/http/functions/BaseHandlerTest.java b/core/src/test/java/org/jclouds/http/functions/BaseHandlerTest.java index 0a48596ace..7503fee9ae 100644 --- a/core/src/test/java/org/jclouds/http/functions/BaseHandlerTest.java +++ b/core/src/test/java/org/jclouds/http/functions/BaseHandlerTest.java @@ -18,8 +18,6 @@ */ package org.jclouds.http.functions; -import javax.ws.rs.core.UriBuilder; - import org.jclouds.http.functions.config.SaxParserModule; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; @@ -27,7 +25,6 @@ import org.testng.annotations.Test; import com.google.inject.Guice; import com.google.inject.Injector; -import com.sun.jersey.api.uri.UriBuilderImpl; /** * @@ -41,12 +38,7 @@ public class BaseHandlerTest { @BeforeTest protected void setUpInjector() { - injector = Guice.createInjector(new SaxParserModule() { - public void configure() { - super.configure(); - bind(UriBuilder.class).to(UriBuilderImpl.class); - } - }); + injector = Guice.createInjector(new SaxParserModule()); factory = injector.getInstance(ParseSax.Factory.class); assert factory != null; } @@ -57,4 +49,4 @@ public class BaseHandlerTest { injector = null; } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/jclouds/http/functions/HeaderToRetryAfterExceptionTest.java b/core/src/test/java/org/jclouds/http/functions/HeaderToRetryAfterExceptionTest.java index 4224bce703..a32f7e90c8 100644 --- a/core/src/test/java/org/jclouds/http/functions/HeaderToRetryAfterExceptionTest.java +++ b/core/src/test/java/org/jclouds/http/functions/HeaderToRetryAfterExceptionTest.java @@ -11,7 +11,6 @@ import org.jclouds.http.HttpResponseException; import org.jclouds.rest.RetryAfterException; import org.testng.annotations.Test; -import com.google.common.base.Function; import com.google.common.base.Ticker; import com.google.common.net.HttpHeaders; diff --git a/core/src/test/java/org/jclouds/http/functions/ParseURIFromListOrLocationHeaderIf20xTest.java b/core/src/test/java/org/jclouds/http/functions/ParseURIFromListOrLocationHeaderIf20xTest.java index f772f5d4a4..f6b193252c 100644 --- a/core/src/test/java/org/jclouds/http/functions/ParseURIFromListOrLocationHeaderIf20xTest.java +++ b/core/src/test/java/org/jclouds/http/functions/ParseURIFromListOrLocationHeaderIf20xTest.java @@ -18,51 +18,35 @@ */ package org.jclouds.http.functions; +import static com.google.common.net.HttpHeaders.CONTENT_TYPE; +import static com.google.common.net.HttpHeaders.LOCATION; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; +import static org.jclouds.util.Strings2.toInputStream; import static org.testng.Assert.assertEquals; -import java.io.IOException; import java.net.URI; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeoutException; -import javax.inject.Provider; -import javax.ws.rs.core.UriBuilder; - -import org.eclipse.jetty.http.HttpHeaders; +import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.io.Payload; -import org.jclouds.rest.internal.GeneratedHttpRequest; -import org.jclouds.util.Strings2; import org.testng.annotations.Test; import com.google.common.base.Function; -import com.sun.jersey.api.uri.UriBuilderImpl; @Test(groups = { "unit" }) public class ParseURIFromListOrLocationHeaderIf20xTest { - Provider uriBuilderProvider = new Provider() { - - @Override - public UriBuilder get() { - return new UriBuilderImpl(); - } - - }; @Test - public void testExceptionWhenNoContentOn200() throws ExecutionException, InterruptedException, - TimeoutException, IOException { - Function function = new ParseURIFromListOrLocationHeaderIf20x( - uriBuilderProvider); + public void testExceptionWhenNoContentOn200() { + Function function = new ParseURIFromListOrLocationHeaderIf20x(); HttpResponse response = createMock(HttpResponse.class); Payload payload = createMock(Payload.class); expect(response.getStatusCode()).andReturn(200).atLeastOnce(); - expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE)).andReturn("text/uri-list"); + expect(response.getFirstHeaderOrNull(CONTENT_TYPE)).andReturn("text/uri-list"); expect(response.getPayload()).andReturn(payload).atLeastOnce(); expect(payload.getInput()).andReturn(null); payload.release(); @@ -79,15 +63,13 @@ public class ParseURIFromListOrLocationHeaderIf20xTest { } @Test - public void testExceptionWhenIOExceptionOn200() throws ExecutionException, InterruptedException, - TimeoutException, IOException { - Function function = new ParseURIFromListOrLocationHeaderIf20x( - uriBuilderProvider); + public void testExceptionWhenIOExceptionOn200() { + Function function = new ParseURIFromListOrLocationHeaderIf20x(); HttpResponse response = createMock(HttpResponse.class); Payload payload = createMock(Payload.class); expect(response.getStatusCode()).andReturn(200).atLeastOnce(); - expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE)).andReturn("text/uri-list"); + expect(response.getFirstHeaderOrNull(CONTENT_TYPE)).andReturn("text/uri-list"); RuntimeException exception = new RuntimeException("bad"); expect(response.getPayload()).andReturn(payload).atLeastOnce(); expect(payload.getInput()).andThrow(exception); @@ -105,16 +87,15 @@ public class ParseURIFromListOrLocationHeaderIf20xTest { } @Test - public void testResponseOk() throws Exception { - Function function = new ParseURIFromListOrLocationHeaderIf20x( - uriBuilderProvider); + public void testResponseOk() { + Function function = new ParseURIFromListOrLocationHeaderIf20x(); HttpResponse response = createMock(HttpResponse.class); Payload payload = createMock(Payload.class); expect(response.getStatusCode()).andReturn(200).atLeastOnce(); - expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE)).andReturn("text/uri-list"); + expect(response.getFirstHeaderOrNull(CONTENT_TYPE)).andReturn("text/uri-list"); expect(response.getPayload()).andReturn(payload).atLeastOnce(); - expect(payload.getInput()).andReturn(Strings2.toInputStream("http://locahost")).atLeastOnce(); + expect(payload.getInput()).andReturn(toInputStream("http://locahost")).atLeastOnce(); payload.release(); replay(payload); @@ -126,15 +107,14 @@ public class ParseURIFromListOrLocationHeaderIf20xTest { } @Test - public void testResponseLocationOk() throws Exception { - Function function = new ParseURIFromListOrLocationHeaderIf20x( - uriBuilderProvider); + public void testResponseLocationOk() { + Function function = new ParseURIFromListOrLocationHeaderIf20x(); HttpResponse response = createMock(HttpResponse.class); Payload payload = createMock(Payload.class); expect(response.getStatusCode()).andReturn(200).atLeastOnce(); - expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE)).andReturn("text/plain"); - expect(response.getFirstHeaderOrNull(HttpHeaders.LOCATION)).andReturn("http://locahost"); + expect(response.getFirstHeaderOrNull(CONTENT_TYPE)).andReturn("text/plain"); + expect(response.getFirstHeaderOrNull(LOCATION)).andReturn("http://locahost"); expect(response.getPayload()).andReturn(payload).atLeastOnce(); payload.release(); @@ -147,15 +127,14 @@ public class ParseURIFromListOrLocationHeaderIf20xTest { } @Test - public void testResponseLowercaseLocationOk() throws Exception { - Function function = new ParseURIFromListOrLocationHeaderIf20x( - uriBuilderProvider); + public void testResponseLowercaseLocationOk() { + Function function = new ParseURIFromListOrLocationHeaderIf20x(); HttpResponse response = createMock(HttpResponse.class); Payload payload = createMock(Payload.class); expect(response.getStatusCode()).andReturn(200).atLeastOnce(); - expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE)).andReturn("text/plain"); - expect(response.getFirstHeaderOrNull(HttpHeaders.LOCATION)).andReturn(null); + expect(response.getFirstHeaderOrNull(CONTENT_TYPE)).andReturn("text/plain"); + expect(response.getFirstHeaderOrNull(LOCATION)).andReturn(null); expect(response.getFirstHeaderOrNull("location")).andReturn("http://locahost"); expect(response.getPayload()).andReturn(payload).atLeastOnce(); payload.release(); @@ -169,80 +148,68 @@ public class ParseURIFromListOrLocationHeaderIf20xTest { } @Test - public void testResponsePathLocationOk() throws Exception { - ParseURIFromListOrLocationHeaderIf20x function = new ParseURIFromListOrLocationHeaderIf20x( - uriBuilderProvider); + public void testResponsePathLocationOk() { + ParseURIFromListOrLocationHeaderIf20x function = new ParseURIFromListOrLocationHeaderIf20x(); HttpResponse response = createMock(HttpResponse.class); - GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class); Payload payload = createMock(Payload.class); - + HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://new/fd").build(); + function.setContext(request); - expect(request.getEndpoint()).andReturn(URI.create("http://new/fd")).atLeastOnce(); expect(response.getStatusCode()).andReturn(200).atLeastOnce(); - expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE)).andReturn("text/plain"); - expect(response.getFirstHeaderOrNull(HttpHeaders.LOCATION)).andReturn("path"); + expect(response.getFirstHeaderOrNull(CONTENT_TYPE)).andReturn("text/plain"); + expect(response.getFirstHeaderOrNull(LOCATION)).andReturn("path"); expect(response.getPayload()).andReturn(payload).atLeastOnce(); payload.release(); - replay(request); replay(payload); replay(response); assertEquals(function.apply(response), URI.create("http://new/path")); - verify(request); verify(response); verify(payload); } @Test - public void testResponsePathPortLocationOk() throws Exception { - ParseURIFromListOrLocationHeaderIf20x function = new ParseURIFromListOrLocationHeaderIf20x( - uriBuilderProvider); + public void testResponsePathPortLocationOk() { + ParseURIFromListOrLocationHeaderIf20x function = new ParseURIFromListOrLocationHeaderIf20x(); HttpResponse response = createMock(HttpResponse.class); - GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class); Payload payload = createMock(Payload.class); + HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://new:8080/fd").build(); function.setContext(request); - expect(request.getEndpoint()).andReturn(URI.create("http://new:8080/fd")).atLeastOnce(); expect(response.getStatusCode()).andReturn(200).atLeastOnce(); - expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE)).andReturn("text/plain"); - expect(response.getFirstHeaderOrNull(HttpHeaders.LOCATION)).andReturn("path"); + expect(response.getFirstHeaderOrNull(CONTENT_TYPE)).andReturn("text/plain"); + expect(response.getFirstHeaderOrNull(LOCATION)).andReturn("path"); expect(response.getPayload()).andReturn(payload).atLeastOnce(); payload.release(); - replay(request); replay(payload); replay(response); assertEquals(function.apply(response), URI.create("http://new:8080/path")); - verify(request); verify(response); verify(payload); } @Test - public void testResponsePathSchemeLocationOk() throws Exception { - ParseURIFromListOrLocationHeaderIf20x function = new ParseURIFromListOrLocationHeaderIf20x( - uriBuilderProvider); + public void testResponsePathSchemeLocationOk() { + ParseURIFromListOrLocationHeaderIf20x function = new ParseURIFromListOrLocationHeaderIf20x(); HttpResponse response = createMock(HttpResponse.class); - GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class); Payload payload = createMock(Payload.class); + HttpRequest request = HttpRequest.builder().method("GET").endpoint("https://new/fd").build(); function.setContext(request); - expect(request.getEndpoint()).andReturn(URI.create("https://new/fd")).atLeastOnce(); expect(response.getStatusCode()).andReturn(200).atLeastOnce(); - expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE)).andReturn("text/plain"); - expect(response.getFirstHeaderOrNull(HttpHeaders.LOCATION)).andReturn("path"); + expect(response.getFirstHeaderOrNull(CONTENT_TYPE)).andReturn("text/plain"); + expect(response.getFirstHeaderOrNull(LOCATION)).andReturn("path"); expect(response.getPayload()).andReturn(payload).atLeastOnce(); payload.release(); - replay(request); replay(payload); replay(response); assertEquals(function.apply(response), URI.create("https://new/path")); - verify(request); verify(response); verify(payload); } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/jclouds/http/handlers/BackoffLimitedRetryHandlerTest.java b/core/src/test/java/org/jclouds/http/handlers/BackoffLimitedRetryHandlerTest.java index 7779761a0e..6a86871e3c 100644 --- a/core/src/test/java/org/jclouds/http/handlers/BackoffLimitedRetryHandlerTest.java +++ b/core/src/test/java/org/jclouds/http/handlers/BackoffLimitedRetryHandlerTest.java @@ -28,11 +28,9 @@ import java.util.Properties; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import javax.inject.Provider; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; -import javax.ws.rs.core.UriBuilder; import org.jclouds.date.internal.DateServiceDateCodecFactory; import org.jclouds.date.internal.SimpleDateFormatDateService; @@ -56,7 +54,6 @@ import org.testng.annotations.Test; import com.google.common.base.Supplier; import com.google.inject.Key; import com.google.inject.TypeLiteral; -import com.sun.jersey.api.uri.UriBuilderImpl; @Test(groups = "unit", testName = "BackoffLimitedRetryHandlerTest") public class BackoffLimitedRetryHandlerTest { @@ -101,14 +98,6 @@ public class BackoffLimitedRetryHandlerTest { } TransformingHttpCommandExecutorServiceImpl executorService; - Provider uriBuilderProvider = new Provider() { - - @Override - public UriBuilder get() { - return new UriBuilderImpl(); - } - - }; @BeforeTest void setupExecutorService() throws Exception { @@ -117,7 +106,7 @@ public class BackoffLimitedRetryHandlerTest { HttpUtils utils = new HttpUtils(0, 500, 1, 1); ContentMetadataCodec contentMetadataCodec = new DefaultContentMetadataCodec(new DateServiceDateCodecFactory( new SimpleDateFormatDateService())); - RedirectionRetryHandler retry = new RedirectionRetryHandler(uriBuilderProvider, backoff); + RedirectionRetryHandler retry = new RedirectionRetryHandler(backoff); JavaUrlHttpCommandExecutorService httpService = new JavaUrlHttpCommandExecutorService(utils, contentMetadataCodec, execService, new DelegatingRetryHandler(backoff, retry), new BackoffLimitedRetryHandler(), diff --git a/core/src/test/java/org/jclouds/http/handlers/RedirectionRetryHandlerTest.java b/core/src/test/java/org/jclouds/http/handlers/RedirectionRetryHandlerTest.java index 4c160f781d..22d67b3d34 100644 --- a/core/src/test/java/org/jclouds/http/handlers/RedirectionRetryHandlerTest.java +++ b/core/src/test/java/org/jclouds/http/handlers/RedirectionRetryHandlerTest.java @@ -18,13 +18,13 @@ */ package org.jclouds.http.handlers; +import static com.google.common.net.HttpHeaders.HOST; +import static com.google.common.net.HttpHeaders.LOCATION; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; -import javax.ws.rs.core.HttpHeaders; - import org.jclouds.ContextBuilder; import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpRequest; @@ -78,7 +78,7 @@ public class RedirectionRetryHandlerTest { HttpResponse response = HttpResponse.builder() .statusCode(302) .message("HTTP/1.1 302 Found") - .addHeader(HttpHeaders.LOCATION, "/api/v0.8b-ext2.5/Error.aspx?aspxerrorpath=/api/v0.8b-ext2.5/org.svc/1906645").build(); + .addHeader(LOCATION, "/api/v0.8b-ext2.5/Error.aspx?aspxerrorpath=/api/v0.8b-ext2.5/org.svc/1906645").build(); expect(command.incrementRedirectCount()).andReturn(5); @@ -102,7 +102,7 @@ public class RedirectionRetryHandlerTest { HttpResponse.builder() .statusCode(302) .message("HTTP/1.1 302 Found") - .addHeader(HttpHeaders.LOCATION, "/api/v0.8b-ext2.5/Error.aspx?aspxerrorpath=/api/v0.8b-ext2.5/org.svc/1906645").build(), + .addHeader(LOCATION, "/api/v0.8b-ext2.5/Error.aspx?aspxerrorpath=/api/v0.8b-ext2.5/org.svc/1906645").build(), HttpRequest.builder() .method("GET") .endpoint("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/Error.aspx?aspxerrorpath=/api/v0.8b-ext2.5/org.svc/1906645").build()); @@ -118,7 +118,7 @@ public class RedirectionRetryHandlerTest { HttpResponse.builder() .statusCode(302) .message("HTTP/1.1 302 Found") - .addHeader(HttpHeaders.LOCATION, "https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645").build(), + .addHeader(LOCATION, "https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645").build(), HttpRequest.builder() .method("GET") .endpoint("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645").build()); @@ -133,7 +133,7 @@ public class RedirectionRetryHandlerTest { HttpResponse.builder() .statusCode(302) .message("HTTP/1.1 302 Found") - .addHeader(HttpHeaders.LOCATION, "http://services.enterprisecloud.terremark.com:3030/api/v0.8b-ext2.5/org/1906645").build(), + .addHeader(LOCATION, "http://services.enterprisecloud.terremark.com:3030/api/v0.8b-ext2.5/org/1906645").build(), HttpRequest.builder() .method("GET") .endpoint("http://services.enterprisecloud.terremark.com:3030/api/v0.8b-ext2.5/org/1906645").build()); @@ -148,7 +148,7 @@ public class RedirectionRetryHandlerTest { HttpResponse.builder() .statusCode(302) .message("HTTP/1.1 302 Found") - .addHeader(HttpHeaders.LOCATION, "https://services1.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645").build(), + .addHeader(LOCATION, "https://services1.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645").build(), HttpRequest.builder() .method("GET") .endpoint("https://services1.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645").build()); @@ -160,15 +160,15 @@ public class RedirectionRetryHandlerTest { HttpRequest.builder() .method("GET") .endpoint("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645") - .addHeader(HttpHeaders.HOST, "services.enterprisecloud.terremark.com").build(), + .addHeader(HOST, "services.enterprisecloud.terremark.com").build(), HttpResponse.builder() .statusCode(302) .message("HTTP/1.1 302 Found") - .addHeader(HttpHeaders.LOCATION, "https://services1.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645").build(), + .addHeader(LOCATION, "https://services1.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645").build(), HttpRequest.builder() .method("GET") .endpoint("https://services1.enterprisecloud.terremark.com/api/v0.8b-ext2.5/org/1906645") - .addHeader(HttpHeaders.HOST, "services1.enterprisecloud.terremark.com").build()); + .addHeader(HOST, "services1.enterprisecloud.terremark.com").build()); } protected void verifyRedirectRoutes(HttpRequest request, HttpResponse response, HttpRequest expected) { diff --git a/core/src/test/java/org/jclouds/http/utils/QueriesTest.java b/core/src/test/java/org/jclouds/http/utils/QueriesTest.java index 0a7ea0399f..7476228b0b 100644 --- a/core/src/test/java/org/jclouds/http/utils/QueriesTest.java +++ b/core/src/test/java/org/jclouds/http/utils/QueriesTest.java @@ -18,7 +18,7 @@ */ package org.jclouds.http.utils; -import static org.jclouds.http.utils.Queries.parseQueryToMap; +import static org.jclouds.http.utils.Queries.queryParser; import static org.testng.Assert.assertEquals; import java.util.Set; @@ -45,13 +45,15 @@ public class QueriesTest { expects.put("Value", "dGVzdA=="); expects.put("InstanceId", "1"); assertEquals( - parseQueryToMap("Version=2010-06-15&Action=ModifyInstanceAttribute&Attribute=userData&Value=dGVzdA%3D%3D&InstanceId=1"), - expects); + queryParser() + .apply( + "Version=2010-06-15&Action=ModifyInstanceAttribute&Attribute=userData&Value=dGVzdA%3D%3D&InstanceId=1"), + expects); } @Test public void testParseQueryToMapSingleParam() { - Multimap parsedMap = parseQueryToMap("v=1.3"); + Multimap parsedMap = queryParser().apply("v=1.3"); assert parsedMap.keySet().size() == 1 : "Expected 1 key, found: " + parsedMap.keySet().size(); assert parsedMap.keySet().contains("v") : "Expected v to be a part of the keys"; String valueForV = Iterables.getOnlyElement(parsedMap.get("v")); @@ -60,7 +62,7 @@ public class QueriesTest { @Test public void testParseQueryToMapMultiParam() { - Multimap parsedMap = parseQueryToMap("v=1.3&sig=123"); + Multimap parsedMap = queryParser().apply("v=1.3&sig=123"); assert parsedMap.keySet().size() == 2 : "Expected 2 keys, found: " + parsedMap.keySet().size(); assert parsedMap.keySet().contains("v") : "Expected v to be a part of the keys"; assert parsedMap.keySet().contains("sig") : "Expected sig to be a part of the keys"; @@ -79,16 +81,16 @@ public class QueriesTest { Set expected = ImmutableSet.of(key); - Multimap parsedMap = parseQueryToMap("a=1&b=1+2&publickey=" + Strings2.urlEncode(key)); + Multimap parsedMap = queryParser().apply("a=1&b=1+2&publickey=" + Strings2.urlEncode(key)); assertEquals(parsedMap.get("publickey"), expected); - parsedMap = parseQueryToMap("publickey=" + Strings2.urlEncode(key)); + parsedMap = queryParser().apply("publickey=" + Strings2.urlEncode(key)); assertEquals(parsedMap.get("publickey"), expected); } @Test public void testParseQueryWithKeysThatRequireDecoding() { - Multimap parsedMap = parseQueryToMap("network%5B0%5D.id=23&network%5B0%5D.address=192.168.0.1"); + Multimap parsedMap = queryParser().apply("network%5B0%5D.id=23&network%5B0%5D.address=192.168.0.1"); assertEquals(parsedMap.get("network[0].id"), ImmutableSet.of("23")); assertEquals(parsedMap.get("network[0].address"), ImmutableSet.of("192.168.0.1")); diff --git a/core/src/test/java/org/jclouds/io/payloads/MultipartFormTest.java b/core/src/test/java/org/jclouds/io/payloads/MultipartFormTest.java index 6b6dce1004..97a21f385f 100644 --- a/core/src/test/java/org/jclouds/io/payloads/MultipartFormTest.java +++ b/core/src/test/java/org/jclouds/io/payloads/MultipartFormTest.java @@ -18,6 +18,7 @@ */ package org.jclouds.io.payloads; +import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; @@ -28,8 +29,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import javax.ws.rs.core.MediaType; - import org.jclouds.io.Payloads; import org.jclouds.io.payloads.Part.PartOptions; import org.jclouds.util.Strings2; @@ -94,7 +93,8 @@ public class MultipartFormTest { } private Part newPart(String data) { - return Part.create("file", new MockFilePayload(data), new PartOptions().contentType(MediaType.TEXT_PLAIN)); + return Part.create("file", new MockFilePayload(data), + new PartOptions().contentType(PLAIN_TEXT_UTF_8.withoutParameters().toString())); } private void addData(String boundary, String data, StringBuilder builder) { diff --git a/core/src/test/java/org/jclouds/rest/InputParamValidatorTest.java b/core/src/test/java/org/jclouds/rest/InputParamValidatorTest.java index 81f051abf0..c14c28f157 100644 --- a/core/src/test/java/org/jclouds/rest/InputParamValidatorTest.java +++ b/core/src/test/java/org/jclouds/rest/InputParamValidatorTest.java @@ -31,7 +31,6 @@ import org.jclouds.http.IntegrationTestClient; import org.jclouds.predicates.validators.AllLowerCaseValidator; import org.jclouds.providers.AnonymousProviderMetadata; import org.jclouds.rest.annotations.ParamValidators; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.internal.RestAnnotationProcessor; import org.testng.TestException; import org.testng.annotations.BeforeClass; @@ -46,8 +45,7 @@ import com.google.inject.util.Types; public class InputParamValidatorTest { @Timeout(duration = 1000, timeUnit = TimeUnit.SECONDS) - @SkipEncoding('/') - class InputParamValidatorForm { + class InputParamValidatorForm { @POST @ParamValidators( { AllLowerCaseValidator.class }) public void allParamsValidated(@PathParam("param1") String param1, @PathParam("param2") String param2) { @@ -109,8 +107,7 @@ public class InputParamValidatorTest { @Test public void testWrongPredicateTypeLiteral() throws Exception { @Timeout(duration = 1000, timeUnit = TimeUnit.SECONDS) - @SkipEncoding('/') - class WrongValidator { + class WrongValidator { @SuppressWarnings("unused") @POST @ParamValidators( { AllLowerCaseValidator.class }) diff --git a/core/src/test/java/org/jclouds/rest/annotationparsing/DelegateAnnotationExpectTest.java b/core/src/test/java/org/jclouds/rest/annotationparsing/DelegateAnnotationExpectTest.java index 64e327ace2..37a5ff0164 100644 --- a/core/src/test/java/org/jclouds/rest/annotationparsing/DelegateAnnotationExpectTest.java +++ b/core/src/test/java/org/jclouds/rest/annotationparsing/DelegateAnnotationExpectTest.java @@ -95,7 +95,7 @@ public class DelegateAnnotationExpectTest extends BaseRestClientExpectTest of(new UriBuilderImpl())); + BindAsHostPrefix binder = new BindAsHostPrefix(); HttpRequest request = binder.bindToRequest(HttpRequest.builder().method("GET").endpoint("https://s3.amazonaws.com").build(), "bucket"); @@ -51,7 +45,7 @@ public class BindAsHostPrefixIfConfiguredTest { @Test(expectedExceptions = IllegalArgumentException.class) public void testPrefixInvalidHostname() { - BindAsHostPrefix binder = new BindAsHostPrefix(Providers. of(new UriBuilderImpl())); + BindAsHostPrefix binder = new BindAsHostPrefix(); binder.bindToRequest(HttpRequest.builder().method("GET").endpoint("https://s3.amazonaws.com").build(), "b_ucket"); diff --git a/core/src/test/java/org/jclouds/rest/binders/BindMapToStringPayloadTest.java b/core/src/test/java/org/jclouds/rest/binders/BindMapToStringPayloadTest.java index 51b1f53bb3..9aa1035203 100644 --- a/core/src/test/java/org/jclouds/rest/binders/BindMapToStringPayloadTest.java +++ b/core/src/test/java/org/jclouds/rest/binders/BindMapToStringPayloadTest.java @@ -23,18 +23,16 @@ import static org.testng.Assert.assertEquals; import java.io.File; import java.lang.reflect.Method; -import javax.ws.rs.HttpMethod; import javax.ws.rs.PathParam; -import javax.ws.rs.core.UriBuilder; import org.jclouds.http.HttpRequest; +import org.jclouds.rest.annotations.Payload; +import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.internal.GeneratedHttpRequest; import org.testng.annotations.Test; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.google.inject.util.Providers; -import com.sun.jersey.api.uri.UriBuilderImpl; /** * Tests behavior of {@code BindMapToStringPayload} @@ -48,6 +46,9 @@ public class BindMapToStringPayloadTest { void testPayload(@PathParam("foo") String path); void noPayload(String path); + + @Payload("%7B\"changePassword\":%7B\"adminPass\":\"{adminPass}\"%7D%7D") + void changeAdminPass(@PayloadParam("adminPass") String adminPass); } @Test @@ -55,7 +56,7 @@ public class BindMapToStringPayloadTest { Method testPayload = TestPayload.class.getMethod("testPayload", String.class); GeneratedHttpRequest request = GeneratedHttpRequest.builder() .declaring(TestPayload.class).javaMethod(testPayload).args(ImmutableList. of("robot")) - .method(HttpMethod.POST).endpoint("http://localhost").build(); + .method("POST").endpoint("http://localhost").build(); GeneratedHttpRequest newRequest = binder() .bindToRequest(request, ImmutableMap.of("fooble", "robot")); @@ -63,13 +64,27 @@ public class BindMapToStringPayloadTest { assertEquals(newRequest.getRequestLine(), request.getRequestLine()); assertEquals(newRequest.getPayload().getRawContent(), "name robot"); } + + @Test + public void testDecodes() throws SecurityException, NoSuchMethodException { + Method testPayload = TestPayload.class.getMethod("changeAdminPass", String.class); + GeneratedHttpRequest request = GeneratedHttpRequest.builder() + .declaring(TestPayload.class).javaMethod(testPayload).args(ImmutableList. of("foo")) + .method("POST").endpoint("http://localhost").build(); + + GeneratedHttpRequest newRequest = binder() + .bindToRequest(request, ImmutableMap.of("adminPass", "foo")); + + assertEquals(newRequest.getRequestLine(), request.getRequestLine()); + assertEquals(newRequest.getPayload().getRawContent(), "{\"changePassword\":{\"adminPass\":\"foo\"}}"); + } @Test(expectedExceptions = IllegalArgumentException.class) public void testMustHavePayloadAnnotation() throws SecurityException, NoSuchMethodException { Method noPayload = TestPayload.class.getMethod("noPayload", String.class); GeneratedHttpRequest request = GeneratedHttpRequest.builder() .declaring(TestPayload.class).javaMethod(noPayload).args(ImmutableList. of("robot")) - .method(HttpMethod.POST).endpoint("http://localhost").build(); + .method("POST").endpoint("http://localhost").build(); binder().bindToRequest(request, ImmutableMap.of("fooble", "robot")); } @@ -88,6 +103,6 @@ public class BindMapToStringPayloadTest { } public BindMapToStringPayload binder() { - return new BindMapToStringPayload(Providers. of(new UriBuilderImpl())); + return new BindMapToStringPayload(); } } diff --git a/core/src/test/java/org/jclouds/rest/binders/BindToXMLPayloadTest.java b/core/src/test/java/org/jclouds/rest/binders/BindToXMLPayloadTest.java index e2d3e99bc3..69d055c10c 100644 --- a/core/src/test/java/org/jclouds/rest/binders/BindToXMLPayloadTest.java +++ b/core/src/test/java/org/jclouds/rest/binders/BindToXMLPayloadTest.java @@ -20,8 +20,6 @@ package org.jclouds.rest.binders; import static org.testng.Assert.assertEquals; -import javax.ws.rs.core.MediaType; - import org.jclouds.http.HttpRequest; import org.jclouds.rest.internal.RestAnnotationProcessorTest.TestJAXBDomain; import org.jclouds.xml.XMLParser; @@ -51,7 +49,7 @@ public class BindToXMLPayloadTest { HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build(); request = binder.bindToRequest(request, obj); assertEquals(request.getPayload().getRawContent(), XMLParser.DEFAULT_XML_HEADER + "\n\n Hello World\n\n"); - assertEquals(request.getPayload().getContentMetadata().getContentType(), MediaType.APPLICATION_XML); + assertEquals(request.getPayload().getContentMetadata().getContentType(), "application/xml"); } @Test @@ -70,7 +68,7 @@ public class BindToXMLPayloadTest { request = binder.bindToRequest(request, obj); assertEquals(request.getPayload().getRawContent(), XMLParser.DEFAULT_XML_HEADER + "\n\n Hello World\n\n"); - assertEquals(request.getPayload().getContentMetadata().getContentType(), MediaType.APPLICATION_XML); + assertEquals(request.getPayload().getContentMetadata().getContentType(), "application/xml"); } @Test(expectedExceptions = NullPointerException.class) diff --git a/core/src/test/java/org/jclouds/rest/internal/BaseRestApiTest.java b/core/src/test/java/org/jclouds/rest/internal/BaseRestApiTest.java index 82ac89bdf2..15b4d5e010 100644 --- a/core/src/test/java/org/jclouds/rest/internal/BaseRestApiTest.java +++ b/core/src/test/java/org/jclouds/rest/internal/BaseRestApiTest.java @@ -22,13 +22,13 @@ import static com.google.common.base.Throwables.propagate; import static com.google.inject.util.Types.newParameterizedType; import static org.easymock.EasyMock.createMock; import static org.eclipse.jetty.http.HttpHeaders.TRANSFER_ENCODING; -import static org.jclouds.http.HttpUtils.sortAndConcatHeadersIntoString; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; import java.io.IOException; import java.lang.reflect.Method; import java.util.Date; +import java.util.Map.Entry; import java.util.concurrent.ExecutorService; import org.jclouds.Constants; @@ -46,6 +46,9 @@ import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions; import org.jclouds.util.Strings2; import org.testng.annotations.Test; +import com.google.common.collect.Multimap; +import com.google.common.collect.SortedSetMultimap; +import com.google.common.collect.TreeMultimap; import com.google.inject.AbstractModule; import com.google.inject.Injector; import com.google.inject.Key; @@ -144,6 +147,17 @@ public abstract class BaseRestApiTest { assertEquals(sortAndConcatHeadersIntoString(request.getHeaders()), toMatch); } + public static String sortAndConcatHeadersIntoString(Multimap headers) { + StringBuilder buffer = new StringBuilder(); + SortedSetMultimap sortedMap = TreeMultimap.create(); + sortedMap.putAll(headers); + for (Entry header : sortedMap.entries()) { + if (header.getKey() != null) + buffer.append(String.format("%s: %s\n", header.getKey(), header.getValue())); + } + return buffer.toString(); + } + protected void assertRequestLineEquals(HttpRequest request, String toMatch) { assertEquals(request.getRequestLine(), toMatch); } @@ -176,4 +190,4 @@ public abstract class BaseRestApiTest { RestAnnotationProcessor.class, clazz)))); } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java index 1bc0288e2e..471b9ff4f3 100644 --- a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java +++ b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java @@ -25,6 +25,7 @@ import static org.jclouds.io.Payloads.newInputStreamPayload; import static org.jclouds.io.Payloads.newStringPayload; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; +import static org.testng.Assert.fail; import java.io.File; import java.io.IOException; @@ -50,7 +51,6 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import javax.inject.Named; -import javax.inject.Provider; import javax.inject.Qualifier; import javax.inject.Singleton; import javax.ws.rs.Consumes; @@ -58,7 +58,6 @@ import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; import javax.ws.rs.HttpMethod; -import javax.ws.rs.MatrixParam; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; @@ -66,7 +65,6 @@ import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.UriBuilder; import javax.xml.bind.annotation.XmlRootElement; import org.eclipse.jetty.http.HttpHeaders; @@ -114,7 +112,6 @@ import org.jclouds.rest.annotations.FormParams; import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.JAXBResponseParser; import org.jclouds.rest.annotations.MapBinder; -import org.jclouds.rest.annotations.MatrixParams; import org.jclouds.rest.annotations.OnlyElement; import org.jclouds.rest.annotations.OverrideRequestFilters; import org.jclouds.rest.annotations.ParamParser; @@ -125,7 +122,6 @@ import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.Transform; import org.jclouds.rest.annotations.Unwrap; import org.jclouds.rest.annotations.VirtualHost; @@ -147,6 +143,7 @@ import com.google.common.base.Joiner; import com.google.common.base.Optional; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; @@ -162,7 +159,6 @@ import com.google.inject.Module; import com.google.inject.Provides; import com.google.inject.TypeLiteral; import com.google.inject.name.Names; -import com.sun.jersey.api.uri.UriBuilderImpl; /** * Tests behavior of {@code RestAnnotationProcessor} @@ -279,7 +275,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { try { child.getInstance(AsyncCallee.class); - assert false : "Callee shouldn't be bound yet"; + fail("Callee shouldn't be bound yet"); } catch (ConfigurationException e) { } @@ -303,7 +299,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { try { child.getInstance(Callee.class); - assert false : "Callee shouldn't be bound yet"; + fail("Callee shouldn't be bound yet"); } catch (ConfigurationException e) { } @@ -328,7 +324,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { try { child.getInstance(AsyncCallee.class); - assert false : "Callee shouldn't be bound yet"; + fail("Callee shouldn't be bound yet"); } catch (ConfigurationException e) { } @@ -353,7 +349,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { try { child.getInstance(AsyncCallee.class); - assert false : "Callee shouldn't be bound yet"; + fail("Callee shouldn't be bound yet"); } catch (ConfigurationException e) { } @@ -377,7 +373,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { try { child.getInstance(AsyncCallee.class); - assert false : "Callee shouldn't be bound yet"; + fail("Callee shouldn't be bound yet"); } catch (ConfigurationException e) { } @@ -416,7 +412,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { try { child.getInstance(AsyncCallee.class); - assert false : "Callee shouldn't be bound yet"; + fail("Callee shouldn't be bound yet"); } catch (ConfigurationException e) { } @@ -441,7 +437,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { try { child.getInstance(Callee.class); - assert false : "Callee shouldn't be bound yet"; + fail("Callee shouldn't be bound yet"); } catch (ConfigurationException e) { } @@ -461,15 +457,6 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { } - Provider uriBuilderProvider = new Provider() { - - @Override - public UriBuilder get() { - return new UriBuilderImpl(); - } - - }; - @Target({ ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @javax.ws.rs.HttpMethod("FOO") @@ -514,16 +501,6 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { } } - public void testUnEncodeQuery() { - URI expects = URI - .create("http://services.nirvanix.com/ws/Metadata/SetMetadata.ashx?output=json&path=adriancole-compute.testObjectOperations&metadata=chef:sushi&metadata=foo:bar&sessionToken=775ef26e-0740-4707-ad92-afe9814bc436"); - - URI start = URI - .create("http://services.nirvanix.com/ws/Metadata/SetMetadata.ashx?output=json&path=adriancole-compute.testObjectOperations&metadata=chef%3Asushi&metadata=foo%3Abar&sessionToken=775ef26e-0740-4707-ad92-afe9814bc436"); - URI value = RestAnnotationProcessor.replaceQuery(uriBuilderProvider, start, start.getQuery(), null, '/', ':'); - assertEquals(value, expects); - } - public void testQuery() throws SecurityException, NoSuchMethodException { Method method = TestQuery.class.getMethod("foo"); HttpRequest request = factory(TestQuery.class).createRequest(method, new Object[] {}); @@ -1062,34 +1039,34 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { @PUT @Path("/{foo}") @MapBinder(BindToJsonPayload.class) - @Consumes(MediaType.APPLICATION_JSON) + @Consumes("application/json") View putWithMethodBinderConsumes(@PathParam("foo") @PayloadParam("fooble") String path); @GET @Path("/") - @Consumes(MediaType.APPLICATION_JSON) + @Consumes("application/json") Map testGeneric(); @GET @Path("/") - @Consumes(MediaType.APPLICATION_JSON) + @Consumes("application/json") ListenableFuture> testGeneric2(); @GET @Path("/") - @Consumes(MediaType.APPLICATION_JSON) + @Consumes("application/json") ListenableFuture> testGeneric3(); @GET @Path("/") @Unwrap - @Consumes(MediaType.APPLICATION_JSON) + @Consumes("application/json") String testUnwrap(); @GET @Path("/") @SelectJson("foo") - @Consumes(MediaType.APPLICATION_JSON) + @Consumes("application/json") String testUnwrapValueNamed(); @POST @@ -1099,19 +1076,19 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { @GET @Path("/") @Unwrap - @Consumes(MediaType.APPLICATION_JSON) + @Consumes("application/json") ListenableFuture testUnwrap2(); @GET @Path("/") @Unwrap - @Consumes(MediaType.APPLICATION_JSON) + @Consumes("application/json") ListenableFuture> testUnwrap3(); @GET @Path("/") @Unwrap - @Consumes(MediaType.APPLICATION_JSON) + @Consumes("application/json") ListenableFuture> testUnwrap4(); @GET @@ -1137,7 +1114,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { @Path("/") @SelectJson("runit") @OnlyElement - @Consumes(MediaType.APPLICATION_JSON) + @Consumes("application/json") ListenableFuture selectOnlyElement(); @Target({ ElementType.METHOD }) @@ -1425,8 +1402,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { assertEquals(request.getFilters().get(0).getClass(), TestRequestFilter2.class); } - @SkipEncoding('/') - public class TestEncoding { + public class TestEncoding { @GET @Path("/{path1}/{path2}") public void twoPaths(@PathParam("path1") String path, @PathParam("path2") String path2) { @@ -1445,14 +1421,13 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { @Test public void testEncodingPath() throws SecurityException, NoSuchMethodException { Method method = TestEncoding.class.getMethod("twoPaths", String.class, String.class); - HttpRequest request = factory(TestEncoding.class).createRequest(method, new Object[] { "/", "localhost" }); + HttpRequest request = factory(TestEncoding.class).createRequest(method, "/", "localhost" ); assertEquals(request.getEndpoint().getPath(), "///localhost"); assertEquals(request.getMethod(), HttpMethod.GET); assertEquals(request.getHeaders().size(), 0); } - @SkipEncoding('/') - @Path("/v1/{identity}") + @Path("/v1/{identity}") public interface TestConstantPathParam { @Named("testidentity") @PathParam("identity") @@ -1509,11 +1484,6 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { public void oneFormParamExtractor(@FormParam("one") @ParamParser(FirstCharacter.class) String one) { } - @GET - @Path("/") - public void oneMatrixParamExtractor(@MatrixParam("one") @ParamParser(FirstCharacter.class) String one) { - } - @GET @Path("/{path}") @PathParam("path") @@ -1549,25 +1519,6 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { assertNonPayloadHeadersEqual(request, ""); assertPayloadEquals(request, null, null, false); } - - @Test - public void testMatrixParamExtractor() throws SecurityException, NoSuchMethodException, IOException { - Method method = TestPath.class.getMethod("oneMatrixParamExtractor", String.class); - HttpRequest request = factory(TestPath.class).createRequest(method, new Object[] { "localhost" }); - assertRequestLineEquals(request, "GET http://localhost:9999/;one=l HTTP/1.1"); - assertNonPayloadHeadersEqual(request, ""); - assertPayloadEquals(request, null, null, false); - } - - @Test - public void testNiceNPEMatrixParam() throws SecurityException, NoSuchMethodException, IOException { - Method method = TestPath.class.getMethod("oneMatrixParamExtractor", String.class); - try { - factory(TestPath.class).createRequest(method, (String) null); - } catch (NullPointerException e) { - assertEquals(e.getMessage(), "param{one} for method TestPath.oneMatrixParamExtractor"); - } - } @Test public void testFormParamExtractor() throws SecurityException, NoSuchMethodException, IOException { @@ -1641,8 +1592,8 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { Multimap headers = factory(TestHeader.class).createRequest(oneHeader, new Object[] { "robot" }) .getHeaders(); assertEquals(headers.size(), 2); - assertEquals(headers.get("slash"), Collections.singletonList("/robot")); - assertEquals(headers.get("hyphen"), Collections.singletonList("-robot")); + assertEquals(headers.get("slash"), ImmutableList.of("/robot")); + assertEquals(headers.get("hyphen"), ImmutableList.of("-robot")); } @Headers(keys = "x-amz-copy-source", values = "/{bucket}") @@ -1659,7 +1610,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { Multimap headers = factory(TestClassHeader.class).createRequest(oneHeader, new Object[] { "robot" }).getHeaders(); assertEquals(headers.size(), 1); - assertEquals(headers.get("x-amz-copy-source"), Collections.singletonList("/robot")); + assertEquals(headers.get("x-amz-copy-source"), ImmutableList.of("/robot")); } @Test @@ -1668,7 +1619,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { Multimap headers = factory(TestHeader.class).createRequest(oneHeader, new Object[] { "robot" }) .getHeaders(); assertEquals(headers.size(), 1); - assertEquals(headers.get("x-amz-copy-source"), Collections.singletonList("/robot")); + assertEquals(headers.get("x-amz-copy-source"), ImmutableList.of("/robot")); } @Test @@ -1677,7 +1628,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { Multimap headers = factory(TestHeader.class).createRequest(twoHeaders, new Object[] { "robot", "eggs" }).getHeaders(); assertEquals(headers.size(), 1); - assertEquals(headers.get("x-amz-copy-source"), Collections.singletonList("/robot/eggs")); + assertEquals(headers.get("x-amz-copy-source"), ImmutableList.of("/robot/eggs")); } @Test @@ -1686,7 +1637,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { Multimap headers = factory(TestHeader.class).createRequest(twoHeadersOutOfOrder, new Object[] { "robot", "eggs" }).getHeaders(); assertEquals(headers.size(), 1); - assertEquals(headers.get("x-amz-copy-source"), Collections.singletonList("/eggs/robot")); + assertEquals(headers.get("x-amz-copy-source"), ImmutableList.of("/eggs/robot")); } public class TestReplaceQueryOptions extends BaseHttpRequestOptions { @@ -1703,8 +1654,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { assertEquals(query, "x-amz-copy-source=/robot"); } - @SkipEncoding('/') - public class TestQueryReplace { + public class TestQueryReplace { @GET @Path("/") @@ -1784,104 +1734,6 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { assertEquals(query, "x-amz-copy-source=/eggs/robot"); } - public class TestReplaceMatrixOptions extends BaseHttpRequestOptions { - public TestReplaceMatrixOptions() { - this.matrixParameters.put("x-amz-copy-source", "/{bucket}"); - } - } - - @Test - public void testMatrixInOptions() throws SecurityException, NoSuchMethodException { - Method oneMatrix = TestMatrixReplace.class.getMethod("matrixInOptions", String.class, - TestReplaceMatrixOptions.class); - String path = factory(TestMatrixReplace.class) - .createRequest(oneMatrix, new Object[] { "robot", new TestReplaceMatrixOptions() }).getEndpoint().getPath(); - assertEquals(path, "/;x-amz-copy-source=/robot"); - } - - @Path("/") - public class TestMatrixReplace { - - @GET - @Path("/") - public void matrixInOptions(@PathParam("bucket") String path, TestReplaceMatrixOptions options) { - } - - @GET - @Path("/") - @MatrixParams(keys = "x-amz-copy-source", values = "/{bucket}") - public void oneMatrix(@PathParam("bucket") String path) { - } - - @GET - @Path("/") - @MatrixParams(keys = { "slash", "hyphen" }, values = { "/{bucket}", "-{bucket}" }) - public void twoMatrix(@PathParam("bucket") String path) { - } - - @GET - @Path("/") - @MatrixParams(keys = "x-amz-copy-source", values = "/{bucket}/{key}") - public void twoMatrixs(@PathParam("bucket") String path, @PathParam("key") String path2) { - } - - @GET - @Path("/") - @MatrixParams(keys = "x-amz-copy-source", values = "/{bucket}/{key}") - public void twoMatrixsOutOfOrder(@PathParam("key") String path, @PathParam("bucket") String path2) { - } - } - - @Test - public void testBuildTwoMatrix() throws SecurityException, NoSuchMethodException { - Method oneMatrix = TestMatrixReplace.class.getMethod("twoMatrix", String.class); - String path = factory(TestMatrixReplace.class).createRequest(oneMatrix, new Object[] { "robot" }).getEndpoint() - .getPath(); - assertEquals(path, "/;slash=/robot;hyphen=-robot"); - } - - @MatrixParams(keys = "x-amz-copy-source", values = "/{bucket}") - @Path("/") - public class TestClassMatrix { - @GET - @Path("/") - public void oneMatrix(@PathParam("bucket") String path) { - } - } - - @Test - public void testBuildOneClassMatrix() throws SecurityException, NoSuchMethodException { - Method oneMatrix = TestClassMatrix.class.getMethod("oneMatrix", String.class); - String path = factory(TestClassMatrix.class).createRequest(oneMatrix, new Object[] { "robot" }).getEndpoint() - .getPath(); - assertEquals(path, "/;x-amz-copy-source=/robot"); - } - - @Test - public void testBuildOneMatrix() throws SecurityException, NoSuchMethodException { - Method oneMatrix = TestMatrixReplace.class.getMethod("oneMatrix", String.class); - String path = factory(TestMatrixReplace.class).createRequest(oneMatrix, new Object[] { "robot" }).getEndpoint() - .getPath(); - assertEquals(path, "/;x-amz-copy-source=/robot"); - } - - @Test - public void testBuildTwoMatrixs() throws SecurityException, NoSuchMethodException { - Method twoMatrixs = TestMatrixReplace.class.getMethod("twoMatrixs", String.class, String.class); - String path = factory(TestMatrixReplace.class).createRequest(twoMatrixs, new Object[] { "robot", "eggs" }) - .getEndpoint().getPath(); - assertEquals(path, "/;x-amz-copy-source=/robot/eggs"); - } - - @Test - public void testBuildTwoMatrixsOutOfOrder() throws SecurityException, NoSuchMethodException { - Method twoMatrixsOutOfOrder = TestMatrixReplace.class.getMethod("twoMatrixsOutOfOrder", String.class, - String.class); - String path = factory(TestMatrixReplace.class) - .createRequest(twoMatrixsOutOfOrder, new Object[] { "robot", "eggs" }).getEndpoint().getPath(); - assertEquals(path, "/;x-amz-copy-source=/eggs/robot"); - } - public interface TestTransformers { @GET int noTransformer(); @@ -2154,9 +2006,9 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { assertEquals(request.getEndpoint().getPath(), "/1"); assertEquals(request.getMethod(), HttpMethod.GET); assertEquals(request.getHeaders().size(), 2); - assertEquals(request.getHeaders().get(HttpHeaders.HOST), Collections.singletonList("localhost:9999")); + assertEquals(request.getHeaders().get(HttpHeaders.HOST), ImmutableList.of("localhost:9999")); assertEquals(request.getHeaders().get(HttpHeaders.IF_MODIFIED_SINCE), - Collections.singletonList(dateService.rfc822DateFormat(date))); + ImmutableList.of(dateService.rfc822DateFormat(date))); } public void testCreateGetOptionsThatProducesHeaders() throws SecurityException, NoSuchMethodException { @@ -2168,9 +2020,9 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { assertEquals(request.getEndpoint().getPath(), "/1"); assertEquals(request.getMethod(), HttpMethod.GET); assertEquals(request.getHeaders().size(), 2); - assertEquals(request.getHeaders().get(HttpHeaders.HOST), Collections.singletonList("localhost:9999")); + assertEquals(request.getHeaders().get(HttpHeaders.HOST), ImmutableList.of("localhost:9999")); assertEquals(request.getHeaders().get(HttpHeaders.IF_MODIFIED_SINCE), - Collections.singletonList(dateService.rfc822DateFormat(date))); + ImmutableList.of(dateService.rfc822DateFormat(date))); } public class PrefixOptions extends BaseHttpRequestOptions { @@ -2245,14 +2097,14 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { public void testCreateGetRequest(String key) throws SecurityException, NoSuchMethodException, UnsupportedEncodingException { Method method = TestRequest.class.getMethod("get", String.class, String.class); - HttpRequest request = factory(TestRequest.class).createRequest(method, new Object[] { key, "localhost" }); + HttpRequest request = factory(TestRequest.class).createRequest(method, key, "localhost"); assertEquals(request.getEndpoint().getHost(), "localhost"); String expectedPath = "/" + URLEncoder.encode(key, "UTF-8").replaceAll("\\+", "%20"); assertEquals(request.getEndpoint().getRawPath(), expectedPath); assertEquals(request.getEndpoint().getPath(), "/" + key); assertEquals(request.getMethod(), HttpMethod.GET); assertEquals(request.getHeaders().size(), 1); - assertEquals(request.getHeaders().get(HttpHeaders.HOST), Collections.singletonList("localhost")); + assertEquals(request.getHeaders().get(HttpHeaders.HOST), ImmutableList.of("localhost")); } public void testCreatePutRequest() throws SecurityException, NoSuchMethodException, IOException { @@ -2291,7 +2143,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { assertEquals(request.getEndpoint().getPath(), "/1"); assertEquals(request.getMethod(), HttpMethod.GET); assertEquals(request.getHeaders().size(), 1); - assertEquals(request.getHeaders().get(HttpHeaders.HOST), Collections.singletonList("localhost:9999")); + assertEquals(request.getHeaders().get(HttpHeaders.HOST), ImmutableList.of("localhost:9999")); } public interface TestVirtualHost { @@ -2314,7 +2166,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { assertEquals(request.getEndpoint().getPath(), "/1"); assertEquals(request.getMethod(), HttpMethod.GET); assertEquals(request.getHeaders().size(), 1); - assertEquals(request.getHeaders().get(HttpHeaders.HOST), Collections.singletonList("localhost:9999")); + assertEquals(request.getHeaders().get(HttpHeaders.HOST), ImmutableList.of("localhost:9999")); } @Test @@ -2351,35 +2203,35 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { public void testOneHeader() throws SecurityException, NoSuchMethodException, ExecutionException { Method method = TestHeaders.class.getMethod("oneHeader", String.class); Multimap headers = factory(TestHeaders.class).buildHeaders( - ImmutableMultimap. of().entries(), method, "robot"); + ImmutableMultimap. of(), method, "robot"); assertEquals(headers.size(), 1); - assertEquals(headers.get("header"), Collections.singletonList("robot")); + assertEquals(headers.get("header"), ImmutableList.of("robot")); } @Test public void testOneIntHeader() throws SecurityException, NoSuchMethodException, ExecutionException { Method method = TestHeaders.class.getMethod("oneIntHeader", int.class); Multimap headers = factory(TestHeaders.class).buildHeaders( - ImmutableMultimap. of().entries(), method, 1); + ImmutableMultimap. of(), method, 1); assertEquals(headers.size(), 1); - assertEquals(headers.get("header"), Collections.singletonList("1")); + assertEquals(headers.get("header"), ImmutableList.of("1")); } @Test public void testTwoDifferentHeaders() throws SecurityException, NoSuchMethodException, ExecutionException { Method method = TestHeaders.class.getMethod("twoDifferentHeaders", String.class, String.class); Multimap headers = factory(TestHeaders.class).buildHeaders( - ImmutableMultimap. of().entries(), method, "robot", "egg"); + ImmutableMultimap. of(), method, "robot", "egg"); assertEquals(headers.size(), 2); - assertEquals(headers.get("header1"), Collections.singletonList("robot")); - assertEquals(headers.get("header2"), Collections.singletonList("egg")); + assertEquals(headers.get("header1"), ImmutableList.of("robot")); + assertEquals(headers.get("header2"), ImmutableList.of("egg")); } @Test public void testTwoSameHeaders() throws SecurityException, NoSuchMethodException, ExecutionException { Method method = TestHeaders.class.getMethod("twoSameHeaders", String.class, String.class); Multimap headers = factory(TestHeaders.class).buildHeaders( - ImmutableMultimap. of().entries(), method, "robot", "egg"); + ImmutableMultimap. of(), method, "robot", "egg"); assertEquals(headers.size(), 2); Collection values = headers.get("header"); assert values.contains("robot"); @@ -2478,8 +2330,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { } } - @SkipEncoding('/') - public class TestFormReplace { + public class TestFormReplace { @POST @Path("/") @@ -2519,8 +2370,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { } @FormParams(keys = "x-amz-copy-source", values = "/{bucket}") - @SkipEncoding('/') - public interface TestClassForm { + public interface TestClassForm { @Provides Set set(); @@ -2601,7 +2451,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest { @GET @Path("/jaxb/header") - @Consumes(MediaType.APPLICATION_XML) + @Consumes("application/xml") public ListenableFuture jaxbGetWithAcceptHeader(); } diff --git a/core/src/test/java/org/jclouds/util/HttpUtilsTest.java b/core/src/test/java/org/jclouds/util/HttpUtilsTest.java index 424a85b1bd..90f313e8d0 100644 --- a/core/src/test/java/org/jclouds/util/HttpUtilsTest.java +++ b/core/src/test/java/org/jclouds/util/HttpUtilsTest.java @@ -22,100 +22,16 @@ import static com.google.common.base.Predicates.equalTo; import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull; import static org.testng.Assert.assertEquals; -import java.net.URI; - -import javax.inject.Provider; -import javax.ws.rs.core.UriBuilder; - -import org.jclouds.PerformanceTest; import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponseException; -import org.jclouds.http.HttpUtils; import org.testng.annotations.Test; -import com.sun.jersey.api.uri.UriBuilderImpl; - /** - * This tests the performance of Digest commands. - * +* * @author Adrian Cole */ -//NOTE:without testName, this will not call @Before* and fail w/NPE during surefire -@Test(groups = "performance", sequential = true, timeOut = 2 * 60 * 1000, testName = "HttpUtilsTest") -public class HttpUtilsTest extends PerformanceTest { - Provider uriBuilderProvider = new Provider() { - - @Override - public UriBuilder get() { - return new UriBuilderImpl(); - } - - }; - - public void testIBM() { - URI ibm = HttpUtils - .createUri("https://www-180.ibm.com/cloud/enterprise/beta/ram/assetDetail/generalDetails.faces?guid={A31FF849-0E97-431A-0324-097385A46298}&v=1.2"); - assertEquals(ibm.getQuery(), "guid={A31FF849-0E97-431A-0324-097385A46298}&v=1.2"); - } - - public void testAtmos() { - URI creds = HttpUtils.createUri("compute://domain/user:Base64==@azureblob/container-hyphen/prefix"); - assertEquals(creds, URI.create("compute://domain%2Fuser:Base64%3D%3D@azureblob/container-hyphen/prefix")); - } - - public void testAzure() { - URI creds = HttpUtils.createUri("compute://identity:Base64==@azureblob/container-hyphen/prefix"); - assertEquals(creds, URI.create("compute://identity:Base64==@azureblob/container-hyphen/prefix")); - } - - public void testDollar() { - URI creds = HttpUtils.createUri("compute://user@domain:pa$sword@host"); - assertEquals(creds.getUserInfo(), "user@domain:pa$sword"); - assertEquals(creds, URI.create("compute://user%40domain:pa%24sword@host")); - } - - public void testTerremark() { - URI creds = HttpUtils.createUri("compute://user@domain:password@terremark"); - assertEquals(creds.getUserInfo(), "user@domain:password"); - assertEquals(creds, URI.create("compute://user%40domain:password@terremark")); - } - - public void testTerremark2() { - URI creds = HttpUtils.createUri("compute://user@domain:passw@rd@terremark"); - assertEquals(creds.getUserInfo(), "user@domain:passw@rd"); - assertEquals(creds, URI.create("compute://user%40domain:passw%40rd@terremark")); - } - - public void testTerremark3() { - URI creds = HttpUtils.createUri("compute://user@domain:AbC!@943!@terremark"); - assertEquals(creds.getUserInfo(), "user@domain:AbC!@943!"); - assertEquals(creds, URI.create("compute://user%40domain:AbC%21%40943%21@terremark")); - } - - public void testCloudFiles() { - URI creds = HttpUtils.createUri("compute://identity:h3c@cloudfiles/container-hyphen/prefix"); - assertEquals(creds, URI.create("compute://identity:h3c@cloudfiles/container-hyphen/prefix")); - } - - public void testS3() { - - URI creds = HttpUtils.createUri("compute://0AB:aA+/0@s3/buck-et/prefix"); - assertEquals(creds, URI.create("compute://0AB:aA%2B%2F0@s3/buck-et/prefix")); - } - - public void testS3Space() { - - URI creds = HttpUtils.createUri("compute://0AB:aA+/0@s3/buck-et/pre fix"); - - assertEquals(creds, URI.create("compute://0AB:aA%2B%2F0@s3/buck-et/pre%20fix")); - } - - public void testPercent() { - URI creds = HttpUtils.createUri("https://jclouds.blob.core.windows.net/jclouds-getpath/write-tests/file1%.txt"); - - assertEquals(creds, URI.create("https://jclouds.blob.core.windows.net/jclouds-getpath/write-tests/file1%25.txt")); - - } +@Test(groups = "unit") +public class HttpUtilsTest { public void test404() { Exception from = new HttpResponseException("message", null, HttpResponse.builder().statusCode(404).message("not found").build()); diff --git a/labs/abiquo/src/main/java/org/jclouds/abiquo/binders/infrastructure/ucs/BindLogicServerParameters.java b/labs/abiquo/src/main/java/org/jclouds/abiquo/binders/infrastructure/ucs/BindLogicServerParameters.java index ef2072fc40..a4f99e8f13 100644 --- a/labs/abiquo/src/main/java/org/jclouds/abiquo/binders/infrastructure/ucs/BindLogicServerParameters.java +++ b/labs/abiquo/src/main/java/org/jclouds/abiquo/binders/infrastructure/ucs/BindLogicServerParameters.java @@ -48,6 +48,6 @@ public class BindLogicServerParameters implements Binder LogicServerDto server = (LogicServerDto) input; - return (R) request.toBuilder().addQueryParam("lsName", server.getName()).build(); - } + return (R) request.toBuilder().addQueryParam("lsName", checkNotNull(server.getName(), "server.name")).build(); + } } diff --git a/labs/abiquo/src/main/java/org/jclouds/abiquo/binders/infrastructure/ucs/BindOrganizationParameters.java b/labs/abiquo/src/main/java/org/jclouds/abiquo/binders/infrastructure/ucs/BindOrganizationParameters.java index ddde0cddc0..3e3126ff90 100644 --- a/labs/abiquo/src/main/java/org/jclouds/abiquo/binders/infrastructure/ucs/BindOrganizationParameters.java +++ b/labs/abiquo/src/main/java/org/jclouds/abiquo/binders/infrastructure/ucs/BindOrganizationParameters.java @@ -49,6 +49,6 @@ public class BindOrganizationParameters implements Binder OrganizationDto org = (OrganizationDto) input; - return (R) request.toBuilder().addQueryParam("org", org.getDn()).build(); - } + return (R) request.toBuilder().addQueryParam("org", checkNotNull(org.getDn(), "org.dn")).build(); + } } diff --git a/labs/abiquo/src/test/java/org/jclouds/abiquo/features/InfrastructureAsyncApiTest.java b/labs/abiquo/src/test/java/org/jclouds/abiquo/features/InfrastructureAsyncApiTest.java index ab5b294af7..03db3bd467 100644 --- a/labs/abiquo/src/test/java/org/jclouds/abiquo/features/InfrastructureAsyncApiTest.java +++ b/labs/abiquo/src/test/java/org/jclouds/abiquo/features/InfrastructureAsyncApiTest.java @@ -581,80 +581,62 @@ public class InfrastructureAsyncApiTest extends BaseAbiquoAsyncApiTestapi doc */ -@SkipEncoding({ '/', '=' }) @RequestFilters({ BasicAuthenticationAndTenantId.class, StripExtraAcceptHeader.class }) @Headers(keys = "X-CDMI-Specification-Version", values = "{jclouds.api-version}") public interface ContainerAsyncApi { diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataAsyncApi.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataAsyncApi.java index 6fe8841bca..af729b03bb 100644 --- a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataAsyncApi.java +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataAsyncApi.java @@ -31,7 +31,6 @@ import org.jclouds.rest.annotations.BinderParam; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; import org.jclouds.snia.cdmi.v1.ObjectTypes; import org.jclouds.snia.cdmi.v1.binders.BindQueryParmsToSuffix; @@ -50,7 +49,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @author Kenneth Nagin * @see api doc */ -@SkipEncoding({ '/', '=' }) @RequestFilters({ BasicAuthenticationAndTenantId.class, StripExtraAcceptHeader.class }) @Headers(keys = "X-CDMI-Specification-Version", values = "{jclouds.api-version}") public interface DataAsyncApi { diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataNonCDMIContentTypeAsyncApi.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataNonCDMIContentTypeAsyncApi.java index b58f80b472..c1202505f4 100644 --- a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataNonCDMIContentTypeAsyncApi.java +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataNonCDMIContentTypeAsyncApi.java @@ -35,7 +35,6 @@ import org.jclouds.rest.annotations.Payload; import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; import org.jclouds.snia.cdmi.v1.binders.BindQueryParmsToSuffix; import org.jclouds.snia.cdmi.v1.domain.DataObject; @@ -54,7 +53,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @author Kenneth Nagin * @see api doc */ -@SkipEncoding({ '/', '=' }) @RequestFilters({ BasicAuthenticationAndTenantId.class, StripExtraAcceptHeader.class }) public interface DataNonCDMIContentTypeAsyncApi { /** diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DomainAsyncApi.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DomainAsyncApi.java index 78c93fd4c8..bd43b025b3 100644 --- a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DomainAsyncApi.java +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DomainAsyncApi.java @@ -20,7 +20,6 @@ package org.jclouds.snia.cdmi.v1.features; import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.snia.cdmi.v1.filters.BasicAuthenticationAndTenantId; import org.jclouds.snia.cdmi.v1.filters.StripExtraAcceptHeader; @@ -31,7 +30,6 @@ import org.jclouds.snia.cdmi.v1.filters.StripExtraAcceptHeader; * @author Adrian Cole * @see api doc */ -@SkipEncoding({ '/', '=' }) @RequestFilters({ BasicAuthenticationAndTenantId.class, StripExtraAcceptHeader.class }) @Headers(keys = "X-CDMI-Specification-Version", values = "{jclouds.api-version}") public interface DomainAsyncApi { diff --git a/labs/elb/src/test/java/org/jclouds/elb/features/AvailabilityZoneApiExpectTest.java b/labs/elb/src/test/java/org/jclouds/elb/features/AvailabilityZoneApiExpectTest.java index a322c930f7..1230bf7bbc 100644 --- a/labs/elb/src/test/java/org/jclouds/elb/features/AvailabilityZoneApiExpectTest.java +++ b/labs/elb/src/test/java/org/jclouds/elb/features/AvailabilityZoneApiExpectTest.java @@ -51,7 +51,7 @@ public class AvailabilityZoneApiExpectTest extends BaseELBApiExpectTest { "Action=EnableAvailabilityZonesForLoadBalancer" + "&AvailabilityZones.member.1=us-east-1a" + "&LoadBalancerName=name" + - "&Signature=lay8JNIpYsgWjiTbA4%2FrgKrQPWhFKToPxw%2FfCLld4SE%3D" + + "&Signature=lay8JNIpYsgWjiTbA4/rgKrQPWhFKToPxw/fCLld4SE%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -135,7 +135,7 @@ public class AvailabilityZoneApiExpectTest extends BaseELBApiExpectTest { "Action=DisableAvailabilityZonesForLoadBalancer" + "&AvailabilityZones.member.1=us-east-1a" + "&LoadBalancerName=name" + - "&Signature=tjzaFDhUghKwTpe%2F9OC8JK%2BJsRMCkF3Kh5YkvPEDPbg%3D" + + "&Signature=tjzaFDhUghKwTpe/9OC8JK%2BJsRMCkF3Kh5YkvPEDPbg%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + diff --git a/labs/elb/src/test/java/org/jclouds/elb/features/InstanceApiExpectTest.java b/labs/elb/src/test/java/org/jclouds/elb/features/InstanceApiExpectTest.java index 5c3d189942..5a05d69247 100644 --- a/labs/elb/src/test/java/org/jclouds/elb/features/InstanceApiExpectTest.java +++ b/labs/elb/src/test/java/org/jclouds/elb/features/InstanceApiExpectTest.java @@ -133,7 +133,7 @@ public class InstanceApiExpectTest extends BaseELBApiExpectTest { "&Instances.member.1.InstanceId=i-6055fa09" + "&Instances.member.2.InstanceId=i-9055fa55" + "&LoadBalancerName=name" + - "&Signature=Yfqg8TxL1J1Ug8SimY%2F30rnbt%2FUVygTEa0vhMT5Fz1Y%3D" + + "&Signature=Yfqg8TxL1J1Ug8SimY/30rnbt/UVygTEa0vhMT5Fz1Y%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -175,7 +175,7 @@ public class InstanceApiExpectTest extends BaseELBApiExpectTest { "Action=DeregisterInstancesFromLoadBalancer" + "&Instances.member.1.InstanceId=i-6055fa09" + "&LoadBalancerName=name" + - "&Signature=d%2BK6b2ggJLEekW8wLyRnm%2FpcEpZvc8VNI%2FW0bpYBGUk%3D" + + "&Signature=d%2BK6b2ggJLEekW8wLyRnm/pcEpZvc8VNI/W0bpYBGUk%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -217,7 +217,7 @@ public class InstanceApiExpectTest extends BaseELBApiExpectTest { "&Instances.member.1.InstanceId=i-6055fa09" + "&Instances.member.2.InstanceId=i-9055fa55" + "&LoadBalancerName=name" + - "&Signature=nqn8iH70979k%2Fu%2FKXEcMlT1Zd%2FPaNK6ZBwFDjvbuMRo%3D" + + "&Signature=nqn8iH70979k/u/KXEcMlT1Zd/PaNK6ZBwFDjvbuMRo%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + diff --git a/labs/elb/src/test/java/org/jclouds/elb/features/LoadBalancerApiExpectTest.java b/labs/elb/src/test/java/org/jclouds/elb/features/LoadBalancerApiExpectTest.java index f82a6eddef..1179ef96cb 100644 --- a/labs/elb/src/test/java/org/jclouds/elb/features/LoadBalancerApiExpectTest.java +++ b/labs/elb/src/test/java/org/jclouds/elb/features/LoadBalancerApiExpectTest.java @@ -55,7 +55,7 @@ public class LoadBalancerApiExpectTest extends BaseELBApiExpectTest { payloadFromStringWithContentType( "Action=DescribeLoadBalancers" + "&LoadBalancerNames.member.1=name" + - "&Signature=EYzZgYDMGi9uFZU%2BVh%2FmmsJ9KmHxm5vEAF%2BhGF12BP4%3D" + + "&Signature=EYzZgYDMGi9uFZU%2BVh/mmsJ9KmHxm5vEAF%2BhGF12BP4%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -93,7 +93,7 @@ public class LoadBalancerApiExpectTest extends BaseELBApiExpectTest { .payload( payloadFromStringWithContentType( "Action=DescribeLoadBalancers" + - "&Signature=3pErfVJXXe4EndOr3nPMu2%2F5eO8aCvwcOaI%2BL64VMqg%3D" + + "&Signature=3pErfVJXXe4EndOr3nPMu2/5eO8aCvwcOaI%2BL64VMqg%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -127,7 +127,7 @@ public class LoadBalancerApiExpectTest extends BaseELBApiExpectTest { payloadFromStringWithContentType( "Action=DescribeLoadBalancers" + "&Marker=MARKER" + - "&Signature=%2FJttkIXuYljhZLJOPYyn%2BYIkDhD9skmePH3LYEnqmes%3D" + + "&Signature=/JttkIXuYljhZLJOPYyn%2BYIkDhD9skmePH3LYEnqmes%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -157,7 +157,7 @@ public class LoadBalancerApiExpectTest extends BaseELBApiExpectTest { .payload( payloadFromStringWithContentType( "Action=DescribeLoadBalancers" + - "&Signature=%2FT6QECRsE52DT6mA7AkBy4%2Bdnvy4RXU3nNt56td0GTo%3D" + + "&Signature=/T6QECRsE52DT6mA7AkBy4%2Bdnvy4RXU3nNt56td0GTo%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -217,7 +217,7 @@ public class LoadBalancerApiExpectTest extends BaseELBApiExpectTest { .payload(payloadFromStringWithContentType( "Action=DescribeLoadBalancers" + "&Marker=MARKER" + - "&Signature=%2FJttkIXuYljhZLJOPYyn%2BYIkDhD9skmePH3LYEnqmes%3D" + + "&Signature=/JttkIXuYljhZLJOPYyn%2BYIkDhD9skmePH3LYEnqmes%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + diff --git a/labs/elb/src/test/java/org/jclouds/elb/features/PolicyApiExpectTest.java b/labs/elb/src/test/java/org/jclouds/elb/features/PolicyApiExpectTest.java index aeba34d7a3..e9499c5056 100644 --- a/labs/elb/src/test/java/org/jclouds/elb/features/PolicyApiExpectTest.java +++ b/labs/elb/src/test/java/org/jclouds/elb/features/PolicyApiExpectTest.java @@ -92,7 +92,7 @@ public class PolicyApiExpectTest extends BaseELBApiExpectTest { .payload( payloadFromStringWithContentType( "Action=DescribeLoadBalancerPolicies" + - "&Signature=0LPrgeysYoQe6PyK2nh3mCgo0lxPNiERxm46W%2FN5GpU%3D" + + "&Signature=0LPrgeysYoQe6PyK2nh3mCgo0lxPNiERxm46W/N5GpU%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -197,7 +197,7 @@ public class PolicyApiExpectTest extends BaseELBApiExpectTest { .payload( payloadFromStringWithContentType( "Action=DescribeLoadBalancerPolicyTypes" + - "&Signature=%2F1mMjugJD8Zvb%2BK%2FQgOZMYVenlveCKtvGBiHaZVc%2B9w%3D" + + "&Signature=/1mMjugJD8Zvb%2BK/QgOZMYVenlveCKtvGBiHaZVc%2B9w%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/filters/RequestAuthenticator.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/filters/RequestAuthenticator.java index 4cf2340d5d..94658d5cc8 100644 --- a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/filters/RequestAuthenticator.java +++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/filters/RequestAuthenticator.java @@ -19,14 +19,15 @@ package org.jclouds.fujitsu.fgcp.filters; import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.http.utils.Queries.queryParser; -import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Signature; +import java.security.SignatureException; import java.security.UnrecoverableKeyException; import java.util.Calendar; import java.util.Locale; @@ -39,24 +40,23 @@ import javax.inject.Singleton; import javax.ws.rs.HttpMethod; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.UriBuilder; import org.jclouds.Constants; +import org.jclouds.crypto.CryptoStreams; import org.jclouds.date.TimeStamp; -import org.jclouds.encryption.internal.Base64; import org.jclouds.fujitsu.fgcp.reference.RequestParameters; import org.jclouds.http.HttpException; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpUtils; import org.jclouds.http.internal.SignatureWire; -import org.jclouds.http.utils.Queries; import org.jclouds.logging.Logger; import org.jclouds.rest.RequestSigner; import org.jclouds.rest.annotations.ApiVersion; import org.jclouds.rest.annotations.Credential; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Charsets; import com.google.common.collect.Multimap; /** @@ -74,7 +74,6 @@ public class RequestAuthenticator implements HttpRequestFilter, RequestSigner { final Provider calendarProvider; final Signature signer; - final Provider builder; final String apiVersion; public String signatureVersion = "1.0"; @@ -83,22 +82,17 @@ public class RequestAuthenticator implements HttpRequestFilter, RequestSigner { private HttpUtils utils; @Inject - public RequestAuthenticator(@TimeStamp Provider calendarProvider, - Provider keyStoreProvider, - @Credential String keyPassword, Provider builder, - HttpUtils utils, SignatureWire signatureWire, - @ApiVersion String apiVersion) throws NoSuchAlgorithmException, - InvalidKeyException, KeyStoreException, UnrecoverableKeyException { + public RequestAuthenticator(@TimeStamp Provider calendarProvider, Provider keyStoreProvider, + @Credential String keyPassword, HttpUtils utils, SignatureWire signatureWire, @ApiVersion String apiVersion) + throws NoSuchAlgorithmException, InvalidKeyException, KeyStoreException, UnrecoverableKeyException { this.calendarProvider = checkNotNull(calendarProvider); - this.builder = checkNotNull(builder); this.utils = checkNotNull(utils, "utils"); this.apiVersion = checkNotNull(apiVersion, "apiVersion"); signer = Signature.getInstance(signatureMethod); KeyStore keyStore = checkNotNull(keyStoreProvider).get(); - String alias = keyStore.aliases().nextElement(); // there should be only - // one private key + String alias = keyStore.aliases().nextElement(); // there should be only one private key PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, keyPassword.toCharArray()); @@ -114,38 +108,13 @@ public class RequestAuthenticator implements HttpRequestFilter, RequestSigner { String accessKeyId = createStringToSign(request); String signature = sign(accessKeyId); - // leaving this in for now for reference in case I need it for multipart - // POSTs - // add parameters. Note that in case of a GET, url escaping is required - /* - * Multimap decodedParams = null; if - * (HttpMethod.GET.equals(request.getMethod())) { decodedParams = - * ModifyRequest.parseQueryToMap(request.getEndpoint().getRawQuery()); - * - * } else if (HttpMethod.POST.equals(request.getMethod())) { - * decodedParams = - * ModifyRequest.parseQueryToMap(request.getPayload().getRawContent() - * .toString()); } - * - * checkNotNull(decodedParams, "no query params found"); - * System.out.println("filter: request params before: " + - * decodedParams.toString()); addAuthenticationParams(decodedParams, - * accessKeyId, signature); addLocaleParam(decodedParams); - * System.out.println("filter: request params after : " + - * decodedParams.toString()); if (signatureWire.enabled()) - * signatureWire.output(decodedParams); - * - * - * request = setPayload(request, decodedParams); - */ // only "en" and "ja" are allowed String lang = Locale.JAPANESE.getLanguage().equals( Locale.getDefault().getLanguage()) ? Locale.JAPANESE .getLanguage() : Locale.ENGLISH.getLanguage(); if (HttpMethod.GET.equals(request.getMethod())) { - Multimap decodedParams = Queries - .parseQueryToMap(request.getEndpoint().getRawQuery()); + Multimap decodedParams = queryParser().apply(request.getEndpoint().getRawQuery()); if (!decodedParams.containsKey(RequestParameters.VERSION)) { decodedParams.put(RequestParameters.VERSION, apiVersion); @@ -153,8 +122,7 @@ public class RequestAuthenticator implements HttpRequestFilter, RequestSigner { decodedParams.put(RequestParameters.LOCALE, lang); decodedParams.put(RequestParameters.ACCESS_KEY_ID, accessKeyId); decodedParams.put(RequestParameters.SIGNATURE, signature); - request = request.toBuilder().replaceQueryParams(decodedParams) - .build(); + request = request.toBuilder().replaceQueryParams(decodedParams).build(); } else { String payload = request.getPayload().getRawContent().toString(); @@ -203,10 +171,9 @@ public class RequestAuthenticator implements HttpRequestFilter, RequestSigner { String signed; try { - signer.update(stringToSign.getBytes("UTF-8")); - signed = Base64.encodeBytes(signer.sign()).replace("\n", "\r\n"); -// signed = CryptoStreams.base64(signer.sign()); - } catch (Exception e) { + signer.update(stringToSign.getBytes(Charsets.UTF_8)); + signed = CryptoStreams.base64(signer.sign()); + } catch (SignatureException e) { throw new HttpException("error signing request", e); } // if (signatureWire.enabled()) @@ -223,14 +190,8 @@ public class RequestAuthenticator implements HttpRequestFilter, RequestSigner { String signatureData = String.format("%s&%s&%s&%s", timezone, expires, signatureVersion, signatureMethod); - try { - String accessKeyId = Base64.encodeBytes(signatureData.getBytes("UTF-8")); - return accessKeyId.replace("\n", "\r\n"); -// return CryptoStreams.base64(signatureData.getBytes("UTF-8")).; - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); // should never happen as - // signatureData contains only ASCII - } + String accessKeyId = CryptoStreams.base64(signatureData.getBytes(Charsets.UTF_8)); + return accessKeyId.replace("\n", "\r\n"); } @Override diff --git a/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/BaseFGCPRestApiExpectTest.java b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/BaseFGCPRestApiExpectTest.java index 4a90da03d0..3a50fc11f4 100644 --- a/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/BaseFGCPRestApiExpectTest.java +++ b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/BaseFGCPRestApiExpectTest.java @@ -95,8 +95,7 @@ public class BaseFGCPRestApiExpectTest extends + "&" + query + "&Locale=en" + "&AccessKeyId=R01ULTA5OjAwJjEyMzQ1Njc4OTAmMS4wJlNIQTF3aXRoUlNB" -// + "&Signature=G2rGfLAkbq0IURQfXIWYxj3BnMGbjRk4KPnZLAze3Lt4SMMRt8lkjqKvR5Cm%2BnFpDN7J6IprVCCsIrRq5BqPeXT6xtWyb6qMNds2BAr1h%2FJePGs0UosOh2tgPUMSFlZwLVjgNyrSa2zeHA3AEHjF6H1jqcWXXqfCAD4SOHaNavk%3D"); - + "&Signature=G2rGfLAkbq0IURQfXIWYxj3BnMGbjRk4KPnZLAze3Lt4SMMRt8lkjqKvR5Cm%2BnFpDN7J6IprVCCs%0D%0AIrRq5BqPeXT6xtWyb6qMNds2BAr1h%2FJePGs0UosOh2tgPUMSFlZwLVjgNyrSa2zeHA3AEHjF6H1j%0D%0AqcWXXqfCAD4SOHaNavk%3D"); + + "&Signature=G2rGfLAkbq0IURQfXIWYxj3BnMGbjRk4KPnZLAze3Lt4SMMRt8lkjqKvR5Cm%20nFpDN7J6IprVCCsIrRq5BqPeXT6xtWyb6qMNds2BAr1h/JePGs0UosOh2tgPUMSFlZwLVjgNyrSa2zeHA3AEHjF6H1jqcWXXqfCAD4SOHaNavk%3D"); return HttpRequest .builder() .method("GET") diff --git a/labs/iam/src/test/java/org/jclouds/iam/features/UserApiExpectTest.java b/labs/iam/src/test/java/org/jclouds/iam/features/UserApiExpectTest.java index 15000246aa..110ddfd70f 100644 --- a/labs/iam/src/test/java/org/jclouds/iam/features/UserApiExpectTest.java +++ b/labs/iam/src/test/java/org/jclouds/iam/features/UserApiExpectTest.java @@ -52,7 +52,7 @@ public class UserApiExpectTest extends BaseIAMApiExpectTest { .endpoint("https://iam.amazonaws.com/") .addHeader("Host", "iam.amazonaws.com") .addFormParam("Action", "GetUser") - .addFormParam("Signature", "2UamWqKKgoSbaZpvixX0LKqGW%2FIIP9L319DLEUtYu3A%3D") + .addFormParam("Signature", "2UamWqKKgoSbaZpvixX0LKqGW/IIP9L319DLEUtYu3A%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") @@ -73,7 +73,7 @@ public class UserApiExpectTest extends BaseIAMApiExpectTest { .endpoint("https://iam.amazonaws.com/") .addHeader("Host", "iam.amazonaws.com") .addFormParam("Action", "GetUser") - .addFormParam("Signature", "cnY%2FAaG656cruOmb3y7YHtjnPB1qg3aavff6PPxIMs0%3D") + .addFormParam("Signature", "cnY/AaG656cruOmb3y7YHtjnPB1qg3aavff6PPxIMs0%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") @@ -137,7 +137,7 @@ public class UserApiExpectTest extends BaseIAMApiExpectTest { .addHeader("Host", "iam.amazonaws.com") .addFormParam("Action", "ListUsers") .addFormParam("Marker", "MARKER") - .addFormParam("Signature", "LKYao6Hll%2FplLDqOcgbNuJ6DhmOw0tZl4Sf3pPY%2By00%3D") + .addFormParam("Signature", "LKYao6Hll/plLDqOcgbNuJ6DhmOw0tZl4Sf3pPY%2By00%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z") @@ -174,7 +174,7 @@ public class UserApiExpectTest extends BaseIAMApiExpectTest { .addHeader("Host", "iam.amazonaws.com") .addFormParam("Action", "ListUsers") .addFormParam("Marker", "MARKER") - .addFormParam("PathPrefix", "%2Ffoo") + .addFormParam("PathPrefix", "/foo") .addFormParam("Signature", "1%2BeCgNIAjHr%2BraNdDd3rsVC5Qok3AuTrJOa5mZwmE7g%3D") .addFormParam("SignatureMethod", "HmacSHA256") .addFormParam("SignatureVersion", "2") diff --git a/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/DatacenterAsyncApi.java b/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/DatacenterAsyncApi.java index a22d5a0c85..c93575d7fc 100644 --- a/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/DatacenterAsyncApi.java +++ b/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/DatacenterAsyncApi.java @@ -30,7 +30,6 @@ import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnEmptyMapOnNotFoundOr404; import com.google.common.util.concurrent.ListenableFuture; @@ -42,7 +41,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @author Adrian Cole * @see api doc */ -@SkipEncoding({ '/', '=' }) @Headers(keys = "X-Api-Version", values = "{jclouds.api-version}") @RequestFilters(BasicAuthentication.class) public interface DatacenterAsyncApi { diff --git a/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/DatasetAsyncApi.java b/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/DatasetAsyncApi.java index d0b4985649..6afad98533 100644 --- a/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/DatasetAsyncApi.java +++ b/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/DatasetAsyncApi.java @@ -13,7 +13,6 @@ import org.jclouds.joyent.cloudapi.v6_5.domain.Dataset; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; @@ -27,7 +26,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @see DatasetApi * @see api doc */ -@SkipEncoding({ '/', '=' }) @Headers(keys = "X-Api-Version", values = "{jclouds.api-version}") @RequestFilters(BasicAuthentication.class) public interface DatasetAsyncApi { diff --git a/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/KeyAsyncApi.java b/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/KeyAsyncApi.java index fb7789eab3..e56f24bf4a 100644 --- a/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/KeyAsyncApi.java +++ b/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/KeyAsyncApi.java @@ -16,7 +16,6 @@ import org.jclouds.rest.annotations.BinderParam; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.binders.BindToJsonPayload; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; @@ -29,7 +28,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @see KeyApi * @see api doc */ -@SkipEncoding({ '/', '=' }) @Headers(keys = "X-Api-Version", values = "{jclouds.api-version}") @RequestFilters(BasicAuthentication.class) public interface KeyAsyncApi { diff --git a/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/MachineAsyncApi.java b/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/MachineAsyncApi.java index 1776941c50..f09462d9fa 100644 --- a/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/MachineAsyncApi.java +++ b/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/MachineAsyncApi.java @@ -38,7 +38,6 @@ import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.Payload; import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; @@ -53,7 +52,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @see MachineApi * @see api doc */ -@SkipEncoding({ '/', '=' }) @Headers(keys = "X-Api-Version", values = "{jclouds.api-version}") @RequestFilters(BasicAuthentication.class) public interface MachineAsyncApi { diff --git a/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/PackageAsyncApi.java b/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/PackageAsyncApi.java index 45c688a96d..c32f192cc2 100644 --- a/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/PackageAsyncApi.java +++ b/labs/joyent-cloudapi/src/main/java/org/jclouds/joyent/cloudapi/v6_5/features/PackageAsyncApi.java @@ -12,7 +12,6 @@ import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; @@ -26,7 +25,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @see PackageApi * @see api doc */ -@SkipEncoding({ '/', '=' }) @Headers(keys = "X-Api-Version", values = "{jclouds.api-version}") @RequestFilters(BasicAuthentication.class) public interface PackageAsyncApi { diff --git a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/features/ImageAsyncApi.java b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/features/ImageAsyncApi.java index 31c7b5d974..b147670aa1 100644 --- a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/features/ImageAsyncApi.java +++ b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/features/ImageAsyncApi.java @@ -49,7 +49,6 @@ import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.Transform; import org.jclouds.rest.functions.ReturnEmptyPagedIterableOnNotFoundOr404; import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404; @@ -66,7 +65,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @see api doc * @see api src */ -@SkipEncoding( { '/', '=' }) @RequestFilters(AuthenticateRequest.class) public interface ImageAsyncApi { diff --git a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/NetworkAsyncApi.java b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/NetworkAsyncApi.java index 64687a5502..3c43994110 100644 --- a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/NetworkAsyncApi.java +++ b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/NetworkAsyncApi.java @@ -36,7 +36,6 @@ import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.WrapWith; import org.jclouds.rest.functions.ReturnEmptyFluentIterableOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; @@ -51,7 +50,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @see org.jclouds.openstack.quantum.v1_0.features.NetworkApi * @see api doc */ -@SkipEncoding({'/', '='}) @RequestFilters(AuthenticateRequest.class) @Consumes(MediaType.APPLICATION_JSON) @Path("/networks") diff --git a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/PortAsyncApi.java b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/PortAsyncApi.java index fccae571b5..05c2a282ad 100644 --- a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/PortAsyncApi.java +++ b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/PortAsyncApi.java @@ -36,7 +36,6 @@ import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.WrapWith; import org.jclouds.rest.functions.ReturnEmptyFluentIterableOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; @@ -51,7 +50,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @see PortApi * @see api doc */ -@SkipEncoding({'/', '='}) @RequestFilters(AuthenticateRequest.class) @Consumes(MediaType.APPLICATION_JSON) @Path("/ports") diff --git a/labs/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/AccountAsyncApi.java b/labs/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/AccountAsyncApi.java index 9473428a5b..a27e691d7e 100644 --- a/labs/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/AccountAsyncApi.java +++ b/labs/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/AccountAsyncApi.java @@ -26,7 +26,6 @@ import org.jclouds.openstack.swift.v1.domain.Account; import org.jclouds.openstack.swift.v1.functions.ParseAccountMetadataResponseFromHeaders; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; -import org.jclouds.rest.annotations.SkipEncoding; import com.google.common.util.concurrent.ListenableFuture; @@ -39,7 +38,6 @@ import com.google.common.util.concurrent.ListenableFuture; * href="http://docs.openstack.org/api/openstack-object-storage/1.0/content/storage-account-services.html" * >api doc */ -@SkipEncoding( { '/', '=' }) @RequestFilters(AuthenticateRequest.class) public interface AccountAsyncApi { diff --git a/labs/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ContainerAsyncApi.java b/labs/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ContainerAsyncApi.java index b5978b1088..bb06b636ae 100644 --- a/labs/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ContainerAsyncApi.java +++ b/labs/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ContainerAsyncApi.java @@ -29,7 +29,6 @@ import org.jclouds.openstack.swift.v1.options.ListContainersOptions; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnEmptyFluentIterableOnNotFoundOr404; import com.google.common.collect.FluentIterable; @@ -44,7 +43,6 @@ import com.google.common.util.concurrent.ListenableFuture; * "http://docs.openstack.org/api/openstack-object-storage/1.0/content/storage-container-services.html" * >api doc */ -@SkipEncoding({ '/', '=' }) @RequestFilters(AuthenticateRequest.class) public interface ContainerAsyncApi { diff --git a/labs/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ObjectAsyncApi.java b/labs/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ObjectAsyncApi.java index a2d790de94..9bd77ccae1 100644 --- a/labs/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ObjectAsyncApi.java +++ b/labs/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ObjectAsyncApi.java @@ -20,7 +20,6 @@ package org.jclouds.openstack.swift.v1.features; import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; /** * Storage Object Services @@ -31,7 +30,6 @@ import org.jclouds.rest.annotations.SkipEncoding; * "http://docs.openstack.org/api/openstack-object-storage/1.0/content/storage-container-services.html" * >api doc */ -@SkipEncoding( { '/', '=' }) @RequestFilters(AuthenticateRequest.class) public interface ObjectAsyncApi { diff --git a/labs/rds/src/test/java/org/jclouds/rds/features/InstanceApiExpectTest.java b/labs/rds/src/test/java/org/jclouds/rds/features/InstanceApiExpectTest.java index cf552098af..ac1b081673 100644 --- a/labs/rds/src/test/java/org/jclouds/rds/features/InstanceApiExpectTest.java +++ b/labs/rds/src/test/java/org/jclouds/rds/features/InstanceApiExpectTest.java @@ -93,7 +93,7 @@ public class InstanceApiExpectTest extends BaseRDSApiExpectTest { .payload( payloadFromStringWithContentType( "Action=DescribeDBInstances" + - "&Signature=SnClCujZG9Sq9sMdf59xZWsjQxIbMOp5YEF%2FFBsurf4%3D" + + "&Signature=SnClCujZG9Sq9sMdf59xZWsjQxIbMOp5YEF/FBsurf4%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -126,7 +126,7 @@ public class InstanceApiExpectTest extends BaseRDSApiExpectTest { payloadFromStringWithContentType( "Action=DescribeDBInstances" + "&Marker=MARKER" + - "&Signature=TFW8vaU2IppmBey0ZHttbWz4rMFh%2F5ACWl6Xyt58sQU%3D" + + "&Signature=TFW8vaU2IppmBey0ZHttbWz4rMFh/5ACWl6Xyt58sQU%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -167,7 +167,7 @@ public class InstanceApiExpectTest extends BaseRDSApiExpectTest { .payload(payloadFromStringWithContentType( "Action=DescribeDBInstances" + "&Marker=MARKER" + - "&Signature=TFW8vaU2IppmBey0ZHttbWz4rMFh%2F5ACWl6Xyt58sQU%3D" + + "&Signature=TFW8vaU2IppmBey0ZHttbWz4rMFh/5ACWl6Xyt58sQU%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -241,7 +241,7 @@ public class InstanceApiExpectTest extends BaseRDSApiExpectTest { "Action=DeleteDBInstance" + "&DBInstanceIdentifier=id" + "&FinalDBSnapshotIdentifier=snap" + - "&Signature=aKuG1%2FYbZAzUFdAZTjke1LYRfR5JU86UxDt%2BtwdPJwE%3D" + + "&Signature=aKuG1/YbZAzUFdAZTjke1LYRfR5JU86UxDt%2BtwdPJwE%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -312,7 +312,7 @@ public class InstanceApiExpectTest extends BaseRDSApiExpectTest { "&Engine=mysql" + "&MasterUserPassword=Password01" + "&MasterUsername=master" + - "&Signature=kfDFp50sxBkSlZd%2Bv8G9u6%2BFdZ133BEVcIRGwwoa8%2Fs%3D" + + "&Signature=kfDFp50sxBkSlZd%2Bv8G9u6%2BFdZ133BEVcIRGwwoa8/s%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + diff --git a/labs/rds/src/test/java/org/jclouds/rds/features/SecurityGroupApiExpectTest.java b/labs/rds/src/test/java/org/jclouds/rds/features/SecurityGroupApiExpectTest.java index 995f64d8aa..6ff123677a 100644 --- a/labs/rds/src/test/java/org/jclouds/rds/features/SecurityGroupApiExpectTest.java +++ b/labs/rds/src/test/java/org/jclouds/rds/features/SecurityGroupApiExpectTest.java @@ -84,7 +84,7 @@ public class SecurityGroupApiExpectTest extends BaseRDSApiExpectTest { "&DBSecurityGroupDescription=My%20new%20DBSecurityGroup" + "&DBSecurityGroupName=mydbsecuritygroup" + "&EC2VpcId=vpc-1a2b3c4d" + - "&Signature=8MXHQRkGSKb0TzCKRIlDN9ymruqzY%2FQKgLMXoxYcqFI%3D" + + "&Signature=8MXHQRkGSKb0TzCKRIlDN9ymruqzY/QKgLMXoxYcqFI%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -109,7 +109,7 @@ public class SecurityGroupApiExpectTest extends BaseRDSApiExpectTest { payloadFromStringWithContentType( "Action=DescribeDBSecurityGroups" + "&DBSecurityGroupName=name" + - "&Signature=F019%2B74qM%2FivsW6ngZWfILFBss4RqPGlppawtAjwUPg%3D" + + "&Signature=F019%2B74qM/ivsW6ngZWfILFBss4RqPGlppawtAjwUPg%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -147,7 +147,7 @@ public class SecurityGroupApiExpectTest extends BaseRDSApiExpectTest { .payload( payloadFromStringWithContentType( "Action=DescribeDBSecurityGroups" + - "&Signature=6PMtOHuBCxE%2FuujPnvn%2FnN8NIZrwcx9X0Jy6hz%2FRXtg%3D" + + "&Signature=6PMtOHuBCxE/uujPnvn/nN8NIZrwcx9X0Jy6hz/RXtg%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -180,7 +180,7 @@ public class SecurityGroupApiExpectTest extends BaseRDSApiExpectTest { payloadFromStringWithContentType( "Action=DescribeDBSecurityGroups" + "&Marker=MARKER" + - "&Signature=DeZcA5ViQu%2FbB3PY9EmRZavRgYxLFMvdbq7topMKKhw%3D" + + "&Signature=DeZcA5ViQu/bB3PY9EmRZavRgYxLFMvdbq7topMKKhw%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -221,7 +221,7 @@ public class SecurityGroupApiExpectTest extends BaseRDSApiExpectTest { .payload(payloadFromStringWithContentType( "Action=DescribeDBSecurityGroups" + "&Marker=MARKER" + - "&Signature=DeZcA5ViQu%2FbB3PY9EmRZavRgYxLFMvdbq7topMKKhw%3D" + + "&Signature=DeZcA5ViQu/bB3PY9EmRZavRgYxLFMvdbq7topMKKhw%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -248,9 +248,9 @@ public class SecurityGroupApiExpectTest extends BaseRDSApiExpectTest { .payload( payloadFromStringWithContentType( "Action=AuthorizeDBSecurityGroupIngress" + - "&CIDRIP=0.0.0.0%2F0" + + "&CIDRIP=0.0.0.0/0" + "&DBSecurityGroupName=mydbsecuritygroup" + - "&Signature=Wk06HjnbFH5j%2FyfguUK6p3ZJU9kpYPgOlN9IGctLVSk%3D" + + "&Signature=Wk06HjnbFH5j/yfguUK6p3ZJU9kpYPgOlN9IGctLVSk%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -305,7 +305,7 @@ public class SecurityGroupApiExpectTest extends BaseRDSApiExpectTest { "Action=AuthorizeDBSecurityGroupIngress" + "&DBSecurityGroupName=mydbsecuritygroup" + "&EC2SecurityGroupId=sg-1312321312" + - "&Signature=o31Wey%2FwliTbHJoxdF7KGqIJwSM6pfqzkjIYio3XNGs%3D" + + "&Signature=o31Wey/wliTbHJoxdF7KGqIJwSM6pfqzkjIYio3XNGs%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -330,9 +330,9 @@ public class SecurityGroupApiExpectTest extends BaseRDSApiExpectTest { .payload( payloadFromStringWithContentType( "Action=RevokeDBSecurityGroupIngress" + - "&CIDRIP=0.0.0.0%2F0" + + "&CIDRIP=0.0.0.0/0" + "&DBSecurityGroupName=mydbsecuritygroup" + - "&Signature=YD1%2BzKmoWyYCmqWq1X9f%2FVj6UC7UnkwkPf%2BA5urnz%2BE%3D" + + "&Signature=YD1%2BzKmoWyYCmqWq1X9f/Vj6UC7UnkwkPf%2BA5urnz%2BE%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -387,7 +387,7 @@ public class SecurityGroupApiExpectTest extends BaseRDSApiExpectTest { "Action=RevokeDBSecurityGroupIngress" + "&DBSecurityGroupName=mydbsecuritygroup" + "&EC2SecurityGroupId=sg-1312321312" + - "&Signature=YI2oGYI%2BCx4DGYx43WH%2FehW6CWe6X6wEipsp5zPySzw%3D" + + "&Signature=YI2oGYI%2BCx4DGYx43WH/ehW6CWe6X6wEipsp5zPySzw%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + diff --git a/labs/rds/src/test/java/org/jclouds/rds/features/SubnetGroupApiExpectTest.java b/labs/rds/src/test/java/org/jclouds/rds/features/SubnetGroupApiExpectTest.java index 64ab2b740b..8e0e1a2fe9 100644 --- a/labs/rds/src/test/java/org/jclouds/rds/features/SubnetGroupApiExpectTest.java +++ b/labs/rds/src/test/java/org/jclouds/rds/features/SubnetGroupApiExpectTest.java @@ -54,7 +54,7 @@ public class SubnetGroupApiExpectTest extends BaseRDSApiExpectTest { payloadFromStringWithContentType( "Action=DescribeDBSubnetGroups" + "&DBSubnetGroupName=name" + - "&Signature=U7DwaG%2BDARTb1iQxztQN%2BBe042ywyD7wxEVUlm4%2FA20%3D" + + "&Signature=U7DwaG%2BDARTb1iQxztQN%2BBe042ywyD7wxEVUlm4/A20%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + @@ -194,7 +194,7 @@ public class SubnetGroupApiExpectTest extends BaseRDSApiExpectTest { payloadFromStringWithContentType( "Action=DeleteDBSubnetGroup" + "&DBSubnetGroupName=name" + - "&Signature=BbT14zD9UyRQzelQYzg%2F0FVcX%2Fs46ZyRtyxsdylOw7o%3D" + + "&Signature=BbT14zD9UyRQzelQYzg/0FVcX/s46ZyRtyxsdylOw7o%3D" + "&SignatureMethod=HmacSHA256" + "&SignatureVersion=2" + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + diff --git a/labs/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/options/BindGetVMOptions.java b/labs/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/options/BindGetVMOptions.java index cfc3fca5d3..f4a57a642e 100644 --- a/labs/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/options/BindGetVMOptions.java +++ b/labs/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/options/BindGetVMOptions.java @@ -19,11 +19,9 @@ package org.jclouds.savvis.vpdc.options; import static com.google.common.base.Preconditions.checkArgument; +import static org.jclouds.http.Uris.uriBuilder; -import javax.inject.Inject; -import javax.inject.Provider; import javax.inject.Singleton; -import javax.ws.rs.core.UriBuilder; import org.jclouds.http.HttpRequest; import org.jclouds.rest.Binder; @@ -34,12 +32,6 @@ import org.jclouds.rest.Binder; */ @Singleton public class BindGetVMOptions implements Binder { - private final Provider uriBuilder; - - @Inject - public BindGetVMOptions(Provider uriBuilder) { - this.uriBuilder = uriBuilder; - } @SuppressWarnings("unchecked") @Override @@ -47,8 +39,8 @@ public class BindGetVMOptions implements Binder { checkArgument(input instanceof GetVMOptions[], "this binder is only valid for GetVAppOptions!"); GetVMOptions[] options = GetVMOptions[].class.cast(input); if (options.length > 0 && options[0].isWithPowerState()) - return (R) request.toBuilder().endpoint( - uriBuilder.get().uri(request.getEndpoint()).path("withpowerstate").build()).build(); + return (R) request.toBuilder() + .endpoint(uriBuilder(request.getEndpoint()).appendPath("withpowerstate").build()).build(); else return request; } diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/admin/VCloudDirectorAdminAsyncApi.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/admin/VCloudDirectorAdminAsyncApi.java index 4df2d93c48..af31875951 100644 --- a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/admin/VCloudDirectorAdminAsyncApi.java +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/admin/VCloudDirectorAdminAsyncApi.java @@ -20,7 +20,6 @@ package org.jclouds.vcloud.director.v1_5.admin; import org.jclouds.rest.annotations.Delegate; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.vcloud.director.v1_5.features.admin.AdminCatalogAsyncApi; import org.jclouds.vcloud.director.v1_5.features.admin.AdminNetworkAsyncApi; import org.jclouds.vcloud.director.v1_5.features.admin.AdminOrgAsyncApi; @@ -38,7 +37,6 @@ import org.jclouds.vcloud.director.v1_5.user.VCloudDirectorAsyncApi; * @author danikov */ @RequestFilters(AddVCloudAuthorizationAndCookieToRequest.class) -@SkipEncoding({ '-', ':' }) public interface VCloudDirectorAdminAsyncApi extends VCloudDirectorAsyncApi { /** * @return asynchronous access to admin query features diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/QueryAsyncApi.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/QueryAsyncApi.java index 3fb5e58989..fef416755b 100644 --- a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/QueryAsyncApi.java +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/QueryAsyncApi.java @@ -26,9 +26,6 @@ import javax.ws.rs.QueryParam; import org.jclouds.rest.annotations.JAXBResponseParser; import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; -import org.jclouds.vcloud.director.v1_5.domain.Catalog; -import org.jclouds.vcloud.director.v1_5.domain.VApp; import org.jclouds.vcloud.director.v1_5.domain.query.CatalogReferences; import org.jclouds.vcloud.director.v1_5.domain.query.QueryList; import org.jclouds.vcloud.director.v1_5.domain.query.QueryResultRecords; @@ -42,7 +39,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @author grkvlt@apache.org */ @RequestFilters(AddVCloudAuthorizationAndCookieToRequest.class) -@SkipEncoding({ '=' }) public interface QueryAsyncApi { /** diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/user/VCloudDirectorAsyncApi.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/user/VCloudDirectorAsyncApi.java index a1eb5b294f..7c00a0df22 100644 --- a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/user/VCloudDirectorAsyncApi.java +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/user/VCloudDirectorAsyncApi.java @@ -27,7 +27,6 @@ import org.jclouds.rest.annotations.Delegate; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.JAXBResponseParser; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; import org.jclouds.vcloud.director.v1_5.domain.Catalog; import org.jclouds.vcloud.director.v1_5.domain.Entity; @@ -62,7 +61,6 @@ import com.google.inject.Provides; * @author Adrian Cole */ @RequestFilters(AddVCloudAuthorizationAndCookieToRequest.class) -@SkipEncoding({ '-', ':' }) public interface VCloudDirectorAsyncApi { /** diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/admin/GroupApiExpectTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/admin/GroupApiExpectTest.java index 5601ad5102..29891edc5c 100644 --- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/admin/GroupApiExpectTest.java +++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/admin/GroupApiExpectTest.java @@ -39,15 +39,15 @@ public class GroupApiExpectTest extends VCloudDirectorAdminApiExpectTest { private Reference groupRef = Reference.builder() .type("application/vnd.vmware.admin.group+xml") - .name("???") - .href(URI.create(endpoint + "/admin/group/???")) + .name("fff") + .href(URI.create(endpoint + "/admin/group/fff")) .build(); @Test(enabled = false) public void testGetGroup() { VCloudDirectorAdminApi api = requestsSendResponses(loginRequest, sessionResponse, new VcloudHttpRequestPrimer() - .apiCommand("GET", "/admin/group/???") + .apiCommand("GET", "/admin/group/fff") .acceptAnyMedia() .httpRequestBuilder().build(), new VcloudHttpResponsePrimer() @@ -69,7 +69,7 @@ public class GroupApiExpectTest extends VCloudDirectorAdminApiExpectTest { public void testEditGroup() { VCloudDirectorAdminApi api = requestsSendResponses(loginRequest, sessionResponse, new VcloudHttpRequestPrimer() - .apiCommand("PUT", "/admin/group/???") + .apiCommand("PUT", "/admin/group/fff") .xmlFilePayload("/group/editGroupSource.xml", VCloudDirectorMediaType.GROUP) .acceptMedia(VCloudDirectorMediaType.GROUP) .httpRequestBuilder().build(), @@ -90,7 +90,7 @@ public class GroupApiExpectTest extends VCloudDirectorAdminApiExpectTest { public void testRemoveGroup() { VCloudDirectorAdminApi api = requestsSendResponses(loginRequest, sessionResponse, new VcloudHttpRequestPrimer() - .apiCommand("DELETE", "/admin/group/???") + .apiCommand("DELETE", "/admin/group/fff") .acceptAnyMedia() .httpRequestBuilder().build(), new VcloudHttpResponsePrimer() diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSAMIAsyncClientTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSAMIAsyncClientTest.java index 0d253b6b96..47665c39a6 100644 --- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSAMIAsyncClientTest.java +++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSAMIAsyncClientTest.java @@ -191,7 +191,7 @@ public class AWSAMIAsyncClientTest extends BaseAWSEC2AsyncClientTest * @author Adrian Cole */ -@SkipEncoding('/') @RequestFilters(SharedKeyLiteAuthentication.class) @Headers(keys = AzureStorageHeaders.VERSION, values = "2009-07-17") public interface AzureBlobUtil { diff --git a/providers/azureblob/src/main/java/org/jclouds/azureblob/xml/ContainerNameEnumerationResultsHandler.java b/providers/azureblob/src/main/java/org/jclouds/azureblob/xml/ContainerNameEnumerationResultsHandler.java index 60816013c3..4a0be726d4 100644 --- a/providers/azureblob/src/main/java/org/jclouds/azureblob/xml/ContainerNameEnumerationResultsHandler.java +++ b/providers/azureblob/src/main/java/org/jclouds/azureblob/xml/ContainerNameEnumerationResultsHandler.java @@ -18,6 +18,8 @@ */ package org.jclouds.azureblob.xml; +import static org.jclouds.http.Uris.uriBuilder; + import java.net.URI; import java.util.Date; import java.util.Map; @@ -33,7 +35,6 @@ import org.jclouds.azureblob.domain.internal.BlobPropertiesImpl; import org.jclouds.azureblob.domain.internal.HashSetListBlobsResponse; import org.jclouds.crypto.CryptoStreams; import org.jclouds.date.DateService; -import org.jclouds.http.HttpUtils; import org.jclouds.http.functions.ParseSax; import org.jclouds.io.ContentMetadataCodec; import org.xml.sax.Attributes; @@ -152,7 +153,7 @@ public class ContainerNameEnumerationResultsHandler extends ParseSax.HandlerWith currentExpires = null; currentMetadata = Maps.newHashMap(); } else if (qName.equals("Url")) { - currentUrl = HttpUtils.createUri(currentText.toString().trim()); + currentUrl = uriBuilder(currentText.toString().trim()).build(); } else if (qName.equals("Last-Modified")) { currentLastModified = dateParser.rfc822DateParse(currentText.toString().trim()); } else if (qName.equals("Etag")) { diff --git a/providers/gogrid/src/main/java/org/jclouds/gogrid/filters/SharedKeyLiteAuthentication.java b/providers/gogrid/src/main/java/org/jclouds/gogrid/filters/SharedKeyLiteAuthentication.java index abdb8666b1..9e8dcee761 100644 --- a/providers/gogrid/src/main/java/org/jclouds/gogrid/filters/SharedKeyLiteAuthentication.java +++ b/providers/gogrid/src/main/java/org/jclouds/gogrid/filters/SharedKeyLiteAuthentication.java @@ -30,14 +30,12 @@ import org.jclouds.date.TimeStamp; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpUtils; -import org.jclouds.http.utils.Queries; import org.jclouds.io.InputSuppliers; import org.jclouds.logging.Logger; import org.jclouds.rest.annotations.Credential; import org.jclouds.rest.annotations.Identity; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Multimap; +import com.google.common.collect.ImmutableMap; /** * @author Oleksiy Yarmula @@ -64,20 +62,9 @@ public class SharedKeyLiteAuthentication implements HttpRequestFilter { @Override public HttpRequest filter(HttpRequest request) { - String toSign = createStringToSign(); String signatureMd5 = getMd5For(toSign); - - String query = request.getEndpoint().getQuery(); - Multimap decodedParams = Queries.parseQueryToMap(query); - - decodedParams.replaceValues("sig", ImmutableSet.of(signatureMd5)); - decodedParams.replaceValues("api_key", ImmutableSet.of(apiKey)); - - String updatedQuery = Queries.makeQueryLine(decodedParams, null); - String requestBasePart = request.getEndpoint().toASCIIString(); - String updatedEndpoint = requestBasePart.substring(0, requestBasePart.indexOf("?") + 1) + updatedQuery; - request = request.toBuilder().endpoint(updatedEndpoint).build(); + request = request.toBuilder().replaceQueryParams(ImmutableMap.of("sig", signatureMd5, "api_key" ,apiKey)).build(); utils.logRequest(signatureLog, request, "<<"); return request; } diff --git a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageAsyncApi.java b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageAsyncApi.java index 19b647516b..346e5e0ef2 100644 --- a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageAsyncApi.java +++ b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageAsyncApi.java @@ -40,7 +40,6 @@ import org.jclouds.rest.annotations.Endpoint; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; import com.google.common.base.Optional; import com.google.common.util.concurrent.ListenableFuture; @@ -59,7 +58,6 @@ import com.google.inject.Provides; * Storage API * @author Jeremy Daggett */ -@SkipEncoding('/') @RequestFilters(AuthenticateRequest.class) @Endpoint(Storage.class) public interface HPCloudObjectStorageAsyncApi extends CommonSwiftAsyncClient { diff --git a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/blobstore/functions/PublicUriForObjectInfo.java b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/blobstore/functions/PublicUriForObjectInfo.java index 903b281bff..c3cc225458 100644 --- a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/blobstore/functions/PublicUriForObjectInfo.java +++ b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/blobstore/functions/PublicUriForObjectInfo.java @@ -18,15 +18,13 @@ */ package org.jclouds.hpcloud.objectstorage.blobstore.functions; -import static com.google.common.base.Throwables.propagate; +import static org.jclouds.http.Uris.uriBuilder; import java.net.URI; import java.net.URISyntaxException; import javax.inject.Inject; -import javax.inject.Provider; import javax.inject.Singleton; -import javax.ws.rs.core.UriBuilder; import org.jclouds.openstack.swift.domain.ObjectInfo; @@ -40,12 +38,10 @@ import com.google.common.cache.LoadingCache; @Singleton public class PublicUriForObjectInfo implements Function { private final LoadingCache cdnContainer; - private final Provider uriBuilders; @Inject - public PublicUriForObjectInfo(LoadingCache cdnContainer, Provider uriBuilders) { + public PublicUriForObjectInfo(LoadingCache cdnContainer) { this.cdnContainer = cdnContainer; - this.uriBuilders = uriBuilders; } private static final URI NEGATIVE_ENTRY = URI.create("http://127.0.0.1"); @@ -61,8 +57,7 @@ public class PublicUriForObjectInfo implements Function { // The LoadingCache removes this value after its normal expiry. return null; } - return uriBuilders.get().uri(uri).path(from.getName()).replaceQuery("") - .build(); + return uriBuilder(uri).clearQuery().appendPath(from.getName()).build(); } catch (CacheLoader.InvalidCacheLoadException e) { // nulls not permitted from cache loader cdnContainer.put(from.getContainer(), NEGATIVE_ENTRY); @@ -73,4 +68,4 @@ public class PublicUriForObjectInfo implements Function { return null; } } -} \ No newline at end of file +} diff --git a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/extensions/CDNContainerAsyncApi.java b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/extensions/CDNContainerAsyncApi.java index 554c19dbc2..95fe5e9fc4 100644 --- a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/extensions/CDNContainerAsyncApi.java +++ b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/extensions/CDNContainerAsyncApi.java @@ -45,7 +45,6 @@ import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.functions.ReturnEmptyFluentIterableOnNotFoundOr404; import com.google.common.annotations.Beta; @@ -65,7 +64,6 @@ import com.google.common.util.concurrent.ListenableFuture; * Storage API * @author Jeremy Daggett */ -@SkipEncoding('/') @RequestFilters(AuthenticateRequest.class) @Endpoint(HPExtensionCDN.class) public interface CDNContainerAsyncApi { diff --git a/providers/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/RimuHostingAsyncClient.java b/providers/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/RimuHostingAsyncClient.java index 9cc4ed3068..38f0e1eeb0 100644 --- a/providers/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/RimuHostingAsyncClient.java +++ b/providers/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/RimuHostingAsyncClient.java @@ -33,7 +33,6 @@ import javax.ws.rs.core.MediaType; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.MapBinder; -import org.jclouds.rest.annotations.MatrixParams; import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; @@ -83,9 +82,8 @@ public interface RimuHostingAsyncClient { * @see RimuHostingClient#getServerList */ @GET - @Path("/orders") + @Path("/orders;include_inactive=N") @ResponseParser(ParseServersFromJsonResponse.class) - @MatrixParams(keys = "include_inactive", values = "N") @Consumes(MediaType.APPLICATION_JSON) @ExceptionParser(ParseRimuHostingException.class) ListenableFuture> getServerList(); @@ -94,8 +92,7 @@ public interface RimuHostingAsyncClient { * @see RimuHostingClient#getPricingPlanList */ @GET - @Path("/pricing-plans") - @MatrixParams(keys = "server-type", values = "VPS") + @Path("/pricing-plans;server-type=VPS") @Consumes(MediaType.APPLICATION_JSON) @ExceptionParser(ParseRimuHostingException.class) @ResponseParser(ParsePricingPlansFromJsonResponse.class) diff --git a/providers/slicehost/src/main/java/org/jclouds/slicehost/SlicehostAsyncClient.java b/providers/slicehost/src/main/java/org/jclouds/slicehost/SlicehostAsyncClient.java index a71ffdbfdc..99958a46bd 100644 --- a/providers/slicehost/src/main/java/org/jclouds/slicehost/SlicehostAsyncClient.java +++ b/providers/slicehost/src/main/java/org/jclouds/slicehost/SlicehostAsyncClient.java @@ -33,7 +33,6 @@ import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.MapBinder; import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.XMLResponseParser; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; @@ -66,7 +65,6 @@ import com.google.common.util.concurrent.ListenableFuture; * @see * @author Adrian Cole */ -@SkipEncoding( { '/', '=' }) @RequestFilters(SlicehostBasic.class) public interface SlicehostAsyncClient {