Issue 116: rolled s3 into aws

git-svn-id: http://jclouds.googlecode.com/svn/trunk@2235 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-11-09 03:35:53 +00:00
parent 99ba4498ec
commit 870becd3f1
166 changed files with 169 additions and 496 deletions

View File

@ -34,7 +34,7 @@
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>
<artifactId>jclouds-aws-core</artifactId> <artifactId>jclouds-aws</artifactId>
<name>jclouds Amazon AWS Components Core</name> <name>jclouds Amazon AWS Components Core</name>
<packaging>jar</packaging> <packaging>jar</packaging>
<description>jclouds Core components to access Amazon AWS</description> <description>jclouds Core components to access Amazon AWS</description>

View File

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

View File

@ -32,7 +32,7 @@ import org.jclouds.http.pool.PoolConstants;
* @author Adrian Cole * @author Adrian Cole
*/ */
public interface AWSConstants extends HttpConstants, PoolConstants { public interface AWSConstants extends HttpConstants, PoolConstants {
public static final String ENDPOINT = "Endpoint";
public static final String PROPERTY_AWS_SECRETACCESSKEY = "jclouds.aws.secretaccesskey"; public static final String PROPERTY_AWS_SECRETACCESSKEY = "jclouds.aws.secretaccesskey";
public static final String PROPERTY_AWS_ACCESSKEYID = "jclouds.aws.accesskeyid"; public static final String PROPERTY_AWS_ACCESSKEYID = "jclouds.aws.accesskeyid";

View File

@ -29,13 +29,14 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.aws.handlers.AWSClientErrorRetryHandler;
import org.jclouds.aws.handlers.AWSRedirectionRetryHandler;
import org.jclouds.aws.handlers.ParseAWSErrorFromXmlContent;
import org.jclouds.aws.s3.S3; import org.jclouds.aws.s3.S3;
import org.jclouds.aws.s3.S3Client; import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature; import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
import org.jclouds.aws.s3.handlers.AWSClientErrorRetryHandler;
import org.jclouds.aws.s3.handlers.AWSRedirectionRetryHandler;
import org.jclouds.aws.s3.handlers.ParseAWSErrorFromXmlContent;
import org.jclouds.aws.s3.reference.S3Constants; import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.aws.util.RequestSigner;
import org.jclouds.concurrent.ExpirableSupplier; import org.jclouds.concurrent.ExpirableSupplier;
import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.HttpRetryHandler;
@ -68,6 +69,13 @@ public class S3RestClientModule extends AbstractModule {
return cache.get(); return cache.get();
} }
@Provides
@Singleton
RequestSigner provideRequestSigner(RequestAuthorizeSignature in){
return in;
}
/** /**
* borrowing concurrency code to ensure that caching takes place properly * borrowing concurrency code to ensure that caching takes place properly
*/ */

View File

@ -38,7 +38,7 @@ import org.jclouds.blobstore.functions.CalculateSize;
import org.jclouds.blobstore.functions.GenerateMD5; import org.jclouds.blobstore.functions.GenerateMD5;
import org.jclouds.blobstore.functions.GenerateMD5Result; import org.jclouds.blobstore.functions.GenerateMD5Result;
import com.google.common.collect.HashMultimap; import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
/** /**
@ -52,7 +52,7 @@ public class S3ObjectImpl implements S3Object, Comparable<S3Object> {
private final CalculateSize calculateSize; private final CalculateSize calculateSize;
private final MutableObjectMetadata metadata; private final MutableObjectMetadata metadata;
private Object data; private Object data;
private Multimap<String, String> allHeaders = HashMultimap.create(); private Multimap<String, String> allHeaders = LinkedHashMultimap.create();
private Long contentLength; private Long contentLength;
@Inject @Inject

View File

@ -39,6 +39,7 @@ import javax.ws.rs.core.HttpHeaders;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.reference.S3Constants; import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.aws.util.RequestSigner;
import org.jclouds.http.HttpConstants; import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
@ -58,7 +59,7 @@ import com.google.common.annotations.VisibleForTesting;
* *
*/ */
@Singleton @Singleton
public class RequestAuthorizeSignature implements HttpRequestFilter { public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSigner {
private final String[] firstHeadersToSign = new String[] { "Content-MD5", private final String[] firstHeadersToSign = new String[] { "Content-MD5",
HttpHeaders.CONTENT_TYPE, HttpHeaders.DATE }; HttpHeaders.CONTENT_TYPE, HttpHeaders.DATE };

View File

@ -40,7 +40,7 @@ import org.jclouds.util.DateService;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap; import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
/** /**
@ -55,7 +55,7 @@ import com.google.common.collect.Multimap;
* <p/> * <p/>
* S3Client connection = // get connection * S3Client connection = // get connection
* <p/> * <p/>
* Multimap<String,String> metadata = HashMultimap.create(); * Multimap<String,String> metadata = LinkedHashMultimap.create();
* metadata.put("x-amz-meta-adrian", "foo"); * metadata.put("x-amz-meta-adrian", "foo");
* <p/> * <p/>
* // this will copy the object, provided it wasn't modified since yesterday. * // this will copy the object, provided it wasn't modified since yesterday.
@ -256,7 +256,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
@Override @Override
public Multimap<String, String> buildRequestHeaders() { public Multimap<String, String> buildRequestHeaders() {
checkState(metadataPrefix != null, "metadataPrefix should have been injected!"); checkState(metadataPrefix != null, "metadataPrefix should have been injected!");
Multimap<String, String> returnVal = HashMultimap.create(); Multimap<String, String> returnVal = LinkedHashMultimap.create();
returnVal.putAll(headers); returnVal.putAll(headers);
if (metadata != null) { if (metadata != null) {
for (String key : metadata.keySet()) { for (String key : metadata.keySet()) {

View File

@ -36,7 +36,6 @@ public interface S3Constants extends AWSConstants, S3Headers {
* S3 service's XML Namespace, as used in XML request and response documents. * S3 service's XML Namespace, as used in XML request and response documents.
*/ */
public static final String S3_REST_API_XML_NAMESPACE = "http://s3.amazonaws.com/doc/2006-03-01/"; public static final String S3_REST_API_XML_NAMESPACE = "http://s3.amazonaws.com/doc/2006-03-01/";
public static final String ENDPOINT = "Endpoint";
public static final String PREFIX = "prefix"; public static final String PREFIX = "prefix";
public static final String MARKER = "marker"; public static final String MARKER = "marker";
public static final String MAX_KEYS = "max-keys"; public static final String MAX_KEYS = "max-keys";

View File

@ -30,18 +30,15 @@ import java.io.ByteArrayInputStream;
import java.io.InputStream; import java.io.InputStream;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Provider;
import org.jclouds.aws.domain.AWSError; import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
import org.jclouds.aws.s3.reference.S3Headers; import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.xml.ErrorHandler; import org.jclouds.aws.util.AWSUtils;
import org.jclouds.blobstore.util.BlobStoreUtils; import org.jclouds.blobstore.util.BlobStoreUtils;
import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.ParseSax;
/** /**
* Encryption, Hashing, and IO Utilities needed to sign and verify S3 requests and responses. * Encryption, Hashing, and IO Utilities needed to sign and verify S3 requests and responses.
@ -51,24 +48,14 @@ import org.jclouds.http.functions.ParseSax;
public class S3Utils extends BlobStoreUtils { public class S3Utils extends BlobStoreUtils {
@Inject @Inject
RequestAuthorizeSignature signer; AWSUtils util;
@Inject
ParseSax.Factory factory;
@Inject
Provider<ErrorHandler> errorHandlerProvider;
public AWSError parseAWSErrorFromContent(HttpCommand command, HttpResponse response, public AWSError parseAWSErrorFromContent(HttpCommand command, HttpResponse response,
InputStream content) throws HttpException { InputStream content) throws HttpException {
AWSError error = (AWSError) factory.create(errorHandlerProvider.get()).parse(content); AWSError error = util.parseAWSErrorFromContent(command, response, content);
if (error.getRequestId() == null) if (error.getRequestId() == null)
error.setRequestId(response.getFirstHeaderOrNull(S3Headers.REQUEST_ID)); error.setRequestId(response.getFirstHeaderOrNull(S3Headers.REQUEST_ID));
error.setRequestToken(response.getFirstHeaderOrNull(S3Headers.REQUEST_TOKEN)); error.setRequestToken(response.getFirstHeaderOrNull(S3Headers.REQUEST_TOKEN));
if ("SignatureDoesNotMatch".equals(error.getCode())) {
error.setStringSigned(signer.createStringToSign(command.getRequest()));
error.setSignature(signer.signString(error.getStringSigned()));
}
return error; return error;
} }

View File

@ -0,0 +1,47 @@
package org.jclouds.aws.util;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import javax.inject.Inject;
import javax.inject.Provider;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.xml.ErrorHandler;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ParseSax;
/**
* Needed to sign and verify requests and responses.
*
* @author Adrian Cole
*/
public class AWSUtils {
@Inject
RequestSigner signer;
@Inject
ParseSax.Factory factory;
@Inject
Provider<ErrorHandler> errorHandlerProvider;
public AWSError parseAWSErrorFromContent(HttpCommand command, HttpResponse response,
InputStream content) throws HttpException {
AWSError error = (AWSError) factory.create(errorHandlerProvider.get()).parse(content);
if ("SignatureDoesNotMatch".equals(error.getCode())) {
error.setStringSigned(signer.createStringToSign(command.getRequest()));
error.setSignature(signer.signString(error.getStringSigned()));
}
return error;
}
public AWSError parseAWSErrorFromContent(HttpCommand command, HttpResponse response,
String content) throws HttpException {
return parseAWSErrorFromContent(command, response, new ByteArrayInputStream(content
.getBytes()));
}
}

View File

@ -0,0 +1,15 @@
package org.jclouds.aws.util;
import org.jclouds.http.HttpRequest;
/**
*
* @author Adrian Cole
*/
public interface RequestSigner {
String createStringToSign(HttpRequest input);
String signString(String toSign);
}

View File

@ -73,6 +73,7 @@ import org.testng.annotations.Test;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Module; import com.google.inject.Module;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
/** /**
@ -119,8 +120,8 @@ public class S3ClientTest extends RestClientTest<S3Client> {
Method method = S3Client.class Method method = S3Client.class
.getMethod("copyObject", String.class, String.class, String.class, String.class, .getMethod("copyObject", String.class, String.class, String.class, String.class,
Array.newInstance(CopyObjectOptions.class, 0).getClass()); Array.newInstance(CopyObjectOptions.class, 0).getClass());
GeneratedHttpRequest<S3Client> httpMethod = processor.createRequest(method, GeneratedHttpRequest<S3Client> httpMethod = processor.createRequest(method, "sourceBucket",
"sourceBucket", "sourceObject", "destinationBucket", "destinationObject"); "sourceObject", "destinationBucket", "destinationObject");
assertRequestLineEquals(httpMethod, assertRequestLineEquals(httpMethod,
"PUT http://destinationBucket.stub:8080/destinationObject HTTP/1.1"); "PUT http://destinationBucket.stub:8080/destinationObject HTTP/1.1");
@ -316,8 +317,8 @@ public class S3ClientTest extends RestClientTest<S3Client> {
public void testPutObjectACL() throws SecurityException, NoSuchMethodException, IOException { public void testPutObjectACL() throws SecurityException, NoSuchMethodException, IOException {
Method method = S3Client.class.getMethod("putObjectACL", String.class, String.class, Method method = S3Client.class.getMethod("putObjectACL", String.class, String.class,
AccessControlList.class); AccessControlList.class);
GeneratedHttpRequest<S3Client> httpMethod = processor.createRequest(method, "bucket", GeneratedHttpRequest<S3Client> httpMethod = processor.createRequest(method, "bucket", "key",
"key", AccessControlList.fromCannedAccessPolicy(CannedAccessPolicy.PRIVATE, "1234")); AccessControlList.fromCannedAccessPolicy(CannedAccessPolicy.PRIVATE, "1234"));
assertRequestLineEquals(httpMethod, "PUT http://bucket.stub:8080/key?acl HTTP/1.1"); assertRequestLineEquals(httpMethod, "PUT http://bucket.stub:8080/key?acl HTTP/1.1");
assertHeadersEqual(httpMethod, assertHeadersEqual(httpMethod,
@ -368,15 +369,19 @@ public class S3ClientTest extends RestClientTest<S3Client> {
.to("key"); .to("key");
bindConstant().annotatedWith( bindConstant().annotatedWith(
Jsr330.named(BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX)).to("prefix"); Jsr330.named(BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX)).to("prefix");
bindConstant().annotatedWith(TimeStamp.class).to("timestamp");
bind(Logger.LoggerFactory.class).toInstance(new LoggerFactory() { bind(Logger.LoggerFactory.class).toInstance(new LoggerFactory() {
public Logger getLogger(String category) { public Logger getLogger(String category) {
return Logger.NULL; return Logger.NULL;
} }
}); });
} }
@SuppressWarnings("unused")
@Provides
@TimeStamp
String provide() {
return "timestamp";
}
}; };
} }
} }

View File

@ -26,9 +26,9 @@ package org.jclouds.aws.s3.config;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertFalse;
import org.jclouds.aws.s3.handlers.AWSClientErrorRetryHandler; import org.jclouds.aws.handlers.AWSClientErrorRetryHandler;
import org.jclouds.aws.s3.handlers.AWSRedirectionRetryHandler; import org.jclouds.aws.handlers.AWSRedirectionRetryHandler;
import org.jclouds.aws.s3.handlers.ParseAWSErrorFromXmlContent; import org.jclouds.aws.handlers.ParseAWSErrorFromXmlContent;
import org.jclouds.aws.s3.reference.S3Constants; import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.concurrent.WithinThreadExecutorService; import org.jclouds.concurrent.WithinThreadExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule; import org.jclouds.concurrent.config.ExecutorServiceModule;

View File

@ -53,7 +53,7 @@ public class CopyObjectHandlerTest extends BaseHandlerTest {
} }
public void testApplyInputStream() { public void testApplyInputStream() {
InputStream is = getClass().getResourceAsStream("/copy_object.xml"); InputStream is = getClass().getResourceAsStream("/s3/copy_object.xml");
ObjectMetadata expected = new CopyObjectResult(new DateService() ObjectMetadata expected = new CopyObjectResult(new DateService()
.iso8601DateParse("2009-03-19T13:23:27.000Z"), "\"92836a3ea45a6984d1b4d23a747d46bb\""); .iso8601DateParse("2009-03-19T13:23:27.000Z"), "\"92836a3ea45a6984d1b4d23a747d46bb\"");

View File

@ -60,7 +60,7 @@ public class ListBucketHandlerTest extends BaseHandlerTest {
} }
public void testApplyInputStream() { public void testApplyInputStream() {
InputStream is = getClass().getResourceAsStream("/list_bucket.xml"); InputStream is = getClass().getResourceAsStream("/s3/list_bucket.xml");
CanonicalUser owner = new CanonicalUser( CanonicalUser owner = new CanonicalUser(
"e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0", "ferncam"); "e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0", "ferncam");
ListBucketResponse expected = new TreeSetListBucketResponse( ListBucketResponse expected = new TreeSetListBucketResponse(

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