mirror of https://github.com/apache/jclouds.git
code cleanup: http request immutability (except payload), builders, test backfill
This commit is contained in:
parent
a23c2dd815
commit
60b6b68556
|
@ -82,7 +82,6 @@ public interface AtmosStorageAsyncClient {
|
||||||
* @see AtmosStorageClient#listDirectories
|
* @see AtmosStorageClient#listDirectories
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
@Path("")
|
|
||||||
@ResponseParser(ParseDirectoryListFromContentAndHeaders.class)
|
@ResponseParser(ParseDirectoryListFromContentAndHeaders.class)
|
||||||
@Consumes(MediaType.TEXT_XML)
|
@Consumes(MediaType.TEXT_XML)
|
||||||
ListenableFuture<BoundedSet<? extends DirectoryEntry>> listDirectories(ListOptions... options);
|
ListenableFuture<BoundedSet<? extends DirectoryEntry>> listDirectories(ListOptions... options);
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class AtmosStorageResponseException extends HttpResponseException {
|
||||||
|
|
||||||
public AtmosStorageResponseException(HttpCommand command, HttpResponse response,
|
public AtmosStorageResponseException(HttpCommand command, HttpResponse response,
|
||||||
AtmosStorageError error) {
|
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);
|
.getRequestLine(), response.getStatusCode(), error.toString()), command, response);
|
||||||
this.setError(error);
|
this.setError(error);
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ public class AtmosStorageResponseException extends HttpResponseException {
|
||||||
|
|
||||||
public AtmosStorageResponseException(HttpCommand command, HttpResponse response,
|
public AtmosStorageResponseException(HttpCommand command, HttpResponse response,
|
||||||
AtmosStorageError error, Throwable cause) {
|
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);
|
.getRequestLine(), error.toString()), command, response, cause);
|
||||||
this.setError(error);
|
this.setError(error);
|
||||||
|
|
||||||
|
|
|
@ -20,28 +20,36 @@
|
||||||
package org.jclouds.atmosonline.saas.binders;
|
package org.jclouds.atmosonline.saas.binders;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.atmosonline.saas.domain.AtmosObject;
|
import org.jclouds.atmosonline.saas.domain.AtmosObject;
|
||||||
import org.jclouds.crypto.Crypto;
|
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.rest.Binder;
|
import org.jclouds.rest.Binder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class BindMetadataToHeaders implements Binder {
|
public class BindMetadataToHeaders implements Binder {
|
||||||
private final BindUserMetadataToHeaders metaBinder;
|
private final BindUserMetadataToHeaders metaBinder;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected BindMetadataToHeaders(BindUserMetadataToHeaders metaBinder, Crypto crypto) {
|
protected BindMetadataToHeaders(BindUserMetadataToHeaders metaBinder) {
|
||||||
this.metaBinder = metaBinder;
|
this.metaBinder = metaBinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bindToRequest(HttpRequest request, Object payload) {
|
@Override
|
||||||
AtmosObject object = (AtmosObject) payload;
|
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,
|
checkArgument(object.getPayload().getContentMetadata().getContentLength() != null,
|
||||||
"contentLength must be set, streaming not supported");
|
"contentLength must be set, streaming not supported");
|
||||||
metaBinder.bindToRequest(request, object.getUserMetadata());
|
return metaBinder.bindToRequest(request, object.getUserMetadata());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,36 +19,57 @@
|
||||||
|
|
||||||
package org.jclouds.atmosonline.saas.binders;
|
package org.jclouds.atmosonline.saas.binders;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.atmosonline.saas.domain.UserMetadata;
|
import org.jclouds.atmosonline.saas.domain.UserMetadata;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.utils.ModifyRequest;
|
||||||
import org.jclouds.rest.Binder;
|
import org.jclouds.rest.Binder;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Joiner;
|
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
|
@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) {
|
return ModifyRequest.putHeaders(request, Multimaps.forMap(apply(UserMetadata.class.cast(input))));
|
||||||
UserMetadata md = (UserMetadata) checkNotNull(payload, "payload");
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> apply(UserMetadata md) {
|
||||||
|
Builder<String, String> headers = ImmutableMap.<String, String> builder();
|
||||||
if (md.getMetadata().size() > 0) {
|
if (md.getMetadata().size() > 0) {
|
||||||
String header = Joiner.on(',').withKeyValueSeparator("=").join(md.getMetadata());
|
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) {
|
if (md.getListableMetadata().size() > 0) {
|
||||||
String header = Joiner.on(',').withKeyValueSeparator("=").join(md.getListableMetadata());
|
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) {
|
if (md.getTags().size() > 0) {
|
||||||
String header = Joiner.on(',').join(md.getTags());
|
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) {
|
if (md.getListableTags().size() > 0) {
|
||||||
String header = Joiner.on(',').join(md.getListableTags());
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,21 +73,22 @@ public class FindMD5InUserMetadata implements ContainsValueInListStrategy {
|
||||||
protected Long maxTime;
|
protected Long maxTime;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private FindMD5InUserMetadata(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
|
FindMD5InUserMetadata(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor, ObjectMD5 objectMD5,
|
||||||
ObjectMD5 objectMD5, ListBlobsInContainer getAllBlobMetadata, AtmosStorageAsyncClient client) {
|
ListBlobsInContainer getAllBlobMetadata, AtmosStorageAsyncClient client) {
|
||||||
this.objectMD5 = objectMD5;
|
this.objectMD5 = objectMD5;
|
||||||
this.getAllBlobMetadata = getAllBlobMetadata;
|
this.getAllBlobMetadata = getAllBlobMetadata;
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.userExecutor = userExecutor;
|
this.userExecutor = userExecutor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean execute(final String containerName, Object value, ListContainerOptions options) {
|
public boolean execute(final String containerName, Object value, ListContainerOptions options) {
|
||||||
final byte[] toSearch = objectMD5.apply(value);
|
final byte[] toSearch = objectMD5.apply(value);
|
||||||
final BlockingQueue<Boolean> queue = new SynchronousQueue<Boolean>();
|
final BlockingQueue<Boolean> queue = new SynchronousQueue<Boolean>();
|
||||||
Map<String, Future<?>> responses = Maps.newHashMap();
|
Map<String, Future<?>> responses = Maps.newHashMap();
|
||||||
for (BlobMetadata md : getAllBlobMetadata.execute(containerName, options)) {
|
for (BlobMetadata md : getAllBlobMetadata.execute(containerName, options)) {
|
||||||
final ListenableFuture<AtmosObject> future = Futures.makeListenable(client.headFile(containerName
|
final ListenableFuture<AtmosObject> future = Futures.makeListenable(
|
||||||
+ "/" + md.getName()), userExecutor);
|
client.headFile(containerName + "/" + md.getName()), userExecutor);
|
||||||
future.addListener(new Runnable() {
|
future.addListener(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
|
@ -109,11 +110,11 @@ public class FindMD5InUserMetadata implements ContainsValueInListStrategy {
|
||||||
}, userExecutor);
|
}, userExecutor);
|
||||||
responses.put(md.getName(), future);
|
responses.put(md.getName(), future);
|
||||||
}
|
}
|
||||||
Map<String, Exception> exceptions = awaitCompletion(responses, userExecutor, maxTime, logger, String.format(
|
Map<String, Exception> exceptions = awaitCompletion(responses, userExecutor, maxTime, logger,
|
||||||
"searching for md5 in container %s", containerName));
|
String.format("searching for md5 in container %s", containerName));
|
||||||
if (exceptions.size() > 0)
|
if (exceptions.size() > 0)
|
||||||
throw new BlobRuntimeException(String.format("searching for md5 in container %s: %s", containerName,
|
throw new BlobRuntimeException(String.format("searching for md5 in container %s: %s", containerName,
|
||||||
exceptions));
|
exceptions));
|
||||||
try {
|
try {
|
||||||
return queue.poll(1, TimeUnit.MICROSECONDS) != null;
|
return queue.poll(1, TimeUnit.MICROSECONDS) != null;
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
@ -122,7 +123,7 @@ public class FindMD5InUserMetadata implements ContainsValueInListStrategy {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Throwables.propagateIfPossible(e, BlobRuntimeException.class);
|
Throwables.propagateIfPossible(e, BlobRuntimeException.class);
|
||||||
throw new BlobRuntimeException(String.format("Error searching for ETAG of value: [%s] in container:%s", value,
|
throw new BlobRuntimeException(String.format("Error searching for ETAG of value: [%s] in container:%s", value,
|
||||||
containerName), e);
|
containerName), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,19 +19,12 @@
|
||||||
|
|
||||||
package org.jclouds.atmosonline.saas.config;
|
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.AtmosObject;
|
||||||
import org.jclouds.atmosonline.saas.domain.MutableContentMetadata;
|
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 org.jclouds.blobstore.config.BlobStoreObjectModule;
|
||||||
|
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
import com.google.inject.Scopes;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the domain object mappings needed for all Atmos implementations
|
* Configures the domain object mappings needed for all Atmos implementations
|
||||||
|
@ -48,27 +41,6 @@ public class AtmosObjectModule extends AbstractModule {
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
// for converters
|
// for converters
|
||||||
install(new BlobStoreObjectModule());
|
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
|
@Provides
|
||||||
|
|
|
@ -21,28 +21,25 @@ package org.jclouds.atmosonline.saas.domain;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.jclouds.atmosonline.saas.domain.internal.AtmosObjectImpl.AtmosObjectFactory;
|
||||||
import org.jclouds.io.PayloadEnclosing;
|
import org.jclouds.io.PayloadEnclosing;
|
||||||
|
|
||||||
import com.google.common.collect.Multimap;
|
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
|
* @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> {
|
public interface AtmosObject extends PayloadEnclosing, Comparable<AtmosObject> {
|
||||||
|
@ImplementedBy(AtmosObjectFactory.class)
|
||||||
public interface Factory {
|
public interface Factory {
|
||||||
AtmosObject create(@Nullable MutableContentMetadata contentMetadata);
|
AtmosObject create(@Nullable MutableContentMetadata contentMetadata);
|
||||||
|
|
||||||
AtmosObject create(SystemMetadata systemMetadata, UserMetadata userMetadata);
|
AtmosObject create(SystemMetadata systemMetadata, UserMetadata userMetadata);
|
||||||
|
|
||||||
AtmosObject create(MutableContentMetadata contentMetadata, SystemMetadata systemMetadata,
|
AtmosObject create(MutableContentMetadata contentMetadata, SystemMetadata systemMetadata,
|
||||||
UserMetadata userMetadata);
|
UserMetadata userMetadata);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,9 @@ package org.jclouds.atmosonline.saas.domain;
|
||||||
|
|
||||||
import java.util.Set;
|
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;
|
import com.google.inject.ImplementedBy;
|
||||||
|
|
||||||
|
@ -30,9 +32,10 @@ import com.google.inject.ImplementedBy;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ImplementedBy(BoundedHashSet.class)
|
@ImplementedBy(BoundedLinkedHashSet.class)
|
||||||
public interface BoundedSet<T> extends Set<T> {
|
public interface BoundedSet<T> extends Set<T> {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
String getToken();
|
String getToken();
|
||||||
|
|
||||||
}
|
}
|
|
@ -19,10 +19,10 @@
|
||||||
|
|
||||||
package org.jclouds.atmosonline.saas.domain;
|
package org.jclouds.atmosonline.saas.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SortedMap;
|
|
||||||
import java.util.SortedSet;
|
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
@ -33,10 +33,25 @@ import com.google.common.collect.Sets;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class UserMetadata {
|
public class UserMetadata {
|
||||||
private final SortedMap<String, String> metadata = Maps.newTreeMap();
|
private final Map<String, String> metadata;
|
||||||
private final SortedMap<String, String> listableMetadata = Maps.newTreeMap();
|
private final Map<String, String> listableMetadata;
|
||||||
private final SortedSet<String> tags = Sets.newTreeSet();
|
private final Set<String> tags;
|
||||||
private final SortedSet<String> listableTags = Sets.newTreeSet();
|
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() {
|
public Map<String, String> getMetadata() {
|
||||||
return metadata;
|
return metadata;
|
||||||
|
@ -54,4 +69,53 @@ public class UserMetadata {
|
||||||
return listableTags;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -22,6 +22,8 @@ package org.jclouds.atmosonline.saas.domain.internal;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
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.AtmosObject;
|
||||||
import org.jclouds.atmosonline.saas.domain.MutableContentMetadata;
|
import org.jclouds.atmosonline.saas.domain.MutableContentMetadata;
|
||||||
|
@ -39,6 +41,26 @@ import com.google.common.collect.Multimap;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class AtmosObjectImpl extends PayloadEnclosingImpl implements AtmosObject, Comparable<AtmosObject> {
|
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 UserMetadata userMetadata;
|
||||||
private final SystemMetadata systemMetadata;
|
private final SystemMetadata systemMetadata;
|
||||||
|
|
||||||
|
@ -50,12 +72,11 @@ public class AtmosObjectImpl extends PayloadEnclosingImpl implements AtmosObject
|
||||||
return userMetadata;
|
return userMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MutableContentMetadata contentMetadata;
|
private MutableContentMetadata contentMetadata;
|
||||||
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
|
private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
|
||||||
|
|
||||||
public AtmosObjectImpl(MutableContentMetadata contentMetadata, SystemMetadata systemMetadata,
|
public AtmosObjectImpl(MutableContentMetadata contentMetadata, SystemMetadata systemMetadata,
|
||||||
UserMetadata userMetadata) {
|
UserMetadata userMetadata) {
|
||||||
super();
|
|
||||||
this.contentMetadata = contentMetadata;
|
this.contentMetadata = contentMetadata;
|
||||||
this.systemMetadata = systemMetadata;
|
this.systemMetadata = systemMetadata;
|
||||||
this.userMetadata = userMetadata;
|
this.userMetadata = userMetadata;
|
||||||
|
@ -145,6 +166,7 @@ public class AtmosObjectImpl extends PayloadEnclosingImpl implements AtmosObject
|
||||||
@Override
|
@Override
|
||||||
public void setPayload(Payload data) {
|
public void setPayload(Payload data) {
|
||||||
this.payload = data;
|
this.payload = data;
|
||||||
this.contentMetadata = new DelegatingMutableContentMetadata(contentMetadata.getName(), payload.getContentMetadata());
|
this.contentMetadata = new DelegatingMutableContentMetadata(contentMetadata.getName(),
|
||||||
|
payload.getContentMetadata());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -22,6 +22,8 @@ package org.jclouds.atmosonline.saas.domain.internal;
|
||||||
import org.jclouds.atmosonline.saas.domain.MutableContentMetadata;
|
import org.jclouds.atmosonline.saas.domain.MutableContentMetadata;
|
||||||
import org.jclouds.io.payloads.BaseMutableContentMetadata;
|
import org.jclouds.io.payloads.BaseMutableContentMetadata;
|
||||||
|
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -150,4 +152,9 @@ public class DelegatingMutableContentMetadata implements MutableContentMetadata
|
||||||
return delegate.getContentLanguage();
|
return delegate.getContentLanguage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPropertiesFromHttpHeaders(Multimap<String, String> headers) {
|
||||||
|
delegate.setPropertiesFromHttpHeaders(headers);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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.NEWLINE_PATTERN;
|
||||||
import static org.jclouds.util.Patterns.TWO_SPACE_PATTERN;
|
import static org.jclouds.util.Patterns.TWO_SPACE_PATTERN;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
@ -45,11 +44,15 @@ import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpRequestFilter;
|
import org.jclouds.http.HttpRequestFilter;
|
||||||
import org.jclouds.http.HttpUtils;
|
import org.jclouds.http.HttpUtils;
|
||||||
import org.jclouds.http.internal.SignatureWire;
|
import org.jclouds.http.internal.SignatureWire;
|
||||||
|
import org.jclouds.http.utils.ModifyRequest;
|
||||||
import org.jclouds.io.InputSuppliers;
|
import org.jclouds.io.InputSuppliers;
|
||||||
import org.jclouds.logging.Logger;
|
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.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.
|
* Signs the EMC Atmos Online Storage request.
|
||||||
|
@ -77,8 +80,8 @@ public class SignRequest implements HttpRequestFilter {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public SignRequest(SignatureWire signatureWire, @Named(PROPERTY_IDENTITY) String uid,
|
public SignRequest(SignatureWire signatureWire, @Named(PROPERTY_IDENTITY) String uid,
|
||||||
@Named(PROPERTY_CREDENTIAL) String encodedKey, @TimeStamp Provider<String> timeStampProvider,
|
@Named(PROPERTY_CREDENTIAL) String encodedKey, @TimeStamp Provider<String> timeStampProvider, Crypto crypto,
|
||||||
Crypto crypto, HttpUtils utils) {
|
HttpUtils utils) {
|
||||||
this.signatureWire = signatureWire;
|
this.signatureWire = signatureWire;
|
||||||
this.uid = uid;
|
this.uid = uid;
|
||||||
this.key = CryptoStreams.base64(encodedKey);
|
this.key = CryptoStreams.base64(encodedKey);
|
||||||
|
@ -87,16 +90,19 @@ public class SignRequest implements HttpRequestFilter {
|
||||||
this.utils = utils;
|
this.utils = utils;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void filter(HttpRequest request) throws HttpException {
|
@Override
|
||||||
String toSign = replaceUIDHeader(request).removeOldSignature(request).replaceDateHeader(request)
|
public HttpRequest filter(HttpRequest request) throws HttpException {
|
||||||
.createStringToSign(request);
|
Builder<String, String> builder = ImmutableMap.builder();
|
||||||
calculateAndReplaceAuthHeader(request, toSign);
|
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, "<<");
|
utils.logRequest(signatureLog, request, "<<");
|
||||||
}
|
return request;
|
||||||
|
|
||||||
private SignRequest removeOldSignature(HttpRequest request) {
|
|
||||||
request.getHeaders().removeAll(AtmosStorageHeaders.SIGNATURE);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String createStringToSign(HttpRequest request) {
|
public String createStringToSign(HttpRequest request) {
|
||||||
|
@ -113,11 +119,11 @@ public class SignRequest implements HttpRequestFilter {
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calculateAndReplaceAuthHeader(HttpRequest request, String toSign) throws HttpException {
|
private String calculateSignature(String toSign) {
|
||||||
String signature = signString(toSign);
|
String signature = signString(toSign);
|
||||||
if (signatureWire.enabled())
|
if (signatureWire.enabled())
|
||||||
signatureWire.input(Utils.toInputStream(signature));
|
signatureWire.input(Strings2.toInputStream(signature));
|
||||||
request.getHeaders().replaceValues(AtmosStorageHeaders.SIGNATURE, Collections.singletonList(signature));
|
return signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String signString(String toSign) {
|
public String signString(String toSign) {
|
||||||
|
@ -134,16 +140,6 @@ public class SignRequest implements HttpRequestFilter {
|
||||||
toSign.append(request.getMethod()).append("\n");
|
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) {
|
private void appendCanonicalizedHeaders(HttpRequest request, StringBuilder toSign) {
|
||||||
// TreeSet == Sort the headers alphabetically.
|
// TreeSet == Sort the headers alphabetically.
|
||||||
Set<String> headers = new TreeSet<String>(request.getHeaders().keySet());
|
Set<String> headers = new TreeSet<String>(request.getHeaders().keySet());
|
||||||
|
@ -155,8 +151,8 @@ public class SignRequest implements HttpRequestFilter {
|
||||||
// replacing any
|
// replacing any
|
||||||
// newline characters and extra embedded white spaces in the value.
|
// newline characters and extra embedded white spaces in the value.
|
||||||
for (String value : request.getHeaders().get(header)) {
|
for (String value : request.getHeaders().get(header)) {
|
||||||
value = Utils.replaceAll(value, TWO_SPACE_PATTERN, " ");
|
value = Strings2.replaceAll(value, TWO_SPACE_PATTERN, " ");
|
||||||
value = Utils.replaceAll(value, NEWLINE_PATTERN, "");
|
value = Strings2.replaceAll(value, NEWLINE_PATTERN, "");
|
||||||
toSign.append(value).append(' ');
|
toSign.append(value).append(' ');
|
||||||
}
|
}
|
||||||
toSign.deleteCharAt(toSign.lastIndexOf(" "));
|
toSign.deleteCharAt(toSign.lastIndexOf(" "));
|
||||||
|
@ -171,8 +167,9 @@ public class SignRequest implements HttpRequestFilter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendPayloadMetadata(HttpRequest request, StringBuilder buffer) {
|
private void appendPayloadMetadata(HttpRequest request, StringBuilder buffer) {
|
||||||
buffer.append(utils.valueOrEmpty(request.getPayload() == null ? null : request.getPayload().getContentMetadata().getContentType()))
|
buffer.append(
|
||||||
.append("\n");
|
utils.valueOrEmpty(request.getPayload() == null ? null : request.getPayload().getContentMetadata()
|
||||||
|
.getContentType())).append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
|
|
||||||
package org.jclouds.atmosonline.saas.functions;
|
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 javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.atmosonline.saas.domain.AtmosObject;
|
import org.jclouds.atmosonline.saas.domain.AtmosObject;
|
||||||
|
@ -31,11 +34,14 @@ import com.google.common.base.Function;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class AtmosObjectName implements Function<Object, String> {
|
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) {
|
return checkNotNull(object.getContentMetadata().getName() != null ? object.getContentMetadata().getName()
|
||||||
AtmosObject from = (AtmosObject) in;
|
: object.getSystemMetadata().getObjectName(), "objectName");
|
||||||
return from.getContentMetadata().getName() != null ? from.getContentMetadata().getName()
|
|
||||||
: from.getSystemMetadata().getObjectName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -19,13 +19,15 @@
|
||||||
|
|
||||||
package org.jclouds.atmosonline.saas.functions;
|
package org.jclouds.atmosonline.saas.functions;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.atmosonline.saas.domain.BoundedSet;
|
import org.jclouds.atmosonline.saas.domain.BoundedSet;
|
||||||
import org.jclouds.atmosonline.saas.domain.DirectoryEntry;
|
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.reference.AtmosStorageHeaders;
|
||||||
import org.jclouds.atmosonline.saas.xml.ListDirectoryResponseHandler;
|
import org.jclouds.atmosonline.saas.xml.ListDirectoryResponseHandler;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
|
@ -40,25 +42,24 @@ import com.google.common.base.Function;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class ParseDirectoryListFromContentAndHeaders implements
|
public class ParseDirectoryListFromContentAndHeaders implements Function<HttpResponse, BoundedSet<DirectoryEntry>> {
|
||||||
Function<HttpResponse, BoundedSet<DirectoryEntry>> {
|
|
||||||
|
|
||||||
private final ParseSax.Factory factory;
|
private final ParseSax.Factory factory;
|
||||||
private final Provider<ListDirectoryResponseHandler> listHandlerProvider;
|
private final Provider<ListDirectoryResponseHandler> listHandlerProvider;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ParseDirectoryListFromContentAndHeaders(Factory factory,
|
ParseDirectoryListFromContentAndHeaders(Factory factory, Provider<ListDirectoryResponseHandler> listHandlerProvider) {
|
||||||
Provider<ListDirectoryResponseHandler> orgHandlerProvider) {
|
this.factory = checkNotNull(factory, "factory");
|
||||||
this.factory = factory;
|
this.listHandlerProvider = checkNotNull(listHandlerProvider, "listHandlerProvider");
|
||||||
this.listHandlerProvider = orgHandlerProvider;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* parses the http response headers to create a new {@link BoundedSet} object.
|
* parses the http response headers to create a new {@link BoundedSet} object.
|
||||||
*/
|
*/
|
||||||
public BoundedSet<DirectoryEntry> apply(HttpResponse from) {
|
public BoundedSet<DirectoryEntry> apply(HttpResponse from) {
|
||||||
|
checkNotNull(from, "http response");
|
||||||
String token = from.getFirstHeaderOrNull(AtmosStorageHeaders.TOKEN);
|
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);
|
from.getPayload().getInput()), token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package org.jclouds.atmosonline.saas.functions;
|
package org.jclouds.atmosonline.saas.functions;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static org.jclouds.http.HttpUtils.attemptToParseSizeAndRangeFromHeaders;
|
import static org.jclouds.http.HttpUtils.attemptToParseSizeAndRangeFromHeaders;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -44,11 +45,11 @@ public class ParseObjectFromHeadersAndHttpContent implements Function<HttpRespon
|
||||||
private final AtmosObject.Factory objectProvider;
|
private final AtmosObject.Factory objectProvider;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ParseObjectFromHeadersAndHttpContent(ParseSystemMetadataFromHeaders metadataParser,
|
public ParseObjectFromHeadersAndHttpContent(ParseSystemMetadataFromHeaders systemMetadataParser,
|
||||||
ParseUserMetadataFromHeaders userMetadataParser, AtmosObject.Factory objectProvider) {
|
ParseUserMetadataFromHeaders userMetadataParser, AtmosObject.Factory objectProvider) {
|
||||||
this.systemMetadataParser = metadataParser;
|
this.systemMetadataParser = checkNotNull(systemMetadataParser, "systemMetadataParser");
|
||||||
this.userMetadataParser = userMetadataParser;
|
this.userMetadataParser = checkNotNull(userMetadataParser, "userMetadataParser");
|
||||||
this.objectProvider = objectProvider;
|
this.objectProvider = checkNotNull(objectProvider, "objectProvider");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,8 +61,9 @@ public class ParseObjectFromHeadersAndHttpContent implements Function<HttpRespon
|
||||||
* @throws org.jclouds.http.HttpException
|
* @throws org.jclouds.http.HttpException
|
||||||
*/
|
*/
|
||||||
public AtmosObject apply(HttpResponse from) {
|
public AtmosObject apply(HttpResponse from) {
|
||||||
AtmosObject object = objectProvider.create(systemMetadataParser.apply(from),
|
checkNotNull(from, "http response");
|
||||||
userMetadataParser.apply(from));
|
AtmosObject object = objectProvider.create(systemMetadataParser.apply(from), userMetadataParser.apply(from));
|
||||||
|
object.getContentMetadata().setName(object.getSystemMetadata().getObjectName());
|
||||||
object.getAllHeaders().putAll(from.getHeaders());
|
object.getAllHeaders().putAll(from.getHeaders());
|
||||||
object.setPayload(from.getPayload());
|
object.setPayload(from.getPayload());
|
||||||
object.getContentMetadata().setContentLength(attemptToParseSizeAndRangeFromHeaders(from));
|
object.getContentMetadata().setContentLength(attemptToParseSizeAndRangeFromHeaders(from));
|
||||||
|
|
|
@ -45,10 +45,11 @@ public class ParseSystemMetadataFromHeaders implements Function<HttpResponse, Sy
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ParseSystemMetadataFromHeaders(DateService dateService) {
|
public ParseSystemMetadataFromHeaders(DateService dateService) {
|
||||||
this.dateService = dateService;
|
this.dateService = checkNotNull(dateService, "dateService");
|
||||||
}
|
}
|
||||||
|
|
||||||
public SystemMetadata apply(HttpResponse from) {
|
public SystemMetadata apply(HttpResponse from) {
|
||||||
|
checkNotNull(from, "http response");
|
||||||
String meta = checkNotNull(from.getFirstHeaderOrNull(AtmosStorageHeaders.META), AtmosStorageHeaders.META);
|
String meta = checkNotNull(from.getFirstHeaderOrNull(AtmosStorageHeaders.META), AtmosStorageHeaders.META);
|
||||||
Map<String, String> metaMap = Maps.newHashMap();
|
Map<String, String> metaMap = Maps.newHashMap();
|
||||||
String[] metas = meta.split(", ");
|
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);
|
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;
|
byte[] md5 = metaMap.containsKey("content-md5") ? CryptoStreams.hex(metaMap.get("content-md5")) : null;
|
||||||
return new SystemMetadata(md5, dateService.iso8601SecondsDateParse(checkNotNull(metaMap.get("atime"), "atime")),
|
return new SystemMetadata(md5, dateService.iso8601SecondsDateParse(checkNotNull(metaMap.get("atime"), "atime")),
|
||||||
dateService.iso8601SecondsDateParse(checkNotNull(metaMap.get("ctime"), "ctime")), checkNotNull(metaMap
|
dateService.iso8601SecondsDateParse(checkNotNull(metaMap.get("ctime"), "ctime")), checkNotNull(
|
||||||
.get("gid"), "gid"), dateService.iso8601SecondsDateParse(checkNotNull(metaMap.get("itime"),
|
metaMap.get("gid"), "gid"), dateService.iso8601SecondsDateParse(checkNotNull(metaMap.get("itime"),
|
||||||
"itime")), dateService.iso8601SecondsDateParse(checkNotNull(metaMap.get("mtime"), "mtime")),
|
"itime")), dateService.iso8601SecondsDateParse(checkNotNull(metaMap.get("mtime"), "mtime")),
|
||||||
Integer.parseInt(checkNotNull(metaMap.get("nlink"), "nlink")), checkNotNull(metaMap.get("objectid"),
|
Integer.parseInt(checkNotNull(metaMap.get("nlink"), "nlink")), checkNotNull(metaMap.get("objectid"),
|
||||||
"objectid"), checkNotNull(metaMap.get("objname"), "objname"), checkNotNull(metaMap
|
"objectid"), checkNotNull(metaMap.get("objname"), "objname"), checkNotNull(metaMap.get("policyname"),
|
||||||
.get("policyname"), "policyname"), Long.parseLong(checkNotNull(metaMap.get("size"), "size")),
|
"policyname"), Long.parseLong(checkNotNull(metaMap.get("size"), "size")),
|
||||||
FileType.fromValue(checkNotNull(metaMap.get("type"), "type")), checkNotNull(metaMap.get("uid"), "uid"));
|
FileType.fromValue(checkNotNull(metaMap.get("type"), "type")), checkNotNull(metaMap.get("uid"), "uid"));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -31,54 +31,55 @@ import org.jclouds.atmosonline.saas.reference.AtmosStorageHeaders;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
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.ImmutableSet;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class ParseUserMetadataFromHeaders implements Function<HttpResponse, UserMetadata> {
|
public class ParseUserMetadataFromHeaders implements Function<HttpResponse, UserMetadata> {
|
||||||
private final Set<String> sysKeys = ImmutableSet.of("atime", "ctime", "gid", "itime", "mtime",
|
private static final Set<String> sysKeys = ImmutableSet.of("atime", "ctime", "gid", "itime", "mtime", "nlink",
|
||||||
"nlink", "policyname", "size", "uid");
|
"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) {
|
public UserMetadata apply(HttpResponse from) {
|
||||||
UserMetadata md = new UserMetadata();
|
checkNotNull(from, "http response");
|
||||||
Map<String, String> metaMap = getMetaMap(checkNotNull(from
|
|
||||||
.getFirstHeaderOrNull(AtmosStorageHeaders.META), AtmosStorageHeaders.META));
|
|
||||||
|
|
||||||
Set<String> keys = Sets.difference(metaMap.keySet(), sysKeys);
|
Map<String, String> meta = Maps.filterKeys(
|
||||||
for (String key : keys) {
|
getMetaMap(checkNotNull(from.getFirstHeaderOrNull(AtmosStorageHeaders.META), AtmosStorageHeaders.META)),
|
||||||
md.getMetadata().put(key, metaMap.get(key));
|
filter);
|
||||||
}
|
|
||||||
if (from.getFirstHeaderOrNull(AtmosStorageHeaders.LISTABLE_META) != null)
|
|
||||||
md.getListableMetadata().putAll(
|
|
||||||
getMetaMap(from.getFirstHeaderOrNull(AtmosStorageHeaders.LISTABLE_META)));
|
|
||||||
|
|
||||||
if (from.getFirstHeaderOrNull(AtmosStorageHeaders.TAGS) != null)
|
Map<String, String> listableMeta = (from.getFirstHeaderOrNull(AtmosStorageHeaders.LISTABLE_META) != null) ? getMetaMap(from
|
||||||
md.getTags().addAll(getTags(from.getFirstHeaderOrNull(AtmosStorageHeaders.TAGS)));
|
.getFirstHeaderOrNull(AtmosStorageHeaders.LISTABLE_META)) : ImmutableMap.<String, String> of();
|
||||||
if (from.getFirstHeaderOrNull(AtmosStorageHeaders.LISTABLE_TAGS) != null)
|
|
||||||
md.getTags().addAll(getTags(from.getFirstHeaderOrNull(AtmosStorageHeaders.LISTABLE_TAGS)));
|
Iterable<String> tags = (from.getFirstHeaderOrNull(AtmosStorageHeaders.TAGS) != null) ? Splitter.on(", ").split(
|
||||||
return md;
|
from.getFirstHeaderOrNull(AtmosStorageHeaders.TAGS)) : ImmutableSet.<String> of();
|
||||||
}
|
|
||||||
|
Iterable<String> listableTags = (from.getFirstHeaderOrNull(AtmosStorageHeaders.LISTABLE_TAGS) != null) ? Splitter
|
||||||
private Set<String> getTags(String meta) {
|
.on(", ").split(from.getFirstHeaderOrNull(AtmosStorageHeaders.LISTABLE_TAGS)) : ImmutableSet.<String> of();
|
||||||
Set<String> tags = Sets.newTreeSet();
|
|
||||||
String[] metas = meta.split(", ");
|
return new UserMetadata(meta, listableMeta, tags, listableTags);
|
||||||
for (String entry : metas) {
|
|
||||||
tags.add(entry);
|
|
||||||
}
|
|
||||||
return tags;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: change to guava
|
||||||
private Map<String, String> getMetaMap(String meta) {
|
private Map<String, String> getMetaMap(String meta) {
|
||||||
Map<String, String> metaMap = Maps.newHashMap();
|
Builder<String, String> metaMap = ImmutableMap.<String, String> builder();
|
||||||
String[] metas = meta.split(", ");
|
for (String entry : Splitter.on(", ").split(meta)) {
|
||||||
for (String entry : metas) {
|
|
||||||
String[] entrySplit = entry.split("=");
|
String[] entrySplit = entry.split("=");
|
||||||
metaMap.put(entrySplit[0], entrySplit[1]);
|
metaMap.put(entrySplit[0], entrySplit[1]);
|
||||||
}
|
}
|
||||||
return metaMap;
|
return metaMap.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -19,26 +19,31 @@
|
||||||
|
|
||||||
package org.jclouds.atmosonline.saas.functions;
|
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 java.net.URI;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import org.jclouds.blobstore.KeyAlreadyExistsException;
|
import org.jclouds.blobstore.KeyAlreadyExistsException;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.rest.InvocationContext;
|
import org.jclouds.rest.InvocationContext;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class ReturnEndpointIfAlreadyExists implements Function<Exception, URI>, InvocationContext {
|
public class ReturnEndpointIfAlreadyExists implements Function<Exception, URI>,
|
||||||
|
InvocationContext<ReturnEndpointIfAlreadyExists> {
|
||||||
|
|
||||||
private URI endpoint;
|
private URI endpoint;
|
||||||
|
|
||||||
public URI apply(Exception from) {
|
public URI apply(Exception from) {
|
||||||
if (from instanceof KeyAlreadyExistsException) {
|
if (checkNotNull(from, "exception") instanceof KeyAlreadyExistsException) {
|
||||||
return endpoint;
|
return endpoint;
|
||||||
}
|
}
|
||||||
return URI.class.cast(propagateOrNull(from));
|
return URI.class.cast(propagateOrNull(from));
|
||||||
|
@ -46,7 +51,12 @@ public class ReturnEndpointIfAlreadyExists implements Function<Exception, URI>,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ReturnEndpointIfAlreadyExists setContext(HttpRequest request) {
|
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;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ public class AtmosStorageClientErrorRetryHandler implements HttpRetryHandler {
|
||||||
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
|
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
|
||||||
if (command.getFailureCount() > retryCountLimit)
|
if (command.getFailureCount() > retryCountLimit)
|
||||||
return false;
|
return false;
|
||||||
if (response.getStatusCode() == 404 && command.getRequest().getMethod().equals("DELETE")) {
|
if (response.getStatusCode() == 404 && command.getCurrentRequest().getMethod().equals("DELETE")) {
|
||||||
command.incrementFailureCount();
|
command.incrementFailureCount();
|
||||||
return true;
|
return true;
|
||||||
} else if (response.getStatusCode() == 409 || response.getStatusCode() == 400) {
|
} else if (response.getStatusCode() == 409 || response.getStatusCode() == 400) {
|
||||||
|
|
|
@ -42,7 +42,7 @@ import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.http.HttpResponseException;
|
import org.jclouds.http.HttpResponseException;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rest.AuthorizationException;
|
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.
|
* This will parse and set an appropriate exception on the command object.
|
||||||
|
@ -72,9 +72,9 @@ public class ParseAtmosStorageErrorFromXmlContent implements HttpErrorHandler {
|
||||||
AtmosStorageError error = null;
|
AtmosStorageError error = null;
|
||||||
if (response.getPayload() != null) {
|
if (response.getPayload() != null) {
|
||||||
try {
|
try {
|
||||||
String content = Utils.toStringAndClose(response.getPayload().getInput());
|
String content = Strings2.toStringAndClose(response.getPayload().getInput());
|
||||||
if (content != null && content.indexOf('<') >= 0) {
|
if (content != null && content.indexOf('<') >= 0) {
|
||||||
error = utils.parseAtmosStorageErrorFromContent(command, response, Utils.toInputStream(content));
|
error = utils.parseAtmosStorageErrorFromContent(command, response, Strings2.toInputStream(content));
|
||||||
} else {
|
} else {
|
||||||
exception = content != null ? new HttpResponseException(command, response, content) : exception;
|
exception = content != null ? new HttpResponseException(command, response, content) : exception;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ public class ParseAtmosStorageErrorFromXmlContent implements HttpErrorHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (error != null && error.getCode() == 1016) {
|
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());
|
exception = new KeyAlreadyExistsException(file.getParentFile().getAbsolutePath(), file.getName());
|
||||||
} else {
|
} else {
|
||||||
switch (response.getStatusCode()) {
|
switch (response.getStatusCode()) {
|
||||||
|
@ -91,10 +91,10 @@ public class ParseAtmosStorageErrorFromXmlContent implements HttpErrorHandler {
|
||||||
exception = new AuthorizationException(exception.getMessage(), exception);
|
exception = new AuthorizationException(exception.getMessage(), exception);
|
||||||
break;
|
break;
|
||||||
case 404:
|
case 404:
|
||||||
if (!command.getRequest().getMethod().equals("DELETE")) {
|
if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
|
||||||
String message = error != null ? error.getMessage() : String.format("%s -> %s", command.getRequest()
|
String message = error != null ? error.getMessage() : String.format("%s -> %s", command.getCurrentRequest()
|
||||||
.getRequestLine(), response.getStatusLine());
|
.getRequestLine(), response.getStatusLine());
|
||||||
String path = command.getRequest().getEndpoint().getPath();
|
String path = command.getCurrentRequest().getEndpoint().getPath();
|
||||||
Matcher matcher = DIRECTORY_PATH.matcher(path);
|
Matcher matcher = DIRECTORY_PATH.matcher(path);
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
exception = new ContainerNotFoundException(matcher.group(1), message);
|
exception = new ContainerNotFoundException(matcher.group(1), message);
|
||||||
|
|
|
@ -36,7 +36,7 @@ import org.jclouds.http.HttpCommand;
|
||||||
import org.jclouds.http.HttpException;
|
import org.jclouds.http.HttpException;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.http.functions.ParseSax;
|
import org.jclouds.http.functions.ParseSax;
|
||||||
import org.jclouds.util.Utils;
|
import org.jclouds.util.Assertions;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ public class AtmosStorageUtils {
|
||||||
InputStream content) throws HttpException {
|
InputStream content) throws HttpException {
|
||||||
AtmosStorageError error = (AtmosStorageError) factory.create(errorHandlerProvider.get()).parse(content);
|
AtmosStorageError error = (AtmosStorageError) factory.create(errorHandlerProvider.get()).parse(content);
|
||||||
if (error.getCode() == 1032) {
|
if (error.getCode() == 1032) {
|
||||||
error.setStringSigned(signer.createStringToSign(command.getRequest()));
|
error.setStringSigned(signer.createStringToSign(command.getCurrentRequest()));
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ public class AtmosStorageUtils {
|
||||||
|
|
||||||
public static void deleteAndEnsureGone(final AtmosStorageClient sync, final String path) {
|
public static void deleteAndEnsureGone(final AtmosStorageClient sync, final String path) {
|
||||||
try {
|
try {
|
||||||
if (!Utils.eventuallyTrue(new Supplier<Boolean>() {
|
if (!Assertions.eventuallyTrue(new Supplier<Boolean>() {
|
||||||
public Boolean get() {
|
public Boolean get() {
|
||||||
sync.deletePath(path);
|
sync.deletePath(path);
|
||||||
return !sync.pathExists(path);
|
return !sync.pathExists(path);
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
package org.jclouds.atmosonline.saas.xml;
|
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.DirectoryEntry;
|
||||||
import org.jclouds.atmosonline.saas.domain.FileType;
|
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" />
|
* @see <a href="https://community.emc.com/community/labs/atmos_online" />
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class ListDirectoryResponseHandler extends
|
public class ListDirectoryResponseHandler extends ParseSax.HandlerWithResult<Set<DirectoryEntry>> {
|
||||||
ParseSax.HandlerWithResult<SortedSet<DirectoryEntry>> {
|
|
||||||
|
|
||||||
private SortedSet<DirectoryEntry> entries = Sets.newTreeSet();
|
private Set<DirectoryEntry> entries = Sets.newLinkedHashSet();
|
||||||
private String currentObjectId;
|
private String currentObjectId;
|
||||||
private FileType currentType;
|
private FileType currentType;
|
||||||
private String currentName;
|
private String currentName;
|
||||||
|
|
||||||
private StringBuilder currentText = new StringBuilder();
|
private StringBuilder currentText = new StringBuilder();
|
||||||
|
|
||||||
public SortedSet<DirectoryEntry> getResult() {
|
public Set<DirectoryEntry> getResult() {
|
||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,11 +61,12 @@ import com.google.inject.Module;
|
||||||
import com.google.inject.TypeLiteral;
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests behavior of {@code AtmosStorageClient}
|
* Tests behavior of {@code AtmosStorageAsyncClient}
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @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> {
|
public class AtmosStorageAsyncClientTest extends RestClientTest<AtmosStorageAsyncClient> {
|
||||||
|
|
||||||
private BlobToObject blobToObject;
|
private BlobToObject blobToObject;
|
||||||
|
|
|
@ -40,7 +40,8 @@ import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
|
||||||
import org.jclouds.http.HttpResponseException;
|
import org.jclouds.http.HttpResponseException;
|
||||||
import org.jclouds.io.Payloads;
|
import org.jclouds.io.Payloads;
|
||||||
import org.jclouds.io.payloads.InputStreamPayload;
|
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 org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
@ -53,7 +54,7 @@ import com.google.common.collect.Sets;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live", sequential = true, testName = "emcsaas.AtmosStorageClientLiveTest")
|
@Test(groups = "live", sequential = true)
|
||||||
public class AtmosStorageClientLiveTest extends BaseBlobStoreIntegrationTest {
|
public class AtmosStorageClientLiveTest extends BaseBlobStoreIntegrationTest {
|
||||||
|
|
||||||
public AtmosStorageClient getApi() {
|
public AtmosStorageClient getApi() {
|
||||||
|
@ -187,7 +188,7 @@ public class AtmosStorageClientLiveTest extends BaseBlobStoreIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
Object makeData(String in, boolean stream) {
|
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 {
|
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)
|
private static void verifyHeadObject(AtmosStorageClient connection, String path, String metadataValue)
|
||||||
throws InterruptedException, ExecutionException, TimeoutException, IOException {
|
throws InterruptedException, ExecutionException, TimeoutException, IOException {
|
||||||
AtmosObject getBlob = connection.headFile(path);
|
AtmosObject getBlob = connection.headFile(path);
|
||||||
assertEquals(Utils.toStringAndClose(getBlob.getPayload().getInput()), "");
|
assertEquals(Strings2.toStringAndClose(getBlob.getPayload().getInput()), "");
|
||||||
verifyMetadata(metadataValue, getBlob);
|
verifyMetadata(metadataValue, getBlob);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void verifyObject(AtmosStorageClient connection, String path, String compare, String metadataValue)
|
private static void verifyObject(AtmosStorageClient connection, String path, String compare, String metadataValue)
|
||||||
throws InterruptedException, ExecutionException, TimeoutException, IOException {
|
throws InterruptedException, ExecutionException, TimeoutException, IOException {
|
||||||
AtmosObject getBlob = connection.readFile(path);
|
AtmosObject getBlob = connection.readFile(path);
|
||||||
assertEquals(Utils.toStringAndClose(getBlob.getPayload().getInput()), compare);
|
assertEquals(Strings2.toStringAndClose(getBlob.getPayload().getInput()), compare);
|
||||||
verifyMetadata(metadataValue, getBlob);
|
verifyMetadata(metadataValue, getBlob);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +270,7 @@ public class AtmosStorageClientLiveTest extends BaseBlobStoreIntegrationTest {
|
||||||
assert md.getUserID() != null;
|
assert md.getUserID() != null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Utils.toStringAndClose(URI.create(
|
Strings2.toStringAndClose(URI.create(
|
||||||
"http://accesspoint.emccis.com/rest/objects/" + getBlob.getSystemMetadata().getObjectID()).toURL()
|
"http://accesspoint.emccis.com/rest/objects/" + getBlob.getSystemMetadata().getObjectID()).toURL()
|
||||||
.openStream());
|
.openStream());
|
||||||
assert false : "shouldn't have worked, since it is private";
|
assert false : "shouldn't have worked, since it is private";
|
||||||
|
@ -325,7 +326,7 @@ public class AtmosStorageClientLiveTest extends BaseBlobStoreIntegrationTest {
|
||||||
getApi().deletePath(path);
|
getApi().deletePath(path);
|
||||||
} catch (KeyNotFoundException ex) {
|
} catch (KeyNotFoundException ex) {
|
||||||
}
|
}
|
||||||
assert Utils.eventuallyTrue(new Supplier<Boolean>() {
|
assert Assertions.eventuallyTrue(new Supplier<Boolean>() {
|
||||||
public Boolean get() {
|
public Boolean get() {
|
||||||
return !getApi().pathExists(path);
|
return !getApi().pathExists(path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
package org.jclouds.atmosonline.saas;
|
package org.jclouds.atmosonline.saas;
|
||||||
|
|
||||||
import org.jclouds.blobstore.util.BlobStoreUtils;
|
import org.jclouds.blobstore.util.BlobStoreUtils;
|
||||||
import org.jclouds.util.Utils;
|
import org.jclouds.rest.Providers;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
@ -35,7 +35,7 @@ public class ProvidersInPropertiesTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSupportedProviders() {
|
public void testSupportedProviders() {
|
||||||
Iterable<String> providers = Utils.getSupportedProviders();
|
Iterable<String> providers = Providers.getSupportedProviders();
|
||||||
assert Iterables.contains(providers, "atmosonline") : providers;
|
assert Iterables.contains(providers, "atmosonline") : providers;
|
||||||
assert Iterables.contains(providers, "synaptic") : providers;
|
assert Iterables.contains(providers, "synaptic") : providers;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -21,8 +21,11 @@ package org.jclouds.atmosonline.saas.binders;
|
||||||
|
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
|
import javax.ws.rs.HttpMethod;
|
||||||
|
|
||||||
import org.jclouds.atmosonline.saas.domain.UserMetadata;
|
import org.jclouds.atmosonline.saas.domain.UserMetadata;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
@ -35,59 +38,56 @@ import com.google.inject.Injector;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit", testName = "atmossaas.BindUserMetadataToHeadersTest")
|
@Test(groups = "unit")
|
||||||
public class BindUserMetadataToHeadersTest {
|
public class BindUserMetadataToHeadersTest {
|
||||||
|
Injector injector = Guice.createInjector();
|
||||||
|
BindUserMetadataToHeaders binder = injector.getInstance(BindUserMetadataToHeaders.class);
|
||||||
|
|
||||||
public void testMeta() {
|
public void testMeta() {
|
||||||
Injector injector = Guice.createInjector();
|
|
||||||
BindUserMetadataToHeaders binder = injector
|
|
||||||
.getInstance(BindUserMetadataToHeaders.class);
|
|
||||||
|
|
||||||
UserMetadata metadata = new UserMetadata();
|
UserMetadata metadata = new UserMetadata();
|
||||||
metadata.getMetadata().put("apple","bear");
|
metadata.getMetadata().put("apple", "bear");
|
||||||
metadata.getMetadata().put("sushi","king");
|
metadata.getMetadata().put("sushi", "king");
|
||||||
HttpRequest request = new HttpRequest("GET",URI.create("http://localhost"));
|
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");
|
assertEquals(request.getFirstHeaderOrNull("x-emc-meta"), "apple=bear,sushi=king");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testListableMeta() {
|
public void testListableMeta() {
|
||||||
Injector injector = Guice.createInjector();
|
|
||||||
BindUserMetadataToHeaders binder = injector
|
|
||||||
.getInstance(BindUserMetadataToHeaders.class);
|
|
||||||
|
|
||||||
UserMetadata metadata = new UserMetadata();
|
UserMetadata metadata = new UserMetadata();
|
||||||
metadata.getListableMetadata().put("apple","bear");
|
metadata.getListableMetadata().put("apple", "bear");
|
||||||
metadata.getListableMetadata().put("sushi","king");
|
metadata.getListableMetadata().put("sushi", "king");
|
||||||
HttpRequest request = new HttpRequest("GET",URI.create("http://localhost"));
|
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");
|
assertEquals(request.getFirstHeaderOrNull("x-emc-listable-meta"), "apple=bear,sushi=king");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testTags() {
|
public void testTags() {
|
||||||
Injector injector = Guice.createInjector();
|
|
||||||
BindUserMetadataToHeaders binder = injector
|
|
||||||
.getInstance(BindUserMetadataToHeaders.class);
|
|
||||||
|
|
||||||
UserMetadata tagsdata = new UserMetadata();
|
UserMetadata tagsdata = new UserMetadata();
|
||||||
tagsdata.getTags().add("apple");
|
tagsdata.getTags().add("apple");
|
||||||
tagsdata.getTags().add("sushi");
|
tagsdata.getTags().add("sushi");
|
||||||
HttpRequest request = new HttpRequest("GET",URI.create("http://localhost"));
|
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");
|
assertEquals(request.getFirstHeaderOrNull("x-emc-tags"), "apple,sushi");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testListableTags() {
|
public void testListableTags() {
|
||||||
Injector injector = Guice.createInjector();
|
|
||||||
BindUserMetadataToHeaders binder = injector
|
|
||||||
.getInstance(BindUserMetadataToHeaders.class);
|
|
||||||
|
|
||||||
UserMetadata tagsdata = new UserMetadata();
|
UserMetadata tagsdata = new UserMetadata();
|
||||||
tagsdata.getListableTags().add("apple");
|
tagsdata.getListableTags().add("apple");
|
||||||
tagsdata.getListableTags().add("sushi");
|
tagsdata.getListableTags().add("sushi");
|
||||||
HttpRequest request = new HttpRequest("GET",URI.create("http://localhost"));
|
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");
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,13 @@ import com.google.common.base.Supplier;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
import com.google.inject.TypeLiteral;
|
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> {
|
public class AtmosBlobRequestSignerTest extends RestClientTest<AtmosStorageAsyncClient> {
|
||||||
|
|
||||||
private BlobRequestSigner signer;
|
private BlobRequestSigner signer;
|
||||||
|
|
|
@ -37,7 +37,7 @@ import com.google.inject.Module;
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit", testName = "emcsaas.AtmosBlobStoreModuleTest")
|
@Test(groups = "unit")
|
||||||
public class AtmosBlobStoreModuleTest {
|
public class AtmosBlobStoreModuleTest {
|
||||||
|
|
||||||
Injector createInjector() {
|
Injector createInjector() {
|
||||||
|
|
|
@ -31,7 +31,7 @@ import com.google.inject.Injector;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit", testName = "atmossaas.ObjectToBlobMetadataTest")
|
@Test(groups = "unit")
|
||||||
public class ObjectToBlobMetadataTest {
|
public class ObjectToBlobMetadataTest {
|
||||||
|
|
||||||
public void testFromWhenTypeIsDirectory() {
|
public void testFromWhenTypeIsDirectory() {
|
||||||
|
|
|
@ -24,7 +24,7 @@ import javax.inject.Singleton;
|
||||||
import org.jclouds.atmosonline.saas.domain.BoundedSet;
|
import org.jclouds.atmosonline.saas.domain.BoundedSet;
|
||||||
import org.jclouds.atmosonline.saas.domain.DirectoryEntry;
|
import org.jclouds.atmosonline.saas.domain.DirectoryEntry;
|
||||||
import org.jclouds.atmosonline.saas.domain.FileType;
|
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.StorageMetadata;
|
||||||
import org.jclouds.blobstore.domain.StorageType;
|
import org.jclouds.blobstore.domain.StorageType;
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ public class ResourceMetadataListToDirectoryEntryList
|
||||||
public BoundedSet<DirectoryEntry> apply(
|
public BoundedSet<DirectoryEntry> apply(
|
||||||
org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> from) {
|
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>() {
|
new Function<StorageMetadata, DirectoryEntry>() {
|
||||||
public DirectoryEntry apply(StorageMetadata from) {
|
public DirectoryEntry apply(StorageMetadata from) {
|
||||||
FileType type = (from.getType() == StorageType.FOLDER || from.getType() == StorageType.RELATIVE_PATH) ? FileType.DIRECTORY
|
FileType type = (from.getType() == StorageType.FOLDER || from.getType() == StorageType.RELATIVE_PATH) ? FileType.DIRECTORY
|
||||||
|
|
|
@ -26,7 +26,7 @@ import org.testng.annotations.Test;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = { "live" }, testName = "emcsaas.AtmosBlobSignerLiveTest")
|
@Test(groups = { "live" })
|
||||||
public class AtmosBlobSignerLiveTest extends BaseBlobSignerLiveTest {
|
public class AtmosBlobSignerLiveTest extends BaseBlobSignerLiveTest {
|
||||||
|
|
||||||
}
|
}
|
|
@ -31,7 +31,7 @@ import org.testng.annotations.Test;
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live", testName = "emcsaas.AtmosStorageContainerIntegrationTest")
|
@Test(groups = "live")
|
||||||
public class AtmosStorageContainerIntegrationLiveTest extends BaseContainerIntegrationTest {
|
public class AtmosStorageContainerIntegrationLiveTest extends BaseContainerIntegrationTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -25,7 +25,7 @@ import org.testng.annotations.Test;
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = { "live" }, testName = "emcsaas.AtmosStorageContainerLiveTest")
|
@Test(groups = { "live" })
|
||||||
public class AtmosStorageContainerLiveTest extends BaseContainerLiveTest {
|
public class AtmosStorageContainerLiveTest extends BaseContainerLiveTest {
|
||||||
|
|
||||||
}
|
}
|
|
@ -28,7 +28,7 @@ import org.testng.annotations.Test;
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live", testName = "emcsaas.AtmosStorageInputStreamMapIntegrationTest")
|
@Test(groups = "live")
|
||||||
public class AtmosStorageInputStreamMapIntegrationLiveTest extends BaseInputStreamMapIntegrationTest {
|
public class AtmosStorageInputStreamMapIntegrationLiveTest extends BaseInputStreamMapIntegrationTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -34,7 +34,7 @@ import org.testng.annotations.Test;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = { "integration", "live" }, testName = "emcsaas.AtmosStorageIntegrationTest")
|
@Test(groups = { "integration", "live" })
|
||||||
public class AtmosStorageIntegrationLiveTest extends BaseBlobIntegrationTest {
|
public class AtmosStorageIntegrationLiveTest extends BaseBlobIntegrationTest {
|
||||||
|
|
||||||
@DataProvider(name = "delete")
|
@DataProvider(name = "delete")
|
||||||
|
|
|
@ -28,7 +28,7 @@ import org.testng.annotations.Test;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = { "live" }, testName = "emcsaas.AtmosStorageLiveTest")
|
@Test(groups = { "live" })
|
||||||
public class AtmosStorageLiveTest extends BaseBlobLiveTest {
|
public class AtmosStorageLiveTest extends BaseBlobLiveTest {
|
||||||
protected void checkMD5(String container, String name, byte[] md5) {
|
protected void checkMD5(String container, String name, byte[] md5) {
|
||||||
// atmos does not support content-md5 yet
|
// atmos does not support content-md5 yet
|
||||||
|
|
|
@ -29,7 +29,7 @@ import org.testng.annotations.Test;
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live", testName = "emcsaas.AtmosStorageMapIntegrationTest")
|
@Test(groups = "live")
|
||||||
public class AtmosStorageMapIntegrationLiveTest extends BaseBlobMapIntegrationTest {
|
public class AtmosStorageMapIntegrationLiveTest extends BaseBlobMapIntegrationTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -25,7 +25,7 @@ import org.testng.annotations.Test;
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live", testName = "emcsaas.AtmosStorageServiceIntegrationTest")
|
@Test(groups = "live")
|
||||||
public class AtmosStorageServiceIntegrationLiveTest extends BaseServiceIntegrationTest {
|
public class AtmosStorageServiceIntegrationLiveTest extends BaseServiceIntegrationTest {
|
||||||
|
|
||||||
}
|
}
|
|
@ -36,57 +36,75 @@ import org.jclouds.date.TimeStamp;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.RequiresHttp;
|
import org.jclouds.http.RequiresHttp;
|
||||||
import org.jclouds.logging.config.NullLoggingModule;
|
import org.jclouds.logging.config.NullLoggingModule;
|
||||||
|
import org.jclouds.rest.BaseRestClientTest.MockModule;
|
||||||
import org.jclouds.rest.ConfiguresRestClient;
|
import org.jclouds.rest.ConfiguresRestClient;
|
||||||
import org.jclouds.rest.RestContextFactory;
|
import org.jclouds.rest.RestContextFactory;
|
||||||
import org.jclouds.rest.BaseRestClientTest.MockModule;
|
import org.jclouds.util.Strings2;
|
||||||
import org.jclouds.util.Utils;
|
|
||||||
import org.testng.annotations.BeforeClass;
|
import org.testng.annotations.BeforeClass;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
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.ImmutableSet;
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
|
|
||||||
@Test(groups = "unit", testName = "emcsaas.SignRequestTest")
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit")
|
||||||
public class SignRequestTest {
|
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 static final String KEY = "LJLuryj6zs8ste6Y3jTGQp71xq0=";
|
||||||
|
|
||||||
private SignRequest filter;
|
private SignRequest filter;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testCreateStringToSign() throws IOException {
|
void testCreateStringToSign() throws IOException {
|
||||||
String expects = Utils.toStringAndClose(getClass().getResourceAsStream("/hashstring.txt"));
|
String expects = Strings2.toStringAndClose(getClass().getResourceAsStream("/hashstring.txt"));
|
||||||
HttpRequest request = newRequest();
|
HttpRequest request = newRequest(preconstructedHeaders().build());
|
||||||
String toSign = filter.replaceDateHeader(request).createStringToSign(request);
|
String toSign = filter.createStringToSign(request);
|
||||||
assertEquals(toSign, expects);
|
assertEquals(toSign, expects);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testUid() throws IOException, NoSuchAlgorithmException, InvalidKeyException {
|
void testSignString() throws IOException, NoSuchAlgorithmException, InvalidKeyException {
|
||||||
HttpRequest request = newRequest();
|
HttpRequest request = newRequest(preconstructedHeaders().build());
|
||||||
filter.replaceUIDHeader(request);
|
String toSign = filter.createStringToSign(request);
|
||||||
assertEquals(request.getFirstHeaderOrNull(AtmosStorageHeaders.UID), "user");
|
String signature = filter.signString(toSign);
|
||||||
|
assertEquals(signature, EXPECTED_SIGNATURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testSignString() throws IOException, NoSuchAlgorithmException, InvalidKeyException {
|
void testFilter() throws IOException, NoSuchAlgorithmException, InvalidKeyException {
|
||||||
String expects = "WHJo1MFevMnK4jCthJ974L3YHoo=";
|
HttpRequest request = newRequest(inputHeaders().build());
|
||||||
|
request = filter.filter(request);
|
||||||
|
assertEquals(request.getFirstHeaderOrNull(AtmosStorageHeaders.SIGNATURE), EXPECTED_SIGNATURE);
|
||||||
|
}
|
||||||
|
|
||||||
HttpRequest request = newRequest();
|
@Test
|
||||||
String toSign = filter.replaceDateHeader(request).createStringToSign(request);
|
void testFilterReplacesOldValues() throws IOException, NoSuchAlgorithmException, InvalidKeyException {
|
||||||
String signature = filter.signString(toSign);
|
HttpRequest request = newRequest(inputHeaders().put(AtmosStorageHeaders.SIGNATURE, "foo")
|
||||||
assertEquals(signature, expects);
|
.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
|
@BeforeClass
|
||||||
protected void createFilter() {
|
protected void createFilter() {
|
||||||
Injector injector = new RestContextFactory().createContextBuilder(
|
Injector injector = new RestContextFactory()
|
||||||
"atmosonline",
|
.createContextBuilder(
|
||||||
"user",
|
"atmosonline",
|
||||||
KEY,
|
UID,
|
||||||
ImmutableSet.<Module> of(new MockModule(), new TestAtmosStorageRestClientModule(),
|
KEY,
|
||||||
|
ImmutableSet.<Module> of(new MockModule(), new TestAtmosStorageRestClientModule(),
|
||||||
new NullLoggingModule()), new Properties()).buildInjector();
|
new NullLoggingModule()), new Properties()).buildInjector();
|
||||||
|
|
||||||
filter = injector.getInstance(SignRequest.class);
|
filter = injector.getInstance(SignRequest.class);
|
||||||
|
@ -96,6 +114,7 @@ public class SignRequestTest {
|
||||||
@RequiresHttp
|
@RequiresHttp
|
||||||
@ConfiguresRestClient
|
@ConfiguresRestClient
|
||||||
private static final class TestAtmosStorageRestClientModule extends AtmosStorageRestClientModule {
|
private static final class TestAtmosStorageRestClientModule extends AtmosStorageRestClientModule {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
super.configure();
|
super.configure();
|
||||||
|
@ -103,24 +122,34 @@ public class SignRequestTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
|
protected String provideTimeStamp(@TimeStamp Supplier<String> cache) {
|
||||||
return "Thu, 05 Jun 2008 16:38:19 GMT";
|
return DEFAULT_DATE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpRequest newRequest() {
|
public HttpRequest newRequest(Multimap<String, String> headers) {
|
||||||
HttpRequest request = new HttpRequest("POST", URI.create("http://localhost/rest/objects"));
|
HttpRequest request = new HttpRequest("POST", URI.create("http://localhost/rest/objects"), headers);
|
||||||
request.setPayload("");
|
request.setPayload("");
|
||||||
request.getPayload().getContentMetadata().setContentLength(4286l);
|
request.getPayload().getContentMetadata().setContentLength(4286l);
|
||||||
request.getPayload().getContentMetadata().setContentType(MediaType.APPLICATION_OCTET_STREAM);
|
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;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,44 +25,35 @@ import org.jclouds.atmosonline.saas.domain.FileType;
|
||||||
import org.jclouds.atmosonline.saas.domain.SystemMetadata;
|
import org.jclouds.atmosonline.saas.domain.SystemMetadata;
|
||||||
import org.jclouds.crypto.CryptoStreams;
|
import org.jclouds.crypto.CryptoStreams;
|
||||||
import org.jclouds.date.DateService;
|
import org.jclouds.date.DateService;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||||
import org.jclouds.io.Payloads;
|
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
import com.google.inject.Injector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests behavior of {@code ParseSystemMetadataFromHeaders}
|
* Tests behavior of {@code ParseSystemMetadataFromHeaders}
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit", testName = "atmossaas.ParseSystemMetadataFromHeadersTest")
|
@Test(groups = "unit")
|
||||||
public class ParseSystemMetadataFromHeadersTest {
|
public class ParseSystemMetadataFromHeadersTest {
|
||||||
|
static final DateService dateService = new SimpleDateFormatDateService();
|
||||||
|
static final 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"
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
public void test() {
|
public void test() {
|
||||||
Injector injector = Guice.createInjector();
|
ParseSystemMetadataFromHeaders parser = Guice.createInjector().getInstance(ParseSystemMetadataFromHeaders.class);
|
||||||
ParseSystemMetadataFromHeaders parser = injector.getInstance(ParseSystemMetadataFromHeaders.class);
|
|
||||||
DateService dateService = injector.getInstance(DateService.class);
|
|
||||||
|
|
||||||
HttpResponse response = new HttpResponse(200, "ok", Payloads.newStringPayload(""));
|
SystemMetadata data = parser.apply(ParseObjectFromHeadersAndHttpContentTest.RESPONSE);
|
||||||
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
|
assertEquals(data, EXPECTED);
|
||||||
.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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,7 +30,7 @@ import com.google.common.collect.ImmutableList;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit", testName = "emcsaas.ListOptionsTest")
|
@Test(groups = "unit")
|
||||||
public class ListOptionsTest {
|
public class ListOptionsTest {
|
||||||
|
|
||||||
public void testToken() {
|
public void testToken() {
|
||||||
|
|
|
@ -33,7 +33,8 @@ import org.testng.annotations.Test;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @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 {
|
public class ErrorHandlerTest extends BaseHandlerTest {
|
||||||
|
|
||||||
ParseSax<AtmosStorageError> createParser() {
|
ParseSax<AtmosStorageError> createParser() {
|
||||||
|
|
|
@ -22,7 +22,7 @@ package org.jclouds.atmosonline.saas.xml;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.io.InputStream;
|
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.DirectoryEntry;
|
||||||
import org.jclouds.atmosonline.saas.domain.FileType;
|
import org.jclouds.atmosonline.saas.domain.FileType;
|
||||||
|
@ -37,24 +37,25 @@ import com.google.common.collect.Sets;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @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 {
|
public class ListDirectoryResponseHandlerTest extends BaseHandlerTest {
|
||||||
|
|
||||||
ParseSax<SortedSet<DirectoryEntry>> createParser() {
|
ParseSax<Set<DirectoryEntry>> createParser() {
|
||||||
ParseSax<SortedSet<DirectoryEntry>> parser = (ParseSax<SortedSet<DirectoryEntry>>) factory
|
ParseSax<Set<DirectoryEntry>> parser = (ParseSax<Set<DirectoryEntry>>) factory
|
||||||
.create(injector.getInstance(ListDirectoryResponseHandler.class));
|
.create(injector.getInstance(ListDirectoryResponseHandler.class));
|
||||||
return parser;
|
return parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testApplyInputStreamBase() {
|
public void testApplyInputStreamBase() {
|
||||||
InputStream is = getClass().getResourceAsStream("/list_basic.xml");
|
InputStream is = getClass().getResourceAsStream("/list_basic.xml");
|
||||||
ParseSax<SortedSet<DirectoryEntry>> parser = createParser();
|
ParseSax<Set<DirectoryEntry>> parser = createParser();
|
||||||
SortedSet<DirectoryEntry> expected = Sets.newTreeSet();
|
Set<DirectoryEntry> expected = Sets.newTreeSet();
|
||||||
expected.add(new DirectoryEntry("4980cdb2a411106a04a4538c92a1b204ad92077de6e3",
|
expected.add(new DirectoryEntry("4980cdb2a411106a04a4538c92a1b204ad92077de6e3",
|
||||||
FileType.DIRECTORY, "adriancole-blobstore-2096685753"));
|
FileType.DIRECTORY, "adriancole-blobstore-2096685753"));
|
||||||
expected.add(new DirectoryEntry("4980cdb2a410105404980d99e53a0504ad93939e7dc3",
|
expected.add(new DirectoryEntry("4980cdb2a410105404980d99e53a0504ad93939e7dc3",
|
||||||
FileType.DIRECTORY, "adriancole-blobstore247496608"));
|
FileType.DIRECTORY, "adriancole-blobstore247496608"));
|
||||||
SortedSet<DirectoryEntry> result = parser.parse(is);
|
Set<DirectoryEntry> result = parser.parse(is);
|
||||||
assertEquals(result, expected);
|
assertEquals(result, expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ public class AWSResponseException extends HttpResponseException {
|
||||||
private AWSError error = new AWSError();
|
private AWSError error = new AWSError();
|
||||||
|
|
||||||
public AWSResponseException(HttpCommand command, HttpResponse response, AWSError error) {
|
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);
|
.getStatusCode(), error.toString()), command, response);
|
||||||
this.setError(error);
|
this.setError(error);
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ public class AWSResponseException extends HttpResponseException {
|
||||||
|
|
||||||
public AWSResponseException(HttpCommand command, HttpResponse response, AWSError error,
|
public AWSResponseException(HttpCommand command, HttpResponse response, AWSError error,
|
||||||
Throwable cause) {
|
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);
|
.toString()), command, response, cause);
|
||||||
this.setError(error);
|
this.setError(error);
|
||||||
|
|
||||||
|
|
|
@ -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.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static java.lang.String.format;
|
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.BlockDeviceMapping;
|
||||||
import org.jclouds.aws.ec2.domain.RunningInstance;
|
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.utils.ModifyRequest;
|
||||||
import org.jclouds.rest.Binder;
|
import org.jclouds.rest.Binder;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
|
import com.google.common.collect.ImmutableMultimap.Builder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Oleksiy Yarmula
|
* @author Oleksiy Yarmula
|
||||||
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class BindBlockDeviceMappingToIndexedFormParams implements Binder {
|
public class BindBlockDeviceMappingToIndexedFormParams implements Binder {
|
||||||
|
|
||||||
private final String deviceNamePattern = "BlockDeviceMapping.%d.DeviceName";
|
private static final String deviceNamePattern = "BlockDeviceMapping.%d.DeviceName";
|
||||||
private final String volumeIdPattern = "BlockDeviceMapping.%d.Ebs.VolumeId";
|
private static final String volumeIdPattern = "BlockDeviceMapping.%d.Ebs.VolumeId";
|
||||||
private final String deleteOnTerminationPattern = "BlockDeviceMapping.%d.Ebs.DeleteOnTermination";
|
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,
|
checkArgument(checkNotNull(input, "input") instanceof BlockDeviceMapping,
|
||||||
"this binder is only valid for BlockDeviceMapping");
|
"this binder is only valid for BlockDeviceMapping");
|
||||||
BlockDeviceMapping blockDeviceMapping = (BlockDeviceMapping) input;
|
BlockDeviceMapping blockDeviceMapping = (BlockDeviceMapping) input;
|
||||||
|
|
||||||
|
Builder<String, String> builder = ImmutableMultimap.<String, String> builder();
|
||||||
int amazonOneBasedIndex = 1; // according to docs, counters must start with 1
|
int amazonOneBasedIndex = 1; // according to docs, counters must start with 1
|
||||||
for (String ebsBlockDeviceName : blockDeviceMapping.getEbsBlockDevices().keySet()) {
|
for (String ebsBlockDeviceName : blockDeviceMapping.getEbsBlockDevices().keySet()) {
|
||||||
for (RunningInstance.EbsBlockDevice ebsBlockDevice : blockDeviceMapping
|
for (RunningInstance.EbsBlockDevice ebsBlockDevice : blockDeviceMapping.getEbsBlockDevices().get(
|
||||||
.getEbsBlockDevices().get(ebsBlockDeviceName)) {
|
ebsBlockDeviceName)) {
|
||||||
|
|
||||||
// not null by contract
|
// not null by contract
|
||||||
addFormParamTo(request, format(volumeIdPattern, amazonOneBasedIndex), ebsBlockDevice
|
builder.put(format(volumeIdPattern, amazonOneBasedIndex), ebsBlockDevice.getVolumeId());
|
||||||
.getVolumeId());
|
|
||||||
|
|
||||||
if (ebsBlockDeviceName != null) {
|
if (ebsBlockDeviceName != null) {
|
||||||
addFormParamTo(request, format(deviceNamePattern, amazonOneBasedIndex),
|
builder.put(format(deviceNamePattern, amazonOneBasedIndex), ebsBlockDeviceName);
|
||||||
ebsBlockDeviceName);
|
|
||||||
}
|
}
|
||||||
addFormParamTo(request, format(deleteOnTerminationPattern, amazonOneBasedIndex), String
|
builder.put(format(deleteOnTerminationPattern, amazonOneBasedIndex),
|
||||||
.valueOf(ebsBlockDevice.isDeleteOnTermination()));
|
String.valueOf(ebsBlockDevice.isDeleteOnTermination()));
|
||||||
|
|
||||||
amazonOneBasedIndex++;
|
amazonOneBasedIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ImmutableMultimap<String, String> forms = builder.build();
|
||||||
|
return forms.size() == 0 ? request : ModifyRequest.putFormParams(request, forms);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,9 +33,9 @@ import org.jclouds.rest.Binder;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class BindBundleIdsToIndexedFormParams implements Binder {
|
public class BindBundleIdsToIndexedFormParams implements Binder {
|
||||||
|
@Override
|
||||||
public void bindToRequest(HttpRequest request, Object input) {
|
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||||
indexStringArrayToFormValuesWithPrefix(request, "BundleId", input);
|
return indexStringArrayToFormValuesWithPrefix(request, "BundleId", input);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -32,10 +32,10 @@ import org.jclouds.rest.Binder;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class BindGroupNameToIndexedFormParams implements Binder {
|
public class BindGroupNamesToIndexedFormParams implements Binder {
|
||||||
|
@Override
|
||||||
public void bindToRequest(HttpRequest request, Object input) {
|
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||||
indexStringArrayToFormValuesWithPrefix(request, "GroupName", input);
|
return indexStringArrayToFormValuesWithPrefix(request, "GroupName", input);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -33,9 +33,9 @@ import org.jclouds.rest.Binder;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class BindInstanceIdsToIndexedFormParams implements Binder {
|
public class BindInstanceIdsToIndexedFormParams implements Binder {
|
||||||
|
@Override
|
||||||
public void bindToRequest(HttpRequest request, Object input) {
|
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||||
indexStringArrayToFormValuesWithPrefix(request, "InstanceId", input);
|
return indexStringArrayToFormValuesWithPrefix(request, "InstanceId", input);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -32,10 +32,10 @@ import org.jclouds.rest.Binder;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class BindKeyNameToIndexedFormParams implements Binder {
|
public class BindKeyNamesToIndexedFormParams implements Binder {
|
||||||
|
@Override
|
||||||
public void bindToRequest(HttpRequest request, Object input) {
|
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||||
indexStringArrayToFormValuesWithPrefix(request, "KeyName", input);
|
return indexStringArrayToFormValuesWithPrefix(request, "KeyName", input);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -27,15 +27,15 @@ import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.rest.Binder;
|
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
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class BindProductCodesToIndexedFormParams implements Binder {
|
public class BindProductCodesToIndexedFormParams implements Binder {
|
||||||
|
@Override
|
||||||
public void bindToRequest(HttpRequest request, Object input) {
|
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||||
indexIterableToFormValuesWithPrefix(request, "ProductCode", input);
|
return indexIterableToFormValuesWithPrefix(request, "ProductCode", input);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -35,11 +35,11 @@ import org.jclouds.rest.Binder;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class BindPublicIpsToIndexedFormParams implements Binder {
|
public class BindPublicIpsToIndexedFormParams implements Binder {
|
||||||
|
@Override
|
||||||
public void bindToRequest(HttpRequest request, Object input) {
|
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||||
checkArgument(checkNotNull(input, "input") instanceof String[],
|
checkArgument(checkNotNull(input, "input") instanceof String[], "this binder is only valid for String[] : "
|
||||||
"this binder is only valid for String[] : " + input.getClass());
|
+ input.getClass());
|
||||||
String[] addressStrings = (String[]) input;
|
String[] addressStrings = (String[]) input;
|
||||||
indexStringArrayToFormValuesWithPrefix(request, "PublicIp", addressStrings);
|
return indexStringArrayToFormValuesWithPrefix(request, "PublicIp", addressStrings);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -20,18 +20,19 @@
|
||||||
package org.jclouds.aws.ec2.binders;
|
package org.jclouds.aws.ec2.binders;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static org.jclouds.http.HttpUtils.addFormParamTo;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.aws.filters.FormSigner;
|
import org.jclouds.aws.filters.FormSigner;
|
||||||
import org.jclouds.crypto.Crypto;
|
|
||||||
import org.jclouds.crypto.CryptoStreams;
|
import org.jclouds.crypto.CryptoStreams;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.utils.ModifyRequest;
|
||||||
import org.jclouds.rest.Binder;
|
import org.jclouds.rest.Binder;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
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;
|
private final FormSigner signer;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
BindS3UploadPolicyAndSignature(FormSigner signer, Crypto crypto) {
|
BindS3UploadPolicyAndSignature(FormSigner signer) {
|
||||||
this.signer = 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));
|
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);
|
String signature = signer.sign(encodedJson);
|
||||||
addFormParamTo(request, "Storage.S3.UploadPolicySignature", signature);
|
builder.put("Storage.S3.UploadPolicySignature", signature);
|
||||||
|
return ModifyRequest.putFormParams(request, builder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -37,19 +37,19 @@ import com.google.common.collect.Iterables;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class BindUserGroupsToIndexedFormParams implements Binder {
|
public class BindUserGroupsToIndexedFormParams implements Binder {
|
||||||
|
@Override
|
||||||
public void bindToRequest(HttpRequest request, Object input) {
|
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||||
checkArgument(checkNotNull(input, "input") instanceof Iterable<?>,
|
checkArgument(checkNotNull(input, "input") instanceof Iterable<?>, "this binder is only valid for Iterable<?>: "
|
||||||
"this binder is only valid for Iterable<?>: " + input.getClass());
|
+ input.getClass());
|
||||||
checkValidUserGroup(input);
|
checkValidUserGroup(input);
|
||||||
indexIterableToFormValuesWithPrefix(request, "UserGroup", input);
|
return indexIterableToFormValuesWithPrefix(request, "UserGroup", input);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkValidUserGroup(Object input) {
|
private void checkValidUserGroup(Object input) {
|
||||||
Iterable<?> values = (Iterable<?>) input;
|
Iterable<?> values = (Iterable<?>) input;
|
||||||
long size = Iterables.size(values);
|
long size = Iterables.size(values);
|
||||||
checkArgument(size == 0 || (size == 1 && Iterables.getOnlyElement(values).equals("all")),
|
checkArgument(size == 0 || (size == 1 && Iterables.getOnlyElement(values).equals("all")),
|
||||||
"only supported UserGroup is 'all'");
|
"only supported UserGroup is 'all'");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static org.jclouds.http.HttpUtils.addFormParamTo;
|
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.aws.ec2.domain.UserIdGroupPair;
|
import org.jclouds.aws.ec2.domain.UserIdGroupPair;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.utils.ModifyRequest;
|
||||||
import org.jclouds.rest.Binder;
|
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
|
* Binds the String [] to query parameters named with GroupName.index
|
||||||
*
|
*
|
||||||
|
@ -36,12 +39,15 @@ import org.jclouds.rest.Binder;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class BindUserIdGroupPairToSourceSecurityGroupFormParams implements Binder {
|
public class BindUserIdGroupPairToSourceSecurityGroupFormParams implements Binder {
|
||||||
|
@Override
|
||||||
public void bindToRequest(HttpRequest request, Object input) {
|
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||||
checkArgument(checkNotNull(input, "input") instanceof UserIdGroupPair,
|
checkArgument(checkNotNull(input, "input") instanceof UserIdGroupPair,
|
||||||
"this binder is only valid for UserIdGroupPair!");
|
"this binder is only valid for UserIdGroupPair!");
|
||||||
UserIdGroupPair pair = (UserIdGroupPair) input;
|
UserIdGroupPair pair = (UserIdGroupPair) input;
|
||||||
addFormParamTo(request, "SourceSecurityGroupOwnerId", pair.getUserId());
|
Builder<String, String> builder = ImmutableMultimap.<String, String> builder();
|
||||||
addFormParamTo(request, "SourceSecurityGroupName", pair.getGroupName());
|
builder.put("SourceSecurityGroupOwnerId", pair.getUserId());
|
||||||
|
builder.put("SourceSecurityGroupName", pair.getGroupName());
|
||||||
|
return ModifyRequest.putFormParams(request, builder.build());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -27,14 +27,15 @@ import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.rest.Binder;
|
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
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class BindUserIdsToIndexedFormParams implements Binder {
|
public class BindUserIdsToIndexedFormParams implements Binder {
|
||||||
public void bindToRequest(HttpRequest request, Object input) {
|
@Override
|
||||||
indexIterableToFormValuesWithPrefix(request, "UserId", input);
|
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||||
|
return indexIterableToFormValuesWithPrefix(request, "UserId", input);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -33,9 +33,9 @@ import org.jclouds.rest.Binder;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class BindVolumeIdsToIndexedFormParams implements Binder {
|
public class BindVolumeIdsToIndexedFormParams implements Binder {
|
||||||
|
@Override
|
||||||
public void bindToRequest(HttpRequest request, Object input) {
|
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||||
indexStringArrayToFormValuesWithPrefix(request, "VolumeId", input);
|
return indexStringArrayToFormValuesWithPrefix(request, "VolumeId", input);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -20,11 +20,11 @@
|
||||||
package org.jclouds.aws.ec2.binders;
|
package org.jclouds.aws.ec2.binders;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static org.jclouds.http.HttpUtils.addFormParamTo;
|
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.utils.ModifyRequest;
|
||||||
import org.jclouds.rest.Binder;
|
import org.jclouds.rest.Binder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,11 +34,13 @@ import org.jclouds.rest.Binder;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class IfNotNullBindAvailabilityZoneToFormParam implements Binder {
|
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) {
|
if (input != null) {
|
||||||
checkArgument(input instanceof String, "this binder is only valid for AvailabilityZone!");
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -21,7 +21,6 @@ package org.jclouds.aws.ec2.compute;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
import static org.jclouds.aws.ec2.util.EC2Utils.parseHandle;
|
import static org.jclouds.aws.ec2.util.EC2Utils.parseHandle;
|
||||||
import static org.jclouds.util.Utils.checkNotEmpty;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
@ -62,6 +61,7 @@ import org.jclouds.compute.util.ComputeUtils;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.http.HttpResponseException;
|
import org.jclouds.http.HttpResponseException;
|
||||||
|
import org.jclouds.util.Preconditions2;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
@ -107,7 +107,7 @@ public class EC2ComputeService extends BaseComputeService {
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void deletePlacementGroup(String region, String tag) {
|
void deletePlacementGroup(String region, String tag) {
|
||||||
checkNotEmpty(tag, "tag");
|
Preconditions2.checkNotEmpty(tag, "tag");
|
||||||
String group = String.format("jclouds#%s#%s", tag, region);
|
String group = String.format("jclouds#%s#%s", tag, region);
|
||||||
try {
|
try {
|
||||||
if (ec2Client.getPlacementGroupServices().describePlacementGroupsInRegion(region, group).size() > 0) {
|
if (ec2Client.getPlacementGroupServices().describePlacementGroupsInRegion(region, group).size() > 0) {
|
||||||
|
@ -137,7 +137,7 @@ public class EC2ComputeService extends BaseComputeService {
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void deleteSecurityGroup(String region, String tag) {
|
void deleteSecurityGroup(String region, String tag) {
|
||||||
checkNotEmpty(tag, "tag");
|
Preconditions2.checkNotEmpty(tag, "tag");
|
||||||
String group = String.format("jclouds#%s#%s", tag, region);
|
String group = String.format("jclouds#%s#%s", tag, region);
|
||||||
if (ec2Client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, group).size() > 0) {
|
if (ec2Client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, group).size() > 0) {
|
||||||
logger.debug(">> deleting securityGroup(%s)", group);
|
logger.debug(">> deleting securityGroup(%s)", group);
|
||||||
|
|
|
@ -20,13 +20,12 @@
|
||||||
package org.jclouds.aws.ec2.compute.functions;
|
package org.jclouds.aws.ec2.compute.functions;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static org.jclouds.util.Utils.nullSafeSet;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -49,6 +48,7 @@ import org.jclouds.compute.domain.internal.VolumeImpl;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
import org.jclouds.util.NullSafeCollections;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
@ -93,8 +93,8 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
|
||||||
builder.tag(tag);
|
builder.tag(tag);
|
||||||
builder.credentials(credentialStore.get("node#" + instance.getRegion() + "/" + providerId));
|
builder.credentials(credentialStore.get("node#" + instance.getRegion() + "/" + providerId));
|
||||||
builder.state(instanceToNodeState.get(instance.getInstanceState()));
|
builder.state(instanceToNodeState.get(instance.getInstanceState()));
|
||||||
builder.publicAddresses(nullSafeSet(instance.getIpAddress()));
|
builder.publicAddresses(NullSafeCollections.nullSafeSet(instance.getIpAddress()));
|
||||||
builder.privateAddresses(nullSafeSet(instance.getPrivateIpAddress()));
|
builder.privateAddresses(NullSafeCollections.nullSafeSet(instance.getPrivateIpAddress()));
|
||||||
builder.hardware(parseHardware(instance));
|
builder.hardware(parseHardware(instance));
|
||||||
Location location = getLocationForAvailabilityZoneOrRegion(instance);
|
Location location = getLocationForAvailabilityZoneOrRegion(instance);
|
||||||
builder.location(location);
|
builder.location(location);
|
||||||
|
|
|
@ -31,7 +31,7 @@ import org.jclouds.compute.options.TemplateOptions;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.io.Payload;
|
import org.jclouds.io.Payload;
|
||||||
import org.jclouds.scriptbuilder.domain.Statement;
|
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.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
@ -80,7 +80,7 @@ public class EC2TemplateOptions extends TemplateOptions {
|
||||||
public EC2TemplateOptions securityGroups(Iterable<String> groupIds) {
|
public EC2TemplateOptions securityGroups(Iterable<String> groupIds) {
|
||||||
checkArgument(Iterables.size(groupIds) > 0, "you must specify at least one security group");
|
checkArgument(Iterables.size(groupIds) > 0, "you must specify at least one security group");
|
||||||
for (String groupId : groupIds)
|
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);
|
this.groupIds = ImmutableSet.copyOf(groupIds);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ public class EC2TemplateOptions extends TemplateOptions {
|
||||||
public EC2TemplateOptions keyPair(String keyPair) {
|
public EC2TemplateOptions keyPair(String keyPair) {
|
||||||
checkNotNull(keyPair, "use noKeyPair option to request boot without a keypair");
|
checkNotNull(keyPair, "use noKeyPair option to request boot without a keypair");
|
||||||
checkState(!noKeyPair, "you cannot specify both options keyPair and noKeyPair");
|
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;
|
this.keyPair = keyPair;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ public class EC2TemplateOptions extends TemplateOptions {
|
||||||
public EC2TemplateOptions placementGroup(String placementGroup) {
|
public EC2TemplateOptions placementGroup(String placementGroup) {
|
||||||
checkNotNull(placementGroup, "use noPlacementGroup option to request boot without a keypair");
|
checkNotNull(placementGroup, "use noPlacementGroup option to request boot without a keypair");
|
||||||
checkState(!noPlacementGroup, "you cannot specify both options placementGroup and noPlacementGroup");
|
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;
|
this.placementGroup = placementGroup;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ public class EC2TemplateOptions extends TemplateOptions {
|
||||||
*/
|
*/
|
||||||
public EC2TemplateOptions subnetId(String subnetId) {
|
public EC2TemplateOptions subnetId(String subnetId) {
|
||||||
checkNotNull(subnetId, "subnetId cannot be null");
|
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;
|
this.subnetId = subnetId;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
package org.jclouds.aws.ec2.functions;
|
package org.jclouds.aws.ec2.functions;
|
||||||
|
|
||||||
import static org.jclouds.util.Utils.propagateOrNull;
|
import static org.jclouds.util.Throwables2.propagateOrNull;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
|
|
||||||
import org.jclouds.aws.ec2.EC2AsyncClient;
|
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.domain.KeyPair;
|
||||||
import org.jclouds.aws.ec2.xml.DescribeKeyPairsResponseHandler;
|
import org.jclouds.aws.ec2.xml.DescribeKeyPairsResponseHandler;
|
||||||
import org.jclouds.aws.ec2.xml.KeyPairResponseHandler;
|
import org.jclouds.aws.ec2.xml.KeyPairResponseHandler;
|
||||||
|
@ -79,7 +79,7 @@ public interface KeyPairAsyncClient {
|
||||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||||
ListenableFuture<? extends Set<KeyPair>> describeKeyPairsInRegion(
|
ListenableFuture<? extends Set<KeyPair>> describeKeyPairsInRegion(
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
||||||
@BinderParam(BindKeyNameToIndexedFormParams.class) String... keyPairNames);
|
@BinderParam(BindKeyNamesToIndexedFormParams.class) String... keyPairNames);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see KeyPairClient#deleteKeyPairInRegion
|
* @see KeyPairClient#deleteKeyPairInRegion
|
||||||
|
|
|
@ -30,7 +30,7 @@ import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
|
|
||||||
import org.jclouds.aws.ec2.EC2AsyncClient;
|
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.domain.PlacementGroup;
|
||||||
import org.jclouds.aws.ec2.xml.DescribePlacementGroupsResponseHandler;
|
import org.jclouds.aws.ec2.xml.DescribePlacementGroupsResponseHandler;
|
||||||
import org.jclouds.aws.filters.FormSigner;
|
import org.jclouds.aws.filters.FormSigner;
|
||||||
|
@ -97,6 +97,6 @@ public interface PlacementGroupAsyncClient {
|
||||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||||
ListenableFuture<? extends Set<PlacementGroup>> describePlacementGroupsInRegion(
|
ListenableFuture<? extends Set<PlacementGroup>> describePlacementGroupsInRegion(
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
||||||
@BinderParam(BindGroupNameToIndexedFormParams.class) String... placementGroupIds);
|
@BinderParam(BindGroupNamesToIndexedFormParams.class) String... placementGroupIds);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
|
|
||||||
import org.jclouds.aws.ec2.EC2AsyncClient;
|
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.binders.BindUserIdGroupPairToSourceSecurityGroupFormParams;
|
||||||
import org.jclouds.aws.ec2.domain.IpProtocol;
|
import org.jclouds.aws.ec2.domain.IpProtocol;
|
||||||
import org.jclouds.aws.ec2.domain.SecurityGroup;
|
import org.jclouds.aws.ec2.domain.SecurityGroup;
|
||||||
|
@ -91,7 +91,7 @@ public interface SecurityGroupAsyncClient {
|
||||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||||
ListenableFuture<? extends Set<SecurityGroup>> describeSecurityGroupsInRegion(
|
ListenableFuture<? extends Set<SecurityGroup>> describeSecurityGroupsInRegion(
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
||||||
@BinderParam(BindGroupNameToIndexedFormParams.class) String... securityGroupNames);
|
@BinderParam(BindGroupNamesToIndexedFormParams.class) String... securityGroupNames);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see SecurityGroupClient#authorizeSecurityGroupIngressInRegion(@Nullable Region,
|
* @see SecurityGroupClient#authorizeSecurityGroupIngressInRegion(@Nullable Region,
|
||||||
|
|
|
@ -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.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static org.jclouds.http.HttpUtils.addFormParamTo;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -38,10 +37,13 @@ import org.jclouds.aws.ec2.services.InstanceClient;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.domain.LocationScope;
|
import org.jclouds.domain.LocationScope;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.utils.ModifyRequest;
|
||||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.ImmutableMap;
|
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;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,37 +54,35 @@ public class EC2Utils {
|
||||||
@Singleton
|
@Singleton
|
||||||
public static class GetRegionFromLocation implements Function<Location, String> {
|
public static class GetRegionFromLocation implements Function<Location, String> {
|
||||||
public String apply(Location location) {
|
public String apply(Location location) {
|
||||||
String region = location.getScope() == LocationScope.REGION ? location.getId() : location
|
String region = location.getScope() == LocationScope.REGION ? location.getId() : location.getParent().getId();
|
||||||
.getParent().getId();
|
|
||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String[] getAvailabilityZonesForRegion(String region)
|
|
||||||
{
|
|
||||||
Set<String> availabilityZones = new HashSet<String>();
|
|
||||||
for (String az : AvailabilityZone.zones) {
|
|
||||||
if (az.startsWith(region))
|
|
||||||
availabilityZones.add(az);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (String[])availabilityZones.toArray(new String[availabilityZones.size()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void indexStringArrayToFormValuesWithPrefix(HttpRequest request, String prefix,
|
public static String[] getAvailabilityZonesForRegion(String region) {
|
||||||
Object input) {
|
Set<String> availabilityZones = new HashSet<String>();
|
||||||
checkArgument(checkNotNull(input, "input") instanceof String[],
|
for (String az : AvailabilityZone.zones) {
|
||||||
"this binder is only valid for String[] : " + input.getClass());
|
if (az.startsWith(region))
|
||||||
String[] values = (String[]) input;
|
availabilityZones.add(az);
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
addFormParamTo(request, prefix + "." + (i + 1), checkNotNull(values[i], prefix
|
|
||||||
.toLowerCase()
|
|
||||||
+ "s[" + i + "]"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (String[]) availabilityZones.toArray(new String[availabilityZones.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Iterable<RunningInstance> getAllRunningInstancesInRegion(InstanceClient client,
|
public static <R extends HttpRequest> R indexStringArrayToFormValuesWithPrefix(R request, String prefix, Object input) {
|
||||||
String region, String id) {
|
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++) {
|
||||||
|
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) {
|
||||||
return Iterables.concat(client.describeInstancesInRegion(region, id));
|
return Iterables.concat(client.describeInstancesInRegion(region, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,17 +92,17 @@ public class EC2Utils {
|
||||||
return parts;
|
return parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void indexIterableToFormValuesWithPrefix(HttpRequest request, String prefix,
|
public static <R extends HttpRequest> R indexIterableToFormValuesWithPrefix(R request, String prefix, Object input) {
|
||||||
Object input) {
|
checkArgument(checkNotNull(input, "input") instanceof Iterable<?>, "this binder is only valid for Iterable<?>: "
|
||||||
checkArgument(checkNotNull(input, "input") instanceof Iterable<?>,
|
+ input.getClass());
|
||||||
"this binder is only valid for Iterable<?>: " + input.getClass());
|
|
||||||
Iterable<?> values = (Iterable<?>) input;
|
Iterable<?> values = (Iterable<?>) input;
|
||||||
|
Builder<String, String> builder = ImmutableMultimap.<String, String> builder();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (Object o : values) {
|
for (Object o : values) {
|
||||||
addFormParamTo(request, prefix + "." + (i++ + 1), checkNotNull(o.toString(), prefix
|
builder.put(prefix + "." + (i++ + 1), checkNotNull(o.toString(), prefix.toLowerCase() + "s[" + i + "]"));
|
||||||
.toLowerCase()
|
|
||||||
+ "s[" + i + "]"));
|
|
||||||
}
|
}
|
||||||
|
ImmutableMultimap<String, String> forms = builder.build();
|
||||||
|
return forms.size() == 0 ? request : ModifyRequest.putFormParams(request, forms);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String findRegionInArgsOrNull(GeneratedHttpRequest<?> gRequest) {
|
public static String findRegionInArgsOrNull(GeneratedHttpRequest<?> gRequest) {
|
||||||
|
@ -118,8 +118,8 @@ public class EC2Utils {
|
||||||
|
|
||||||
public static boolean isRegion(String regionName) {
|
public static boolean isRegion(String regionName) {
|
||||||
return Region.EU_WEST_1.equals(regionName) || Region.US_WEST_1.equals(regionName)
|
return Region.EU_WEST_1.equals(regionName) || Region.US_WEST_1.equals(regionName)
|
||||||
|| Region.US_EAST_1.equals(regionName) || Region.US_STANDARD.equals(regionName)
|
|| Region.US_EAST_1.equals(regionName) || Region.US_STANDARD.equals(regionName)
|
||||||
|| Region.AP_SOUTHEAST_1.equals(regionName);
|
|| Region.AP_SOUTHEAST_1.equals(regionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String findAvailabilityZoneInArgsOrNull(GeneratedHttpRequest<?> gRequest) {
|
public static String findAvailabilityZoneInArgsOrNull(GeneratedHttpRequest<?> gRequest) {
|
||||||
|
@ -133,29 +133,28 @@ public class EC2Utils {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void indexStringArrayToFormValuesWithStringFormat(HttpRequest request,
|
public static <R extends HttpRequest> R indexStringArrayToFormValuesWithStringFormat(R request, String format,
|
||||||
String format, Object input) {
|
Object input) {
|
||||||
checkArgument(checkNotNull(input, "input") instanceof String[],
|
checkArgument(checkNotNull(input, "input") instanceof String[], "this binder is only valid for String[] : "
|
||||||
"this binder is only valid for String[] : " + input.getClass());
|
+ input.getClass());
|
||||||
String[] values = (String[]) input;
|
String[] values = (String[]) input;
|
||||||
|
Builder<String, String> builder = ImmutableMultimap.<String, String> builder();
|
||||||
for (int i = 0; i < values.length; i++) {
|
for (int i = 0; i < values.length; i++) {
|
||||||
addFormParamTo(request, String.format(format, (i + 1)), checkNotNull(values[i], format
|
builder.put(String.format(format, (i + 1)), checkNotNull(values[i], format.toLowerCase() + "s[" + i + "]"));
|
||||||
.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
|
private static final Pattern ELB_PATTERN = Pattern.compile("([^.]+)-[^.]+\\.([^.]+)\\.elb\\.amazonaws\\.com");
|
||||||
.compile("([^.]+)-[^.]+\\.([^.]+)\\.elb\\.amazonaws\\.com");
|
|
||||||
|
|
||||||
public static Map<String, String> getLoadBalancerNameAndRegionFromDnsName(String dnsName) {
|
public static Map<String, String> getLoadBalancerNameAndRegionFromDnsName(String dnsName) {
|
||||||
Matcher matcher = ELB_PATTERN.matcher(checkNotNull(dnsName, "dnsName"));
|
Matcher matcher = ELB_PATTERN.matcher(checkNotNull(dnsName, "dnsName"));
|
||||||
checkArgument(matcher.find(), "dnsName syntax is " + ELB_PATTERN + " didn't match: "
|
checkArgument(matcher.find(), "dnsName syntax is " + ELB_PATTERN + " didn't match: " + dnsName);
|
||||||
+ dnsName);
|
|
||||||
String loadBalancerName = matcher.group(1);
|
String loadBalancerName = matcher.group(1);
|
||||||
String regionName = matcher.group(2);
|
String regionName = matcher.group(2);
|
||||||
checkArgument((isRegion(regionName)), String.format(
|
checkArgument((isRegion(regionName)),
|
||||||
"Region (%s) parsed from (%s) is not a valid region", regionName, dnsName));
|
String.format("Region (%s) parsed from (%s) is not a valid region", regionName, dnsName));
|
||||||
return ImmutableMap.<String, String> of(regionName, loadBalancerName);
|
return ImmutableMap.<String, String> of(regionName, loadBalancerName);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -33,9 +33,9 @@ import org.jclouds.rest.Binder;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class BindAvailabilityZonesToIndexedFormParams implements Binder {
|
public class BindAvailabilityZonesToIndexedFormParams implements Binder {
|
||||||
|
@Override
|
||||||
public void bindToRequest(HttpRequest request, Object input) {
|
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||||
indexStringArrayToFormValuesWithStringFormat(request, "AvailabilityZones.member.%s", input);
|
return indexStringArrayToFormValuesWithStringFormat(request, "AvailabilityZones.member.%s", input);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -33,9 +33,9 @@ import org.jclouds.rest.Binder;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class BindELBInstanceIdsToIndexedFormParams implements Binder {
|
public class BindELBInstanceIdsToIndexedFormParams implements Binder {
|
||||||
|
@Override
|
||||||
public void bindToRequest(HttpRequest request, Object input) {
|
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||||
indexStringArrayToFormValuesWithStringFormat(request, "Instances.member.%s.InstanceId", input);
|
return indexStringArrayToFormValuesWithStringFormat(request, "Instances.member.%s.InstanceId", input);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -34,7 +34,6 @@ import org.jclouds.date.DateService;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.functions.ParseSax;
|
import org.jclouds.http.functions.ParseSax;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
|
||||||
import org.xml.sax.Attributes;
|
import org.xml.sax.Attributes;
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
|
@ -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.SIGNATURE_VERSION;
|
||||||
import static org.jclouds.aws.ec2.reference.EC2Parameters.TIMESTAMP;
|
import static org.jclouds.aws.ec2.reference.EC2Parameters.TIMESTAMP;
|
||||||
import static org.jclouds.aws.ec2.reference.EC2Parameters.VERSION;
|
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.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
@ -52,10 +50,11 @@ import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpRequestFilter;
|
import org.jclouds.http.HttpRequestFilter;
|
||||||
import org.jclouds.http.HttpUtils;
|
import org.jclouds.http.HttpUtils;
|
||||||
import org.jclouds.http.internal.SignatureWire;
|
import org.jclouds.http.internal.SignatureWire;
|
||||||
|
import org.jclouds.http.utils.ModifyRequest;
|
||||||
import org.jclouds.io.InputSuppliers;
|
import org.jclouds.io.InputSuppliers;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rest.RequestSigner;
|
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.annotations.VisibleForTesting;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
@ -73,7 +72,7 @@ import com.google.common.collect.Multimap;
|
||||||
public class FormSigner implements HttpRequestFilter, RequestSigner {
|
public class FormSigner implements HttpRequestFilter, RequestSigner {
|
||||||
|
|
||||||
public static String[] mandatoryParametersForSignature = new String[] { ACTION, SIGNATURE_METHOD, SIGNATURE_VERSION,
|
public static String[] mandatoryParametersForSignature = new String[] { ACTION, SIGNATURE_METHOD, SIGNATURE_VERSION,
|
||||||
VERSION };
|
VERSION };
|
||||||
private final SignatureWire signatureWire;
|
private final SignatureWire signatureWire;
|
||||||
private final String accessKey;
|
private final String accessKey;
|
||||||
private final String secretKey;
|
private final String secretKey;
|
||||||
|
@ -87,8 +86,8 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public FormSigner(SignatureWire signatureWire, @Named(Constants.PROPERTY_IDENTITY) String accessKey,
|
public FormSigner(SignatureWire signatureWire, @Named(Constants.PROPERTY_IDENTITY) String accessKey,
|
||||||
@Named(Constants.PROPERTY_CREDENTIAL) String secretKey, @TimeStamp Provider<String> dateService,
|
@Named(Constants.PROPERTY_CREDENTIAL) String secretKey, @TimeStamp Provider<String> dateService,
|
||||||
Crypto crypto, HttpUtils utils) {
|
Crypto crypto, HttpUtils utils) {
|
||||||
this.signatureWire = signatureWire;
|
this.signatureWire = signatureWire;
|
||||||
this.accessKey = accessKey;
|
this.accessKey = accessKey;
|
||||||
this.secretKey = secretKey;
|
this.secretKey = secretKey;
|
||||||
|
@ -97,16 +96,18 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
|
||||||
this.utils = utils;
|
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");
|
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);
|
addSigningParams(decodedParams);
|
||||||
validateParams(decodedParams);
|
validateParams(decodedParams);
|
||||||
String stringToSign = createStringToSign(request, decodedParams);
|
String stringToSign = createStringToSign(request, decodedParams);
|
||||||
String signature = sign(stringToSign);
|
String signature = sign(stringToSign);
|
||||||
addSignature(decodedParams, signature);
|
addSignature(decodedParams, signature);
|
||||||
setPayload(request, decodedParams);
|
request = setPayload(request, decodedParams);
|
||||||
utils.logRequest(signatureLog, request, "<<");
|
utils.logRequest(signatureLog, request, "<<");
|
||||||
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] sortForSigning(String queryLine) {
|
String[] sortForSigning(String queryLine) {
|
||||||
|
@ -124,8 +125,8 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
|
||||||
return parts;
|
return parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPayload(HttpRequest request, Multimap<String, String> decodedParams) {
|
HttpRequest setPayload(HttpRequest request, Multimap<String, String> decodedParams) {
|
||||||
request.setPayload(makeQueryLine(decodedParams, new Comparator<Map.Entry<String, String>>() {
|
request.setPayload(ModifyRequest.makeQueryLine(decodedParams, new Comparator<Map.Entry<String, String>>() {
|
||||||
public int compare(Entry<String, String> o1, Entry<String, String> o2) {
|
public int compare(Entry<String, String> o1, Entry<String, String> o2) {
|
||||||
if (o1.getKey().startsWith("Action") || o2.getKey().startsWith("AWSAccessKeyId"))
|
if (o1.getKey().startsWith("Action") || o2.getKey().startsWith("AWSAccessKeyId"))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -135,6 +136,7 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
request.getPayload().getContentMetadata().setContentType("application/x-www-form-urlencoded");
|
request.getPayload().getContentMetadata().setContentType("application/x-www-form-urlencoded");
|
||||||
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
@ -153,10 +155,10 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
|
||||||
public String sign(String stringToSign) {
|
public String sign(String stringToSign) {
|
||||||
String signature;
|
String signature;
|
||||||
try {
|
try {
|
||||||
signature = CryptoStreams.base64(CryptoStreams.mac(InputSuppliers.of(stringToSign), crypto
|
signature = CryptoStreams.base64(CryptoStreams.mac(InputSuppliers.of(stringToSign),
|
||||||
.hmacSHA256(secretKey.getBytes())));
|
crypto.hmacSHA256(secretKey.getBytes())));
|
||||||
if (signatureWire.enabled())
|
if (signatureWire.enabled())
|
||||||
signatureWire.input(Utils.toInputStream(signature));
|
signatureWire.input(Strings2.toInputStream(signature));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new HttpException("error signing request", e);
|
throw new HttpException("error signing request", e);
|
||||||
}
|
}
|
||||||
|
@ -182,7 +184,7 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
String buildCanonicalizedString(Multimap<String, String> decodedParams) {
|
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) {
|
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
|
||||||
if (o1.getKey().startsWith("AWSAccessKeyId"))
|
if (o1.getKey().startsWith("AWSAccessKeyId"))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -201,7 +203,7 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String createStringToSign(HttpRequest input) {
|
public String createStringToSign(HttpRequest input) {
|
||||||
return createStringToSign(input, parseQueryToMap(input.getPayload().getRawContent().toString()));
|
return createStringToSign(input, ModifyRequest.parseQueryToMap(input.getPayload().getRawContent().toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ public class AWSClientErrorRetryHandler implements HttpRetryHandler {
|
||||||
// Content can be null in the case of HEAD requests
|
// Content can be null in the case of HEAD requests
|
||||||
if (response.getPayload() != null) {
|
if (response.getPayload() != null) {
|
||||||
closeClientButKeepContentStream(response);
|
closeClientButKeepContentStream(response);
|
||||||
AWSError error = utils.parseAWSErrorFromContent(command.getRequest(), response);
|
AWSError error = utils.parseAWSErrorFromContent(command.getCurrentRequest(), response);
|
||||||
if (error != null
|
if (error != null
|
||||||
&& ("RequestTimeout".equals(error.getCode())
|
&& ("RequestTimeout".equals(error.getCode())
|
||||||
|| "OperationAborted".equals(error.getCode()) || "SignatureDoesNotMatch"
|
|| "OperationAborted".equals(error.getCode()) || "SignatureDoesNotMatch"
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
|
|
||||||
package org.jclouds.aws.handlers;
|
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 static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -48,7 +46,7 @@ public class AWSRedirectionRetryHandler extends RedirectionRetryHandler {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AWSRedirectionRetryHandler(Provider<UriBuilder> uriBuilderProvider,
|
public AWSRedirectionRetryHandler(Provider<UriBuilder> uriBuilderProvider,
|
||||||
BackoffLimitedRetryHandler backoffHandler, AWSUtils utils) {
|
BackoffLimitedRetryHandler backoffHandler, AWSUtils utils) {
|
||||||
super(uriBuilderProvider, backoffHandler);
|
super(uriBuilderProvider, backoffHandler);
|
||||||
this.utils = utils;
|
this.utils = utils;
|
||||||
}
|
}
|
||||||
|
@ -56,24 +54,24 @@ public class AWSRedirectionRetryHandler extends RedirectionRetryHandler {
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
|
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
|
||||||
if (response.getFirstHeaderOrNull(HttpHeaders.LOCATION) == null
|
if (response.getFirstHeaderOrNull(HttpHeaders.LOCATION) == null
|
||||||
&& (response.getStatusCode() == 301 || response.getStatusCode() == 307)) {
|
&& (response.getStatusCode() == 301 || response.getStatusCode() == 307)) {
|
||||||
if (command.getRequest().getMethod() == HttpMethod.HEAD) {
|
if (command.getCurrentRequest().getMethod() == HttpMethod.HEAD) {
|
||||||
changeToGETRequest(command.getRequest());
|
command.setCurrentRequest(command.getCurrentRequest().toBuilder().method("GET").build());
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
command.incrementRedirectCount();
|
command.incrementRedirectCount();
|
||||||
closeClientButKeepContentStream(response);
|
closeClientButKeepContentStream(response);
|
||||||
AWSError error = utils.parseAWSErrorFromContent(command.getRequest(), response);
|
AWSError error = utils.parseAWSErrorFromContent(command.getCurrentRequest(), response);
|
||||||
String host = error.getDetails().get("Endpoint");
|
String host = error.getDetails().get("Endpoint");
|
||||||
if (host != null) {
|
if (host != null) {
|
||||||
if (host.equals(command.getRequest().getEndpoint().getHost())) {
|
if (host.equals(command.getCurrentRequest().getEndpoint().getHost())) {
|
||||||
// must be an amazon error related to
|
// must be an amazon error related to
|
||||||
// http://developer.amazonwebservices.com/connect/thread.jspa?messageID=72287𑩟
|
// http://developer.amazonwebservices.com/connect/thread.jspa?messageID=72287𑩟
|
||||||
return backoffHandler.shouldRetryRequest(command, response);
|
return backoffHandler.shouldRetryRequest(command, response);
|
||||||
} else {
|
} else {
|
||||||
changeSchemeHostAndPortTo(command.getRequest(), command.getRequest()
|
UriBuilder builder = uriBuilderProvider.get().uri(command.getCurrentRequest().getEndpoint());
|
||||||
.getEndpoint().getScheme(), host, command.getRequest().getEndpoint()
|
builder.host(host);
|
||||||
.getPort(), uriBuilderProvider.get());
|
command.setCurrentRequest(command.getCurrentRequest().toBuilder().endpoint(builder.build()).build());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -27,7 +27,6 @@ import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.aws.AWSResponseException;
|
|
||||||
import org.jclouds.aws.domain.AWSError;
|
import org.jclouds.aws.domain.AWSError;
|
||||||
import org.jclouds.aws.util.AWSUtils;
|
import org.jclouds.aws.util.AWSUtils;
|
||||||
import org.jclouds.blobstore.ContainerNotFoundException;
|
import org.jclouds.blobstore.ContainerNotFoundException;
|
||||||
|
@ -40,7 +39,7 @@ import org.jclouds.http.HttpResponseException;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rest.AuthorizationException;
|
import org.jclouds.rest.AuthorizationException;
|
||||||
import org.jclouds.rest.ResourceNotFoundException;
|
import org.jclouds.rest.ResourceNotFoundException;
|
||||||
import org.jclouds.util.Utils;
|
import org.jclouds.util.Strings2;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
|
||||||
|
@ -65,7 +64,7 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleError(HttpCommand command, HttpResponse response) {
|
public void handleError(HttpCommand command, HttpResponse response) {
|
||||||
HttpRequest request = command.getRequest();
|
HttpRequest request = command.getCurrentRequest();
|
||||||
Exception exception = new HttpResponseException(command, response);
|
Exception exception = new HttpResponseException(command, response);
|
||||||
try {
|
try {
|
||||||
AWSError error = null;
|
AWSError error = null;
|
||||||
|
@ -80,7 +79,7 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
message = Utils.toStringAndClose(response.getPayload().getInput());
|
message = Strings2.toStringAndClose(response.getPayload().getInput());
|
||||||
exception = new HttpResponseException(command, response, message);
|
exception = new HttpResponseException(command, response, message);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
}
|
}
|
||||||
|
@ -109,7 +108,7 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
|
||||||
exception = new AuthorizationException(exception.getMessage(), exception);
|
exception = new AuthorizationException(exception.getMessage(), exception);
|
||||||
break;
|
break;
|
||||||
case 404:
|
case 404:
|
||||||
if (!command.getRequest().getMethod().equals("DELETE")) {
|
if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
|
||||||
String container = request.getEndpoint().getHost();
|
String container = request.getEndpoint().getHost();
|
||||||
String key = request.getEndpoint().getPath();
|
String key = request.getEndpoint().getPath();
|
||||||
if (key == null || key.equals("/"))
|
if (key == null || key.equals("/"))
|
||||||
|
|
|
@ -39,7 +39,7 @@ import org.jclouds.aws.s3.binders.BindAsHostPrefixIfConfigured;
|
||||||
import org.jclouds.aws.s3.binders.BindBucketLoggingToXmlPayload;
|
import org.jclouds.aws.s3.binders.BindBucketLoggingToXmlPayload;
|
||||||
import org.jclouds.aws.s3.binders.BindNoBucketLoggingToXmlPayload;
|
import org.jclouds.aws.s3.binders.BindNoBucketLoggingToXmlPayload;
|
||||||
import org.jclouds.aws.s3.binders.BindPayerToXmlPayload;
|
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.AccessControlList;
|
||||||
import org.jclouds.aws.s3.domain.BucketLogging;
|
import org.jclouds.aws.s3.domain.BucketLogging;
|
||||||
import org.jclouds.aws.s3.domain.BucketMetadata;
|
import org.jclouds.aws.s3.domain.BucketMetadata;
|
||||||
|
@ -162,7 +162,7 @@ public interface S3AsyncClient {
|
||||||
@ResponseParser(ParseETagHeader.class)
|
@ResponseParser(ParseETagHeader.class)
|
||||||
ListenableFuture<String> putObject(
|
ListenableFuture<String> putObject(
|
||||||
@Bucket @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators( { BucketNameValidator.class }) String bucketName,
|
@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);
|
PutObjectOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -44,8 +44,8 @@ import com.jamesmurty.utils.XMLBuilder;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class BindACLToXMLPayload implements Binder {
|
public class BindACLToXMLPayload implements Binder {
|
||||||
|
@Override
|
||||||
public void bindToRequest(HttpRequest request, Object payload) {
|
public <R extends HttpRequest> R bindToRequest(R request, Object payload) {
|
||||||
AccessControlList from = (AccessControlList) payload;
|
AccessControlList from = (AccessControlList) payload;
|
||||||
Properties outputProperties = new Properties();
|
Properties outputProperties = new Properties();
|
||||||
outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes");
|
outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes");
|
||||||
|
@ -57,12 +57,13 @@ public class BindACLToXMLPayload implements Binder {
|
||||||
Throwables.propagateIfPossible(e);
|
Throwables.propagateIfPossible(e);
|
||||||
throw new RuntimeException("error transforming acl: " + from, e);
|
throw new RuntimeException("error transforming acl: " + from, e);
|
||||||
}
|
}
|
||||||
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected XMLBuilder generateBuilder(AccessControlList acl) throws ParserConfigurationException,
|
protected XMLBuilder generateBuilder(AccessControlList acl) throws ParserConfigurationException,
|
||||||
FactoryConfigurationError {
|
FactoryConfigurationError {
|
||||||
XMLBuilder rootBuilder = XMLBuilder.create("AccessControlPolicy").attr("xmlns",
|
XMLBuilder rootBuilder = XMLBuilder.create("AccessControlPolicy").attr("xmlns",
|
||||||
S3Constants.S3_REST_API_XML_NAMESPACE);
|
S3Constants.S3_REST_API_XML_NAMESPACE);
|
||||||
if (acl.getOwner() != null) {
|
if (acl.getOwner() != null) {
|
||||||
XMLBuilder ownerBuilder = rootBuilder.elem("Owner");
|
XMLBuilder ownerBuilder = rootBuilder.elem("Owner");
|
||||||
ownerBuilder.elem("ID").text(acl.getOwner().getId()).up();
|
ownerBuilder.elem("ID").text(acl.getOwner().getId()).up();
|
||||||
|
@ -74,21 +75,19 @@ public class BindACLToXMLPayload implements Binder {
|
||||||
for (Grant grant : acl.getGrants()) {
|
for (Grant grant : acl.getGrants()) {
|
||||||
XMLBuilder grantBuilder = grantsBuilder.elem("Grant");
|
XMLBuilder grantBuilder = grantsBuilder.elem("Grant");
|
||||||
XMLBuilder granteeBuilder = grantBuilder.elem("Grantee").attr("xmlns:xsi",
|
XMLBuilder granteeBuilder = grantBuilder.elem("Grantee").attr("xmlns:xsi",
|
||||||
"http://www.w3.org/2001/XMLSchema-instance");
|
"http://www.w3.org/2001/XMLSchema-instance");
|
||||||
|
|
||||||
if (grant.getGrantee() instanceof GroupGrantee) {
|
if (grant.getGrantee() instanceof GroupGrantee) {
|
||||||
granteeBuilder.attr("xsi:type", "Group").elem("URI").text(
|
granteeBuilder.attr("xsi:type", "Group").elem("URI").text(grant.getGrantee().getIdentifier());
|
||||||
grant.getGrantee().getIdentifier());
|
|
||||||
} else if (grant.getGrantee() instanceof CanonicalUserGrantee) {
|
} else if (grant.getGrantee() instanceof CanonicalUserGrantee) {
|
||||||
CanonicalUserGrantee grantee = (CanonicalUserGrantee) grant.getGrantee();
|
CanonicalUserGrantee grantee = (CanonicalUserGrantee) grant.getGrantee();
|
||||||
granteeBuilder.attr("xsi:type", "CanonicalUser").elem("ID").text(
|
granteeBuilder.attr("xsi:type", "CanonicalUser").elem("ID").text(grantee.getIdentifier()).up();
|
||||||
grantee.getIdentifier()).up();
|
|
||||||
if (grantee.getDisplayName() != null) {
|
if (grantee.getDisplayName() != null) {
|
||||||
granteeBuilder.elem("DisplayName").text(grantee.getDisplayName());
|
granteeBuilder.elem("DisplayName").text(grantee.getDisplayName());
|
||||||
}
|
}
|
||||||
} else if (grant.getGrantee() instanceof EmailAddressGrantee) {
|
} else if (grant.getGrantee() instanceof EmailAddressGrantee) {
|
||||||
granteeBuilder.attr("xsi:type", "AmazonCustomerByEmail").elem("EmailAddress").text(
|
granteeBuilder.attr("xsi:type", "AmazonCustomerByEmail").elem("EmailAddress")
|
||||||
grant.getGrantee().getIdentifier());
|
.text(grant.getGrantee().getIdentifier());
|
||||||
}
|
}
|
||||||
grantBuilder.elem("Permission").text(grant.getPermission().toString());
|
grantBuilder.elem("Permission").text(grant.getPermission().toString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_SERVICE_PATH;
|
||||||
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_VIRTUAL_HOST_BUCKETS;
|
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.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
@ -32,11 +31,12 @@ import javax.ws.rs.core.UriBuilder;
|
||||||
|
|
||||||
import org.jclouds.aws.s3.S3AsyncClient;
|
import org.jclouds.aws.s3.S3AsyncClient;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.utils.ModifyRequest;
|
||||||
import org.jclouds.rest.Binder;
|
import org.jclouds.rest.Binder;
|
||||||
import org.jclouds.rest.annotations.SkipEncoding;
|
import org.jclouds.rest.annotations.SkipEncoding;
|
||||||
import org.jclouds.rest.binders.BindAsHostPrefix;
|
import org.jclouds.rest.binders.BindAsHostPrefix;
|
||||||
|
import org.jclouds.util.Strings2;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,30 +53,31 @@ public class BindAsHostPrefixIfConfigured implements Binder {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public BindAsHostPrefixIfConfigured(BindAsHostPrefix bindAsHostPrefix,
|
public BindAsHostPrefixIfConfigured(BindAsHostPrefix bindAsHostPrefix,
|
||||||
@Named(PROPERTY_S3_VIRTUAL_HOST_BUCKETS) boolean isVhostStyle,
|
@Named(PROPERTY_S3_VIRTUAL_HOST_BUCKETS) boolean isVhostStyle,
|
||||||
@Named(PROPERTY_S3_SERVICE_PATH) String servicePath,
|
@Named(PROPERTY_S3_SERVICE_PATH) String servicePath, Provider<UriBuilder> uriBuilderProvider) {
|
||||||
Provider<UriBuilder> uriBuilderProvider) {
|
|
||||||
this.bindAsHostPrefix = bindAsHostPrefix;
|
this.bindAsHostPrefix = bindAsHostPrefix;
|
||||||
this.isVhostStyle = isVhostStyle;
|
this.isVhostStyle = isVhostStyle;
|
||||||
this.servicePath = servicePath;
|
this.servicePath = servicePath;
|
||||||
this.uriBuilderProvider = uriBuilderProvider;
|
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) {
|
if (isVhostStyle) {
|
||||||
bindAsHostPrefix.bindToRequest(request, payload);
|
request = bindAsHostPrefix.bindToRequest(request, payload);
|
||||||
request.getHeaders().replaceValues(HttpHeaders.HOST,
|
return ModifyRequest.replaceHeader(request, HttpHeaders.HOST, request.getEndpoint().getHost());
|
||||||
ImmutableSet.of(request.getEndpoint().getHost()));
|
|
||||||
} else {
|
} else {
|
||||||
UriBuilder builder = uriBuilderProvider.get().uri(request.getEndpoint());
|
UriBuilder builder = uriBuilderProvider.get().uri(request.getEndpoint());
|
||||||
StringBuilder path = new StringBuilder(urlEncode(request.getEndpoint().getPath(),
|
StringBuilder path = new StringBuilder(Strings2.urlEncode(request.getEndpoint().getPath(), S3AsyncClient.class
|
||||||
S3AsyncClient.class.getAnnotation(SkipEncoding.class).value()));
|
.getAnnotation(SkipEncoding.class).value()));
|
||||||
int indexToInsert = path.indexOf(servicePath);
|
int indexToInsert = path.indexOf(servicePath);
|
||||||
indexToInsert = indexToInsert == -1 ? 0 : indexToInsert;
|
indexToInsert = indexToInsert == -1 ? 0 : indexToInsert;
|
||||||
indexToInsert += servicePath.length();
|
indexToInsert += servicePath.length();
|
||||||
path.insert(indexToInsert, "/" + payload.toString());
|
path.insert(indexToInsert, "/" + payload.toString());
|
||||||
builder.replacePath(path.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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,8 +44,8 @@ import com.jamesmurty.utils.XMLBuilder;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class BindBucketLoggingToXmlPayload implements Binder {
|
public class BindBucketLoggingToXmlPayload implements Binder {
|
||||||
|
@Override
|
||||||
public void bindToRequest(HttpRequest request, Object payload) {
|
public <R extends HttpRequest> R bindToRequest(R request, Object payload) {
|
||||||
BucketLogging from = (BucketLogging) payload;
|
BucketLogging from = (BucketLogging) payload;
|
||||||
Properties outputProperties = new Properties();
|
Properties outputProperties = new Properties();
|
||||||
outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes");
|
outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes");
|
||||||
|
@ -57,33 +57,32 @@ public class BindBucketLoggingToXmlPayload implements Binder {
|
||||||
Throwables.propagateIfPossible(e);
|
Throwables.propagateIfPossible(e);
|
||||||
throw new RuntimeException("error transforming bucketLogging: " + from, e);
|
throw new RuntimeException("error transforming bucketLogging: " + from, e);
|
||||||
}
|
}
|
||||||
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected XMLBuilder generateBuilder(BucketLogging bucketLogging)
|
protected XMLBuilder generateBuilder(BucketLogging bucketLogging) throws ParserConfigurationException,
|
||||||
throws ParserConfigurationException, FactoryConfigurationError {
|
FactoryConfigurationError {
|
||||||
XMLBuilder rootBuilder = XMLBuilder.create("BucketLoggingStatus").attr("xmlns",
|
XMLBuilder rootBuilder = XMLBuilder.create("BucketLoggingStatus")
|
||||||
S3Constants.S3_REST_API_XML_NAMESPACE).e("LoggingEnabled");
|
.attr("xmlns", S3Constants.S3_REST_API_XML_NAMESPACE).e("LoggingEnabled");
|
||||||
rootBuilder.e("TargetBucket").t(bucketLogging.getTargetBucket());
|
rootBuilder.e("TargetBucket").t(bucketLogging.getTargetBucket());
|
||||||
rootBuilder.e("TargetPrefix").t(bucketLogging.getTargetPrefix());
|
rootBuilder.e("TargetPrefix").t(bucketLogging.getTargetPrefix());
|
||||||
XMLBuilder grantsBuilder = rootBuilder.elem("TargetGrants");
|
XMLBuilder grantsBuilder = rootBuilder.elem("TargetGrants");
|
||||||
for (Grant grant : bucketLogging.getTargetGrants()) {
|
for (Grant grant : bucketLogging.getTargetGrants()) {
|
||||||
XMLBuilder grantBuilder = grantsBuilder.elem("Grant");
|
XMLBuilder grantBuilder = grantsBuilder.elem("Grant");
|
||||||
XMLBuilder granteeBuilder = grantBuilder.elem("Grantee").attr("xmlns:xsi",
|
XMLBuilder granteeBuilder = grantBuilder.elem("Grantee").attr("xmlns:xsi",
|
||||||
"http://www.w3.org/2001/XMLSchema-instance");
|
"http://www.w3.org/2001/XMLSchema-instance");
|
||||||
|
|
||||||
if (grant.getGrantee() instanceof GroupGrantee) {
|
if (grant.getGrantee() instanceof GroupGrantee) {
|
||||||
granteeBuilder.attr("xsi:type", "Group").elem("URI").text(
|
granteeBuilder.attr("xsi:type", "Group").elem("URI").text(grant.getGrantee().getIdentifier());
|
||||||
grant.getGrantee().getIdentifier());
|
|
||||||
} else if (grant.getGrantee() instanceof CanonicalUserGrantee) {
|
} else if (grant.getGrantee() instanceof CanonicalUserGrantee) {
|
||||||
CanonicalUserGrantee grantee = (CanonicalUserGrantee) grant.getGrantee();
|
CanonicalUserGrantee grantee = (CanonicalUserGrantee) grant.getGrantee();
|
||||||
granteeBuilder.attr("xsi:type", "CanonicalUser").elem("ID").text(
|
granteeBuilder.attr("xsi:type", "CanonicalUser").elem("ID").text(grantee.getIdentifier()).up();
|
||||||
grantee.getIdentifier()).up();
|
|
||||||
if (grantee.getDisplayName() != null) {
|
if (grantee.getDisplayName() != null) {
|
||||||
granteeBuilder.elem("DisplayName").text(grantee.getDisplayName());
|
granteeBuilder.elem("DisplayName").text(grantee.getDisplayName());
|
||||||
}
|
}
|
||||||
} else if (grant.getGrantee() instanceof EmailAddressGrantee) {
|
} else if (grant.getGrantee() instanceof EmailAddressGrantee) {
|
||||||
granteeBuilder.attr("xsi:type", "AmazonCustomerByEmail").elem("EmailAddress").text(
|
granteeBuilder.attr("xsi:type", "AmazonCustomerByEmail").elem("EmailAddress")
|
||||||
grant.getGrantee().getIdentifier());
|
.text(grant.getGrantee().getIdentifier());
|
||||||
}
|
}
|
||||||
grantBuilder.elem("Permission").text(grant.getPermission().toString());
|
grantBuilder.elem("Permission").text(grant.getPermission().toString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,10 +38,12 @@ public class BindNoBucketLoggingToXmlPayload implements Binder {
|
||||||
this.bindAsHostPrefixIfConfigured = bindAsHostPrefixIfConfigured;
|
this.bindAsHostPrefixIfConfigured = bindAsHostPrefixIfConfigured;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bindToRequest(HttpRequest request, Object payload) {
|
@Override
|
||||||
bindAsHostPrefixIfConfigured.bindToRequest(request, payload);
|
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/\"/>";
|
String stringPayload = "<BucketLoggingStatus xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"/>";
|
||||||
request.setPayload(stringPayload);
|
request.setPayload(stringPayload);
|
||||||
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,15 +36,15 @@ import org.jclouds.rest.Binder;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class BindPayerToXmlPayload implements Binder {
|
public class BindPayerToXmlPayload implements Binder {
|
||||||
|
@Override
|
||||||
public void bindToRequest(HttpRequest request, Object toBind) {
|
public <R extends HttpRequest> R bindToRequest(R request, Object toBind) {
|
||||||
checkArgument(checkNotNull(toBind, "toBind") instanceof Payer,
|
checkArgument(checkNotNull(toBind, "toBind") instanceof Payer, "this binder is only valid for Payer!");
|
||||||
"this binder is only valid for Payer!");
|
|
||||||
String text = String
|
String text = String
|
||||||
.format(
|
.format(
|
||||||
"<RequestPaymentConfiguration xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Payer>%s</Payer></RequestPaymentConfiguration>",
|
"<RequestPaymentConfiguration xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Payer>%s</Payer></RequestPaymentConfiguration>",
|
||||||
((Payer) toBind).value());
|
((Payer) toBind).value());
|
||||||
request.setPayload(text);
|
request.setPayload(text);
|
||||||
request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_XML);
|
request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_XML);
|
||||||
|
return request;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
package org.jclouds.aws.s3.binders;
|
package org.jclouds.aws.s3.binders;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
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.aws.s3.domain.S3Object;
|
||||||
import org.jclouds.blobstore.binders.BindUserMetadataToHeadersWithPrefix;
|
import org.jclouds.blobstore.binders.BindUserMetadataToHeadersWithPrefix;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.utils.ModifyRequest;
|
||||||
import org.jclouds.rest.Binder;
|
import org.jclouds.rest.Binder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,27 +38,33 @@ import org.jclouds.rest.Binder;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class BindS3ObjectToPayload implements Binder {
|
public class BindS3ObjectMetadataToRequest implements Binder {
|
||||||
private final BindUserMetadataToHeadersWithPrefix blobBinder;
|
private final BindUserMetadataToHeadersWithPrefix blobBinder;
|
||||||
private final ObjectToBlob object2Blob;
|
private final ObjectToBlob object2Blob;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public BindS3ObjectToPayload(ObjectToBlob object2Blob, BindUserMetadataToHeadersWithPrefix blobBinder) {
|
public BindS3ObjectMetadataToRequest(ObjectToBlob object2Blob, BindUserMetadataToHeadersWithPrefix blobBinder) {
|
||||||
this.blobBinder = blobBinder;
|
this.blobBinder = checkNotNull(blobBinder, "blobBinder");
|
||||||
this.object2Blob = object2Blob;
|
this.object2Blob = checkNotNull(object2Blob, "object2Blob");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bindToRequest(HttpRequest request, Object payload) {
|
@Override
|
||||||
S3Object s3Object = (S3Object) payload;
|
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,
|
checkArgument(s3Object.getPayload().getContentMetadata().getContentLength() != null,
|
||||||
"contentLength must be set, streaming not supported");
|
"contentLength must be set, streaming not supported");
|
||||||
checkArgument(s3Object.getPayload().getContentMetadata().getContentLength() <= 5l * 1024 * 1024 * 1024,
|
checkArgument(s3Object.getPayload().getContentMetadata().getContentLength() <= 5l * 1024 * 1024 * 1024,
|
||||||
"maximum size for put object is 5GB");
|
"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) {
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -52,7 +52,7 @@ import org.jclouds.blobstore.util.BlobUtils;
|
||||||
import org.jclouds.collect.Memoized;
|
import org.jclouds.collect.Memoized;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.http.options.GetOptions;
|
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.Function;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
@ -160,7 +160,7 @@ public class S3BlobStore extends BaseBlobStore {
|
||||||
*/
|
*/
|
||||||
public void clearAndDeleteContainer(final String container) {
|
public void clearAndDeleteContainer(final String container) {
|
||||||
try {
|
try {
|
||||||
if (!Utils.eventuallyTrue(new Supplier<Boolean>() {
|
if (!Assertions.eventuallyTrue(new Supplier<Boolean>() {
|
||||||
public Boolean get() {
|
public Boolean get() {
|
||||||
clearContainer(container);
|
clearContainer(container);
|
||||||
return sync.deleteBucketIfEmpty(container);
|
return sync.deleteBucketIfEmpty(container);
|
||||||
|
|
|
@ -32,10 +32,10 @@ import com.google.inject.TypeLiteral;
|
||||||
*/
|
*/
|
||||||
public class ScaleUpCloudBlobStoreContextModule extends S3BlobStoreContextModule {
|
public class ScaleUpCloudBlobStoreContextModule extends S3BlobStoreContextModule {
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
@Override
|
@Override
|
||||||
protected void bindBucketLocationStrategy() {
|
protected void bindBucketLocationStrategy() {
|
||||||
bind(new TypeLiteral<Function<BucketMetadata, Location>>() {
|
bind(new TypeLiteral<Function<BucketMetadata, Location>>() {
|
||||||
}).toInstance((Function)Functions.constant(null));
|
}).toInstance((Function) Functions.constant(null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@ import static org.jclouds.util.Patterns.NEWLINE_PATTERN;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
@ -52,16 +51,20 @@ import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpRequestFilter;
|
import org.jclouds.http.HttpRequestFilter;
|
||||||
import org.jclouds.http.HttpUtils;
|
import org.jclouds.http.HttpUtils;
|
||||||
import org.jclouds.http.internal.SignatureWire;
|
import org.jclouds.http.internal.SignatureWire;
|
||||||
|
import org.jclouds.http.utils.ModifyRequest;
|
||||||
import org.jclouds.io.InputSuppliers;
|
import org.jclouds.io.InputSuppliers;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rest.RequestSigner;
|
import org.jclouds.rest.RequestSigner;
|
||||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
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.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Predicate;
|
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.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Multimaps;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signs the S3 request.
|
* Signs the S3 request.
|
||||||
|
@ -75,7 +78,7 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
|
||||||
private final String[] firstHeadersToSign = new String[] { HttpHeaders.DATE };
|
private final String[] firstHeadersToSign = new String[] { HttpHeaders.DATE };
|
||||||
|
|
||||||
public static Set<String> SPECIAL_QUERIES = ImmutableSet.of("acl", "torrent", "logging", "location",
|
public static Set<String> SPECIAL_QUERIES = ImmutableSet.of("acl", "torrent", "logging", "location",
|
||||||
"requestPayment");
|
"requestPayment");
|
||||||
private final SignatureWire signatureWire;
|
private final SignatureWire signatureWire;
|
||||||
private final String accessKey;
|
private final String accessKey;
|
||||||
private final String secretKey;
|
private final String secretKey;
|
||||||
|
@ -94,10 +97,10 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public RequestAuthorizeSignature(SignatureWire signatureWire, @Named(PROPERTY_AUTH_TAG) String authTag,
|
public RequestAuthorizeSignature(SignatureWire signatureWire, @Named(PROPERTY_AUTH_TAG) String authTag,
|
||||||
@Named(PROPERTY_S3_VIRTUAL_HOST_BUCKETS) boolean isVhostStyle,
|
@Named(PROPERTY_S3_VIRTUAL_HOST_BUCKETS) boolean isVhostStyle,
|
||||||
@Named(PROPERTY_S3_SERVICE_PATH) String servicePath, @Named(PROPERTY_HEADER_TAG) String headerTag,
|
@Named(PROPERTY_S3_SERVICE_PATH) String servicePath, @Named(PROPERTY_HEADER_TAG) String headerTag,
|
||||||
@Named(PROPERTY_IDENTITY) String accessKey, @Named(PROPERTY_CREDENTIAL) String secretKey,
|
@Named(PROPERTY_IDENTITY) String accessKey, @Named(PROPERTY_CREDENTIAL) String secretKey,
|
||||||
@TimeStamp Provider<String> timeStampProvider, Crypto crypto, HttpUtils utils) {
|
@TimeStamp Provider<String> timeStampProvider, Crypto crypto, HttpUtils utils) {
|
||||||
this.isVhostStyle = isVhostStyle;
|
this.isVhostStyle = isVhostStyle;
|
||||||
this.servicePath = servicePath;
|
this.servicePath = servicePath;
|
||||||
this.headerTag = headerTag;
|
this.headerTag = headerTag;
|
||||||
|
@ -110,11 +113,26 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
|
||||||
this.utils = utils;
|
this.utils = utils;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void filter(HttpRequest request) throws HttpException {
|
public HttpRequest filter(HttpRequest request) throws HttpException {
|
||||||
replaceDateHeader(request);
|
request = replaceDateHeader(request);
|
||||||
String toSign = createStringToSign(request);
|
String signature = calculateSignature(createStringToSign(request));
|
||||||
calculateAndReplaceAuthHeader(request, toSign);
|
request = replaceAuthorizationHeader(request, signature);
|
||||||
utils.logRequest(signatureLog, request, "<<");
|
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) {
|
public String createStringToSign(HttpRequest request) {
|
||||||
|
@ -133,19 +151,18 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void calculateAndReplaceAuthHeader(HttpRequest request, String toSign) throws HttpException {
|
String calculateSignature(String toSign) throws HttpException {
|
||||||
String signature = sign(toSign);
|
String signature = sign(toSign);
|
||||||
if (signatureWire.enabled())
|
if (signatureWire.enabled())
|
||||||
signatureWire.input(Utils.toInputStream(signature));
|
signatureWire.input(Strings2.toInputStream(signature));
|
||||||
request.getHeaders().replaceValues(HttpHeaders.AUTHORIZATION,
|
return signature;
|
||||||
Collections.singletonList(authTag + " " + accessKey + ":" + signature));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String sign(String toSign) {
|
public String sign(String toSign) {
|
||||||
String signature;
|
String signature;
|
||||||
try {
|
try {
|
||||||
signature = CryptoStreams.base64(CryptoStreams.mac(InputSuppliers.of(toSign), crypto.hmacSHA1(secretKey
|
signature = CryptoStreams.base64(CryptoStreams.mac(InputSuppliers.of(toSign),
|
||||||
.getBytes())));
|
crypto.hmacSHA1(secretKey.getBytes())));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new HttpException("error signing request", e);
|
throw new HttpException("error signing request", e);
|
||||||
}
|
}
|
||||||
|
@ -156,17 +173,13 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
|
||||||
toSign.append(request.getMethod()).append("\n");
|
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) {
|
void appendAmzHeaders(HttpRequest request, StringBuilder toSign) {
|
||||||
Set<String> headers = new TreeSet<String>(request.getHeaders().keySet());
|
Set<String> headers = new TreeSet<String>(request.getHeaders().keySet());
|
||||||
for (String header : headers) {
|
for (String header : headers) {
|
||||||
if (header.startsWith("x-" + headerTag + "-")) {
|
if (header.startsWith("x-" + headerTag + "-")) {
|
||||||
toSign.append(header.toLowerCase()).append(":");
|
toSign.append(header.toLowerCase()).append(":");
|
||||||
for (String value : request.getHeaders().get(header)) {
|
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.deleteCharAt(toSign.lastIndexOf(","));
|
||||||
toSign.append("\n");
|
toSign.append("\n");
|
||||||
|
@ -176,11 +189,11 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
|
||||||
|
|
||||||
void appendPayloadMetadata(HttpRequest request, StringBuilder buffer) {
|
void appendPayloadMetadata(HttpRequest request, StringBuilder buffer) {
|
||||||
buffer.append(
|
buffer.append(
|
||||||
utils.valueOrEmpty(request.getPayload() == null ? null : request.getPayload().getContentMetadata()
|
utils.valueOrEmpty(request.getPayload() == null ? null : request.getPayload().getContentMetadata()
|
||||||
.getContentMD5())).append("\n");
|
.getContentMD5())).append("\n");
|
||||||
buffer.append(
|
buffer.append(
|
||||||
utils.valueOrEmpty(request.getPayload() == null ? null : request.getPayload().getContentMetadata()
|
utils.valueOrEmpty(request.getPayload() == null ? null : request.getPayload().getContentMetadata()
|
||||||
.getContentType())).append("\n");
|
.getContentType())).append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void appendHttpHeaders(HttpRequest request, StringBuilder toSign) {
|
void appendHttpHeaders(HttpRequest request, StringBuilder toSign) {
|
||||||
|
@ -197,12 +210,12 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
|
||||||
|
|
||||||
for (int i = 0; i < request.getJavaMethod().getParameterAnnotations().length; i++) {
|
for (int i = 0; i < request.getJavaMethod().getParameterAnnotations().length; i++) {
|
||||||
if (Iterables.any(Arrays.asList(request.getJavaMethod().getParameterAnnotations()[i]),
|
if (Iterables.any(Arrays.asList(request.getJavaMethod().getParameterAnnotations()[i]),
|
||||||
new Predicate<Annotation>() {
|
new Predicate<Annotation>() {
|
||||||
public boolean apply(Annotation input) {
|
public boolean apply(Annotation input) {
|
||||||
return input.annotationType().equals(Bucket.class);
|
return input.annotationType().equals(Bucket.class);
|
||||||
}
|
}
|
||||||
})) {
|
})) {
|
||||||
bucketName = (String) request.getArgs()[i];
|
bucketName = (String) request.getArgs().get(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,20 +55,20 @@ public class BindRegionToXmlPayload extends BindToStringPayload {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
BindRegionToXmlPayload(@Named(PROPERTY_DEFAULT_REGIONS) String defaultRegions,
|
BindRegionToXmlPayload(@Named(PROPERTY_DEFAULT_REGIONS) String defaultRegions,
|
||||||
@Named(PROPERTY_REGIONS) String regions) {
|
@Named(PROPERTY_REGIONS) String regions) {
|
||||||
this.defaultRegions = Splitter.on(',').split(defaultRegions);
|
this.defaultRegions = Splitter.on(',').split(defaultRegions);
|
||||||
this.regions = Splitter.on(',').split(regions);
|
this.regions = Splitter.on(',').split(regions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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;
|
input = input == null ? Iterables.get(defaultRegions, 0) : input;
|
||||||
checkArgument(input instanceof String, "this binder is only valid for Region!");
|
checkArgument(input instanceof String, "this binder is only valid for Region!");
|
||||||
String constraint = (String) input;
|
String constraint = (String) input;
|
||||||
String value = null;
|
String value = null;
|
||||||
if (Iterables.contains(defaultRegions, constraint)) {
|
if (Iterables.contains(defaultRegions, constraint)) {
|
||||||
// nothing to bind as this is default.
|
// nothing to bind as this is default.
|
||||||
return;
|
return request;
|
||||||
} else if (Iterables.contains(regions, constraint)) {
|
} else if (Iterables.contains(regions, constraint)) {
|
||||||
value = constraint;
|
value = constraint;
|
||||||
} else {
|
} else {
|
||||||
|
@ -79,10 +79,12 @@ public class BindRegionToXmlPayload extends BindToStringPayload {
|
||||||
value = constraint;
|
value = constraint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String payload = String.format(
|
String payload = String
|
||||||
"<CreateBucketConfiguration><LocationConstraint>%s</LocationConstraint></CreateBucketConfiguration>",
|
.format(
|
||||||
value);
|
"<CreateBucketConfiguration><LocationConstraint>%s</LocationConstraint></CreateBucketConfiguration>",
|
||||||
super.bindToRequest(request, payload);
|
value);
|
||||||
|
request = super.bindToRequest(request, payload);
|
||||||
request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_XML);
|
request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_XML);
|
||||||
|
return request;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,14 +35,15 @@ import com.google.common.base.Function;
|
||||||
* @see ParseMetadataFromHeaders
|
* @see ParseMetadataFromHeaders
|
||||||
* @author Adrian Cole
|
* @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 ParseObjectMetadataFromHeaders metadataParser;
|
||||||
private final S3Object.Factory objectProvider;
|
private final S3Object.Factory objectProvider;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ParseObjectFromHeadersAndHttpContent(ParseObjectMetadataFromHeaders metadataParser,
|
public ParseObjectFromHeadersAndHttpContent(ParseObjectMetadataFromHeaders metadataParser,
|
||||||
S3Object.Factory objectProvider) {
|
S3Object.Factory objectProvider) {
|
||||||
this.metadataParser = metadataParser;
|
this.metadataParser = metadataParser;
|
||||||
this.objectProvider = objectProvider;
|
this.objectProvider = objectProvider;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,14 +44,15 @@ import com.google.common.base.Function;
|
||||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTObjectGET.html" />
|
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTObjectGET.html" />
|
||||||
* @author Adrian Cole
|
* @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 ParseSystemAndUserMetadataFromHeaders blobMetadataParser;
|
||||||
private final BlobToObjectMetadata blobToObjectMetadata;
|
private final BlobToObjectMetadata blobToObjectMetadata;
|
||||||
private final String userMdPrefix;
|
private final String userMdPrefix;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ParseObjectMetadataFromHeaders(ParseSystemAndUserMetadataFromHeaders blobMetadataParser,
|
public ParseObjectMetadataFromHeaders(ParseSystemAndUserMetadataFromHeaders blobMetadataParser,
|
||||||
BlobToObjectMetadata blobToObjectMetadata, @Named(PROPERTY_USER_METADATA_PREFIX) String userMdPrefix) {
|
BlobToObjectMetadata blobToObjectMetadata, @Named(PROPERTY_USER_METADATA_PREFIX) String userMdPrefix) {
|
||||||
this.blobMetadataParser = blobMetadataParser;
|
this.blobMetadataParser = blobMetadataParser;
|
||||||
this.blobToObjectMetadata = blobToObjectMetadata;
|
this.blobToObjectMetadata = blobToObjectMetadata;
|
||||||
this.userMdPrefix = userMdPrefix;
|
this.userMdPrefix = userMdPrefix;
|
||||||
|
|
|
@ -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.filter;
|
||||||
import static com.google.common.collect.Iterables.get;
|
import static com.google.common.collect.Iterables.get;
|
||||||
import static com.google.common.collect.Iterables.size;
|
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;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
|
@ -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.get;
|
||||||
import static com.google.common.collect.Iterables.size;
|
import static com.google.common.collect.Iterables.size;
|
||||||
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
|
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;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ import org.jclouds.aws.s3.domain.internal.ListBucketResponseImpl;
|
||||||
import org.jclouds.crypto.CryptoStreams;
|
import org.jclouds.crypto.CryptoStreams;
|
||||||
import org.jclouds.date.DateService;
|
import org.jclouds.date.DateService;
|
||||||
import org.jclouds.http.functions.ParseSax;
|
import org.jclouds.http.functions.ParseSax;
|
||||||
import org.jclouds.util.Utils;
|
import org.jclouds.util.Strings2;
|
||||||
import org.xml.sax.Attributes;
|
import org.xml.sax.Attributes;
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
@ -101,7 +101,7 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult<ListBucketResp
|
||||||
currentLastModified = dateParser.iso8601DateParse(currentText.toString().trim());
|
currentLastModified = dateParser.iso8601DateParse(currentText.toString().trim());
|
||||||
} else if (qName.equals("ETag")) {
|
} else if (qName.equals("ETag")) {
|
||||||
currentETag = currentText.toString().trim();
|
currentETag = currentText.toString().trim();
|
||||||
currentMD5 = CryptoStreams.hex(Utils.replaceAll(currentETag, '"', ""));
|
currentMD5 = CryptoStreams.hex(Strings2.replaceAll(currentETag, '"', ""));
|
||||||
} else if (qName.equals("Size")) {
|
} else if (qName.equals("Size")) {
|
||||||
currentSize = new Long(currentText.toString().trim());
|
currentSize = new Long(currentText.toString().trim());
|
||||||
} else if (qName.equals("Owner")) {
|
} else if (qName.equals("Owner")) {
|
||||||
|
|
|
@ -47,7 +47,7 @@ import org.testng.annotations.Test;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live", testName = "jclouds.ComputeAndBlobStoreTogetherHappilyLiveTest")
|
@Test(groups = "live")
|
||||||
public class ComputeAndBlobStoreTogetherHappilyLiveTest extends BlobStoreAndComputeServiceLiveTest {
|
public class ComputeAndBlobStoreTogetherHappilyLiveTest extends BlobStoreAndComputeServiceLiveTest {
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
protected void setupCredentials() {
|
protected void setupCredentials() {
|
||||||
|
|
|
@ -36,7 +36,7 @@ import org.jclouds.compute.RunNodesException;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.rest.config.CredentialStoreModule;
|
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.BeforeTest;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ public class CredentialsStoredInBlobStoreTest {
|
||||||
assertEquals(credentialsMap.size(), 10);
|
assertEquals(credentialsMap.size(), 10);
|
||||||
for (Entry<String, InputStream> entry : credentialsMap.entrySet()) {
|
for (Entry<String, InputStream> entry : credentialsMap.entrySet()) {
|
||||||
Credentials credentials = computeContext.credentialStore().get(entry.getKey());
|
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));
|
"{\"identity\":\"%s\",\"credential\":\"%s\"}", credentials.identity, credentials.credential));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ package org.jclouds.aws;
|
||||||
|
|
||||||
import org.jclouds.blobstore.util.BlobStoreUtils;
|
import org.jclouds.blobstore.util.BlobStoreUtils;
|
||||||
import org.jclouds.compute.util.ComputeServiceUtils;
|
import org.jclouds.compute.util.ComputeServiceUtils;
|
||||||
import org.jclouds.util.Utils;
|
import org.jclouds.rest.Providers;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
@ -49,7 +49,7 @@ public class ProvidersInPropertiesTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSupportedProviders() {
|
public void testSupportedProviders() {
|
||||||
Iterable<String> providers = Utils.getSupportedProviders();
|
Iterable<String> providers = Providers.getSupportedProviders();
|
||||||
assert Iterables.contains(providers, "sqs") : providers;
|
assert Iterables.contains(providers, "sqs") : providers;
|
||||||
assert Iterables.contains(providers, "elb") : providers;
|
assert Iterables.contains(providers, "elb") : providers;
|
||||||
assert Iterables.contains(providers, "s3") : providers;
|
assert Iterables.contains(providers, "s3") : providers;
|
||||||
|
|
|
@ -51,7 +51,8 @@ import com.google.inject.TypeLiteral;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @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 class CloudWatchAsyncClientTest extends RestClientTest<CloudWatchAsyncClient> {
|
||||||
|
|
||||||
public void testRegisterInstancesWithMeasure() throws SecurityException, NoSuchMethodException, IOException {
|
public void testRegisterInstancesWithMeasure() throws SecurityException, NoSuchMethodException, IOException {
|
||||||
|
|
|
@ -43,7 +43,7 @@ import com.google.inject.Module;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live", sequential = true, testName = "cloudwatch.CloudWatchClientLiveTest")
|
@Test(groups = "live", sequential = true)
|
||||||
public class CloudWatchClientLiveTest {
|
public class CloudWatchClientLiveTest {
|
||||||
|
|
||||||
private CloudWatchClient client;
|
private CloudWatchClient client;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue