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