code cleanup: http request immutability (except payload), builders, test backfill

This commit is contained in:
Adrian Cole 2010-12-30 23:40:23 +01:00
parent a23c2dd815
commit 60b6b68556
865 changed files with 8904 additions and 5432 deletions

View File

@ -82,7 +82,6 @@ public interface AtmosStorageAsyncClient {
* @see AtmosStorageClient#listDirectories
*/
@GET
@Path("")
@ResponseParser(ParseDirectoryListFromContentAndHeaders.class)
@Consumes(MediaType.TEXT_XML)
ListenableFuture<BoundedSet<? extends DirectoryEntry>> listDirectories(ListOptions... options);

View File

@ -41,7 +41,7 @@ public class AtmosStorageResponseException extends HttpResponseException {
public AtmosStorageResponseException(HttpCommand command, HttpResponse response,
AtmosStorageError error) {
super(String.format("command %s failed with code %s, error: %s", command.getRequest()
super(String.format("command %s failed with code %s, error: %s", command.getCurrentRequest()
.getRequestLine(), response.getStatusCode(), error.toString()), command, response);
this.setError(error);
@ -49,7 +49,7 @@ public class AtmosStorageResponseException extends HttpResponseException {
public AtmosStorageResponseException(HttpCommand command, HttpResponse response,
AtmosStorageError error, Throwable cause) {
super(String.format("command %1$s failed with error: %2$s", command.getRequest()
super(String.format("command %1$s failed with error: %2$s", command.getCurrentRequest()
.getRequestLine(), error.toString()), command, response, cause);
this.setError(error);

View File

@ -20,28 +20,36 @@
package org.jclouds.atmosonline.saas.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.atmosonline.saas.domain.AtmosObject;
import org.jclouds.crypto.Crypto;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
/**
* @author Adrian Cole
*/
@Singleton
public class BindMetadataToHeaders implements Binder {
private final BindUserMetadataToHeaders metaBinder;
@Inject
protected BindMetadataToHeaders(BindUserMetadataToHeaders metaBinder, Crypto crypto) {
protected BindMetadataToHeaders(BindUserMetadataToHeaders metaBinder) {
this.metaBinder = metaBinder;
}
public void bindToRequest(HttpRequest request, Object payload) {
AtmosObject object = (AtmosObject) payload;
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
checkArgument(checkNotNull(input, "input") instanceof AtmosObject, "this binder is only valid for AtmosObject!");
checkNotNull(request, "request");
AtmosObject object = AtmosObject.class.cast(input);
checkNotNull(object.getPayload(), "object payload");
checkArgument(object.getPayload().getContentMetadata().getContentLength() != null,
"contentLength must be set, streaming not supported");
metaBinder.bindToRequest(request, object.getUserMetadata());
return metaBinder.bindToRequest(request, object.getUserMetadata());
}
}

View File

@ -19,36 +19,57 @@
package org.jclouds.atmosonline.saas.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import javax.inject.Singleton;
import org.jclouds.atmosonline.saas.domain.UserMetadata;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.utils.ModifyRequest;
import org.jclouds.rest.Binder;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.Multimaps;
/**
* @author Adrian Cole
*/
@Singleton
public class BindUserMetadataToHeaders implements Binder {
public class BindUserMetadataToHeaders implements Binder, Function<UserMetadata, Map<String, String>> {
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
checkArgument(checkNotNull(input, "input") instanceof UserMetadata,
"this binder is only valid for UserMetadatas!");
checkNotNull(request, "request");
public void bindToRequest(HttpRequest request, Object payload) {
UserMetadata md = (UserMetadata) checkNotNull(payload, "payload");
return ModifyRequest.putHeaders(request, Multimaps.forMap(apply(UserMetadata.class.cast(input))));
}
@Override
public Map<String, String> apply(UserMetadata md) {
Builder<String, String> headers = ImmutableMap.<String, String> builder();
if (md.getMetadata().size() > 0) {
String header = Joiner.on(',').withKeyValueSeparator("=").join(md.getMetadata());
request.getHeaders().put("x-emc-meta", header);
headers.put("x-emc-meta", header);
}
if (md.getListableMetadata().size() > 0) {
String header = Joiner.on(',').withKeyValueSeparator("=").join(md.getListableMetadata());
request.getHeaders().put("x-emc-listable-meta", header);
headers.put("x-emc-listable-meta", header);
}
if (md.getTags().size() > 0) {
String header = Joiner.on(',').join(md.getTags());
request.getHeaders().put("x-emc-tags", header);
headers.put("x-emc-tags", header);
}
if (md.getListableTags().size() > 0) {
String header = Joiner.on(',').join(md.getListableTags());
request.getHeaders().put("x-emc-listable-tags", header);
}
headers.put("x-emc-listable-tags", header);
}
return headers.build();
}
}

View File

@ -73,21 +73,22 @@ public class FindMD5InUserMetadata implements ContainsValueInListStrategy {
protected Long maxTime;
@Inject
private FindMD5InUserMetadata(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
ObjectMD5 objectMD5, ListBlobsInContainer getAllBlobMetadata, AtmosStorageAsyncClient client) {
FindMD5InUserMetadata(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor, ObjectMD5 objectMD5,
ListBlobsInContainer getAllBlobMetadata, AtmosStorageAsyncClient client) {
this.objectMD5 = objectMD5;
this.getAllBlobMetadata = getAllBlobMetadata;
this.client = client;
this.userExecutor = userExecutor;
}
@Override
public boolean execute(final String containerName, Object value, ListContainerOptions options) {
final byte[] toSearch = objectMD5.apply(value);
final BlockingQueue<Boolean> queue = new SynchronousQueue<Boolean>();
Map<String, Future<?>> responses = Maps.newHashMap();
for (BlobMetadata md : getAllBlobMetadata.execute(containerName, options)) {
final ListenableFuture<AtmosObject> future = Futures.makeListenable(client.headFile(containerName
+ "/" + md.getName()), userExecutor);
final ListenableFuture<AtmosObject> future = Futures.makeListenable(
client.headFile(containerName + "/" + md.getName()), userExecutor);
future.addListener(new Runnable() {
public void run() {
try {
@ -109,8 +110,8 @@ public class FindMD5InUserMetadata implements ContainsValueInListStrategy {
}, userExecutor);
responses.put(md.getName(), future);
}
Map<String, Exception> exceptions = awaitCompletion(responses, userExecutor, maxTime, logger, String.format(
"searching for md5 in container %s", containerName));
Map<String, Exception> exceptions = awaitCompletion(responses, userExecutor, maxTime, logger,
String.format("searching for md5 in container %s", containerName));
if (exceptions.size() > 0)
throw new BlobRuntimeException(String.format("searching for md5 in container %s: %s", containerName,
exceptions));

View File

@ -19,19 +19,12 @@
package org.jclouds.atmosonline.saas.config;
import javax.inject.Inject;
import javax.inject.Provider;
import org.jclouds.atmosonline.saas.domain.AtmosObject;
import org.jclouds.atmosonline.saas.domain.MutableContentMetadata;
import org.jclouds.atmosonline.saas.domain.SystemMetadata;
import org.jclouds.atmosonline.saas.domain.UserMetadata;
import org.jclouds.atmosonline.saas.domain.internal.AtmosObjectImpl;
import org.jclouds.blobstore.config.BlobStoreObjectModule;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Scopes;
/**
* Configures the domain object mappings needed for all Atmos implementations
@ -48,27 +41,6 @@ public class AtmosObjectModule extends AbstractModule {
protected void configure() {
// for converters
install(new BlobStoreObjectModule());
bind(AtmosObject.Factory.class).to(AtmosObjectFactory.class).in(Scopes.SINGLETON);
}
private static class AtmosObjectFactory implements AtmosObject.Factory {
@Inject
Provider<MutableContentMetadata> metadataProvider;
public AtmosObject create(MutableContentMetadata contentMetadata) {
return new AtmosObjectImpl(contentMetadata != null ? contentMetadata : metadataProvider
.get());
}
public AtmosObject create(SystemMetadata systemMetadata, UserMetadata userMetadata) {
return new AtmosObjectImpl(metadataProvider.get(), systemMetadata, userMetadata);
}
public AtmosObject create(MutableContentMetadata contentMetadata,
SystemMetadata systemMetadata, UserMetadata userMetadata) {
return new AtmosObjectImpl(contentMetadata, systemMetadata, userMetadata);
}
}
@Provides

View File

@ -21,21 +21,18 @@ package org.jclouds.atmosonline.saas.domain;
import javax.annotation.Nullable;
import org.jclouds.atmosonline.saas.domain.internal.AtmosObjectImpl.AtmosObjectFactory;
import org.jclouds.io.PayloadEnclosing;
import com.google.common.collect.Multimap;
import com.google.inject.ImplementedBy;
/**
* Amazon Atmos is designed to store objects. Objects are stored in buckets and consist of a
* {@link ObjectMetadataAtmosObject#getInput() value}, a {@link ObjectMetadata#getKey key},
* {@link ObjectMetadata#getUserMetadata() metadata}, and an access control policy.
*
* @author Adrian Cole
* @see <a
* href="http://docs.amazonwebservices.com/AmazonAtmos/2006-03-01/index.html?UsingObjects.html"
* />
*/
public interface AtmosObject extends PayloadEnclosing, Comparable<AtmosObject> {
@ImplementedBy(AtmosObjectFactory.class)
public interface Factory {
AtmosObject create(@Nullable MutableContentMetadata contentMetadata);

View File

@ -21,7 +21,9 @@ package org.jclouds.atmosonline.saas.domain;
import java.util.Set;
import org.jclouds.atmosonline.saas.domain.internal.BoundedHashSet;
import javax.annotation.Nullable;
import org.jclouds.atmosonline.saas.domain.internal.BoundedLinkedHashSet;
import com.google.inject.ImplementedBy;
@ -30,9 +32,10 @@ import com.google.inject.ImplementedBy;
* @author Adrian Cole
*
*/
@ImplementedBy(BoundedHashSet.class)
@ImplementedBy(BoundedLinkedHashSet.class)
public interface BoundedSet<T> extends Set<T> {
@Nullable
String getToken();
}

View File

@ -19,10 +19,10 @@
package org.jclouds.atmosonline.saas.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@ -33,10 +33,25 @@ import com.google.common.collect.Sets;
* @author Adrian Cole
*/
public class UserMetadata {
private final SortedMap<String, String> metadata = Maps.newTreeMap();
private final SortedMap<String, String> listableMetadata = Maps.newTreeMap();
private final SortedSet<String> tags = Sets.newTreeSet();
private final SortedSet<String> listableTags = Sets.newTreeSet();
private final Map<String, String> metadata;
private final Map<String, String> listableMetadata;
private final Set<String> tags;
private final Set<String> listableTags;
public UserMetadata(Map<String, String> metadata, Map<String, String> listableMetadata, Iterable<String> tags,
Iterable<String> listableTags) {
this.metadata = Maps.newLinkedHashMap(checkNotNull(metadata, "metadata"));
this.listableMetadata = Maps.newLinkedHashMap(checkNotNull(listableMetadata, "listableMetadata"));
this.tags = Sets.newLinkedHashSet(checkNotNull(tags, "tags"));
this.listableTags = Sets.newLinkedHashSet(checkNotNull(listableTags, "listableTags"));
}
public UserMetadata() {
this.metadata = Maps.newLinkedHashMap();
this.listableMetadata = Maps.newLinkedHashMap();
this.tags = Sets.newLinkedHashSet();
this.listableTags = Sets.newLinkedHashSet();
}
public Map<String, String> getMetadata() {
return metadata;
@ -54,4 +69,53 @@ public class UserMetadata {
return listableTags;
}
@Override
public String toString() {
return "[metadata=" + metadata + ", listableMetadata=" + listableMetadata + ", tags=" + tags + ", listableTags="
+ listableTags + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((listableMetadata == null) ? 0 : listableMetadata.hashCode());
result = prime * result + ((listableTags == null) ? 0 : listableTags.hashCode());
result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
result = prime * result + ((tags == null) ? 0 : tags.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
UserMetadata other = (UserMetadata) obj;
if (listableMetadata == null) {
if (other.listableMetadata != null)
return false;
} else if (!listableMetadata.equals(other.listableMetadata))
return false;
if (listableTags == null) {
if (other.listableTags != null)
return false;
} else if (!listableTags.equals(other.listableTags))
return false;
if (metadata == null) {
if (other.metadata != null)
return false;
} else if (!metadata.equals(other.metadata))
return false;
if (tags == null) {
if (other.tags != null)
return false;
} else if (!tags.equals(other.tags))
return false;
return true;
}
}

View File

@ -22,6 +22,8 @@ package org.jclouds.atmosonline.saas.domain.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.jclouds.atmosonline.saas.domain.AtmosObject;
import org.jclouds.atmosonline.saas.domain.MutableContentMetadata;
@ -39,6 +41,26 @@ import com.google.common.collect.Multimap;
* @author Adrian Cole
*/
public class AtmosObjectImpl extends PayloadEnclosingImpl implements AtmosObject, Comparable<AtmosObject> {
@Singleton
public static class AtmosObjectFactory implements AtmosObject.Factory {
@Inject
Provider<MutableContentMetadata> metadataProvider;
public AtmosObject create(MutableContentMetadata contentMetadata) {
return new AtmosObjectImpl(contentMetadata != null ? contentMetadata : metadataProvider.get());
}
public AtmosObject create(SystemMetadata systemMetadata, UserMetadata userMetadata) {
return new AtmosObjectImpl(metadataProvider.get(), systemMetadata, userMetadata);
}
public AtmosObject create(MutableContentMetadata contentMetadata, SystemMetadata systemMetadata,
UserMetadata userMetadata) {
return new AtmosObjectImpl(contentMetadata, systemMetadata, userMetadata);
}
}
private final UserMetadata userMetadata;
private final SystemMetadata systemMetadata;
@ -55,7 +77,6 @@ public class AtmosObjectImpl extends PayloadEnclosingImpl implements AtmosObject
public AtmosObjectImpl(MutableContentMetadata contentMetadata, SystemMetadata systemMetadata,
UserMetadata userMetadata) {
super();
this.contentMetadata = contentMetadata;
this.systemMetadata = systemMetadata;
this.userMetadata = userMetadata;
@ -145,6 +166,7 @@ public class AtmosObjectImpl extends PayloadEnclosingImpl implements AtmosObject
@Override
public void setPayload(Payload data) {
this.payload = data;
this.contentMetadata = new DelegatingMutableContentMetadata(contentMetadata.getName(), payload.getContentMetadata());
this.contentMetadata = new DelegatingMutableContentMetadata(contentMetadata.getName(),
payload.getContentMetadata());
}
}

View File

@ -0,0 +1,83 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.atmosonline.saas.domain.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.LinkedHashSet;
import javax.annotation.Nullable;
import org.jclouds.atmosonline.saas.domain.BoundedSet;
import com.google.common.collect.Iterables;
/**
*
* @author Adrian Cole
*
*/
public class BoundedLinkedHashSet<T> extends LinkedHashSet<T> implements BoundedSet<T> {
/** The serialVersionUID */
private static final long serialVersionUID = -7133632087734650835L;
protected final String token;
public BoundedLinkedHashSet(Iterable<T> contents, @Nullable String token) {
Iterables.addAll(this, checkNotNull(contents, "contents"));
this.token = token;
}
@Nullable
public String getToken() {
return token;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((token == null) ? 0 : token.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
BoundedLinkedHashSet<?> other = (BoundedLinkedHashSet<?>) obj;
if (token == null) {
if (other.token != null)
return false;
} else if (!token.equals(other.token))
return false;
return true;
}
@Override
public String toString() {
return "[token=" + token + ", contents=" + super.toString() + "]";
}
}

View File

@ -22,6 +22,8 @@ package org.jclouds.atmosonline.saas.domain.internal;
import org.jclouds.atmosonline.saas.domain.MutableContentMetadata;
import org.jclouds.io.payloads.BaseMutableContentMetadata;
import com.google.common.collect.Multimap;
/**
*
* @author Adrian Cole
@ -150,4 +152,9 @@ public class DelegatingMutableContentMetadata implements MutableContentMetadata
return delegate.getContentLanguage();
}
@Override
public void setPropertiesFromHttpHeaders(Multimap<String, String> headers) {
delegate.setPropertiesFromHttpHeaders(headers);
}
}

View File

@ -25,7 +25,6 @@ import static org.jclouds.Constants.PROPERTY_IDENTITY;
import static org.jclouds.util.Patterns.NEWLINE_PATTERN;
import static org.jclouds.util.Patterns.TWO_SPACE_PATTERN;
import java.util.Collections;
import java.util.Set;
import java.util.TreeSet;
@ -45,11 +44,15 @@ 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.ModifyRequest;
import org.jclouds.io.InputSuppliers;
import org.jclouds.logging.Logger;
import org.jclouds.util.Utils;
import org.jclouds.util.Strings2;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.Multimaps;
/**
* Signs the EMC Atmos Online Storage request.
@ -77,8 +80,8 @@ public class SignRequest implements HttpRequestFilter {
@Inject
public SignRequest(SignatureWire signatureWire, @Named(PROPERTY_IDENTITY) String uid,
@Named(PROPERTY_CREDENTIAL) String encodedKey, @TimeStamp Provider<String> timeStampProvider,
Crypto crypto, HttpUtils utils) {
@Named(PROPERTY_CREDENTIAL) String encodedKey, @TimeStamp Provider<String> timeStampProvider, Crypto crypto,
HttpUtils utils) {
this.signatureWire = signatureWire;
this.uid = uid;
this.key = CryptoStreams.base64(encodedKey);
@ -87,16 +90,19 @@ public class SignRequest implements HttpRequestFilter {
this.utils = utils;
}
public void filter(HttpRequest request) throws HttpException {
String toSign = replaceUIDHeader(request).removeOldSignature(request).replaceDateHeader(request)
.createStringToSign(request);
calculateAndReplaceAuthHeader(request, toSign);
@Override
public HttpRequest filter(HttpRequest request) throws HttpException {
Builder<String, String> builder = ImmutableMap.builder();
builder.put(AtmosStorageHeaders.UID, uid);
String date = timeStampProvider.get();
builder.put(HttpHeaders.DATE, date);
if (request.getHeaders().containsKey(AtmosStorageHeaders.DATE))
builder.put(AtmosStorageHeaders.DATE, date);
request = ModifyRequest.replaceHeaders(request, Multimaps.forMap(builder.build()));
String signature = calculateSignature(createStringToSign(request));
request = ModifyRequest.replaceHeader(request, AtmosStorageHeaders.SIGNATURE, signature);
utils.logRequest(signatureLog, request, "<<");
}
private SignRequest removeOldSignature(HttpRequest request) {
request.getHeaders().removeAll(AtmosStorageHeaders.SIGNATURE);
return this;
return request;
}
public String createStringToSign(HttpRequest request) {
@ -113,11 +119,11 @@ public class SignRequest implements HttpRequestFilter {
return buffer.toString();
}
private void calculateAndReplaceAuthHeader(HttpRequest request, String toSign) throws HttpException {
private String calculateSignature(String toSign) {
String signature = signString(toSign);
if (signatureWire.enabled())
signatureWire.input(Utils.toInputStream(signature));
request.getHeaders().replaceValues(AtmosStorageHeaders.SIGNATURE, Collections.singletonList(signature));
signatureWire.input(Strings2.toInputStream(signature));
return signature;
}
public String signString(String toSign) {
@ -134,16 +140,6 @@ public class SignRequest implements HttpRequestFilter {
toSign.append(request.getMethod()).append("\n");
}
SignRequest replaceUIDHeader(HttpRequest request) {
request.getHeaders().replaceValues(AtmosStorageHeaders.UID, Collections.singletonList(uid));
return this;
}
SignRequest replaceDateHeader(HttpRequest request) {
request.getHeaders().replaceValues(HttpHeaders.DATE, Collections.singletonList(timeStampProvider.get()));
return this;
}
private void appendCanonicalizedHeaders(HttpRequest request, StringBuilder toSign) {
// TreeSet == Sort the headers alphabetically.
Set<String> headers = new TreeSet<String>(request.getHeaders().keySet());
@ -155,8 +151,8 @@ public class SignRequest implements HttpRequestFilter {
// replacing any
// newline characters and extra embedded white spaces in the value.
for (String value : request.getHeaders().get(header)) {
value = Utils.replaceAll(value, TWO_SPACE_PATTERN, " ");
value = Utils.replaceAll(value, NEWLINE_PATTERN, "");
value = Strings2.replaceAll(value, TWO_SPACE_PATTERN, " ");
value = Strings2.replaceAll(value, NEWLINE_PATTERN, "");
toSign.append(value).append(' ');
}
toSign.deleteCharAt(toSign.lastIndexOf(" "));
@ -171,8 +167,9 @@ public class SignRequest implements HttpRequestFilter {
}
private void appendPayloadMetadata(HttpRequest request, StringBuilder buffer) {
buffer.append(utils.valueOrEmpty(request.getPayload() == null ? null : request.getPayload().getContentMetadata().getContentType()))
.append("\n");
buffer.append(
utils.valueOrEmpty(request.getPayload() == null ? null : request.getPayload().getContentMetadata()
.getContentType())).append("\n");
}
@VisibleForTesting

View File

@ -19,6 +19,9 @@
package org.jclouds.atmosonline.saas.functions;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Singleton;
import org.jclouds.atmosonline.saas.domain.AtmosObject;
@ -31,11 +34,14 @@ import com.google.common.base.Function;
*/
@Singleton
public class AtmosObjectName implements Function<Object, String> {
@Override
public String apply(Object input) {
checkArgument(checkNotNull(input, "input") instanceof AtmosObject,
"this function is only valid for AtmosObjects!");
AtmosObject object = AtmosObject.class.cast(input);
public String apply(Object in) {
AtmosObject from = (AtmosObject) in;
return from.getContentMetadata().getName() != null ? from.getContentMetadata().getName()
: from.getSystemMetadata().getObjectName();
return checkNotNull(object.getContentMetadata().getName() != null ? object.getContentMetadata().getName()
: object.getSystemMetadata().getObjectName(), "objectName");
}
}

View File

@ -19,13 +19,15 @@
package org.jclouds.atmosonline.saas.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.jclouds.atmosonline.saas.domain.BoundedSet;
import org.jclouds.atmosonline.saas.domain.DirectoryEntry;
import org.jclouds.atmosonline.saas.domain.internal.BoundedHashSet;
import org.jclouds.atmosonline.saas.domain.internal.BoundedLinkedHashSet;
import org.jclouds.atmosonline.saas.reference.AtmosStorageHeaders;
import org.jclouds.atmosonline.saas.xml.ListDirectoryResponseHandler;
import org.jclouds.http.HttpResponse;
@ -40,25 +42,24 @@ import com.google.common.base.Function;
* @author Adrian Cole
*/
@Singleton
public class ParseDirectoryListFromContentAndHeaders implements
Function<HttpResponse, BoundedSet<DirectoryEntry>> {
public class ParseDirectoryListFromContentAndHeaders implements Function<HttpResponse, BoundedSet<DirectoryEntry>> {
private final ParseSax.Factory factory;
private final Provider<ListDirectoryResponseHandler> listHandlerProvider;
@Inject
private ParseDirectoryListFromContentAndHeaders(Factory factory,
Provider<ListDirectoryResponseHandler> orgHandlerProvider) {
this.factory = factory;
this.listHandlerProvider = orgHandlerProvider;
ParseDirectoryListFromContentAndHeaders(Factory factory, Provider<ListDirectoryResponseHandler> listHandlerProvider) {
this.factory = checkNotNull(factory, "factory");
this.listHandlerProvider = checkNotNull(listHandlerProvider, "listHandlerProvider");
}
/**
* parses the http response headers to create a new {@link BoundedSet} object.
*/
public BoundedSet<DirectoryEntry> apply(HttpResponse from) {
checkNotNull(from, "http response");
String token = from.getFirstHeaderOrNull(AtmosStorageHeaders.TOKEN);
return new BoundedHashSet<DirectoryEntry>(factory.create(listHandlerProvider.get()).parse(
return new BoundedLinkedHashSet<DirectoryEntry>(factory.create(listHandlerProvider.get()).parse(
from.getPayload().getInput()), token);
}
}

View File

@ -19,6 +19,7 @@
package org.jclouds.atmosonline.saas.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.http.HttpUtils.attemptToParseSizeAndRangeFromHeaders;
import javax.inject.Inject;
@ -44,11 +45,11 @@ public class ParseObjectFromHeadersAndHttpContent implements Function<HttpRespon
private final AtmosObject.Factory objectProvider;
@Inject
public ParseObjectFromHeadersAndHttpContent(ParseSystemMetadataFromHeaders metadataParser,
public ParseObjectFromHeadersAndHttpContent(ParseSystemMetadataFromHeaders systemMetadataParser,
ParseUserMetadataFromHeaders userMetadataParser, AtmosObject.Factory objectProvider) {
this.systemMetadataParser = metadataParser;
this.userMetadataParser = userMetadataParser;
this.objectProvider = objectProvider;
this.systemMetadataParser = checkNotNull(systemMetadataParser, "systemMetadataParser");
this.userMetadataParser = checkNotNull(userMetadataParser, "userMetadataParser");
this.objectProvider = checkNotNull(objectProvider, "objectProvider");
}
/**
@ -60,8 +61,9 @@ public class ParseObjectFromHeadersAndHttpContent implements Function<HttpRespon
* @throws org.jclouds.http.HttpException
*/
public AtmosObject apply(HttpResponse from) {
AtmosObject object = objectProvider.create(systemMetadataParser.apply(from),
userMetadataParser.apply(from));
checkNotNull(from, "http response");
AtmosObject object = objectProvider.create(systemMetadataParser.apply(from), userMetadataParser.apply(from));
object.getContentMetadata().setName(object.getSystemMetadata().getObjectName());
object.getAllHeaders().putAll(from.getHeaders());
object.setPayload(from.getPayload());
object.getContentMetadata().setContentLength(attemptToParseSizeAndRangeFromHeaders(from));

View File

@ -45,10 +45,11 @@ public class ParseSystemMetadataFromHeaders implements Function<HttpResponse, Sy
@Inject
public ParseSystemMetadataFromHeaders(DateService dateService) {
this.dateService = dateService;
this.dateService = checkNotNull(dateService, "dateService");
}
public SystemMetadata apply(HttpResponse from) {
checkNotNull(from, "http response");
String meta = checkNotNull(from.getFirstHeaderOrNull(AtmosStorageHeaders.META), AtmosStorageHeaders.META);
Map<String, String> metaMap = Maps.newHashMap();
String[] metas = meta.split(", ");
@ -59,12 +60,12 @@ public class ParseSystemMetadataFromHeaders implements Function<HttpResponse, Sy
assert metaMap.size() >= 12 : String.format("Should be 12 entries in %s", metaMap);
byte[] md5 = metaMap.containsKey("content-md5") ? CryptoStreams.hex(metaMap.get("content-md5")) : null;
return new SystemMetadata(md5, dateService.iso8601SecondsDateParse(checkNotNull(metaMap.get("atime"), "atime")),
dateService.iso8601SecondsDateParse(checkNotNull(metaMap.get("ctime"), "ctime")), checkNotNull(metaMap
.get("gid"), "gid"), dateService.iso8601SecondsDateParse(checkNotNull(metaMap.get("itime"),
dateService.iso8601SecondsDateParse(checkNotNull(metaMap.get("ctime"), "ctime")), checkNotNull(
metaMap.get("gid"), "gid"), dateService.iso8601SecondsDateParse(checkNotNull(metaMap.get("itime"),
"itime")), dateService.iso8601SecondsDateParse(checkNotNull(metaMap.get("mtime"), "mtime")),
Integer.parseInt(checkNotNull(metaMap.get("nlink"), "nlink")), checkNotNull(metaMap.get("objectid"),
"objectid"), checkNotNull(metaMap.get("objname"), "objname"), checkNotNull(metaMap
.get("policyname"), "policyname"), Long.parseLong(checkNotNull(metaMap.get("size"), "size")),
"objectid"), checkNotNull(metaMap.get("objname"), "objname"), checkNotNull(metaMap.get("policyname"),
"policyname"), Long.parseLong(checkNotNull(metaMap.get("size"), "size")),
FileType.fromValue(checkNotNull(metaMap.get("type"), "type")), checkNotNull(metaMap.get("uid"), "uid"));
}
}

View File

@ -31,54 +31,55 @@ import org.jclouds.atmosonline.saas.reference.AtmosStorageHeaders;
import org.jclouds.http.HttpResponse;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/**
* @author Adrian Cole
*/
@Singleton
public class ParseUserMetadataFromHeaders implements Function<HttpResponse, UserMetadata> {
private final Set<String> sysKeys = ImmutableSet.of("atime", "ctime", "gid", "itime", "mtime",
"nlink", "policyname", "size", "uid");
private static final Set<String> sysKeys = ImmutableSet.of("atime", "ctime", "gid", "itime", "mtime", "nlink",
"policyname", "size", "uid", "content-md5", "objectid", "objname", "type");
private static final Predicate<String> filter = new Predicate<String>() {
@Override
public boolean apply(String arg0) {
return !sysKeys.contains(arg0);
}
};
public UserMetadata apply(HttpResponse from) {
UserMetadata md = new UserMetadata();
Map<String, String> metaMap = getMetaMap(checkNotNull(from
.getFirstHeaderOrNull(AtmosStorageHeaders.META), AtmosStorageHeaders.META));
checkNotNull(from, "http response");
Set<String> keys = Sets.difference(metaMap.keySet(), sysKeys);
for (String key : keys) {
md.getMetadata().put(key, metaMap.get(key));
}
if (from.getFirstHeaderOrNull(AtmosStorageHeaders.LISTABLE_META) != null)
md.getListableMetadata().putAll(
getMetaMap(from.getFirstHeaderOrNull(AtmosStorageHeaders.LISTABLE_META)));
Map<String, String> meta = Maps.filterKeys(
getMetaMap(checkNotNull(from.getFirstHeaderOrNull(AtmosStorageHeaders.META), AtmosStorageHeaders.META)),
filter);
if (from.getFirstHeaderOrNull(AtmosStorageHeaders.TAGS) != null)
md.getTags().addAll(getTags(from.getFirstHeaderOrNull(AtmosStorageHeaders.TAGS)));
if (from.getFirstHeaderOrNull(AtmosStorageHeaders.LISTABLE_TAGS) != null)
md.getTags().addAll(getTags(from.getFirstHeaderOrNull(AtmosStorageHeaders.LISTABLE_TAGS)));
return md;
}
private Set<String> getTags(String meta) {
Set<String> tags = Sets.newTreeSet();
String[] metas = meta.split(", ");
for (String entry : metas) {
tags.add(entry);
}
return tags;
Map<String, String> listableMeta = (from.getFirstHeaderOrNull(AtmosStorageHeaders.LISTABLE_META) != null) ? getMetaMap(from
.getFirstHeaderOrNull(AtmosStorageHeaders.LISTABLE_META)) : ImmutableMap.<String, String> of();
Iterable<String> tags = (from.getFirstHeaderOrNull(AtmosStorageHeaders.TAGS) != null) ? Splitter.on(", ").split(
from.getFirstHeaderOrNull(AtmosStorageHeaders.TAGS)) : ImmutableSet.<String> of();
Iterable<String> listableTags = (from.getFirstHeaderOrNull(AtmosStorageHeaders.LISTABLE_TAGS) != null) ? Splitter
.on(", ").split(from.getFirstHeaderOrNull(AtmosStorageHeaders.LISTABLE_TAGS)) : ImmutableSet.<String> of();
return new UserMetadata(meta, listableMeta, tags, listableTags);
}
// TODO: change to guava
private Map<String, String> getMetaMap(String meta) {
Map<String, String> metaMap = Maps.newHashMap();
String[] metas = meta.split(", ");
for (String entry : metas) {
Builder<String, String> metaMap = ImmutableMap.<String, String> builder();
for (String entry : Splitter.on(", ").split(meta)) {
String[] entrySplit = entry.split("=");
metaMap.put(entrySplit[0], entrySplit[1]);
}
return metaMap;
return metaMap.build();
}
}

View File

@ -19,26 +19,31 @@
package org.jclouds.atmosonline.saas.functions;
import static org.jclouds.util.Utils.propagateOrNull;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.util.Throwables2.propagateOrNull;
import java.net.URI;
import javax.annotation.Nullable;
import org.jclouds.blobstore.KeyAlreadyExistsException;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.InvocationContext;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
/**
*
* @author Adrian Cole
*/
public class ReturnEndpointIfAlreadyExists implements Function<Exception, URI>, InvocationContext {
public class ReturnEndpointIfAlreadyExists implements Function<Exception, URI>,
InvocationContext<ReturnEndpointIfAlreadyExists> {
private URI endpoint;
public URI apply(Exception from) {
if (from instanceof KeyAlreadyExistsException) {
if (checkNotNull(from, "exception") instanceof KeyAlreadyExistsException) {
return endpoint;
}
return URI.class.cast(propagateOrNull(from));
@ -46,7 +51,12 @@ public class ReturnEndpointIfAlreadyExists implements Function<Exception, URI>,
@Override
public ReturnEndpointIfAlreadyExists setContext(HttpRequest request) {
this.endpoint = request == null ? null : request.getEndpoint();
return setEndpoint(request == null ? null : request.getEndpoint());
}
@VisibleForTesting
ReturnEndpointIfAlreadyExists setEndpoint(@Nullable URI endpoint) {
this.endpoint = endpoint;
return this;
}

View File

@ -60,7 +60,7 @@ public class AtmosStorageClientErrorRetryHandler implements HttpRetryHandler {
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
if (command.getFailureCount() > retryCountLimit)
return false;
if (response.getStatusCode() == 404 && command.getRequest().getMethod().equals("DELETE")) {
if (response.getStatusCode() == 404 && command.getCurrentRequest().getMethod().equals("DELETE")) {
command.incrementFailureCount();
return true;
} else if (response.getStatusCode() == 409 || response.getStatusCode() == 400) {

View File

@ -42,7 +42,7 @@ import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.jclouds.logging.Logger;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.util.Utils;
import org.jclouds.util.Strings2;
/**
* This will parse and set an appropriate exception on the command object.
@ -72,9 +72,9 @@ public class ParseAtmosStorageErrorFromXmlContent implements HttpErrorHandler {
AtmosStorageError error = null;
if (response.getPayload() != null) {
try {
String content = Utils.toStringAndClose(response.getPayload().getInput());
String content = Strings2.toStringAndClose(response.getPayload().getInput());
if (content != null && content.indexOf('<') >= 0) {
error = utils.parseAtmosStorageErrorFromContent(command, response, Utils.toInputStream(content));
error = utils.parseAtmosStorageErrorFromContent(command, response, Strings2.toInputStream(content));
} else {
exception = content != null ? new HttpResponseException(command, response, content) : exception;
}
@ -83,7 +83,7 @@ public class ParseAtmosStorageErrorFromXmlContent implements HttpErrorHandler {
}
}
if (error != null && error.getCode() == 1016) {
File file = new File(command.getRequest().getEndpoint().getPath());
File file = new File(command.getCurrentRequest().getEndpoint().getPath());
exception = new KeyAlreadyExistsException(file.getParentFile().getAbsolutePath(), file.getName());
} else {
switch (response.getStatusCode()) {
@ -91,10 +91,10 @@ public class ParseAtmosStorageErrorFromXmlContent implements HttpErrorHandler {
exception = new AuthorizationException(exception.getMessage(), exception);
break;
case 404:
if (!command.getRequest().getMethod().equals("DELETE")) {
String message = error != null ? error.getMessage() : String.format("%s -> %s", command.getRequest()
if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
String message = error != null ? error.getMessage() : String.format("%s -> %s", command.getCurrentRequest()
.getRequestLine(), response.getStatusLine());
String path = command.getRequest().getEndpoint().getPath();
String path = command.getCurrentRequest().getEndpoint().getPath();
Matcher matcher = DIRECTORY_PATH.matcher(path);
if (matcher.find()) {
exception = new ContainerNotFoundException(matcher.group(1), message);

View File

@ -36,7 +36,7 @@ import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.util.Utils;
import org.jclouds.util.Assertions;
import com.google.common.base.Supplier;
@ -61,7 +61,7 @@ public class AtmosStorageUtils {
InputStream content) throws HttpException {
AtmosStorageError error = (AtmosStorageError) factory.create(errorHandlerProvider.get()).parse(content);
if (error.getCode() == 1032) {
error.setStringSigned(signer.createStringToSign(command.getRequest()));
error.setStringSigned(signer.createStringToSign(command.getCurrentRequest()));
}
return error;
@ -77,7 +77,7 @@ public class AtmosStorageUtils {
public static void deleteAndEnsureGone(final AtmosStorageClient sync, final String path) {
try {
if (!Utils.eventuallyTrue(new Supplier<Boolean>() {
if (!Assertions.eventuallyTrue(new Supplier<Boolean>() {
public Boolean get() {
sync.deletePath(path);
return !sync.pathExists(path);

View File

@ -19,7 +19,7 @@
package org.jclouds.atmosonline.saas.xml;
import java.util.SortedSet;
import java.util.Set;
import org.jclouds.atmosonline.saas.domain.DirectoryEntry;
import org.jclouds.atmosonline.saas.domain.FileType;
@ -34,17 +34,16 @@ import com.google.common.collect.Sets;
* @see <a href="https://community.emc.com/community/labs/atmos_online" />
* @author Adrian Cole
*/
public class ListDirectoryResponseHandler extends
ParseSax.HandlerWithResult<SortedSet<DirectoryEntry>> {
public class ListDirectoryResponseHandler extends ParseSax.HandlerWithResult<Set<DirectoryEntry>> {
private SortedSet<DirectoryEntry> entries = Sets.newTreeSet();
private Set<DirectoryEntry> entries = Sets.newLinkedHashSet();
private String currentObjectId;
private FileType currentType;
private String currentName;
private StringBuilder currentText = new StringBuilder();
public SortedSet<DirectoryEntry> getResult() {
public Set<DirectoryEntry> getResult() {
return entries;
}

View File

@ -61,11 +61,12 @@ import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of {@code AtmosStorageClient}
* Tests behavior of {@code AtmosStorageAsyncClient}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "emcsaas.AtmosStorageClientTest")
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "AtmosStorageAsyncClientTest")
public class AtmosStorageAsyncClientTest extends RestClientTest<AtmosStorageAsyncClient> {
private BlobToObject blobToObject;

View File

@ -40,7 +40,8 @@ import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
import org.jclouds.http.HttpResponseException;
import org.jclouds.io.Payloads;
import org.jclouds.io.payloads.InputStreamPayload;
import org.jclouds.util.Utils;
import org.jclouds.util.Assertions;
import org.jclouds.util.Strings2;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
@ -53,7 +54,7 @@ import com.google.common.collect.Sets;
*
* @author Adrian Cole
*/
@Test(groups = "live", sequential = true, testName = "emcsaas.AtmosStorageClientLiveTest")
@Test(groups = "live", sequential = true)
public class AtmosStorageClientLiveTest extends BaseBlobStoreIntegrationTest {
public AtmosStorageClient getApi() {
@ -187,7 +188,7 @@ public class AtmosStorageClientLiveTest extends BaseBlobStoreIntegrationTest {
}
Object makeData(String in, boolean stream) {
return stream ? Utils.toInputStream(in) : in;
return stream ? Strings2.toInputStream(in) : in;
}
private void createOrReplaceObject(String name, Object data, String metadataValue) throws Exception {
@ -239,14 +240,14 @@ public class AtmosStorageClientLiveTest extends BaseBlobStoreIntegrationTest {
private static void verifyHeadObject(AtmosStorageClient connection, String path, String metadataValue)
throws InterruptedException, ExecutionException, TimeoutException, IOException {
AtmosObject getBlob = connection.headFile(path);
assertEquals(Utils.toStringAndClose(getBlob.getPayload().getInput()), "");
assertEquals(Strings2.toStringAndClose(getBlob.getPayload().getInput()), "");
verifyMetadata(metadataValue, getBlob);
}
private static void verifyObject(AtmosStorageClient connection, String path, String compare, String metadataValue)
throws InterruptedException, ExecutionException, TimeoutException, IOException {
AtmosObject getBlob = connection.readFile(path);
assertEquals(Utils.toStringAndClose(getBlob.getPayload().getInput()), compare);
assertEquals(Strings2.toStringAndClose(getBlob.getPayload().getInput()), compare);
verifyMetadata(metadataValue, getBlob);
}
@ -269,7 +270,7 @@ public class AtmosStorageClientLiveTest extends BaseBlobStoreIntegrationTest {
assert md.getUserID() != null;
try {
Utils.toStringAndClose(URI.create(
Strings2.toStringAndClose(URI.create(
"http://accesspoint.emccis.com/rest/objects/" + getBlob.getSystemMetadata().getObjectID()).toURL()
.openStream());
assert false : "shouldn't have worked, since it is private";
@ -325,7 +326,7 @@ public class AtmosStorageClientLiveTest extends BaseBlobStoreIntegrationTest {
getApi().deletePath(path);
} catch (KeyNotFoundException ex) {
}
assert Utils.eventuallyTrue(new Supplier<Boolean>() {
assert Assertions.eventuallyTrue(new Supplier<Boolean>() {
public Boolean get() {
return !getApi().pathExists(path);
}

View File

@ -20,7 +20,7 @@
package org.jclouds.atmosonline.saas;
import org.jclouds.blobstore.util.BlobStoreUtils;
import org.jclouds.util.Utils;
import org.jclouds.rest.Providers;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
@ -35,7 +35,7 @@ public class ProvidersInPropertiesTest {
@Test
public void testSupportedProviders() {
Iterable<String> providers = Utils.getSupportedProviders();
Iterable<String> providers = Providers.getSupportedProviders();
assert Iterables.contains(providers, "atmosonline") : providers;
assert Iterables.contains(providers, "synaptic") : providers;
}

View File

@ -0,0 +1,89 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.atmosonline.saas.binders;
import static org.testng.Assert.assertEquals;
import java.io.File;
import java.net.URI;
import javax.ws.rs.HttpMethod;
import org.jclouds.atmosonline.saas.domain.AtmosObject;
import org.jclouds.http.HttpRequest;
import org.jclouds.io.Payload;
import org.jclouds.io.Payloads;
import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* Tests behavior of {@code BindMetadataToHeaders}
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class BindMetadataToHeadersTest {
Injector injector = Guice.createInjector();
BindMetadataToHeaders binder = injector.getInstance(BindMetadataToHeaders.class);
public void testGood() {
AtmosObject object = injector.getInstance(AtmosObject.Factory.class).create(null);
Payload payload = Payloads.newStringPayload("");
object.setPayload(payload);
object.getUserMetadata().getListableMetadata().put("apple", "bear");
object.getUserMetadata().getListableMetadata().put("sushi", "king");
HttpRequest request = new HttpRequest("GET", URI.create("http://localhost"));
request = binder.bindToRequest(request, object);
assertEquals(request.getFirstHeaderOrNull("x-emc-listable-meta"), "apple=bear,sushi=king");
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testMustBeAtmosObject() {
HttpRequest request = new HttpRequest(HttpMethod.POST, URI.create("http://localhost"));
binder.bindToRequest(request, new File("foo"));
}
@Test(expectedExceptions = NullPointerException.class)
public void testNullIsBad() {
HttpRequest request = HttpRequest.builder().method("GET").endpoint(URI.create("http://momma")).build();
binder.bindToRequest(request, null);
}
@Test(expectedExceptions = NullPointerException.class)
public void testNullPayloadIsBad() {
AtmosObject object = injector.getInstance(AtmosObject.Factory.class).create(null);
HttpRequest request = new HttpRequest("GET", URI.create("http://localhost"));
binder.bindToRequest(request, object);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullContentLengthIllegal() {
AtmosObject object = injector.getInstance(AtmosObject.Factory.class).create(null);
Payload payload = Payloads.newStringPayload("");
payload.getContentMetadata().setContentLength(null);
object.setPayload(payload);
HttpRequest request = new HttpRequest("GET", URI.create("http://localhost"));
binder.bindToRequest(request, object);
}
}

View File

@ -21,8 +21,11 @@ package org.jclouds.atmosonline.saas.binders;
import static org.testng.Assert.assertEquals;
import java.io.File;
import java.net.URI;
import javax.ws.rs.HttpMethod;
import org.jclouds.atmosonline.saas.domain.UserMetadata;
import org.jclouds.http.HttpRequest;
import org.testng.annotations.Test;
@ -35,59 +38,56 @@ import com.google.inject.Injector;
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "atmossaas.BindUserMetadataToHeadersTest")
@Test(groups = "unit")
public class BindUserMetadataToHeadersTest {
Injector injector = Guice.createInjector();
BindUserMetadataToHeaders binder = injector.getInstance(BindUserMetadataToHeaders.class);
public void testMeta() {
Injector injector = Guice.createInjector();
BindUserMetadataToHeaders binder = injector
.getInstance(BindUserMetadataToHeaders.class);
UserMetadata metadata = new UserMetadata();
metadata.getMetadata().put("apple", "bear");
metadata.getMetadata().put("sushi", "king");
HttpRequest request = new HttpRequest("GET", URI.create("http://localhost"));
binder.bindToRequest(request, metadata);
request = binder.bindToRequest(request, metadata);
assertEquals(request.getFirstHeaderOrNull("x-emc-meta"), "apple=bear,sushi=king");
}
public void testListableMeta() {
Injector injector = Guice.createInjector();
BindUserMetadataToHeaders binder = injector
.getInstance(BindUserMetadataToHeaders.class);
UserMetadata metadata = new UserMetadata();
metadata.getListableMetadata().put("apple", "bear");
metadata.getListableMetadata().put("sushi", "king");
HttpRequest request = new HttpRequest("GET", URI.create("http://localhost"));
binder.bindToRequest(request, metadata);
request = binder.bindToRequest(request, metadata);
assertEquals(request.getFirstHeaderOrNull("x-emc-listable-meta"), "apple=bear,sushi=king");
}
public void testTags() {
Injector injector = Guice.createInjector();
BindUserMetadataToHeaders binder = injector
.getInstance(BindUserMetadataToHeaders.class);
UserMetadata tagsdata = new UserMetadata();
tagsdata.getTags().add("apple");
tagsdata.getTags().add("sushi");
HttpRequest request = new HttpRequest("GET", URI.create("http://localhost"));
binder.bindToRequest(request, tagsdata);
request = binder.bindToRequest(request, tagsdata);
assertEquals(request.getFirstHeaderOrNull("x-emc-tags"), "apple,sushi");
}
public void testListableTags() {
Injector injector = Guice.createInjector();
BindUserMetadataToHeaders binder = injector
.getInstance(BindUserMetadataToHeaders.class);
UserMetadata tagsdata = new UserMetadata();
tagsdata.getListableTags().add("apple");
tagsdata.getListableTags().add("sushi");
HttpRequest request = new HttpRequest("GET", URI.create("http://localhost"));
binder.bindToRequest(request, tagsdata);
request = binder.bindToRequest(request, tagsdata);
assertEquals(request.getFirstHeaderOrNull("x-emc-listable-tags"), "apple,sushi");
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testMustBeUserMetadata() {
HttpRequest request = new HttpRequest(HttpMethod.POST, URI.create("http://localhost"));
binder.bindToRequest(request, new File("foo"));
}
@Test(expectedExceptions = { NullPointerException.class, IllegalStateException.class })
public void testNullIsBad() {
HttpRequest request = HttpRequest.builder().method("GET").endpoint(URI.create("http://momma")).build();
binder.bindToRequest(request, null);
}
}

View File

@ -45,7 +45,13 @@ import com.google.common.base.Supplier;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
@Test(groups = "unit", testName = "emcsaas.AtmosBlobRequestSignerTest")
/**
* Tests behavior of {@code AtmosBlobRequestSigner}
*
* @author Adrian Cole
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "AtmosBlobRequestSignerTest")
public class AtmosBlobRequestSignerTest extends RestClientTest<AtmosStorageAsyncClient> {
private BlobRequestSigner signer;

View File

@ -37,7 +37,7 @@ import com.google.inject.Module;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "emcsaas.AtmosBlobStoreModuleTest")
@Test(groups = "unit")
public class AtmosBlobStoreModuleTest {
Injector createInjector() {

View File

@ -31,7 +31,7 @@ import com.google.inject.Injector;
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "atmossaas.ObjectToBlobMetadataTest")
@Test(groups = "unit")
public class ObjectToBlobMetadataTest {
public void testFromWhenTypeIsDirectory() {

View File

@ -24,7 +24,7 @@ import javax.inject.Singleton;
import org.jclouds.atmosonline.saas.domain.BoundedSet;
import org.jclouds.atmosonline.saas.domain.DirectoryEntry;
import org.jclouds.atmosonline.saas.domain.FileType;
import org.jclouds.atmosonline.saas.domain.internal.BoundedHashSet;
import org.jclouds.atmosonline.saas.domain.internal.BoundedLinkedHashSet;
import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.domain.StorageType;
@ -42,7 +42,7 @@ public class ResourceMetadataListToDirectoryEntryList
public BoundedSet<DirectoryEntry> apply(
org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> from) {
return new BoundedHashSet<DirectoryEntry>(Iterables.transform(from,
return new BoundedLinkedHashSet<DirectoryEntry>(Iterables.transform(from,
new Function<StorageMetadata, DirectoryEntry>() {
public DirectoryEntry apply(StorageMetadata from) {
FileType type = (from.getType() == StorageType.FOLDER || from.getType() == StorageType.RELATIVE_PATH) ? FileType.DIRECTORY

View File

@ -26,7 +26,7 @@ import org.testng.annotations.Test;
*
* @author Adrian Cole
*/
@Test(groups = { "live" }, testName = "emcsaas.AtmosBlobSignerLiveTest")
@Test(groups = { "live" })
public class AtmosBlobSignerLiveTest extends BaseBlobSignerLiveTest {
}

View File

@ -31,7 +31,7 @@ import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "live", testName = "emcsaas.AtmosStorageContainerIntegrationTest")
@Test(groups = "live")
public class AtmosStorageContainerIntegrationLiveTest extends BaseContainerIntegrationTest {
@Override

View File

@ -25,7 +25,7 @@ import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = { "live" }, testName = "emcsaas.AtmosStorageContainerLiveTest")
@Test(groups = { "live" })
public class AtmosStorageContainerLiveTest extends BaseContainerLiveTest {
}

View File

@ -28,7 +28,7 @@ import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "live", testName = "emcsaas.AtmosStorageInputStreamMapIntegrationTest")
@Test(groups = "live")
public class AtmosStorageInputStreamMapIntegrationLiveTest extends BaseInputStreamMapIntegrationTest {
@Override

View File

@ -34,7 +34,7 @@ import org.testng.annotations.Test;
*
* @author Adrian Cole
*/
@Test(groups = { "integration", "live" }, testName = "emcsaas.AtmosStorageIntegrationTest")
@Test(groups = { "integration", "live" })
public class AtmosStorageIntegrationLiveTest extends BaseBlobIntegrationTest {
@DataProvider(name = "delete")

View File

@ -28,7 +28,7 @@ import org.testng.annotations.Test;
*
* @author Adrian Cole
*/
@Test(groups = { "live" }, testName = "emcsaas.AtmosStorageLiveTest")
@Test(groups = { "live" })
public class AtmosStorageLiveTest extends BaseBlobLiveTest {
protected void checkMD5(String container, String name, byte[] md5) {
// atmos does not support content-md5 yet

View File

@ -29,7 +29,7 @@ import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "live", testName = "emcsaas.AtmosStorageMapIntegrationTest")
@Test(groups = "live")
public class AtmosStorageMapIntegrationLiveTest extends BaseBlobMapIntegrationTest {
@Override

View File

@ -25,7 +25,7 @@ import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "live", testName = "emcsaas.AtmosStorageServiceIntegrationTest")
@Test(groups = "live")
public class AtmosStorageServiceIntegrationLiveTest extends BaseServiceIntegrationTest {
}

View File

@ -36,55 +36,73 @@ import org.jclouds.date.TimeStamp;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.RequiresHttp;
import org.jclouds.logging.config.NullLoggingModule;
import org.jclouds.rest.BaseRestClientTest.MockModule;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestContextFactory;
import org.jclouds.rest.BaseRestClientTest.MockModule;
import org.jclouds.util.Utils;
import org.jclouds.util.Strings2;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableMultimap.Builder;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.inject.Injector;
import com.google.inject.Module;
@Test(groups = "unit", testName = "emcsaas.SignRequestTest")
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class SignRequestTest {
private static final String EXPECTED_SIGNATURE = "WHJo1MFevMnK4jCthJ974L3YHoo=";
private static final String UID = "6039ac182f194e15b9261d73ce044939/user1";
private static final String DEFAULT_DATE = "Thu, 05 Jun 2008 16:38:19 GMT";
private static final String KEY = "LJLuryj6zs8ste6Y3jTGQp71xq0=";
private SignRequest filter;
@Test
void testCreateStringToSign() throws IOException {
String expects = Utils.toStringAndClose(getClass().getResourceAsStream("/hashstring.txt"));
HttpRequest request = newRequest();
String toSign = filter.replaceDateHeader(request).createStringToSign(request);
String expects = Strings2.toStringAndClose(getClass().getResourceAsStream("/hashstring.txt"));
HttpRequest request = newRequest(preconstructedHeaders().build());
String toSign = filter.createStringToSign(request);
assertEquals(toSign, expects);
}
@Test
void testUid() throws IOException, NoSuchAlgorithmException, InvalidKeyException {
HttpRequest request = newRequest();
filter.replaceUIDHeader(request);
assertEquals(request.getFirstHeaderOrNull(AtmosStorageHeaders.UID), "user");
void testSignString() throws IOException, NoSuchAlgorithmException, InvalidKeyException {
HttpRequest request = newRequest(preconstructedHeaders().build());
String toSign = filter.createStringToSign(request);
String signature = filter.signString(toSign);
assertEquals(signature, EXPECTED_SIGNATURE);
}
@Test
void testSignString() throws IOException, NoSuchAlgorithmException, InvalidKeyException {
String expects = "WHJo1MFevMnK4jCthJ974L3YHoo=";
void testFilter() throws IOException, NoSuchAlgorithmException, InvalidKeyException {
HttpRequest request = newRequest(inputHeaders().build());
request = filter.filter(request);
assertEquals(request.getFirstHeaderOrNull(AtmosStorageHeaders.SIGNATURE), EXPECTED_SIGNATURE);
}
HttpRequest request = newRequest();
String toSign = filter.replaceDateHeader(request).createStringToSign(request);
String signature = filter.signString(toSign);
assertEquals(signature, expects);
@Test
void testFilterReplacesOldValues() throws IOException, NoSuchAlgorithmException, InvalidKeyException {
HttpRequest request = newRequest(inputHeaders().put(AtmosStorageHeaders.SIGNATURE, "foo")
.put(HttpHeaders.DATE, "foo").put(AtmosStorageHeaders.DATE, "foo").put(AtmosStorageHeaders.UID, "foo")
.build());
request = filter.filter(request);
assertEquals(request.getFirstHeaderOrNull(AtmosStorageHeaders.SIGNATURE), EXPECTED_SIGNATURE);
}
@BeforeClass
protected void createFilter() {
Injector injector = new RestContextFactory().createContextBuilder(
Injector injector = new RestContextFactory()
.createContextBuilder(
"atmosonline",
"user",
UID,
KEY,
ImmutableSet.<Module> of(new MockModule(), new TestAtmosStorageRestClientModule(),
new NullLoggingModule()), new Properties()).buildInjector();
@ -96,6 +114,7 @@ public class SignRequestTest {
@RequiresHttp
@ConfiguresRestClient
private static final class TestAtmosStorageRestClientModule extends AtmosStorageRestClientModule {
@Override
protected void configure() {
super.configure();
@ -103,24 +122,34 @@ public class SignRequestTest {
@Override
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
return "Thu, 05 Jun 2008 16:38:19 GMT";
return DEFAULT_DATE;
}
}
public HttpRequest newRequest() {
HttpRequest request = new HttpRequest("POST", URI.create("http://localhost/rest/objects"));
public HttpRequest newRequest(Multimap<String, String> headers) {
HttpRequest request = new HttpRequest("POST", URI.create("http://localhost/rest/objects"), headers);
request.setPayload("");
request.getPayload().getContentMetadata().setContentLength(4286l);
request.getPayload().getContentMetadata().setContentType(MediaType.APPLICATION_OCTET_STREAM);
request.getHeaders().put(AtmosStorageHeaders.LISTABLE_META, "part4/part7/part8=quick");
request.getHeaders().put(AtmosStorageHeaders.META, "part1=buy");
request.getHeaders().put(HttpHeaders.ACCEPT, "*/*");
request.getHeaders().put(AtmosStorageHeaders.USER_ACL, "john=FULL_CONTROL,mary=WRITE");
request.getHeaders().put(AtmosStorageHeaders.DATE, "Thu, 05 Jun 2008 16:38:19 GMT");
request.getHeaders().put(AtmosStorageHeaders.GROUP_ACL, "other=NONE");
request.getHeaders().put(HttpHeaders.HOST, "10.5.115.118");
request.getHeaders().put(AtmosStorageHeaders.UID, "6039ac182f194e15b9261d73ce044939/user1");
return request;
}
protected Builder<String, String> preconstructedHeaders() {
Builder<String, String> builder = inputHeaders();
builder.put(HttpHeaders.DATE, DEFAULT_DATE);
builder.put(AtmosStorageHeaders.UID, UID);
return builder;
}
protected Builder<String, String> inputHeaders() {
Builder<String, String> builder = ImmutableMultimap.builder();
builder.put(AtmosStorageHeaders.LISTABLE_META, "part4/part7/part8=quick");
builder.put(AtmosStorageHeaders.META, "part1=buy");
builder.put(HttpHeaders.ACCEPT, "*/*");
builder.put(AtmosStorageHeaders.USER_ACL, "john=FULL_CONTROL,mary=WRITE");
builder.put(AtmosStorageHeaders.GROUP_ACL, "other=NONE");
builder.put(AtmosStorageHeaders.DATE, DEFAULT_DATE);
builder.put(HttpHeaders.HOST, "10.5.115.118");
return builder;
}
}

View File

@ -0,0 +1,69 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.atmosonline.saas.functions;
import static org.testng.Assert.assertEquals;
import java.io.File;
import org.jclouds.atmosonline.saas.domain.AtmosObject;
import org.jclouds.atmosonline.saas.domain.AtmosObject.Factory;
import org.jclouds.atmosonline.saas.domain.SystemMetadata;
import org.jclouds.atmosonline.saas.domain.UserMetadata;
import org.testng.annotations.Test;
import com.google.inject.Guice;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class AtmosObjectNameTest {
AtmosObjectName fn = new AtmosObjectName();
private static final Factory BLOB_FACTORY = Guice.createInjector().getInstance(AtmosObject.Factory.class);
@Test
public void testCorrectContentMetadataName() throws SecurityException, NoSuchMethodException {
AtmosObject blob = BLOB_FACTORY.create(null);
blob.getContentMetadata().setName("foo");
assertEquals(fn.apply(blob), "foo");
}
@Test
public void testCorrectSystemMetadataObjectName() throws SecurityException, NoSuchMethodException {
AtmosObject blob = BLOB_FACTORY.create(new SystemMetadata(null, null, null, null, null, null, 0, null, "foo",
null, 0, null, null), new UserMetadata());
assertEquals(fn.apply(blob), "foo");
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testMustBeAtmosObject() {
fn.apply(new File("foo"));
}
@Test(expectedExceptions = { NullPointerException.class, IllegalStateException.class })
public void testNullIsBad() {
fn.apply(null);
}
}

View File

@ -0,0 +1,79 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.atmosonline.saas.functions;
import static org.testng.Assert.assertEquals;
import java.util.Set;
import org.jclouds.atmosonline.saas.domain.BoundedSet;
import org.jclouds.atmosonline.saas.domain.DirectoryEntry;
import org.jclouds.atmosonline.saas.domain.FileType;
import org.jclouds.atmosonline.saas.domain.internal.BoundedLinkedHashSet;
import org.jclouds.atmosonline.saas.reference.AtmosStorageHeaders;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.io.Payloads;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Sets;
/**
* Tests behavior of {@code ParseDirectoryListFromContentAndHeaders}
*
* @author Adrian Cole
*/
//NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "ParseDirectoryListFromContentAndHeadersTest")
public class ParseDirectoryListFromContentAndHeadersTest extends BaseHandlerTest {
Function<HttpResponse, BoundedSet<DirectoryEntry>> createFn() {
return injector.getInstance(ParseDirectoryListFromContentAndHeaders.class);
}
public void testWithToken() {
HttpResponse response = new HttpResponse(200, "ok", Payloads.newPayload(getClass().getResourceAsStream(
"/list_basic.xml")), ImmutableMultimap.of(AtmosStorageHeaders.TOKEN, "token"));
BoundedSet<DirectoryEntry> result = createFn().apply(response);
assertEquals(result, new BoundedLinkedHashSet<DirectoryEntry>(values(), "token"));
assertEquals(result.getToken(), "token");
}
public void testWithoutToken() {
HttpResponse response = new HttpResponse(200, "ok", Payloads.newPayload(getClass().getResourceAsStream(
"/list_basic.xml")));
BoundedSet<DirectoryEntry> result = createFn().apply(response);
assertEquals(result, values());
assertEquals(result.getToken(), null);
}
protected Set<DirectoryEntry> values() {
Set<DirectoryEntry> expected = Sets.newLinkedHashSet();
expected.add(new DirectoryEntry("4980cdb2a411106a04a4538c92a1b204ad92077de6e3", FileType.DIRECTORY,
"adriancole-blobstore-2096685753"));
expected.add(new DirectoryEntry("4980cdb2a410105404980d99e53a0504ad93939e7dc3", FileType.DIRECTORY,
"adriancole-blobstore247496608"));
return expected;
}
}

View File

@ -0,0 +1,66 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.atmosonline.saas.functions;
import static org.testng.Assert.assertEquals;
import org.jclouds.atmosonline.saas.domain.AtmosObject;
import org.jclouds.atmosonline.saas.reference.AtmosStorageHeaders;
import org.jclouds.http.HttpResponse;
import org.jclouds.io.Payloads;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
import com.google.inject.Guice;
/**
* Tests behavior of {@code ParseObjectFromHeadersAndHttpContent}
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class ParseObjectFromHeadersAndHttpContentTest {
static final HttpResponse RESPONSE = new HttpResponse(200, "ok", Payloads.newStringPayload(""),
ImmutableMultimap.of(AtmosStorageHeaders.TAGS, "tag1, tag2", AtmosStorageHeaders.LISTABLE_TAGS,
"listabletag1, listabletag2", AtmosStorageHeaders.META,
"meta1=foo1, content-md5=1f3870be274f6c49b3e31a0c6728957f, atime=2009-10-12T16:09:42Z, mtime=2009-10-19T04:37:00Z,"
+ " ctime=2009-10-19T04:37:00Z, itime=2009-10-12T16:09:42Z, type=directory, uid=root, "
+ "gid=rootr, objectid=4980cdb2b010109b04a44f7bb83f5f04ad354c638ae5, "
+ "objname=e913e09366364e9ba384b8fead643d43, size=4096, nlink=1, policyname=default",
AtmosStorageHeaders.LISTABLE_META, "listablemeta1=listablefoo1, listablemeta2=listablefoo2"));
public static final AtmosObject EXPECTED;
static {
EXPECTED = Guice.createInjector().getInstance(AtmosObject.Factory.class)
.create(ParseSystemMetadataFromHeadersTest.EXPECTED, ParseUserMetadataFromHeadersTest.EXPECTED);
EXPECTED.getContentMetadata().setName("e913e09366364e9ba384b8fead643d43");
EXPECTED.setPayload(RESPONSE.getPayload());
}
public void test() {
ParseObjectFromHeadersAndHttpContent parser = Guice.createInjector().getInstance(
ParseObjectFromHeadersAndHttpContent.class);
AtmosObject data = parser.apply(RESPONSE);
assertEquals(data, EXPECTED);
}
}

View File

@ -25,44 +25,35 @@ import org.jclouds.atmosonline.saas.domain.FileType;
import org.jclouds.atmosonline.saas.domain.SystemMetadata;
import org.jclouds.crypto.CryptoStreams;
import org.jclouds.date.DateService;
import org.jclouds.http.HttpResponse;
import org.jclouds.io.Payloads;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* Tests behavior of {@code ParseSystemMetadataFromHeaders}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "atmossaas.ParseSystemMetadataFromHeadersTest")
@Test(groups = "unit")
public class ParseSystemMetadataFromHeadersTest {
static final DateService dateService = new SimpleDateFormatDateService();
static final SystemMetadata EXPECTED = new SystemMetadata(CryptoStreams.hex("1f3870be274f6c49b3e31a0c6728957f"),
public void test() {
Injector injector = Guice.createInjector();
ParseSystemMetadataFromHeaders parser = injector.getInstance(ParseSystemMetadataFromHeaders.class);
DateService dateService = injector.getInstance(DateService.class);
HttpResponse response = new HttpResponse(200, "ok", Payloads.newStringPayload(""));
response.getHeaders().put(
"x-emc-meta",
"content-md5=1f3870be274f6c49b3e31a0c6728957f, atime=2009-10-12T16:09:42Z, mtime=2009-10-19T04:37:00Z,"
+ " ctime=2009-10-19T04:37:00Z, itime=2009-10-12T16:09:42Z, type=directory, uid=root, "
+ "gid=rootr, objectid=4980cdb2b010109b04a44f7bb83f5f04ad354c638ae5, "
+ "objname=e913e09366364e9ba384b8fead643d43, size=4096, nlink=1, policyname=default");
SystemMetadata expected = new SystemMetadata(CryptoStreams.hex("1f3870be274f6c49b3e31a0c6728957f"),
dateService.iso8601SecondsDateParse("2009-10-12T16:09:42Z"), dateService
.iso8601SecondsDateParse("2009-10-19T04:37:00Z"), "rootr", dateService
.iso8601SecondsDateParse("2009-10-12T16:09:42Z"), dateService
.iso8601SecondsDateParse("2009-10-19T04:37:00Z"), 1, "4980cdb2b010109b04a44f7bb83f5f04ad354c638ae5",
"e913e09366364e9ba384b8fead643d43", "default", 4096l, FileType.DIRECTORY, "root"
dateService.iso8601SecondsDateParse("2009-10-12T16:09:42Z"),
dateService.iso8601SecondsDateParse("2009-10-19T04:37:00Z"), "rootr",
dateService.iso8601SecondsDateParse("2009-10-12T16:09:42Z"),
dateService.iso8601SecondsDateParse("2009-10-19T04:37:00Z"), 1,
"4980cdb2b010109b04a44f7bb83f5f04ad354c638ae5", "e913e09366364e9ba384b8fead643d43", "default", 4096l,
FileType.DIRECTORY, "root"
);
SystemMetadata data = parser.apply(response);
assertEquals(data, expected);
public void test() {
ParseSystemMetadataFromHeaders parser = Guice.createInjector().getInstance(ParseSystemMetadataFromHeaders.class);
SystemMetadata data = parser.apply(ParseObjectFromHeadersAndHttpContentTest.RESPONSE);
assertEquals(data, EXPECTED);
}
}

View File

@ -0,0 +1,48 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.atmosonline.saas.functions;
import static org.testng.Assert.assertEquals;
import org.jclouds.atmosonline.saas.domain.UserMetadata;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
/**
* Tests behavior of {@code ParseUserMetadataFromHeaders}
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class ParseUserMetadataFromHeadersTest {
static final UserMetadata EXPECTED = new UserMetadata(ImmutableMap.<String, String> of("meta1", "foo1"),
ImmutableMap.of("listablemeta1", "listablefoo1", "listablemeta2", "listablefoo2"), ImmutableSet.of("tag1",
"tag2"), ImmutableSet.of("listabletag1", "listabletag2"));
public void test() {
ParseUserMetadataFromHeaders parser = Guice.createInjector().getInstance(ParseUserMetadataFromHeaders.class);
UserMetadata data = parser.apply(ParseObjectFromHeadersAndHttpContentTest.RESPONSE);
assertEquals(data, EXPECTED);
}
}

View File

@ -0,0 +1,38 @@
package org.jclouds.atmosonline.saas.functions;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import org.jclouds.blobstore.KeyAlreadyExistsException;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class ReturnEndpointIfAlreadyExistsTest {
@Test
public void testFoundIsNullWhenEndpointNotSet() {
assertEquals(new ReturnEndpointIfAlreadyExists().apply(new KeyAlreadyExistsException()), null);
}
@Test
public void testFoundIsEndpointWhenSet() {
assertEquals(
new ReturnEndpointIfAlreadyExists().setEndpoint(URI.create("foo")).apply(new KeyAlreadyExistsException()),
URI.create("foo"));
}
@Test(expectedExceptions = RuntimeException.class)
public void testNotFoundPropagates() {
new ReturnEndpointIfAlreadyExists().apply(new RuntimeException());
}
@Test(expectedExceptions = NullPointerException.class)
public void testNullIsBad() {
new ReturnEndpointIfAlreadyExists().apply(null);
}
}

View File

@ -30,7 +30,7 @@ import com.google.common.collect.ImmutableList;
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "emcsaas.ListOptionsTest")
@Test(groups = "unit")
public class ListOptionsTest {
public void testToken() {

View File

@ -33,7 +33,8 @@ import org.testng.annotations.Test;
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "atmossaas.ErrorHandlerTest")
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "ErrorHandlerTest")
public class ErrorHandlerTest extends BaseHandlerTest {
ParseSax<AtmosStorageError> createParser() {

View File

@ -22,7 +22,7 @@ package org.jclouds.atmosonline.saas.xml;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import java.util.SortedSet;
import java.util.Set;
import org.jclouds.atmosonline.saas.domain.DirectoryEntry;
import org.jclouds.atmosonline.saas.domain.FileType;
@ -37,24 +37,25 @@ import com.google.common.collect.Sets;
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "atmossaas.ListDirectoryResponseHandlerTest")
//NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "ListDirectoryResponseHandlerTest")
public class ListDirectoryResponseHandlerTest extends BaseHandlerTest {
ParseSax<SortedSet<DirectoryEntry>> createParser() {
ParseSax<SortedSet<DirectoryEntry>> parser = (ParseSax<SortedSet<DirectoryEntry>>) factory
ParseSax<Set<DirectoryEntry>> createParser() {
ParseSax<Set<DirectoryEntry>> parser = (ParseSax<Set<DirectoryEntry>>) factory
.create(injector.getInstance(ListDirectoryResponseHandler.class));
return parser;
}
public void testApplyInputStreamBase() {
InputStream is = getClass().getResourceAsStream("/list_basic.xml");
ParseSax<SortedSet<DirectoryEntry>> parser = createParser();
SortedSet<DirectoryEntry> expected = Sets.newTreeSet();
ParseSax<Set<DirectoryEntry>> parser = createParser();
Set<DirectoryEntry> expected = Sets.newTreeSet();
expected.add(new DirectoryEntry("4980cdb2a411106a04a4538c92a1b204ad92077de6e3",
FileType.DIRECTORY, "adriancole-blobstore-2096685753"));
expected.add(new DirectoryEntry("4980cdb2a410105404980d99e53a0504ad93939e7dc3",
FileType.DIRECTORY, "adriancole-blobstore247496608"));
SortedSet<DirectoryEntry> result = parser.parse(is);
Set<DirectoryEntry> result = parser.parse(is);
assertEquals(result, expected);
}
}

View File

@ -40,7 +40,7 @@ public class AWSResponseException extends HttpResponseException {
private AWSError error = new AWSError();
public AWSResponseException(HttpCommand command, HttpResponse response, AWSError error) {
super(String.format("request %s failed with code %s, error: %s", command.getRequest().getRequestLine(), response
super(String.format("request %s failed with code %s, error: %s", command.getCurrentRequest().getRequestLine(), response
.getStatusCode(), error.toString()), command, response);
this.setError(error);
@ -48,7 +48,7 @@ public class AWSResponseException extends HttpResponseException {
public AWSResponseException(HttpCommand command, HttpResponse response, AWSError error,
Throwable cause) {
super(String.format("request %1$s failed with error: %2$s", command.getRequest().getRequestLine(), error
super(String.format("request %1$s failed with error: %2$s", command.getCurrentRequest().getRequestLine(), error
.toString()), command, response, cause);
this.setError(error);

View File

@ -22,47 +22,52 @@ package org.jclouds.aws.ec2.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.lang.String.format;
import static org.jclouds.http.HttpUtils.addFormParamTo;
import org.jclouds.aws.ec2.domain.BlockDeviceMapping;
import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.utils.ModifyRequest;
import org.jclouds.rest.Binder;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableMultimap.Builder;
/**
* @author Oleksiy Yarmula
* @author Adrian Cole
*/
public class BindBlockDeviceMappingToIndexedFormParams implements Binder {
private final String deviceNamePattern = "BlockDeviceMapping.%d.DeviceName";
private final String volumeIdPattern = "BlockDeviceMapping.%d.Ebs.VolumeId";
private final String deleteOnTerminationPattern = "BlockDeviceMapping.%d.Ebs.DeleteOnTermination";
private static final String deviceNamePattern = "BlockDeviceMapping.%d.DeviceName";
private static final String volumeIdPattern = "BlockDeviceMapping.%d.Ebs.VolumeId";
private static final String deleteOnTerminationPattern = "BlockDeviceMapping.%d.Ebs.DeleteOnTermination";
public void bindToRequest(HttpRequest request, Object input) {
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
checkArgument(checkNotNull(input, "input") instanceof BlockDeviceMapping,
"this binder is only valid for BlockDeviceMapping");
BlockDeviceMapping blockDeviceMapping = (BlockDeviceMapping) input;
Builder<String, String> builder = ImmutableMultimap.<String, String> builder();
int amazonOneBasedIndex = 1; // according to docs, counters must start with 1
for (String ebsBlockDeviceName : blockDeviceMapping.getEbsBlockDevices().keySet()) {
for (RunningInstance.EbsBlockDevice ebsBlockDevice : blockDeviceMapping
.getEbsBlockDevices().get(ebsBlockDeviceName)) {
for (RunningInstance.EbsBlockDevice ebsBlockDevice : blockDeviceMapping.getEbsBlockDevices().get(
ebsBlockDeviceName)) {
// not null by contract
addFormParamTo(request, format(volumeIdPattern, amazonOneBasedIndex), ebsBlockDevice
.getVolumeId());
builder.put(format(volumeIdPattern, amazonOneBasedIndex), ebsBlockDevice.getVolumeId());
if (ebsBlockDeviceName != null) {
addFormParamTo(request, format(deviceNamePattern, amazonOneBasedIndex),
ebsBlockDeviceName);
builder.put(format(deviceNamePattern, amazonOneBasedIndex), ebsBlockDeviceName);
}
addFormParamTo(request, format(deleteOnTerminationPattern, amazonOneBasedIndex), String
.valueOf(ebsBlockDevice.isDeleteOnTermination()));
builder.put(format(deleteOnTerminationPattern, amazonOneBasedIndex),
String.valueOf(ebsBlockDevice.isDeleteOnTermination()));
amazonOneBasedIndex++;
}
}
ImmutableMultimap<String, String> forms = builder.build();
return forms.size() == 0 ? request : ModifyRequest.putFormParams(request, forms);
}
}

View File

@ -33,9 +33,9 @@ import org.jclouds.rest.Binder;
*/
@Singleton
public class BindBundleIdsToIndexedFormParams implements Binder {
public void bindToRequest(HttpRequest request, Object input) {
indexStringArrayToFormValuesWithPrefix(request, "BundleId", input);
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
return indexStringArrayToFormValuesWithPrefix(request, "BundleId", input);
}
}

View File

@ -32,10 +32,10 @@ import org.jclouds.rest.Binder;
* @author Adrian Cole
*/
@Singleton
public class BindGroupNameToIndexedFormParams implements Binder {
public void bindToRequest(HttpRequest request, Object input) {
indexStringArrayToFormValuesWithPrefix(request, "GroupName", input);
public class BindGroupNamesToIndexedFormParams implements Binder {
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
return indexStringArrayToFormValuesWithPrefix(request, "GroupName", input);
}
}

View File

@ -33,9 +33,9 @@ import org.jclouds.rest.Binder;
*/
@Singleton
public class BindInstanceIdsToIndexedFormParams implements Binder {
public void bindToRequest(HttpRequest request, Object input) {
indexStringArrayToFormValuesWithPrefix(request, "InstanceId", input);
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
return indexStringArrayToFormValuesWithPrefix(request, "InstanceId", input);
}
}

View File

@ -32,10 +32,10 @@ import org.jclouds.rest.Binder;
* @author Adrian Cole
*/
@Singleton
public class BindKeyNameToIndexedFormParams implements Binder {
public void bindToRequest(HttpRequest request, Object input) {
indexStringArrayToFormValuesWithPrefix(request, "KeyName", input);
public class BindKeyNamesToIndexedFormParams implements Binder {
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
return indexStringArrayToFormValuesWithPrefix(request, "KeyName", input);
}
}

View File

@ -27,15 +27,15 @@ import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
/**
* Binds the String [] to form parameters named with ProductCode.index
* Binds the Iterable to form parameters named with ProductCode.index
*
* @author Adrian Cole
*/
@Singleton
public class BindProductCodesToIndexedFormParams implements Binder {
public void bindToRequest(HttpRequest request, Object input) {
indexIterableToFormValuesWithPrefix(request, "ProductCode", input);
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
return indexIterableToFormValuesWithPrefix(request, "ProductCode", input);
}
}

View File

@ -35,11 +35,11 @@ import org.jclouds.rest.Binder;
*/
@Singleton
public class BindPublicIpsToIndexedFormParams implements Binder {
public void bindToRequest(HttpRequest request, Object input) {
checkArgument(checkNotNull(input, "input") instanceof String[],
"this binder is only valid for String[] : " + input.getClass());
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
checkArgument(checkNotNull(input, "input") instanceof String[], "this binder is only valid for String[] : "
+ input.getClass());
String[] addressStrings = (String[]) input;
indexStringArrayToFormValuesWithPrefix(request, "PublicIp", addressStrings);
return indexStringArrayToFormValuesWithPrefix(request, "PublicIp", addressStrings);
}
}

View File

@ -20,18 +20,19 @@
package org.jclouds.aws.ec2.binders;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.http.HttpUtils.addFormParamTo;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.crypto.Crypto;
import org.jclouds.crypto.CryptoStreams;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.utils.ModifyRequest;
import org.jclouds.rest.Binder;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableMultimap.Builder;
/**
*
@ -42,15 +43,18 @@ public class BindS3UploadPolicyAndSignature implements Binder {
private final FormSigner signer;
@Inject
BindS3UploadPolicyAndSignature(FormSigner signer, Crypto crypto) {
BindS3UploadPolicyAndSignature(FormSigner signer) {
this.signer = signer;
}
public void bindToRequest(HttpRequest request, Object input) {
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
String encodedJson = CryptoStreams.base64(checkNotNull(input, "json").toString().getBytes(Charsets.UTF_8));
addFormParamTo(request, "Storage.S3.UploadPolicy", encodedJson);
Builder<String, String> builder = ImmutableMultimap.<String, String> builder();
builder.put("Storage.S3.UploadPolicy", encodedJson);
String signature = signer.sign(encodedJson);
addFormParamTo(request, "Storage.S3.UploadPolicySignature", signature);
builder.put("Storage.S3.UploadPolicySignature", signature);
return ModifyRequest.putFormParams(request, builder.build());
}
}

View File

@ -37,12 +37,12 @@ import com.google.common.collect.Iterables;
*/
@Singleton
public class BindUserGroupsToIndexedFormParams implements Binder {
public void bindToRequest(HttpRequest request, Object input) {
checkArgument(checkNotNull(input, "input") instanceof Iterable<?>,
"this binder is only valid for Iterable<?>: " + input.getClass());
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
checkArgument(checkNotNull(input, "input") instanceof Iterable<?>, "this binder is only valid for Iterable<?>: "
+ input.getClass());
checkValidUserGroup(input);
indexIterableToFormValuesWithPrefix(request, "UserGroup", input);
return indexIterableToFormValuesWithPrefix(request, "UserGroup", input);
}
private void checkValidUserGroup(Object input) {

View File

@ -21,14 +21,17 @@ package org.jclouds.aws.ec2.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.http.HttpUtils.addFormParamTo;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.domain.UserIdGroupPair;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.utils.ModifyRequest;
import org.jclouds.rest.Binder;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableMultimap.Builder;
/**
* Binds the String [] to query parameters named with GroupName.index
*
@ -36,12 +39,15 @@ import org.jclouds.rest.Binder;
*/
@Singleton
public class BindUserIdGroupPairToSourceSecurityGroupFormParams implements Binder {
public void bindToRequest(HttpRequest request, Object input) {
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
checkArgument(checkNotNull(input, "input") instanceof UserIdGroupPair,
"this binder is only valid for UserIdGroupPair!");
UserIdGroupPair pair = (UserIdGroupPair) input;
addFormParamTo(request, "SourceSecurityGroupOwnerId", pair.getUserId());
addFormParamTo(request, "SourceSecurityGroupName", pair.getGroupName());
Builder<String, String> builder = ImmutableMultimap.<String, String> builder();
builder.put("SourceSecurityGroupOwnerId", pair.getUserId());
builder.put("SourceSecurityGroupName", pair.getGroupName());
return ModifyRequest.putFormParams(request, builder.build());
}
}

View File

@ -27,14 +27,15 @@ import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
/**
* Binds the String [] to form parameters named with UserId.index
* Binds the Iterable to form parameters named with UserId.index
*
* @author Adrian Cole
*/
@Singleton
public class BindUserIdsToIndexedFormParams implements Binder {
public void bindToRequest(HttpRequest request, Object input) {
indexIterableToFormValuesWithPrefix(request, "UserId", input);
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
return indexIterableToFormValuesWithPrefix(request, "UserId", input);
}
}

View File

@ -33,9 +33,9 @@ import org.jclouds.rest.Binder;
*/
@Singleton
public class BindVolumeIdsToIndexedFormParams implements Binder {
public void bindToRequest(HttpRequest request, Object input) {
indexStringArrayToFormValuesWithPrefix(request, "VolumeId", input);
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
return indexStringArrayToFormValuesWithPrefix(request, "VolumeId", input);
}
}

View File

@ -20,11 +20,11 @@
package org.jclouds.aws.ec2.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static org.jclouds.http.HttpUtils.addFormParamTo;
import javax.inject.Singleton;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.utils.ModifyRequest;
import org.jclouds.rest.Binder;
/**
@ -34,11 +34,13 @@ import org.jclouds.rest.Binder;
*/
@Singleton
public class IfNotNullBindAvailabilityZoneToFormParam implements Binder {
public void bindToRequest(HttpRequest request, Object input) {
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
if (input != null) {
checkArgument(input instanceof String, "this binder is only valid for AvailabilityZone!");
addFormParamTo(request, "Placement.AvailabilityZone", (String) input);
return ModifyRequest.addFormParam(request, "Placement.AvailabilityZone", (String) input);
}
return request;
}
}

View File

@ -21,7 +21,6 @@ package org.jclouds.aws.ec2.compute;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.aws.ec2.util.EC2Utils.parseHandle;
import static org.jclouds.util.Utils.checkNotEmpty;
import java.util.Map;
import java.util.Map.Entry;
@ -62,6 +61,7 @@ import org.jclouds.compute.util.ComputeUtils;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.http.HttpResponseException;
import org.jclouds.util.Preconditions2;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
@ -107,7 +107,7 @@ public class EC2ComputeService extends BaseComputeService {
@VisibleForTesting
void deletePlacementGroup(String region, String tag) {
checkNotEmpty(tag, "tag");
Preconditions2.checkNotEmpty(tag, "tag");
String group = String.format("jclouds#%s#%s", tag, region);
try {
if (ec2Client.getPlacementGroupServices().describePlacementGroupsInRegion(region, group).size() > 0) {
@ -137,7 +137,7 @@ public class EC2ComputeService extends BaseComputeService {
@VisibleForTesting
void deleteSecurityGroup(String region, String tag) {
checkNotEmpty(tag, "tag");
Preconditions2.checkNotEmpty(tag, "tag");
String group = String.format("jclouds#%s#%s", tag, region);
if (ec2Client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, group).size() > 0) {
logger.debug(">> deleting securityGroup(%s)", group);

View File

@ -20,13 +20,12 @@
package org.jclouds.aws.ec2.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.util.Utils.nullSafeSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.Map.Entry;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -49,6 +48,7 @@ import org.jclouds.compute.domain.internal.VolumeImpl;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import org.jclouds.util.NullSafeCollections;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
@ -93,8 +93,8 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
builder.tag(tag);
builder.credentials(credentialStore.get("node#" + instance.getRegion() + "/" + providerId));
builder.state(instanceToNodeState.get(instance.getInstanceState()));
builder.publicAddresses(nullSafeSet(instance.getIpAddress()));
builder.privateAddresses(nullSafeSet(instance.getPrivateIpAddress()));
builder.publicAddresses(NullSafeCollections.nullSafeSet(instance.getIpAddress()));
builder.privateAddresses(NullSafeCollections.nullSafeSet(instance.getPrivateIpAddress()));
builder.hardware(parseHardware(instance));
Location location = getLocationForAvailabilityZoneOrRegion(instance);
builder.location(location);

View File

@ -31,7 +31,7 @@ import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Credentials;
import org.jclouds.io.Payload;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.util.Utils;
import org.jclouds.util.Preconditions2;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
@ -80,7 +80,7 @@ public class EC2TemplateOptions extends TemplateOptions {
public EC2TemplateOptions securityGroups(Iterable<String> groupIds) {
checkArgument(Iterables.size(groupIds) > 0, "you must specify at least one security group");
for (String groupId : groupIds)
Utils.checkNotEmpty(groupId, "all security groups must be non-empty");
Preconditions2.checkNotEmpty(groupId, "all security groups must be non-empty");
this.groupIds = ImmutableSet.copyOf(groupIds);
return this;
}
@ -112,7 +112,7 @@ public class EC2TemplateOptions extends TemplateOptions {
public EC2TemplateOptions keyPair(String keyPair) {
checkNotNull(keyPair, "use noKeyPair option to request boot without a keypair");
checkState(!noKeyPair, "you cannot specify both options keyPair and noKeyPair");
Utils.checkNotEmpty(keyPair, "keypair must be non-empty");
Preconditions2.checkNotEmpty(keyPair, "keypair must be non-empty");
this.keyPair = keyPair;
return this;
}
@ -132,7 +132,7 @@ public class EC2TemplateOptions extends TemplateOptions {
public EC2TemplateOptions placementGroup(String placementGroup) {
checkNotNull(placementGroup, "use noPlacementGroup option to request boot without a keypair");
checkState(!noPlacementGroup, "you cannot specify both options placementGroup and noPlacementGroup");
Utils.checkNotEmpty(placementGroup, "placementGroup must be non-empty");
Preconditions2.checkNotEmpty(placementGroup, "placementGroup must be non-empty");
this.placementGroup = placementGroup;
return this;
}
@ -151,7 +151,7 @@ public class EC2TemplateOptions extends TemplateOptions {
*/
public EC2TemplateOptions subnetId(String subnetId) {
checkNotNull(subnetId, "subnetId cannot be null");
Utils.checkNotEmpty(subnetId, "subnetId must be non-empty");
Preconditions2.checkNotEmpty(subnetId, "subnetId must be non-empty");
this.subnetId = subnetId;
return this;
}

View File

@ -19,7 +19,7 @@
package org.jclouds.aws.ec2.functions;
import static org.jclouds.util.Utils.propagateOrNull;
import static org.jclouds.util.Throwables2.propagateOrNull;
import javax.inject.Singleton;

View File

@ -30,7 +30,7 @@ import javax.ws.rs.POST;
import javax.ws.rs.Path;
import org.jclouds.aws.ec2.EC2AsyncClient;
import org.jclouds.aws.ec2.binders.BindKeyNameToIndexedFormParams;
import org.jclouds.aws.ec2.binders.BindKeyNamesToIndexedFormParams;
import org.jclouds.aws.ec2.domain.KeyPair;
import org.jclouds.aws.ec2.xml.DescribeKeyPairsResponseHandler;
import org.jclouds.aws.ec2.xml.KeyPairResponseHandler;
@ -79,7 +79,7 @@ public interface KeyPairAsyncClient {
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<? extends Set<KeyPair>> describeKeyPairsInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@BinderParam(BindKeyNameToIndexedFormParams.class) String... keyPairNames);
@BinderParam(BindKeyNamesToIndexedFormParams.class) String... keyPairNames);
/**
* @see KeyPairClient#deleteKeyPairInRegion

View File

@ -30,7 +30,7 @@ import javax.ws.rs.POST;
import javax.ws.rs.Path;
import org.jclouds.aws.ec2.EC2AsyncClient;
import org.jclouds.aws.ec2.binders.BindGroupNameToIndexedFormParams;
import org.jclouds.aws.ec2.binders.BindGroupNamesToIndexedFormParams;
import org.jclouds.aws.ec2.domain.PlacementGroup;
import org.jclouds.aws.ec2.xml.DescribePlacementGroupsResponseHandler;
import org.jclouds.aws.filters.FormSigner;
@ -97,6 +97,6 @@ public interface PlacementGroupAsyncClient {
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<? extends Set<PlacementGroup>> describePlacementGroupsInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@BinderParam(BindGroupNameToIndexedFormParams.class) String... placementGroupIds);
@BinderParam(BindGroupNamesToIndexedFormParams.class) String... placementGroupIds);
}

View File

@ -30,7 +30,7 @@ import javax.ws.rs.POST;
import javax.ws.rs.Path;
import org.jclouds.aws.ec2.EC2AsyncClient;
import org.jclouds.aws.ec2.binders.BindGroupNameToIndexedFormParams;
import org.jclouds.aws.ec2.binders.BindGroupNamesToIndexedFormParams;
import org.jclouds.aws.ec2.binders.BindUserIdGroupPairToSourceSecurityGroupFormParams;
import org.jclouds.aws.ec2.domain.IpProtocol;
import org.jclouds.aws.ec2.domain.SecurityGroup;
@ -91,7 +91,7 @@ public interface SecurityGroupAsyncClient {
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<? extends Set<SecurityGroup>> describeSecurityGroupsInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@BinderParam(BindGroupNameToIndexedFormParams.class) String... securityGroupNames);
@BinderParam(BindGroupNamesToIndexedFormParams.class) String... securityGroupNames);
/**
* @see SecurityGroupClient#authorizeSecurityGroupIngressInRegion(@Nullable Region,

View File

@ -21,7 +21,6 @@ package org.jclouds.aws.ec2.util;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.http.HttpUtils.addFormParamTo;
import java.util.HashSet;
import java.util.Map;
@ -38,10 +37,13 @@ import org.jclouds.aws.ec2.services.InstanceClient;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.utils.ModifyRequest;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableMultimap.Builder;
import com.google.common.collect.Iterables;
/**
@ -52,14 +54,12 @@ public class EC2Utils {
@Singleton
public static class GetRegionFromLocation implements Function<Location, String> {
public String apply(Location location) {
String region = location.getScope() == LocationScope.REGION ? location.getId() : location
.getParent().getId();
String region = location.getScope() == LocationScope.REGION ? location.getId() : location.getParent().getId();
return region;
}
}
public static String[] getAvailabilityZonesForRegion(String region)
{
public static String[] getAvailabilityZonesForRegion(String region) {
Set<String> availabilityZones = new HashSet<String>();
for (String az : AvailabilityZone.zones) {
if (az.startsWith(region))
@ -69,20 +69,20 @@ public class EC2Utils {
return (String[]) availabilityZones.toArray(new String[availabilityZones.size()]);
}
public static void indexStringArrayToFormValuesWithPrefix(HttpRequest request, String prefix,
Object input) {
checkArgument(checkNotNull(input, "input") instanceof String[],
"this binder is only valid for String[] : " + input.getClass());
public static <R extends HttpRequest> R indexStringArrayToFormValuesWithPrefix(R request, String prefix, Object input) {
checkArgument(checkNotNull(input, "input") instanceof String[], "this binder is only valid for String[] : "
+ input.getClass());
String[] values = (String[]) input;
Builder<String, String> builder = ImmutableMultimap.<String, String> builder();
for (int i = 0; i < values.length; i++) {
addFormParamTo(request, prefix + "." + (i + 1), checkNotNull(values[i], prefix
.toLowerCase()
+ "s[" + i + "]"));
builder.put(prefix + "." + (i + 1), checkNotNull(values[i], prefix.toLowerCase() + "s[" + i + "]"));
}
ImmutableMultimap<String, String> forms = builder.build();
return forms.size() == 0 ? request : ModifyRequest.putFormParams(request, forms);
}
public static Iterable<RunningInstance> getAllRunningInstancesInRegion(InstanceClient client,
String region, String id) {
public static Iterable<RunningInstance> getAllRunningInstancesInRegion(InstanceClient client, String region,
String id) {
return Iterables.concat(client.describeInstancesInRegion(region, id));
}
@ -92,17 +92,17 @@ public class EC2Utils {
return parts;
}
public static void indexIterableToFormValuesWithPrefix(HttpRequest request, String prefix,
Object input) {
checkArgument(checkNotNull(input, "input") instanceof Iterable<?>,
"this binder is only valid for Iterable<?>: " + input.getClass());
public static <R extends HttpRequest> R indexIterableToFormValuesWithPrefix(R request, String prefix, Object input) {
checkArgument(checkNotNull(input, "input") instanceof Iterable<?>, "this binder is only valid for Iterable<?>: "
+ input.getClass());
Iterable<?> values = (Iterable<?>) input;
Builder<String, String> builder = ImmutableMultimap.<String, String> builder();
int i = 0;
for (Object o : values) {
addFormParamTo(request, prefix + "." + (i++ + 1), checkNotNull(o.toString(), prefix
.toLowerCase()
+ "s[" + i + "]"));
builder.put(prefix + "." + (i++ + 1), checkNotNull(o.toString(), prefix.toLowerCase() + "s[" + i + "]"));
}
ImmutableMultimap<String, String> forms = builder.build();
return forms.size() == 0 ? request : ModifyRequest.putFormParams(request, forms);
}
public static String findRegionInArgsOrNull(GeneratedHttpRequest<?> gRequest) {
@ -133,29 +133,28 @@ public class EC2Utils {
return null;
}
public static void indexStringArrayToFormValuesWithStringFormat(HttpRequest request,
String format, Object input) {
checkArgument(checkNotNull(input, "input") instanceof String[],
"this binder is only valid for String[] : " + input.getClass());
public static <R extends HttpRequest> R indexStringArrayToFormValuesWithStringFormat(R request, String format,
Object input) {
checkArgument(checkNotNull(input, "input") instanceof String[], "this binder is only valid for String[] : "
+ input.getClass());
String[] values = (String[]) input;
Builder<String, String> builder = ImmutableMultimap.<String, String> builder();
for (int i = 0; i < values.length; i++) {
addFormParamTo(request, String.format(format, (i + 1)), checkNotNull(values[i], format
.toLowerCase()
+ "s[" + i + "]"));
builder.put(String.format(format, (i + 1)), checkNotNull(values[i], format.toLowerCase() + "s[" + i + "]"));
}
ImmutableMultimap<String, String> forms = builder.build();
return forms.size() == 0 ? request : ModifyRequest.putFormParams(request, forms);
}
private static final Pattern ELB_PATTERN = Pattern
.compile("([^.]+)-[^.]+\\.([^.]+)\\.elb\\.amazonaws\\.com");
private static final Pattern ELB_PATTERN = Pattern.compile("([^.]+)-[^.]+\\.([^.]+)\\.elb\\.amazonaws\\.com");
public static Map<String, String> getLoadBalancerNameAndRegionFromDnsName(String dnsName) {
Matcher matcher = ELB_PATTERN.matcher(checkNotNull(dnsName, "dnsName"));
checkArgument(matcher.find(), "dnsName syntax is " + ELB_PATTERN + " didn't match: "
+ dnsName);
checkArgument(matcher.find(), "dnsName syntax is " + ELB_PATTERN + " didn't match: " + dnsName);
String loadBalancerName = matcher.group(1);
String regionName = matcher.group(2);
checkArgument((isRegion(regionName)), String.format(
"Region (%s) parsed from (%s) is not a valid region", regionName, dnsName));
checkArgument((isRegion(regionName)),
String.format("Region (%s) parsed from (%s) is not a valid region", regionName, dnsName));
return ImmutableMap.<String, String> of(regionName, loadBalancerName);
}
}

View File

@ -33,9 +33,9 @@ import org.jclouds.rest.Binder;
*/
@Singleton
public class BindAvailabilityZonesToIndexedFormParams implements Binder {
public void bindToRequest(HttpRequest request, Object input) {
indexStringArrayToFormValuesWithStringFormat(request, "AvailabilityZones.member.%s", input);
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
return indexStringArrayToFormValuesWithStringFormat(request, "AvailabilityZones.member.%s", input);
}
}

View File

@ -33,9 +33,9 @@ import org.jclouds.rest.Binder;
*/
@Singleton
public class BindELBInstanceIdsToIndexedFormParams implements Binder {
public void bindToRequest(HttpRequest request, Object input) {
indexStringArrayToFormValuesWithStringFormat(request, "Instances.member.%s.InstanceId", input);
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
return indexStringArrayToFormValuesWithStringFormat(request, "Instances.member.%s.InstanceId", input);
}
}

View File

@ -34,7 +34,6 @@ import org.jclouds.date.DateService;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.logging.Logger;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.xml.sax.Attributes;
import com.google.common.collect.Sets;

View File

@ -28,8 +28,6 @@ import static org.jclouds.aws.ec2.reference.EC2Parameters.SIGNATURE_METHOD;
import static org.jclouds.aws.ec2.reference.EC2Parameters.SIGNATURE_VERSION;
import static org.jclouds.aws.ec2.reference.EC2Parameters.TIMESTAMP;
import static org.jclouds.aws.ec2.reference.EC2Parameters.VERSION;
import static org.jclouds.http.HttpUtils.makeQueryLine;
import static org.jclouds.http.HttpUtils.parseQueryToMap;
import java.util.Arrays;
import java.util.Comparator;
@ -52,10 +50,11 @@ 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.ModifyRequest;
import org.jclouds.io.InputSuppliers;
import org.jclouds.logging.Logger;
import org.jclouds.rest.RequestSigner;
import org.jclouds.util.Utils;
import org.jclouds.util.Strings2;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
@ -97,16 +96,18 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
this.utils = utils;
}
public void filter(HttpRequest request) throws HttpException {
public HttpRequest filter(HttpRequest request) throws HttpException {
checkNotNull(request.getFirstHeaderOrNull(HttpHeaders.HOST), "request is not ready to sign; host not present");
Multimap<String, String> decodedParams = parseQueryToMap(request.getPayload().getRawContent().toString());
Multimap<String, String> decodedParams = ModifyRequest.parseQueryToMap(request.getPayload().getRawContent()
.toString());
addSigningParams(decodedParams);
validateParams(decodedParams);
String stringToSign = createStringToSign(request, decodedParams);
String signature = sign(stringToSign);
addSignature(decodedParams, signature);
setPayload(request, decodedParams);
request = setPayload(request, decodedParams);
utils.logRequest(signatureLog, request, "<<");
return request;
}
String[] sortForSigning(String queryLine) {
@ -124,8 +125,8 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
return parts;
}
void setPayload(HttpRequest request, Multimap<String, String> decodedParams) {
request.setPayload(makeQueryLine(decodedParams, new Comparator<Map.Entry<String, String>>() {
HttpRequest setPayload(HttpRequest request, Multimap<String, String> decodedParams) {
request.setPayload(ModifyRequest.makeQueryLine(decodedParams, new Comparator<Map.Entry<String, String>>() {
public int compare(Entry<String, String> o1, Entry<String, String> o2) {
if (o1.getKey().startsWith("Action") || o2.getKey().startsWith("AWSAccessKeyId"))
return -1;
@ -135,6 +136,7 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
}
}));
request.getPayload().getContentMetadata().setContentType("application/x-www-form-urlencoded");
return request;
}
@VisibleForTesting
@ -153,10 +155,10 @@ 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 = CryptoStreams.base64(CryptoStreams.mac(InputSuppliers.of(stringToSign),
crypto.hmacSHA256(secretKey.getBytes())));
if (signatureWire.enabled())
signatureWire.input(Utils.toInputStream(signature));
signatureWire.input(Strings2.toInputStream(signature));
} catch (Exception e) {
throw new HttpException("error signing request", e);
}
@ -182,7 +184,7 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
@VisibleForTesting
String buildCanonicalizedString(Multimap<String, String> decodedParams) {
return makeQueryLine(decodedParams, new Comparator<Map.Entry<String, String>>() {
return ModifyRequest.makeQueryLine(decodedParams, new Comparator<Map.Entry<String, String>>() {
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
if (o1.getKey().startsWith("AWSAccessKeyId"))
return -1;
@ -201,7 +203,7 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
}
public String createStringToSign(HttpRequest input) {
return createStringToSign(input, parseQueryToMap(input.getPayload().getRawContent().toString()));
return createStringToSign(input, ModifyRequest.parseQueryToMap(input.getPayload().getRawContent().toString()));
}
}

View File

@ -64,7 +64,7 @@ public class AWSClientErrorRetryHandler implements HttpRetryHandler {
// Content can be null in the case of HEAD requests
if (response.getPayload() != null) {
closeClientButKeepContentStream(response);
AWSError error = utils.parseAWSErrorFromContent(command.getRequest(), response);
AWSError error = utils.parseAWSErrorFromContent(command.getCurrentRequest(), response);
if (error != null
&& ("RequestTimeout".equals(error.getCode())
|| "OperationAborted".equals(error.getCode()) || "SignatureDoesNotMatch"

View File

@ -19,8 +19,6 @@
package org.jclouds.aws.handlers;
import static org.jclouds.http.HttpUtils.changeSchemeHostAndPortTo;
import static org.jclouds.http.HttpUtils.changeToGETRequest;
import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
import javax.inject.Inject;
@ -57,23 +55,23 @@ public class AWSRedirectionRetryHandler extends RedirectionRetryHandler {
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
if (response.getFirstHeaderOrNull(HttpHeaders.LOCATION) == null
&& (response.getStatusCode() == 301 || response.getStatusCode() == 307)) {
if (command.getRequest().getMethod() == HttpMethod.HEAD) {
changeToGETRequest(command.getRequest());
if (command.getCurrentRequest().getMethod() == HttpMethod.HEAD) {
command.setCurrentRequest(command.getCurrentRequest().toBuilder().method("GET").build());
return true;
} else {
command.incrementRedirectCount();
closeClientButKeepContentStream(response);
AWSError error = utils.parseAWSErrorFromContent(command.getRequest(), response);
AWSError error = utils.parseAWSErrorFromContent(command.getCurrentRequest(), response);
String host = error.getDetails().get("Endpoint");
if (host != null) {
if (host.equals(command.getRequest().getEndpoint().getHost())) {
if (host.equals(command.getCurrentRequest().getEndpoint().getHost())) {
// must be an amazon error related to
// http://developer.amazonwebservices.com/connect/thread.jspa?messageID=72287&#72287
return backoffHandler.shouldRetryRequest(command, response);
} else {
changeSchemeHostAndPortTo(command.getRequest(), command.getRequest()
.getEndpoint().getScheme(), host, command.getRequest().getEndpoint()
.getPort(), uriBuilderProvider.get());
UriBuilder builder = uriBuilderProvider.get().uri(command.getCurrentRequest().getEndpoint());
builder.host(host);
command.setCurrentRequest(command.getCurrentRequest().toBuilder().endpoint(builder.build()).build());
}
return true;
} else {

View File

@ -27,7 +27,6 @@ import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.blobstore.ContainerNotFoundException;
@ -40,7 +39,7 @@ import org.jclouds.http.HttpResponseException;
import org.jclouds.logging.Logger;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ResourceNotFoundException;
import org.jclouds.util.Utils;
import org.jclouds.util.Strings2;
import com.google.common.annotations.VisibleForTesting;
@ -65,7 +64,7 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
}
public void handleError(HttpCommand command, HttpResponse response) {
HttpRequest request = command.getRequest();
HttpRequest request = command.getCurrentRequest();
Exception exception = new HttpResponseException(command, response);
try {
AWSError error = null;
@ -80,7 +79,7 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
}
} else {
try {
message = Utils.toStringAndClose(response.getPayload().getInput());
message = Strings2.toStringAndClose(response.getPayload().getInput());
exception = new HttpResponseException(command, response, message);
} catch (IOException e) {
}
@ -109,7 +108,7 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
exception = new AuthorizationException(exception.getMessage(), exception);
break;
case 404:
if (!command.getRequest().getMethod().equals("DELETE")) {
if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
String container = request.getEndpoint().getHost();
String key = request.getEndpoint().getPath();
if (key == null || key.equals("/"))

View File

@ -39,7 +39,7 @@ import org.jclouds.aws.s3.binders.BindAsHostPrefixIfConfigured;
import org.jclouds.aws.s3.binders.BindBucketLoggingToXmlPayload;
import org.jclouds.aws.s3.binders.BindNoBucketLoggingToXmlPayload;
import org.jclouds.aws.s3.binders.BindPayerToXmlPayload;
import org.jclouds.aws.s3.binders.BindS3ObjectToPayload;
import org.jclouds.aws.s3.binders.BindS3ObjectMetadataToRequest;
import org.jclouds.aws.s3.domain.AccessControlList;
import org.jclouds.aws.s3.domain.BucketLogging;
import org.jclouds.aws.s3.domain.BucketMetadata;
@ -162,7 +162,7 @@ public interface S3AsyncClient {
@ResponseParser(ParseETagHeader.class)
ListenableFuture<String> putObject(
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName,
@PathParam("key") @ParamParser(ObjectKey.class) @BinderParam(BindS3ObjectToPayload.class) S3Object object,
@PathParam("key") @ParamParser(ObjectKey.class) @BinderParam(BindS3ObjectMetadataToRequest.class) S3Object object,
PutObjectOptions... options);
/**

View File

@ -44,8 +44,8 @@ import com.jamesmurty.utils.XMLBuilder;
*/
@Singleton
public class BindACLToXMLPayload implements Binder {
public void bindToRequest(HttpRequest request, Object payload) {
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object payload) {
AccessControlList from = (AccessControlList) payload;
Properties outputProperties = new Properties();
outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes");
@ -57,6 +57,7 @@ public class BindACLToXMLPayload implements Binder {
Throwables.propagateIfPossible(e);
throw new RuntimeException("error transforming acl: " + from, e);
}
return request;
}
protected XMLBuilder generateBuilder(AccessControlList acl) throws ParserConfigurationException,
@ -77,18 +78,16 @@ public class BindACLToXMLPayload implements Binder {
"http://www.w3.org/2001/XMLSchema-instance");
if (grant.getGrantee() instanceof GroupGrantee) {
granteeBuilder.attr("xsi:type", "Group").elem("URI").text(
grant.getGrantee().getIdentifier());
granteeBuilder.attr("xsi:type", "Group").elem("URI").text(grant.getGrantee().getIdentifier());
} else if (grant.getGrantee() instanceof CanonicalUserGrantee) {
CanonicalUserGrantee grantee = (CanonicalUserGrantee) grant.getGrantee();
granteeBuilder.attr("xsi:type", "CanonicalUser").elem("ID").text(
grantee.getIdentifier()).up();
granteeBuilder.attr("xsi:type", "CanonicalUser").elem("ID").text(grantee.getIdentifier()).up();
if (grantee.getDisplayName() != null) {
granteeBuilder.elem("DisplayName").text(grantee.getDisplayName());
}
} else if (grant.getGrantee() instanceof EmailAddressGrantee) {
granteeBuilder.attr("xsi:type", "AmazonCustomerByEmail").elem("EmailAddress").text(
grant.getGrantee().getIdentifier());
granteeBuilder.attr("xsi:type", "AmazonCustomerByEmail").elem("EmailAddress")
.text(grant.getGrantee().getIdentifier());
}
grantBuilder.elem("Permission").text(grant.getPermission().toString());
}

View File

@ -21,7 +21,6 @@ package org.jclouds.aws.s3.binders;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_SERVICE_PATH;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_VIRTUAL_HOST_BUCKETS;
import static org.jclouds.http.HttpUtils.urlEncode;
import javax.inject.Inject;
import javax.inject.Named;
@ -32,11 +31,12 @@ import javax.ws.rs.core.UriBuilder;
import org.jclouds.aws.s3.S3AsyncClient;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.utils.ModifyRequest;
import org.jclouds.rest.Binder;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.binders.BindAsHostPrefix;
import org.jclouds.util.Strings2;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
/**
@ -54,29 +54,30 @@ public class BindAsHostPrefixIfConfigured implements Binder {
@Inject
public BindAsHostPrefixIfConfigured(BindAsHostPrefix bindAsHostPrefix,
@Named(PROPERTY_S3_VIRTUAL_HOST_BUCKETS) boolean isVhostStyle,
@Named(PROPERTY_S3_SERVICE_PATH) String servicePath,
Provider<UriBuilder> uriBuilderProvider) {
@Named(PROPERTY_S3_SERVICE_PATH) String servicePath, Provider<UriBuilder> uriBuilderProvider) {
this.bindAsHostPrefix = bindAsHostPrefix;
this.isVhostStyle = isVhostStyle;
this.servicePath = servicePath;
this.uriBuilderProvider = uriBuilderProvider;
}
public void bindToRequest(HttpRequest request, Object payload) {
@SuppressWarnings("unchecked")
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object payload) {
if (isVhostStyle) {
bindAsHostPrefix.bindToRequest(request, payload);
request.getHeaders().replaceValues(HttpHeaders.HOST,
ImmutableSet.of(request.getEndpoint().getHost()));
request = bindAsHostPrefix.bindToRequest(request, payload);
return ModifyRequest.replaceHeader(request, HttpHeaders.HOST, request.getEndpoint().getHost());
} else {
UriBuilder builder = uriBuilderProvider.get().uri(request.getEndpoint());
StringBuilder path = new StringBuilder(urlEncode(request.getEndpoint().getPath(),
S3AsyncClient.class.getAnnotation(SkipEncoding.class).value()));
StringBuilder path = new StringBuilder(Strings2.urlEncode(request.getEndpoint().getPath(), S3AsyncClient.class
.getAnnotation(SkipEncoding.class).value()));
int indexToInsert = path.indexOf(servicePath);
indexToInsert = indexToInsert == -1 ? 0 : indexToInsert;
indexToInsert += servicePath.length();
path.insert(indexToInsert, "/" + payload.toString());
builder.replacePath(path.toString());
request.setEndpoint(builder.buildFromEncodedMap(Maps.<String, Object> newHashMap()));
return (R) request.toBuilder().endpoint(builder.buildFromEncodedMap(Maps.<String, Object> newLinkedHashMap()))
.build();
}
}
}

View File

@ -44,8 +44,8 @@ import com.jamesmurty.utils.XMLBuilder;
*/
@Singleton
public class BindBucketLoggingToXmlPayload implements Binder {
public void bindToRequest(HttpRequest request, Object payload) {
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object payload) {
BucketLogging from = (BucketLogging) payload;
Properties outputProperties = new Properties();
outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes");
@ -57,12 +57,13 @@ public class BindBucketLoggingToXmlPayload implements Binder {
Throwables.propagateIfPossible(e);
throw new RuntimeException("error transforming bucketLogging: " + from, e);
}
return request;
}
protected XMLBuilder generateBuilder(BucketLogging bucketLogging)
throws ParserConfigurationException, FactoryConfigurationError {
XMLBuilder rootBuilder = XMLBuilder.create("BucketLoggingStatus").attr("xmlns",
S3Constants.S3_REST_API_XML_NAMESPACE).e("LoggingEnabled");
protected XMLBuilder generateBuilder(BucketLogging bucketLogging) throws ParserConfigurationException,
FactoryConfigurationError {
XMLBuilder rootBuilder = XMLBuilder.create("BucketLoggingStatus")
.attr("xmlns", S3Constants.S3_REST_API_XML_NAMESPACE).e("LoggingEnabled");
rootBuilder.e("TargetBucket").t(bucketLogging.getTargetBucket());
rootBuilder.e("TargetPrefix").t(bucketLogging.getTargetPrefix());
XMLBuilder grantsBuilder = rootBuilder.elem("TargetGrants");
@ -72,18 +73,16 @@ public class BindBucketLoggingToXmlPayload implements Binder {
"http://www.w3.org/2001/XMLSchema-instance");
if (grant.getGrantee() instanceof GroupGrantee) {
granteeBuilder.attr("xsi:type", "Group").elem("URI").text(
grant.getGrantee().getIdentifier());
granteeBuilder.attr("xsi:type", "Group").elem("URI").text(grant.getGrantee().getIdentifier());
} else if (grant.getGrantee() instanceof CanonicalUserGrantee) {
CanonicalUserGrantee grantee = (CanonicalUserGrantee) grant.getGrantee();
granteeBuilder.attr("xsi:type", "CanonicalUser").elem("ID").text(
grantee.getIdentifier()).up();
granteeBuilder.attr("xsi:type", "CanonicalUser").elem("ID").text(grantee.getIdentifier()).up();
if (grantee.getDisplayName() != null) {
granteeBuilder.elem("DisplayName").text(grantee.getDisplayName());
}
} else if (grant.getGrantee() instanceof EmailAddressGrantee) {
granteeBuilder.attr("xsi:type", "AmazonCustomerByEmail").elem("EmailAddress").text(
grant.getGrantee().getIdentifier());
granteeBuilder.attr("xsi:type", "AmazonCustomerByEmail").elem("EmailAddress")
.text(grant.getGrantee().getIdentifier());
}
grantBuilder.elem("Permission").text(grant.getPermission().toString());
}

View File

@ -38,10 +38,12 @@ public class BindNoBucketLoggingToXmlPayload implements Binder {
this.bindAsHostPrefixIfConfigured = bindAsHostPrefixIfConfigured;
}
public void bindToRequest(HttpRequest request, Object payload) {
bindAsHostPrefixIfConfigured.bindToRequest(request, payload);
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object payload) {
request = bindAsHostPrefixIfConfigured.bindToRequest(request, payload);
String stringPayload = "<BucketLoggingStatus xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"/>";
request.setPayload(stringPayload);
return request;
}
}

View File

@ -36,15 +36,15 @@ import org.jclouds.rest.Binder;
*/
@Singleton
public class BindPayerToXmlPayload implements Binder {
public void bindToRequest(HttpRequest request, Object toBind) {
checkArgument(checkNotNull(toBind, "toBind") instanceof Payer,
"this binder is only valid for Payer!");
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object toBind) {
checkArgument(checkNotNull(toBind, "toBind") instanceof Payer, "this binder is only valid for Payer!");
String text = String
.format(
"<RequestPaymentConfiguration xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Payer>%s</Payer></RequestPaymentConfiguration>",
((Payer) toBind).value());
request.setPayload(text);
request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_XML);
return request;
}
}

View File

@ -20,6 +20,7 @@
package org.jclouds.aws.s3.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -29,6 +30,7 @@ import org.jclouds.aws.s3.blobstore.functions.ObjectToBlob;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.blobstore.binders.BindUserMetadataToHeadersWithPrefix;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.utils.ModifyRequest;
import org.jclouds.rest.Binder;
/**
@ -36,27 +38,33 @@ import org.jclouds.rest.Binder;
* @author Adrian Cole
*/
@Singleton
public class BindS3ObjectToPayload implements Binder {
public class BindS3ObjectMetadataToRequest implements Binder {
private final BindUserMetadataToHeadersWithPrefix blobBinder;
private final ObjectToBlob object2Blob;
@Inject
public BindS3ObjectToPayload(ObjectToBlob object2Blob, BindUserMetadataToHeadersWithPrefix blobBinder) {
this.blobBinder = blobBinder;
this.object2Blob = object2Blob;
public BindS3ObjectMetadataToRequest(ObjectToBlob object2Blob, BindUserMetadataToHeadersWithPrefix blobBinder) {
this.blobBinder = checkNotNull(blobBinder, "blobBinder");
this.object2Blob = checkNotNull(object2Blob, "object2Blob");
}
public void bindToRequest(HttpRequest request, Object payload) {
S3Object s3Object = (S3Object) payload;
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
checkArgument(checkNotNull(input, "input") instanceof S3Object, "this binder is only valid for S3Object!");
checkNotNull(request, "request");
S3Object s3Object = S3Object.class.cast(input);
checkArgument(s3Object.getMetadata().getKey() != null, "s3Object.getMetadata().getKey() must be set!");
checkArgument(s3Object.getPayload().getContentMetadata().getContentLength() != null,
"contentLength must be set, streaming not supported");
checkArgument(s3Object.getPayload().getContentMetadata().getContentLength() <= 5l * 1024 * 1024 * 1024,
"maximum size for put object is 5GB");
blobBinder.bindToRequest(request, object2Blob.apply(s3Object));
request = blobBinder.bindToRequest(request, object2Blob.apply(s3Object));
if (s3Object.getMetadata().getCacheControl() != null) {
request.getHeaders().put(HttpHeaders.CACHE_CONTROL, s3Object.getMetadata().getCacheControl());
request = ModifyRequest.replaceHeader(request, HttpHeaders.CACHE_CONTROL, s3Object.getMetadata()
.getCacheControl());
}
return request;
}
}

View File

@ -52,7 +52,7 @@ import org.jclouds.blobstore.util.BlobUtils;
import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location;
import org.jclouds.http.options.GetOptions;
import org.jclouds.util.Utils;
import org.jclouds.util.Assertions;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
@ -160,7 +160,7 @@ public class S3BlobStore extends BaseBlobStore {
*/
public void clearAndDeleteContainer(final String container) {
try {
if (!Utils.eventuallyTrue(new Supplier<Boolean>() {
if (!Assertions.eventuallyTrue(new Supplier<Boolean>() {
public Boolean get() {
clearContainer(container);
return sync.deleteBucketIfEmpty(container);

View File

@ -32,7 +32,7 @@ import com.google.inject.TypeLiteral;
*/
public class ScaleUpCloudBlobStoreContextModule extends S3BlobStoreContextModule {
@SuppressWarnings("rawtypes")
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
protected void bindBucketLocationStrategy() {
bind(new TypeLiteral<Function<BucketMetadata, Location>>() {

View File

@ -31,7 +31,6 @@ import static org.jclouds.util.Patterns.NEWLINE_PATTERN;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.TreeSet;
@ -52,16 +51,20 @@ 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.ModifyRequest;
import org.jclouds.io.InputSuppliers;
import org.jclouds.logging.Logger;
import org.jclouds.rest.RequestSigner;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.util.Utils;
import org.jclouds.util.Strings2;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimaps;
/**
* Signs the S3 request.
@ -110,11 +113,26 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
this.utils = utils;
}
public void filter(HttpRequest request) throws HttpException {
replaceDateHeader(request);
String toSign = createStringToSign(request);
calculateAndReplaceAuthHeader(request, toSign);
public HttpRequest filter(HttpRequest request) throws HttpException {
request = replaceDateHeader(request);
String signature = calculateSignature(createStringToSign(request));
request = replaceAuthorizationHeader(request, signature);
utils.logRequest(signatureLog, request, "<<");
return request;
}
HttpRequest replaceAuthorizationHeader(HttpRequest request, String signature) {
request = ModifyRequest.replaceHeader(request, HttpHeaders.AUTHORIZATION, authTag + " " + accessKey + ":"
+ signature);
return request;
}
HttpRequest replaceDateHeader(HttpRequest request) {
Builder<String, String> builder = ImmutableMap.builder();
String date = timeStampProvider.get();
builder.put(HttpHeaders.DATE, date);
request = ModifyRequest.replaceHeaders(request, Multimaps.forMap(builder.build()));
return request;
}
public String createStringToSign(HttpRequest request) {
@ -133,19 +151,18 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
return buffer.toString();
}
void calculateAndReplaceAuthHeader(HttpRequest request, String toSign) throws HttpException {
String calculateSignature(String toSign) throws HttpException {
String signature = sign(toSign);
if (signatureWire.enabled())
signatureWire.input(Utils.toInputStream(signature));
request.getHeaders().replaceValues(HttpHeaders.AUTHORIZATION,
Collections.singletonList(authTag + " " + accessKey + ":" + signature));
signatureWire.input(Strings2.toInputStream(signature));
return signature;
}
public String sign(String toSign) {
String signature;
try {
signature = CryptoStreams.base64(CryptoStreams.mac(InputSuppliers.of(toSign), crypto.hmacSHA1(secretKey
.getBytes())));
signature = CryptoStreams.base64(CryptoStreams.mac(InputSuppliers.of(toSign),
crypto.hmacSHA1(secretKey.getBytes())));
} catch (Exception e) {
throw new HttpException("error signing request", e);
}
@ -156,17 +173,13 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
toSign.append(request.getMethod()).append("\n");
}
void replaceDateHeader(HttpRequest request) {
request.getHeaders().replaceValues(HttpHeaders.DATE, Collections.singletonList(timeStampProvider.get()));
}
void appendAmzHeaders(HttpRequest request, StringBuilder toSign) {
Set<String> headers = new TreeSet<String>(request.getHeaders().keySet());
for (String header : headers) {
if (header.startsWith("x-" + headerTag + "-")) {
toSign.append(header.toLowerCase()).append(":");
for (String value : request.getHeaders().get(header)) {
toSign.append(Utils.replaceAll(value, NEWLINE_PATTERN, "")).append(",");
toSign.append(Strings2.replaceAll(value, NEWLINE_PATTERN, "")).append(",");
}
toSign.deleteCharAt(toSign.lastIndexOf(","));
toSign.append("\n");
@ -202,7 +215,7 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
return input.annotationType().equals(Bucket.class);
}
})) {
bucketName = (String) request.getArgs()[i];
bucketName = (String) request.getArgs().get(i);
break;
}
}

View File

@ -61,14 +61,14 @@ public class BindRegionToXmlPayload extends BindToStringPayload {
}
@Override
public void bindToRequest(HttpRequest request, Object input) {
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
input = input == null ? Iterables.get(defaultRegions, 0) : input;
checkArgument(input instanceof String, "this binder is only valid for Region!");
String constraint = (String) input;
String value = null;
if (Iterables.contains(defaultRegions, constraint)) {
// nothing to bind as this is default.
return;
return request;
} else if (Iterables.contains(regions, constraint)) {
value = constraint;
} else {
@ -79,10 +79,12 @@ public class BindRegionToXmlPayload extends BindToStringPayload {
value = constraint;
}
}
String payload = String.format(
String payload = String
.format(
"<CreateBucketConfiguration><LocationConstraint>%s</LocationConstraint></CreateBucketConfiguration>",
value);
super.bindToRequest(request, payload);
request = super.bindToRequest(request, payload);
request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_XML);
return request;
}
}

View File

@ -35,7 +35,8 @@ import com.google.common.base.Function;
* @see ParseMetadataFromHeaders
* @author Adrian Cole
*/
public class ParseObjectFromHeadersAndHttpContent implements Function<HttpResponse, S3Object>, InvocationContext {
public class ParseObjectFromHeadersAndHttpContent implements Function<HttpResponse, S3Object>,
InvocationContext<ParseObjectFromHeadersAndHttpContent> {
private final ParseObjectMetadataFromHeaders metadataParser;
private final S3Object.Factory objectProvider;

View File

@ -44,7 +44,8 @@ import com.google.common.base.Function;
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTObjectGET.html" />
* @author Adrian Cole
*/
public class ParseObjectMetadataFromHeaders implements Function<HttpResponse, MutableObjectMetadata>, InvocationContext {
public class ParseObjectMetadataFromHeaders implements Function<HttpResponse, MutableObjectMetadata>,
InvocationContext<ParseObjectMetadataFromHeaders> {
private final ParseSystemAndUserMetadataFromHeaders blobMetadataParser;
private final BlobToObjectMetadata blobToObjectMetadata;
private final String userMdPrefix;

View File

@ -23,7 +23,7 @@ import static com.google.common.base.Throwables.getCausalChain;
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 org.jclouds.util.Utils.propagateOrNull;
import static org.jclouds.util.Throwables2.propagateOrNull;
import java.util.List;

View File

@ -25,7 +25,7 @@ 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 org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
import static org.jclouds.util.Utils.propagateOrNull;
import static org.jclouds.util.Throwables2.propagateOrNull;
import java.util.List;

View File

@ -33,7 +33,7 @@ import org.jclouds.aws.s3.domain.internal.ListBucketResponseImpl;
import org.jclouds.crypto.CryptoStreams;
import org.jclouds.date.DateService;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.util.Utils;
import org.jclouds.util.Strings2;
import org.xml.sax.Attributes;
import com.google.common.collect.Sets;
@ -101,7 +101,7 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult<ListBucketResp
currentLastModified = dateParser.iso8601DateParse(currentText.toString().trim());
} else if (qName.equals("ETag")) {
currentETag = currentText.toString().trim();
currentMD5 = CryptoStreams.hex(Utils.replaceAll(currentETag, '"', ""));
currentMD5 = CryptoStreams.hex(Strings2.replaceAll(currentETag, '"', ""));
} else if (qName.equals("Size")) {
currentSize = new Long(currentText.toString().trim());
} else if (qName.equals("Owner")) {

View File

@ -47,7 +47,7 @@ import org.testng.annotations.Test;
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "jclouds.ComputeAndBlobStoreTogetherHappilyLiveTest")
@Test(groups = "live")
public class ComputeAndBlobStoreTogetherHappilyLiveTest extends BlobStoreAndComputeServiceLiveTest {
@BeforeClass
protected void setupCredentials() {

View File

@ -36,7 +36,7 @@ import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.domain.Credentials;
import org.jclouds.rest.config.CredentialStoreModule;
import org.jclouds.util.Utils;
import org.jclouds.util.Strings2;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
@ -95,7 +95,7 @@ public class CredentialsStoredInBlobStoreTest {
assertEquals(credentialsMap.size(), 10);
for (Entry<String, InputStream> entry : credentialsMap.entrySet()) {
Credentials credentials = computeContext.credentialStore().get(entry.getKey());
assertEquals(Utils.toStringAndClose(entry.getValue()), String.format(
assertEquals(Strings2.toStringAndClose(entry.getValue()), String.format(
"{\"identity\":\"%s\",\"credential\":\"%s\"}", credentials.identity, credentials.credential));
}
}

View File

@ -21,7 +21,7 @@ package org.jclouds.aws;
import org.jclouds.blobstore.util.BlobStoreUtils;
import org.jclouds.compute.util.ComputeServiceUtils;
import org.jclouds.util.Utils;
import org.jclouds.rest.Providers;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
@ -49,7 +49,7 @@ public class ProvidersInPropertiesTest {
@Test
public void testSupportedProviders() {
Iterable<String> providers = Utils.getSupportedProviders();
Iterable<String> providers = Providers.getSupportedProviders();
assert Iterables.contains(providers, "sqs") : providers;
assert Iterables.contains(providers, "elb") : providers;
assert Iterables.contains(providers, "s3") : providers;

View File

@ -51,7 +51,8 @@ import com.google.inject.TypeLiteral;
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "cloudwatch.MonitoringAsyncClientTest")
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "CloudWatchAsyncClientTest")
public class CloudWatchAsyncClientTest extends RestClientTest<CloudWatchAsyncClient> {
public void testRegisterInstancesWithMeasure() throws SecurityException, NoSuchMethodException, IOException {

View File

@ -43,7 +43,7 @@ import com.google.inject.Module;
*
* @author Adrian Cole
*/
@Test(groups = "live", sequential = true, testName = "cloudwatch.CloudWatchClientLiveTest")
@Test(groups = "live", sequential = true)
public class CloudWatchClientLiveTest {
private CloudWatchClient client;

Some files were not shown because too many files have changed in this diff Show More