Issue 74, Issue 76, Issue 101: revamped blobstore and rest subsystems; Issue 10: removed assisted inject

git-svn-id: http://jclouds.googlecode.com/svn/trunk@2001 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-10-29 20:17:42 +00:00
parent 71377b29a1
commit 050f6e9a82
891 changed files with 17804 additions and 13616 deletions

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -27,7 +27,6 @@ import static org.testng.Assert.assertEquals;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jclouds.aws.domain.AWSError; import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.xml.ErrorHandler;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.functions.BaseHandlerTest; import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
@ -37,7 +36,6 @@ import org.testng.annotations.Test;
public class ErrorHandlerTest extends BaseHandlerTest { public class ErrorHandlerTest extends BaseHandlerTest {
public static final String errorFromAmazonIfYouDontRemoveTransferEncodingHeader = "<Error><Code>NotImplemented</Code><Message>A header you provided implies functionality that is not implemented</Message><Header>Transfer-Encoding</Header><RequestId>7C59925D75D15561</RequestId><HostId>fbskVU51OZJg2yZS/wNIxoE2PmCf0ZqFd0iH6Vrzw0uKG3KmokswBytL/Bfp/GWb</HostId></Error>"; public static final String errorFromAmazonIfYouDontRemoveTransferEncodingHeader = "<Error><Code>NotImplemented</Code><Message>A header you provided implies functionality that is not implemented</Message><Header>Transfer-Encoding</Header><RequestId>7C59925D75D15561</RequestId><HostId>fbskVU51OZJg2yZS/wNIxoE2PmCf0ZqFd0iH6Vrzw0uKG3KmokswBytL/Bfp/GWb</HostId></Error>";
@SuppressWarnings("unchecked")
ParseSax<AWSError> createParser() { ParseSax<AWSError> createParser() {
ParseSax<AWSError> parser = (ParseSax<AWSError>) factory.create(injector ParseSax<AWSError> parser = (ParseSax<AWSError>) factory.create(injector
.getInstance(ErrorHandler.class)); .getInstance(ErrorHandler.class));

View File

@ -1,4 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
====================================================================
-->
<Error> <Error>
<Code>NoSuchKey</Code> <Code>NoSuchKey</Code>
<Message>The resource you requested does not exist</Message> <Message>The resource you requested does not exist</Message>

View File

@ -2,7 +2,7 @@
<!-- <!--
Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
==================================================================== ====================================================================
Licensed to the Apache Software Foundation (ASF) under one Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,258 +0,0 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3;
import java.util.SortedSet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HEAD;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import org.jclouds.aws.s3.binders.BindS3ObjectToEntity;
import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.ListBucketResponse;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
import org.jclouds.aws.s3.functions.ClearAndDeleteBucketIfNotEmpty;
import org.jclouds.aws.s3.functions.ParseObjectFromHeadersAndHttpContent;
import org.jclouds.aws.s3.functions.ParseObjectMetadataFromHeaders;
import org.jclouds.aws.s3.functions.ReturnTrueIfBucketAlreadyOwnedByYou;
import org.jclouds.aws.s3.options.ListBucketOptions;
import org.jclouds.aws.s3.xml.ListAllMyBucketsHandler;
import org.jclouds.aws.s3.xml.ListBucketHandler;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.functions.BlobName;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.http.functions.ParseETagHeader;
import org.jclouds.http.functions.ReturnFalseOn404;
import org.jclouds.http.options.GetOptions;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.HostPrefixParam;
import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.annotations.XMLResponseParser;
/**
* Provides access to S3 via their REST API.
* <p/>
* All commands return a Future of the result from S3. Any exceptions incurred during processing
* will be wrapped in an {@link ExecutionException} as documented in {@link Future#get()}.
*
* @author Adrian Cole
* @author James Murty
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAPI.html" />
*/
@VirtualHost
@SkipEncoding('/')
@RequestFilters(RequestAuthorizeSignature.class)
@Endpoint(S3.class)
public interface S3BlobStore extends BlobStore<BucketMetadata, ObjectMetadata, S3Object> {
/**
* Retrieves the S3Object associated with the Key or {@link Blob <ObjectMetadata>#NOT_FOUND} if
* not available;
*
* <p/>
* To use GET, you must have READ access to the object. If READ access is granted to the
* anonymous user, you can request the object without an authorization header.
*
* <p />
* This command allows you to specify {@link GetObjectOptions} to control delivery of content.
*
* <h2>Note</h2> If you specify any of the below options, you will receive partial content:
* <ul>
* <li>{@link GetObjectOptions#range}</li>
* <li>{@link GetObjectOptions#startAt}</li>
* <li>{@link GetObjectOptions#tail}</li>
* </ul>
*
* @param bucketName
* namespace of the object you are retrieving
* @param key
* unique key in the s3Bucket identifying the object
* @return Future reference to a fully populated S3Object including data stored in S3 or
* {@link S3Object#NOT_FOUND} if not present.
*
* @throws org.jclouds.http.HttpResponseException
* if the conditions requested set were not satisfied by the object on the server.
* @see #getBlob(String, String)
* @see GetObjectOptions
*/
@GET
@Path("{key}")
@ExceptionParser(ThrowKeyNotFoundOn404.class)
@ResponseParser(ParseObjectFromHeadersAndHttpContent.class)
Future<S3Object> getBlob(@HostPrefixParam String bucketName, @PathParam("key") String key);
@GET
@Path("{key}")
@ExceptionParser(ThrowKeyNotFoundOn404.class)
@ResponseParser(ParseObjectFromHeadersAndHttpContent.class)
Future<S3Object> getBlob(@HostPrefixParam String bucketName, @PathParam("key") String key,
GetOptions options);
/**
* Retrieves the {@link org.jclouds.aws.s3.domain.ObjectMetadata metadata} of the object
* associated with the key or {@link org.jclouds.aws.s3.domain.ObjectMetadata#NOT_FOUND} if not
* available.
*
* <p/>
* The HEAD operation is used to retrieve information about a specific object or object size,
* without actually fetching the object itself. This is useful if you're only interested in the
* object metadata, and don't want to waste bandwidth on the object data.
*
*
* @param bucketName
* namespace of the metadata you are retrieving
* @param key
* unique key in the s3Bucket identifying the object
* @return metadata associated with the key or
* {@link org.jclouds.aws.s3.domain.ObjectMetadata#NOT_FOUND} if not present;
* @see #getBlob(String, String)
* @see <a
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectHEAD.html"
* />
*/
@HEAD
@Path("{key}")
@ExceptionParser(ThrowKeyNotFoundOn404.class)
@ResponseParser(ParseObjectMetadataFromHeaders.class)
ObjectMetadata blobMetadata(@HostPrefixParam String bucketName, @PathParam("key") String key);
/**
* Removes the object and metadata associated with the key.
* <p/>
* The DELETE request operation removes the specified object from Amazon S3. Once deleted, there
* is no method to restore or undelete an object.
*
*
* @param bucketName
* namespace of the object you are deleting
* @param key
* unique key in the s3Bucket identifying the object
* @return true if deleted
* @throws org.jclouds.http.HttpResponseException
* if the bucket is not available
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?
* RESTObjectDELETE.html" />
*/
@DELETE
@Path("{key}")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
Future<Void> removeBlob(@HostPrefixParam String bucketName, @PathParam("key") String key);
@PUT
@Path("{key}")
@ResponseParser(ParseETagHeader.class)
Future<String> putBlob(
@HostPrefixParam String bucketName,
@PathParam("key") @ParamParser(BlobName.class) @BinderParam(BindS3ObjectToEntity.class) S3Object object);
@PUT
@Path("/")
@ExceptionParser(ReturnTrueIfBucketAlreadyOwnedByYou.class)
Future<Boolean> createContainer(@HostPrefixParam String bucketName);
/**
* Deletes the bucket, if it is empty.
* <p/>
* The DELETE request operation deletes the bucket named in the URI. All objects in the bucket
* must be deleted before the bucket itself can be deleted.
* <p />
* Only the owner of a bucket can delete it, regardless of the bucket's access control policy.
*
*
* @param bucketName
* what to delete
* @see org.jclouds.aws.s3.commands.DeleteBucket
* @see <a href=
* "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketDELETE.html"
* />
*/
@DELETE
@Path("/")
@ExceptionParser(ClearAndDeleteBucketIfNotEmpty.class)
Future<Void> deleteContainer(@HostPrefixParam String bucketName);
/**
* Issues a HEAD command to determine if the bucket exists or not.
*/
@HEAD
@Path("/")
@QueryParams(keys = "max-keys", values = "0")
@ExceptionParser(ReturnFalseOn404.class)
boolean containerExists(@HostPrefixParam String bucketName);
/**
* Retrieve a <code>S3Bucket</code> listing. A GET request operation using a bucket URI lists
* information about the objects in the bucket. You can use {@link ListBucketOptions} to control
* the amount of S3Objects to return.
* <p />
* To list the keys of a bucket, you must have READ access to the bucket.
* <p/>
*
* @param bucketName
* namespace of the objects you wish to list
* @return Future reference to a fully populated S3Bucket including metadata of the S3Objects it
* contains or {@link BoundedList<ObjectMetadata>#NOT_FOUND} if not present.
* @see ListBucketOptions
*
* @see <a
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET.html"
* />
*/
@GET
@Path("/")
@XMLResponseParser(ListBucketHandler.class)
Future<ListBucketResponse> listBlobs(@HostPrefixParam String bucketName);
/**
* Returns a list of all of the buckets owned by the authenticated sender of the request.
*
* @return list of all of the buckets owned by the authenticated sender of the request.
* @see <a
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTServiceGET.html"
* />
*
*/
@GET
@XMLResponseParser(ListAllMyBucketsHandler.class)
@Path("/")
SortedSet<BucketMetadata> listContainers();
}

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -23,6 +23,8 @@
*/ */
package org.jclouds.aws.s3; package org.jclouds.aws.s3;
import static org.jclouds.blobstore.attr.BlobScopes.CONTAINER;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@ -42,6 +44,7 @@ import org.jclouds.aws.s3.domain.ListBucketResponse;
import org.jclouds.aws.s3.domain.ObjectMetadata; import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature; import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
import org.jclouds.aws.s3.functions.ObjectKey;
import org.jclouds.aws.s3.functions.ParseObjectFromHeadersAndHttpContent; import org.jclouds.aws.s3.functions.ParseObjectFromHeadersAndHttpContent;
import org.jclouds.aws.s3.functions.ParseObjectMetadataFromHeaders; import org.jclouds.aws.s3.functions.ParseObjectMetadataFromHeaders;
import org.jclouds.aws.s3.functions.ReturnTrueIfBucketAlreadyOwnedByYou; import org.jclouds.aws.s3.functions.ReturnTrueIfBucketAlreadyOwnedByYou;
@ -54,8 +57,7 @@ import org.jclouds.aws.s3.xml.AccessControlListHandler;
import org.jclouds.aws.s3.xml.CopyObjectHandler; import org.jclouds.aws.s3.xml.CopyObjectHandler;
import org.jclouds.aws.s3.xml.ListAllMyBucketsHandler; import org.jclouds.aws.s3.xml.ListAllMyBucketsHandler;
import org.jclouds.aws.s3.xml.ListBucketHandler; import org.jclouds.aws.s3.xml.ListBucketHandler;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.attr.BlobScope;
import org.jclouds.blobstore.functions.BlobName;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404; import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404; import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404; import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
@ -89,11 +91,16 @@ import org.jclouds.rest.annotations.XMLResponseParser;
@SkipEncoding('/') @SkipEncoding('/')
@RequestFilters(RequestAuthorizeSignature.class) @RequestFilters(RequestAuthorizeSignature.class)
@Endpoint(S3.class) @Endpoint(S3.class)
public interface S3Connection { @BlobScope(CONTAINER)
public interface S3Client {
/** /**
* Retrieves the S3Object associated with the Key or {@link Blob <ObjectMetadata>#NOT_FOUND} if * Creates a default implementation of S3Object
* not available; */
public S3Object newS3Object();
/**
* Retrieves the S3Object associated with the Key or KeyNotFoundException if not available;
* *
* <p/> * <p/>
* To use GET, you must have READ access to the object. If READ access is granted to the * To use GET, you must have READ access to the object. If READ access is granted to the
@ -129,8 +136,9 @@ public interface S3Connection {
GetOptions... options); GetOptions... options);
/** /**
* Retrieves the {@link org.jclouds.aws.s3.domain.ObjectMetadata metadata} of the object * Retrieves the {@link org.jclouds.aws.s3.domain.internal.BucketListObjectMetadata metadata} of
* associated with the key or {@link org.jclouds.aws.s3.domain.ObjectMetadata#NOT_FOUND} if not * the object associated with the key or
* {@link org.jclouds.aws.s3.domain.internal.BucketListObjectMetadata#NOT_FOUND} if not
* available. * available.
* *
* <p/> * <p/>
@ -144,7 +152,8 @@ public interface S3Connection {
* @param key * @param key
* unique key in the s3Bucket identifying the object * unique key in the s3Bucket identifying the object
* @return metadata associated with the key or * @return metadata associated with the key or
* {@link org.jclouds.aws.s3.domain.ObjectMetadata#NOT_FOUND} if not present; * {@link org.jclouds.aws.s3.domain.internal.BucketListObjectMetadata#NOT_FOUND} if not
* present;
* @see #getObject(String, String) * @see #getObject(String, String)
* @see <a * @see <a
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectHEAD.html" * href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectHEAD.html"
@ -206,7 +215,7 @@ public interface S3Connection {
@ResponseParser(ParseETagHeader.class) @ResponseParser(ParseETagHeader.class)
Future<String> putObject( Future<String> putObject(
@HostPrefixParam String bucketName, @HostPrefixParam String bucketName,
@PathParam("key") @ParamParser(BlobName.class) @BinderParam(BindS3ObjectToEntity.class) S3Object object, @PathParam("key") @ParamParser(ObjectKey.class) @BinderParam(BindS3ObjectToEntity.class) S3Object object,
PutObjectOptions... options); PutObjectOptions... options);
/** /**
@ -303,7 +312,7 @@ public interface S3Connection {
@GET @GET
@XMLResponseParser(ListAllMyBucketsHandler.class) @XMLResponseParser(ListAllMyBucketsHandler.class)
@Path("/") @Path("/")
SortedSet<BucketMetadata> listOwnedBuckets(); Future<? extends SortedSet<BucketMetadata>> listOwnedBuckets();
/** /**
* Copies one object to another bucket, retaining UserMetadata from the source. The destination * Copies one object to another bucket, retaining UserMetadata from the source. The destination

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -23,26 +23,15 @@
*/ */
package org.jclouds.aws.s3; package org.jclouds.aws.s3;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_SESSIONINTERVAL;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import java.net.URI;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import org.jclouds.aws.s3.config.RestS3ConnectionModule;
import org.jclouds.aws.s3.config.S3ContextModule; import org.jclouds.aws.s3.config.S3ContextModule;
import org.jclouds.aws.s3.domain.BucketMetadata; import org.jclouds.aws.s3.config.S3RestClientModule;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.blobstore.BlobStoreContextBuilder;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule; import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.rest.RestContextBuilder;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Module; import com.google.inject.Module;
@ -61,98 +50,12 @@ import com.google.inject.TypeLiteral;
* @author Adrian Cole, Andrew Newdigate * @author Adrian Cole, Andrew Newdigate
* @see S3Context * @see S3Context
*/ */
public class S3ContextBuilder extends public class S3ContextBuilder extends RestContextBuilder<S3Client> {
BlobStoreContextBuilder<S3Connection, BucketMetadata, ObjectMetadata, S3Object> {
@Override
public S3Context buildContext() {
return this.buildInjector().getInstance(S3Context.class);
}
public S3ContextBuilder(Properties props) { public S3ContextBuilder(Properties props) {
super(new TypeLiteral<S3Connection>() { super(new TypeLiteral<S3Client>() {
}, new TypeLiteral<BucketMetadata>() {
}, new TypeLiteral<ObjectMetadata>() {
}, new TypeLiteral<S3Object>() {
}, props); }, props);
properties.setProperty(S3Constants.PROPERTY_S3_ENDPOINT, "https://s3.amazonaws.com");
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "x-amz-meta-");
if (!properties.containsKey(PROPERTY_S3_SESSIONINTERVAL))
this.withTimeStampExpiration(60);
}
public S3ContextBuilder(String id, String secret) {
this(new Properties());
properties.setProperty(PROPERTY_AWS_ACCESSKEYID, checkNotNull(id, "awsAccessKeyId"));
properties.setProperty(PROPERTY_AWS_SECRETACCESSKEY, checkNotNull(secret,
"awsSecretAccessKey"));
}
@Override
public S3ContextBuilder relaxSSLHostname() {
return (S3ContextBuilder) super.relaxSSLHostname();
}
@Override
public S3ContextBuilder withRequestTimeout(long milliseconds) {
return (S3ContextBuilder) super.withRequestTimeout(milliseconds);
}
@Override
public S3ContextBuilder withExecutorService(ExecutorService service) {
return (S3ContextBuilder) super.withExecutorService(service);
}
@Override
public S3ContextBuilder withHttpMaxRedirects(int httpMaxRedirects) {
return (S3ContextBuilder) super.withHttpMaxRedirects(httpMaxRedirects);
}
@Override
public S3ContextBuilder withHttpMaxRetries(int httpMaxRetries) {
return (S3ContextBuilder) super.withHttpMaxRetries(httpMaxRetries);
}
@Override
public S3ContextBuilder withModule(Module module) {
return (S3ContextBuilder) super.withModule(module);
}
@Override
public S3ContextBuilder withModules(Module... modules) {
return (S3ContextBuilder) super.withModules(modules);
}
@Override
public S3ContextBuilder withPoolIoWorkerThreads(int poolIoWorkerThreads) {
return (S3ContextBuilder) super.withPoolIoWorkerThreads(poolIoWorkerThreads);
}
@Override
public S3ContextBuilder withPoolMaxConnectionReuse(int poolMaxConnectionReuse) {
return (S3ContextBuilder) super.withPoolMaxConnectionReuse(poolMaxConnectionReuse);
}
@Override
public S3ContextBuilder withPoolMaxConnections(int poolMaxConnections) {
return (S3ContextBuilder) super.withPoolMaxConnections(poolMaxConnections);
}
@Override
public S3ContextBuilder withPoolMaxSessionFailures(int poolMaxSessionFailures) {
return (S3ContextBuilder) super.withPoolMaxSessionFailures(poolMaxSessionFailures);
}
@Override
public S3ContextBuilder withPoolRequestInvokerThreads(int poolRequestInvokerThreads) {
return (S3ContextBuilder) super.withPoolRequestInvokerThreads(poolRequestInvokerThreads);
}
@Override
public S3ContextBuilder withEndpoint(URI endpoint) {
properties.setProperty(S3Constants.PROPERTY_S3_ENDPOINT, checkNotNull(endpoint, "endpoint")
.toString());
return (S3ContextBuilder) this;
} }
@Override @Override
@ -161,12 +64,18 @@ public class S3ContextBuilder extends
} }
@Override @Override
protected void addConnectionModule(List<Module> modules) { protected void addClientModule(List<Module> modules) {
modules.add(new RestS3ConnectionModule()); modules.add(new S3RestClientModule());
} }
public S3ContextBuilder withTimeStampExpiration(long seconds) { @Override
getProperties().setProperty(PROPERTY_S3_SESSIONINTERVAL, seconds + ""); public S3ContextBuilder withExecutorService(ExecutorService service) {
return this; return (S3ContextBuilder) super.withExecutorService(service);
} }
@Override
public S3ContextBuilder withModules(Module... modules) {
return (S3ContextBuilder) super.withModules(modules);
}
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -24,9 +24,11 @@
package org.jclouds.aws.s3; package org.jclouds.aws.s3;
import java.net.URI; import java.net.URI;
import java.util.Properties;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule; import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.rest.RestContext;
import com.google.inject.Module; import com.google.inject.Module;
@ -39,20 +41,25 @@ import com.google.inject.Module;
* If no <code>Module</code>s are specified, the default {@link JDKLoggingModule logging} and * If no <code>Module</code>s are specified, the default {@link JDKLoggingModule logging} and
* {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed. * {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
* *
* @author Adrian Cole, Andrew Newdigate * @author Adrian Cole
* @see S3Context * @see S3Client
*/ */
public class S3ContextFactory { public class S3ContextFactory {
public static S3Context createContext( public static RestContext<S3Client> createContext(Properties properties, Module... modules) {
String awsAccessKeyId, String awsSecretAccessKey, Module... modules) { return new S3ContextBuilder(new S3PropertiesBuilder(properties).build()).withModules(modules)
return new S3ContextBuilder(awsAccessKeyId, awsSecretAccessKey).withModules(modules)
.buildContext(); .buildContext();
} }
public static S3Context createContext( public static RestContext<S3Client> createContext(String awsAccessKeyId,
URI endpoint, String awsAccessKeyId, String awsSecretAccessKey, Module... modules) { String awsSecretAccessKey, Module... modules) {
return new S3ContextBuilder(awsAccessKeyId, awsSecretAccessKey).withEndpoint(endpoint) return new S3ContextBuilder(new S3PropertiesBuilder(awsAccessKeyId, awsSecretAccessKey)
.withModules(modules).buildContext(); .build()).withModules(modules).buildContext();
}
public static RestContext<S3Client> createContext(URI endpoint, String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) {
return new S3ContextBuilder(new S3PropertiesBuilder(awsAccessKeyId, awsSecretAccessKey)
.withEndpoint(endpoint).build()).withModules(modules).buildContext();
} }
} }

View File

@ -0,0 +1,80 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_METADATA_PREFIX;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_SESSIONINTERVAL;
import java.net.URI;
import java.util.Properties;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.http.HttpPropertiesBuilder;
/**
* Builds properties used in S3 Connections
*
* @author Adrian Cole
*/
public class S3PropertiesBuilder extends HttpPropertiesBuilder {
@Override
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();
properties.setProperty(S3Constants.PROPERTY_S3_ENDPOINT, "https://s3.amazonaws.com");
properties.setProperty(PROPERTY_S3_METADATA_PREFIX, "x-amz-meta-");
properties.setProperty(PROPERTY_S3_SESSIONINTERVAL, "60");
return properties;
}
public S3PropertiesBuilder(Properties properties) {
super(properties);
}
public S3PropertiesBuilder(String id, String secret) {
super();
withCredentials(id, secret);
}
public S3PropertiesBuilder withCredentials(String id, String secret) {
properties.setProperty(PROPERTY_AWS_ACCESSKEYID, checkNotNull(id, "awsAccessKeyId"));
properties.setProperty(PROPERTY_AWS_SECRETACCESSKEY, checkNotNull(secret,
"awsSecretAccessKey"));
return this;
}
public S3PropertiesBuilder withEndpoint(URI endpoint) {
properties.setProperty(S3Constants.PROPERTY_S3_ENDPOINT, checkNotNull(endpoint, "endpoint")
.toString());
return this;
}
public S3PropertiesBuilder withTimeStampExpiration(long seconds) {
properties.setProperty(PROPERTY_S3_SESSIONINTERVAL, seconds + "");
return this;
}
}

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -24,30 +24,35 @@
package org.jclouds.aws.s3.binders; package org.jclouds.aws.s3.binders;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX; import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import org.jclouds.aws.s3.blobstore.functions.ObjectToBlob;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.blobstore.binders.BindBlobToEntityAndUserMetadataToHeadersWithPrefix; import org.jclouds.blobstore.binders.BindBlobToEntityAndUserMetadataToHeadersWithPrefix;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
public class BindS3ObjectToEntity implements Binder {
private final BindBlobToEntityAndUserMetadataToHeadersWithPrefix blobBinder;
private final ObjectToBlob object2Blob;
public class BindS3ObjectToEntity extends BindBlobToEntityAndUserMetadataToHeadersWithPrefix {
@Inject @Inject
public BindS3ObjectToEntity(@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix) { public BindS3ObjectToEntity(ObjectToBlob object2Blob,
super(metadataPrefix); BindBlobToEntityAndUserMetadataToHeadersWithPrefix blobBinder) {
this.blobBinder = blobBinder;
this.object2Blob = object2Blob;
} }
public void bindToRequest(HttpRequest request, Object entity) { public void bindToRequest(HttpRequest request, Object entity) {
Blob<?> object = (Blob<?>) entity; S3Object s3Object = (S3Object) entity;
checkArgument(object.getMetadata().getSize() >= 0, "size must be set"); checkNotNull(s3Object.getContentLength(), "contentLength");
checkArgument(object.getContentLength() <= 5 * 1024 * 1024 * 1024, checkArgument(s3Object.getContentLength() <= 5 * 1024 * 1024 * 1024,
"maximum size for put object is 5GB"); "maximum size for put object is 5GB");
if (object instanceof S3Object) { blobBinder.bindToRequest(request, object2Blob.apply(s3Object));
S3Object s3Object = (S3Object) object;
if (s3Object.getMetadata().getCacheControl() != null) { if (s3Object.getMetadata().getCacheControl() != null) {
request.getHeaders().put(HttpHeaders.CACHE_CONTROL, request.getHeaders().put(HttpHeaders.CACHE_CONTROL,
s3Object.getMetadata().getCacheControl()); s3Object.getMetadata().getCacheControl());
@ -62,7 +67,6 @@ public class BindS3ObjectToEntity extends BindBlobToEntityAndUserMetadataToHeade
request.getHeaders().put(HttpHeaders.CONTENT_ENCODING, request.getHeaders().put(HttpHeaders.CONTENT_ENCODING,
s3Object.getMetadata().getContentEncoding()); s3Object.getMetadata().getContentEncoding());
} }
}
super.bindToRequest(request, entity);
} }
} }

View File

@ -0,0 +1,181 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.blobstore;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.blobstore.options.ListOptions.Builder.recursive;
import java.util.SortedSet;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.inject.Inject;
import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.blobstore.functions.BlobToObject;
import org.jclouds.aws.s3.blobstore.functions.BlobToObjectGetOptions;
import org.jclouds.aws.s3.blobstore.functions.BucketToResourceList;
import org.jclouds.aws.s3.blobstore.functions.BucketToResourceMetadata;
import org.jclouds.aws.s3.blobstore.functions.ContainerToBucketListOptions;
import org.jclouds.aws.s3.blobstore.functions.ObjectToBlob;
import org.jclouds.aws.s3.blobstore.functions.ObjectToBlobMetadata;
import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.ListBucketResponse;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.options.ListBucketOptions;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.attr.ConsistencyModel;
import org.jclouds.blobstore.attr.ConsistencyModels;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.BoundedSortedSet;
import org.jclouds.blobstore.domain.ResourceMetadata;
import org.jclouds.blobstore.options.ListOptions;
import org.jclouds.blobstore.strategy.ClearListStrategy;
import org.jclouds.concurrent.FutureFunctionWrapper;
import org.jclouds.http.options.GetOptions;
import org.jclouds.logging.Logger.LoggerFactory;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
@ConsistencyModel(ConsistencyModels.EVENTUAL)
public class S3BlobStore implements BlobStore {
private final S3Client connection;
private final Blob.Factory blobFactory;
private final LoggerFactory logFactory;
private final ClearListStrategy clearContainerStrategy;
private final ObjectToBlobMetadata object2BlobMd;
private final ObjectToBlob object2Blob;
private final BlobToObject blob2Object;
private final ContainerToBucketListOptions container2BucketListOptions;
private final BlobToObjectGetOptions blob2ObjectGetOptions;
private final BucketToResourceMetadata bucket2ResourceMd;
private final BucketToResourceList bucket2ResourceList;
private final ExecutorService service;
@Inject
private S3BlobStore(S3Client connection, Blob.Factory blobFactory, LoggerFactory logFactory,
ClearListStrategy clearContainerStrategy, ObjectToBlobMetadata object2BlobMd,
ObjectToBlob object2Blob, BlobToObject blob2Object,
ContainerToBucketListOptions container2BucketListOptions,
BlobToObjectGetOptions blob2ObjectGetOptions,
BucketToResourceMetadata bucket2ResourceMd, BucketToResourceList bucket2ResourceList,
ExecutorService service) {
this.connection = checkNotNull(connection, "connection");
this.blobFactory = checkNotNull(blobFactory, "blobFactory");
this.logFactory = checkNotNull(logFactory, "logFactory");
this.clearContainerStrategy = checkNotNull(clearContainerStrategy, "clearContainerStrategy");
this.object2BlobMd = checkNotNull(object2BlobMd, "object2BlobMd");
this.object2Blob = checkNotNull(object2Blob, "object2Blob");
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
this.container2BucketListOptions = checkNotNull(container2BucketListOptions,
"container2BucketListOptions");
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
this.bucket2ResourceMd = checkNotNull(bucket2ResourceMd, "bucket2ResourceMd");
this.bucket2ResourceList = checkNotNull(bucket2ResourceList, "bucket2ResourceList");
this.service = checkNotNull(service, "service");
}
protected <F, T> Future<T> wrapFuture(Future<? extends F> future, Function<F, T> function) {
return new FutureFunctionWrapper<F, T>(future, function, logFactory.getLogger(function
.getClass().getName()));
}
/**
* This implementation uses the S3 HEAD Object command to return the result
*/
public BlobMetadata blobMetadata(String container, String key) {
return object2BlobMd.apply(connection.headObject(container, key));
}
public Future<Void> clearContainer(final String container) {
return service.submit(new Callable<Void>() {
public Void call() throws Exception {
clearContainerStrategy.execute(container, recursive());
return null;
}
});
}
public Future<Boolean> createContainer(String container) {
return connection.putBucketIfNotExists(container);
}
public Future<Void> deleteContainer(final String container) {
return service.submit(new Callable<Void>() {
public Void call() throws Exception {
clearContainerStrategy.execute(container, recursive());
connection.deleteBucketIfEmpty(container).get();
return null;
}
});
}
public boolean exists(String container) {
return connection.bucketExists(container);
}
public Future<Blob> getBlob(String container, String key,
org.jclouds.blobstore.options.GetOptions... optionsList) {
GetOptions httpOptions = blob2ObjectGetOptions.apply(optionsList);
Future<S3Object> returnVal = connection.getObject(container, key, httpOptions);
return wrapFuture(returnVal, object2Blob);
}
public Future<? extends SortedSet<? extends ResourceMetadata>> list() {
return wrapFuture(connection.listOwnedBuckets(),
new Function<SortedSet<BucketMetadata>, SortedSet<? extends ResourceMetadata>>() {
public SortedSet<? extends ResourceMetadata> apply(SortedSet<BucketMetadata> from) {
return Sets.newTreeSet(Iterables.transform(from, bucket2ResourceMd));
}
});
}
public Future<? extends BoundedSortedSet<? extends ResourceMetadata>> list(String container,
ListOptions... optionsList) {
ListBucketOptions httpOptions = container2BucketListOptions.apply(optionsList);
Future<ListBucketResponse> returnVal = connection.listBucket(container, httpOptions);
return wrapFuture(returnVal, bucket2ResourceList);
}
public Future<String> putBlob(String container, Blob blob) {
return connection.putObject(container, blob2Object.apply(blob));
}
public Future<Void> removeBlob(String container, String key) {
return connection.deleteObject(container, key);
}
public Blob newBlob() {
return blobFactory.create(null);
}
}

View File

@ -0,0 +1,80 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.blobstore;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.blobstore.config.S3BlobStoreContextModule;
import org.jclouds.aws.s3.config.S3RestClientModule;
import org.jclouds.blobstore.BlobStoreContextBuilder;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Creates {@link S3BlobStoreContext} or {@link Injector} instances based on the most commonly
* requested arguments.
* <p/>
* Note that Threadsafe objects will be bound as singletons to the Injector or Context provided.
* <p/>
* <p/>
* If no <code>Module</code>s are specified, the default {@link JDKLoggingModule logging} and
* {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
*
* @author Adrian Cole, Andrew Newdigate
* @see S3BlobStoreContext
*/
public class S3BlobStoreContextBuilder extends BlobStoreContextBuilder<S3Client> {
public S3BlobStoreContextBuilder(Properties props) {
super(new TypeLiteral<S3Client>() {
}, props);
}
@Override
public S3BlobStoreContextBuilder withExecutorService(ExecutorService service) {
return (S3BlobStoreContextBuilder) super.withExecutorService(service);
}
@Override
public S3BlobStoreContextBuilder withModules(Module... modules) {
return (S3BlobStoreContextBuilder) super.withModules(modules);
}
@Override
protected void addContextModule(List<Module> modules) {
modules.add(new S3BlobStoreContextModule());
}
@Override
protected void addClientModule(List<Module> modules) {
modules.add(new S3RestClientModule());
}
}

View File

@ -0,0 +1,66 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.blobstore;
import java.net.URI;
import java.util.Properties;
import org.jclouds.aws.s3.S3Client;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import com.google.inject.Module;
/**
* Creates {@link S3BlobStoreContext} instances based on the most commonly requested arguments.
* <p/>
* Note that Threadsafe objects will be bound as singletons to the Injector or Context provided.
* <p/>
* <p/>
* If no <code>Module</code>s are specified, the default {@link JDKLoggingModule logging} and
* {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
*
* @author Adrian Cole, Andrew Newdigate
* @see S3BlobStoreContext
*/
public class S3BlobStoreContextFactory {
public static BlobStoreContext<S3Client> createContext(Properties properties, Module... modules) {
return new S3BlobStoreContextBuilder(new S3BlobStorePropertiesBuilder(properties).build())
.withModules(modules).buildContext();
}
public static BlobStoreContext<S3Client> createContext(String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) {
return new S3BlobStoreContextBuilder(new S3BlobStorePropertiesBuilder(awsAccessKeyId,
awsSecretAccessKey).build()).withModules(modules).buildContext();
}
public static BlobStoreContext<S3Client> createContext(URI endpoint, String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) {
return new S3BlobStoreContextBuilder(new S3BlobStorePropertiesBuilder(awsAccessKeyId,
awsSecretAccessKey).withEndpoint(endpoint).build()).withModules(modules)
.buildContext();
}
}

View File

@ -0,0 +1,63 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.blobstore;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import java.util.Properties;
import org.jclouds.aws.s3.S3PropertiesBuilder;
import org.jclouds.blobstore.reference.BlobStoreConstants;
/**
* Builds properties used in S3 Blob Stores
*
* @author Adrian Cole, Andrew Newdigate
*/
public class S3BlobStorePropertiesBuilder extends S3PropertiesBuilder {
public S3BlobStorePropertiesBuilder(String id, String secret) {
super(id, secret);
}
public S3BlobStorePropertiesBuilder(Properties properties) {
super(properties);
}
/**
* longest time a single synchronous operation can take before throwing an exception.
*/
public S3BlobStorePropertiesBuilder withRequestTimeout(long milliseconds) {
properties.setProperty(BlobStoreConstants.PROPERTY_BLOBSTORE_TIMEOUT, Long
.toString(milliseconds));
return this;
}
@Override
protected Properties defaultProperties() {
Properties props = super.defaultProperties();
props.setProperty(PROPERTY_USER_METADATA_PREFIX, "x-amz-meta-");
return props;
}
}

View File

@ -0,0 +1,73 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.blobstore.config;
import java.net.URI;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.aws.reference.AWSConstants;
import org.jclouds.aws.s3.S3;
import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.blobstore.S3BlobStore;
import org.jclouds.aws.s3.config.S3ObjectModule;
import org.jclouds.blobstore.BlobMap;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.InputStreamMap;
import org.jclouds.blobstore.config.BlobStoreMapModule;
import org.jclouds.blobstore.config.BlobStoreObjectModule;
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
import org.jclouds.lifecycle.Closer;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
/**
* Configures the {@link S3BlobStoreContext}; requires {@link S3BlobStore} bound.
*
* @author Adrian Cole
*/
public class S3BlobStoreContextModule extends AbstractModule {
@Override
protected void configure() {
install(new BlobStoreObjectModule());
install(new BlobStoreMapModule());
install(new S3ObjectModule());
bind(BlobStore.class).to(S3BlobStore.class).asEagerSingleton();
}
@Provides
@Singleton
BlobStoreContext<S3Client> provideContext(BlobMap.Factory blobMapFactory,
InputStreamMap.Factory inputStreamMapFactory, Closer closer, BlobStore blobStore,
S3Client defaultApi, @S3 URI endPoint,
@Named(AWSConstants.PROPERTY_AWS_ACCESSKEYID) String account) {
return new BlobStoreContextImpl<S3Client>(blobMapFactory, inputStreamMapFactory, closer,
blobStore, defaultApi, endPoint, account);
}
}

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -21,43 +21,36 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.mezeo.pcs2.functions; package org.jclouds.aws.s3.blobstore.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.concurrent.ConcurrentMap;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.blobstore.ContainerNotFoundException; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.util.Utils; import org.jclouds.blobstore.domain.Blob;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.ComputationException;
/** /**
*
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class ContainerNameToResourceId implements Function<Object, String> { public class BlobToObject implements Function<Blob, S3Object> {
private final BlobToObjectMetadata blob2ObjectMd;
private final ConcurrentMap<String, String> finder; private final S3Object.Factory objectProvider;
@Inject @Inject
public ContainerNameToResourceId(ConcurrentMap<String, String> finder) { BlobToObject(BlobToObjectMetadata blob2ObjectMd, S3Object.Factory objectProvider) {
this.finder = finder; this.blob2ObjectMd = blob2ObjectMd;
this.objectProvider = objectProvider;
} }
public String apply(Object from) { public S3Object apply(Blob from) {
String toFind = checkNotNull(from, "name").toString(); S3Object object = objectProvider.create(blob2ObjectMd.apply(from.getMetadata()));
try { if (from.getContentLength() != null)
return finder.get(toFind); object.setContentLength(from.getContentLength());
} catch (ComputationException e) { object.setData(from.getData());
Utils.<ContainerNotFoundException> rethrowIfRuntimeOrSameType(e); object.setAllHeaders(from.getAllHeaders());
throw e; return object;
} }
} }
}

View File

@ -0,0 +1,60 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.blobstore.functions;
import javax.inject.Singleton;
import org.jclouds.http.options.GetOptions;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Singleton
public class BlobToObjectGetOptions implements
Function<org.jclouds.blobstore.options.GetOptions[], GetOptions> {
public GetOptions apply(org.jclouds.blobstore.options.GetOptions[] from) {
GetOptions httpOptions = new GetOptions();
if (from.length != 0) {
if (from[0].getIfMatch() != null) {
httpOptions.ifETagMatches(from[0].getIfMatch());
}
if (from[0].getIfModifiedSince() != null) {
httpOptions.ifModifiedSince(from[0].getIfModifiedSince());
}
if (from[0].getIfNoneMatch() != null) {
httpOptions.ifETagDoesntMatch(from[0].getIfNoneMatch());
}
if (from[0].getIfUnmodifiedSince() != null) {
httpOptions.ifUnmodifiedSince(from[0].getIfUnmodifiedSince());
}
for (String range : from[0].getRanges()) {
String[] firstLast = range.split("\\-");
httpOptions.range(Long.parseLong(firstLast[0]), Long.parseLong(firstLast[1]));
}
}
return httpOptions;
}
}

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -21,25 +21,33 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.rackspace.cloudfiles; package org.jclouds.aws.s3.blobstore.functions;
import org.jclouds.blobstore.BlobStoreContext; import javax.inject.Singleton;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.aws.s3.domain.MutableObjectMetadata;
import org.jclouds.aws.s3.domain.internal.MutableObjectMetadataImpl;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.cloud.CloudContext;
import org.jclouds.rackspace.cloudfiles.domain.ContainerMetadata; import com.google.common.base.Function;
/** /**
* Represents an authenticated context to Cloud Files.
*
* @see <a href="http://www.rackspacecloud.com/cf-devguide-20090311.pdf" />
* @see CloudFilesBlobStore
* @see CloudContext
* @author Adrian Cole * @author Adrian Cole
*
*/ */
public interface CloudFilesContext @Singleton
extends public class BlobToObjectMetadata implements Function<BlobMetadata, MutableObjectMetadata> {
BlobStoreContext<CloudFilesConnection, ContainerMetadata, BlobMetadata, Blob<BlobMetadata>> { public MutableObjectMetadata apply(BlobMetadata base) {
MutableObjectMetadata to = new MutableObjectMetadataImpl();
to.setContentType(base.getContentType());
to.setETag(base.getETag());
to.setContentMD5(base.getContentMD5());
to.setKey(base.getName());
to.setLastModified(base.getLastModified());
if (base.getSize() != null)
to.setSize(base.getSize());
if (base.getUserMetadata() != null)
to.setUserMetadata(base.getUserMetadata());
return to;
}
} }

View File

@ -0,0 +1,58 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.blobstore.functions;
import javax.inject.Singleton;
import org.jclouds.aws.s3.options.ListBucketOptions;
import org.jclouds.blobstore.options.ListOptions;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Singleton
public class BucketToContainerListOptions implements Function<ListBucketOptions[], ListOptions> {
public ListOptions apply(ListBucketOptions[] optionsList) {
ListOptions options = new ListOptions();
if (optionsList.length != 0) {
if (optionsList[0].getDelimiter() == null) {
options.recursive();
} else if (!optionsList[0].getDelimiter().equals("/")) {
throw new IllegalArgumentException("only '/' is allowed as a blobstore delimiter");
}
if (optionsList[0].getMarker() != null) {
options.afterMarker(optionsList[0].getMarker());
}
if (optionsList[0].getMaxResults() != null) {
options.maxResults(optionsList[0].getMaxResults());
}
if (optionsList[0].getPrefix() != null) {
options.underPath(optionsList[0].getPrefix());
}
}
return options;
}
}

View File

@ -0,0 +1,63 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.blobstore.functions;
import java.util.SortedSet;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.aws.s3.domain.ListBucketResponse;
import org.jclouds.blobstore.domain.BoundedSortedSet;
import org.jclouds.blobstore.domain.ResourceMetadata;
import org.jclouds.blobstore.domain.internal.BoundedTreeSet;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
/**
* @author Adrian Cole
*/
@Singleton
public class BucketToResourceList implements
Function<ListBucketResponse, BoundedSortedSet<? extends ResourceMetadata>> {
private final ObjectToBlobMetadata object2blobMd;
private final CommonPrefixesToResourceMetadata prefix2ResourceMd;
@Inject
public BucketToResourceList(ObjectToBlobMetadata object2blobMd,
CommonPrefixesToResourceMetadata prefix2ResourceMd) {
this.object2blobMd = object2blobMd;
this.prefix2ResourceMd = prefix2ResourceMd;
}
public BoundedSortedSet<? extends ResourceMetadata> apply(ListBucketResponse from) {
SortedSet<ResourceMetadata> contents = Sets.newTreeSet(Iterables.concat(Iterables.transform(
from, object2blobMd), prefix2ResourceMd.apply(from.getCommonPrefixes())));
return new BoundedTreeSet<ResourceMetadata>(contents, from.getPrefix(), from.getMarker(),
from.getMaxKeys(), from.isTruncated());
}
}

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -21,26 +21,27 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.aws.s3; package org.jclouds.aws.s3.blobstore.functions;
import javax.inject.Singleton;
import org.jclouds.aws.s3.domain.BucketMetadata; import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.ObjectMetadata; import org.jclouds.blobstore.domain.MutableResourceMetadata;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.blobstore.domain.ResourceMetadata;
import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.blobstore.domain.ResourceType;
import org.jclouds.blobstore.domain.internal.MutableResourceMetadataImpl;
import com.google.common.base.Function;
/** /**
* Represents an authenticated context to S3.
*
* <h2>Note</h2> Please issue {@link #close()} when you are finished with this context in order to
* release resources.
*
*
* @see S3BlobStore
* @see BlobStoreContext
* @author Adrian Cole * @author Adrian Cole
*
*/ */
public interface S3Context extends @Singleton
BlobStoreContext<S3Connection, BucketMetadata, ObjectMetadata, S3Object> { public class BucketToResourceMetadata implements Function<BucketMetadata, ResourceMetadata> {
public ResourceMetadata apply(BucketMetadata from) {
MutableResourceMetadata to = new MutableResourceMetadataImpl();
to.setName(from.getName());
to.setType(ResourceType.CONTAINER);
return to;
}
} }

View File

@ -0,0 +1,54 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.blobstore.functions;
import javax.inject.Singleton;
import org.jclouds.blobstore.domain.MutableResourceMetadata;
import org.jclouds.blobstore.domain.ResourceMetadata;
import org.jclouds.blobstore.domain.ResourceType;
import org.jclouds.blobstore.domain.internal.MutableResourceMetadataImpl;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
/**
* @author Adrian Cole
*/
@Singleton
public class CommonPrefixesToResourceMetadata implements
Function<Iterable<String>, Iterable<ResourceMetadata>> {
public Iterable<ResourceMetadata> apply(
Iterable<String> prefixes) {
return Iterables.transform(prefixes, new Function<String, ResourceMetadata>() {
public ResourceMetadata apply(String from) {
MutableResourceMetadata returnVal = new MutableResourceMetadataImpl();
returnVal.setType(ResourceType.RELATIVE_PATH);
returnVal.setName(from);
return returnVal;
}
});
}
}

View File

@ -0,0 +1,56 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.blobstore.functions;
import javax.inject.Singleton;
import org.jclouds.aws.s3.options.ListBucketOptions;
import org.jclouds.blobstore.options.ListOptions;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Singleton
public class ContainerToBucketListOptions implements Function<ListOptions[], ListBucketOptions> {
public ListBucketOptions apply(ListOptions[] optionsList) {
ListBucketOptions httpOptions = new ListBucketOptions();
if (optionsList.length != 0) {
if (!optionsList[0].getRecursive()) {
httpOptions.delimiter("/");
}
if (optionsList[0].getPath() != null) {
httpOptions.withPrefix(optionsList[0].getPath());
}
if (optionsList[0].getMarker() != null) {
httpOptions.afterMarker(optionsList[0].getMarker());
}
if (optionsList[0].getMaxResults() != null) {
httpOptions.maxResults(optionsList[0].getMaxResults());
}
}
return httpOptions;
}
}

View File

@ -0,0 +1,57 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.blobstore.functions;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.Blob.Factory;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Singleton
public class ObjectToBlob implements Function<S3Object, Blob> {
private final Blob.Factory blobFactory;
private final ObjectToBlobMetadata object2BlobMd;
@Inject
ObjectToBlob(Factory blobFactory, ObjectToBlobMetadata object2BlobMd) {
this.blobFactory = blobFactory;
this.object2BlobMd = object2BlobMd;
}
public Blob apply(S3Object from) {
Blob blob = blobFactory.create(object2BlobMd.apply(from.getMetadata()));
if (from.getContentLength() != null)
blob.setContentLength(from.getContentLength());
blob.setData(from.getData());
blob.setAllHeaders(from.getAllHeaders());
return blob;
}
}

View File

@ -0,0 +1,55 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.blobstore.functions;
import javax.inject.Singleton;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.ResourceType;
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Singleton
public class ObjectToBlobMetadata implements Function<ObjectMetadata, MutableBlobMetadata> {
public MutableBlobMetadata apply(ObjectMetadata from) {
MutableBlobMetadata to = new MutableBlobMetadataImpl();
to.setContentMD5(from.getContentMD5());
if (from.getContentType() != null)
to.setContentType(from.getContentType());
to.setETag(from.getETag());
to.setName(from.getKey());
to.setSize(from.getSize());
to.setType(ResourceType.BLOB);
to.setUserMetadata(from.getUserMetadata());
if (from.getContentType() != null && from.getContentType().equals("application/directory")) {
to.setType(ResourceType.RELATIVE_PATH);
}
return to;
}
}

View File

@ -0,0 +1,92 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.blobstore.functions;
import java.util.SortedSet;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.aws.s3.domain.ListBucketResponse;
import org.jclouds.aws.s3.domain.MutableObjectMetadata;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.internal.TreeSetListBucketResponse;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.BoundedSortedSet;
import org.jclouds.blobstore.domain.ResourceMetadata;
import org.jclouds.blobstore.domain.ResourceType;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
/**
* @author Adrian Cole
*/
@Singleton
public class ResourceToBucketList implements
Function<BoundedSortedSet<? extends ResourceMetadata>, ListBucketResponse> {
private final BlobToObjectMetadata blob2ObjectMd;
@Inject
public ResourceToBucketList(BlobToObjectMetadata blob2ObjectMd) {
this.blob2ObjectMd = blob2ObjectMd;
}
public ListBucketResponse apply(BoundedSortedSet<? extends ResourceMetadata> list) {
SortedSet<ObjectMetadata> contents = Sets.newTreeSet(Iterables.transform(Iterables.filter(
list, new Predicate<ResourceMetadata>() {
public boolean apply(ResourceMetadata input) {
return input.getType() == ResourceType.BLOB;
}
}), new Function<ResourceMetadata, ObjectMetadata>() {
public MutableObjectMetadata apply(ResourceMetadata from) {
return blob2ObjectMd.apply((BlobMetadata) from);
}
}));
SortedSet<String> commonPrefixes = Sets.newTreeSet(Iterables.transform(Iterables.filter(list,
new Predicate<ResourceMetadata>() {
public boolean apply(ResourceMetadata input) {
return input.getType() == ResourceType.RELATIVE_PATH;
}
}), new Function<ResourceMetadata, String>() {
public String apply(ResourceMetadata from) {
return from.getName();
}
}));
return new TreeSetListBucketResponse(null, contents, list.getPath(), list.getMarker(), list
.getMaxResults(), "/", contents.size() == list.getMaxResults(), commonPrefixes);
}
}

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -25,28 +25,22 @@ package org.jclouds.aws.s3.config;
import java.net.URI; import java.net.URI;
import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Provider; import javax.inject.Singleton;
import org.jclouds.aws.reference.AWSConstants; import org.jclouds.aws.reference.AWSConstants;
import org.jclouds.aws.s3.S3; import org.jclouds.aws.s3.S3;
import org.jclouds.aws.s3.S3BlobStore; import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.S3Connection; import org.jclouds.blobstore.config.BlobStoreObjectModule;
import org.jclouds.aws.s3.S3Context;
import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.BlobStoreContextImpl;
import org.jclouds.blobstore.BlobMap.Factory;
import org.jclouds.lifecycle.Closer; import org.jclouds.lifecycle.Closer;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.RestContextImpl;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Scopes; import com.google.inject.Provides;
/** /**
* Configures the {@link S3Context}; requires {@link S3BlobStore} bound. * Configures the {@link S3ContextModule}; requires {@link S3Client} bound.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@ -54,23 +48,16 @@ public class S3ContextModule extends AbstractModule {
@Override @Override
protected void configure() { protected void configure() {
bind(S3Context.class).to(S3ContextImpl.class).in(Scopes.SINGLETON); // for converters
install(new BlobStoreObjectModule());
install(new S3ObjectModule());
} }
public static class S3ContextImpl extends @Provides
BlobStoreContextImpl<S3Connection, BucketMetadata, ObjectMetadata, S3Object> implements @Singleton
S3Context { RestContext<S3Client> provideContext(Closer closer, S3Client defaultApi, @S3 URI endPoint,
@Inject
S3ContextImpl(Factory<ObjectMetadata, S3Object> blobMapFactory,
org.jclouds.blobstore.InputStreamMap.Factory<ObjectMetadata> inputStreamMapFactory,
Closer closer, Provider<S3Object> blobProvider,
BlobStore<BucketMetadata, ObjectMetadata, S3Object> blobStore,
S3Connection defaultApi, @S3 URI endPoint,
@Named(AWSConstants.PROPERTY_AWS_ACCESSKEYID) String account) { @Named(AWSConstants.PROPERTY_AWS_ACCESSKEYID) String account) {
super(blobMapFactory, inputStreamMapFactory, closer, blobProvider, blobStore, defaultApi, return new RestContextImpl<S3Client>(closer, defaultApi, endPoint, account);
endPoint, account);
}
} }
} }

View File

@ -0,0 +1,78 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.config;
import javax.inject.Inject;
import javax.inject.Provider;
import org.jclouds.aws.s3.domain.MutableObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.internal.S3ObjectImpl;
import org.jclouds.blobstore.functions.CalculateSize;
import org.jclouds.blobstore.functions.GenerateMD5;
import org.jclouds.blobstore.functions.GenerateMD5Result;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Scopes;
/**
* Configures the domain object mappings needed for all S3 implementations
*
* @author Adrian Cole
*/
public class S3ObjectModule extends AbstractModule {
/**
* explicit factories are created here as it has been shown that Assisted Inject is extremely
* inefficient. http://code.google.com/p/google-guice/issues/detail?id=435
*/
@Override
protected void configure() {
bind(S3Object.Factory.class).to(S3ObjectFactory.class).in(Scopes.SINGLETON);
}
private static class S3ObjectFactory implements S3Object.Factory {
@Inject
GenerateMD5Result generateMD5Result;
@Inject
GenerateMD5 generateMD5;
@Inject
CalculateSize calculateSize;
@Inject
Provider<MutableObjectMetadata> metadataProvider;
public S3Object create(MutableObjectMetadata metadata) {
return new S3ObjectImpl(generateMD5Result, generateMD5, calculateSize,
metadata != null ? metadata : metadataProvider.get());
}
}
@Provides
S3Object provideS3Object(S3Object.Factory factory) {
return factory.create(null);
}
}

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -31,24 +31,19 @@ import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.aws.s3.S3; import org.jclouds.aws.s3.S3;
import org.jclouds.aws.s3.S3BlobStore; import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object;
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.AWSClientErrorRetryHandler;
import org.jclouds.aws.s3.handlers.AWSRedirectionRetryHandler; import org.jclouds.aws.s3.handlers.AWSRedirectionRetryHandler;
import org.jclouds.aws.s3.handlers.ParseAWSErrorFromXmlContent; import org.jclouds.aws.s3.handlers.ParseAWSErrorFromXmlContent;
import org.jclouds.aws.s3.reference.S3Constants; import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.cloud.ConfiguresCloudConnection;
import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.RequiresHttp; import org.jclouds.http.RequiresHttp;
import org.jclouds.http.annotation.ClientError; import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError; import org.jclouds.http.annotation.ServerError;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestClientFactory; import org.jclouds.rest.RestClientFactory;
import org.jclouds.util.DateService; import org.jclouds.util.DateService;
import org.jclouds.util.TimeStamp; import org.jclouds.util.TimeStamp;
@ -64,9 +59,9 @@ import com.google.inject.Scopes;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@ConfiguresCloudConnection @ConfiguresRestClient
@RequiresHttp @RequiresHttp
public class RestS3ConnectionModule extends AbstractModule { public class S3RestClientModule extends AbstractModule {
@Provides @Provides
@TimeStamp @TimeStamp
@ -106,15 +101,8 @@ public class RestS3ConnectionModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
protected BlobStore<BucketMetadata, ObjectMetadata, S3Object> provideS3BlobStore( protected S3Client provideS3Client(RestClientFactory factory) {
RestClientFactory factory) { return factory.create(S3Client.class);
return factory.create(S3BlobStore.class);
}
@Provides
@Singleton
protected S3Connection provideS3Connection(RestClientFactory factory) {
return factory.create(S3Connection.class);
} }
protected void bindErrorHandlers() { protected void bindErrorHandlers() {

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -22,7 +22,7 @@
* ==================================================================== * ====================================================================
*/ */
/** /**
* This package contains modules who manage the dependencies of the S3Context, S3Connection, and S3 Map views. * This package contains modules who manage the dependencies of the S3Context, S3Client, and S3 Map views.
* @author Adrian Cole * @author Adrian Cole
*/ */
package org.jclouds.aws.s3.config; package org.jclouds.aws.s3.config;

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -410,4 +410,35 @@ public class AccessControlList {
sb.append('}'); sb.append('}');
return sb.toString(); return sb.toString();
} }
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((grants == null) ? 0 : grants.hashCode());
result = prime * result + ((owner == null) ? 0 : owner.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;
AccessControlList other = (AccessControlList) obj;
if (grants == null) {
if (other.grants != null)
return false;
} else if (!grants.equals(other.grants))
return false;
if (owner == null) {
if (other.owner != null)
return false;
} else if (!owner.equals(other.owner))
return false;
return true;
}
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -23,7 +23,6 @@
*/ */
package org.jclouds.aws.s3.domain; package org.jclouds.aws.s3.domain;
import org.jclouds.blobstore.internal.ContainerMetadataImpl;
import org.joda.time.DateTime; import org.joda.time.DateTime;
/** /**
@ -31,36 +30,41 @@ import org.joda.time.DateTime;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class BucketMetadata extends ContainerMetadataImpl { public class BucketMetadata implements Comparable<BucketMetadata> {
protected DateTime creationDate; /** The serialVersionUID */
private static final long serialVersionUID = -6965068835316857535L;
public DateTime getCreationDate() { private final DateTime creationDate;
return creationDate; private final CanonicalUser owner;
} private final String name;
public void setCreationDate(DateTime creationDate) {
this.creationDate = creationDate;
}
/** /**
* Location constraint of the bucket. * Location constraint of the bucket.
* *
* @author Adrian Cole * @author Adrian Cole
* @see <a href= * @see <a href= "http://docs.amazonwebservices.com/AmazonS3/latest/RESTBucketLocationGET.html"
* "http://docs.amazonwebservices.com/AmazonS3/latest/RESTBucketLocationGET.html" /> * />
*/ */
public static enum LocationConstraint { public static enum LocationConstraint {
EU EU
} }
private CanonicalUser canonicalUser; public BucketMetadata(String name, DateTime creationDate, CanonicalUser owner) {
this.name = name;
public BucketMetadata(String name) { this.creationDate = creationDate;
super(name); this.owner = owner;
} }
public BucketMetadata() { /**
super(); * Every bucket and object in Amazon S3 has an owner, the user that created the bucket or object.
* The owner of a bucket or object cannot be changed. However, if the object is overwritten by
* another user (deleted and rewritten), the new object will have a new owner.
*/
public CanonicalUser getOwner() {
return owner;
}
public DateTime getCreationDate() {
return creationDate;
} }
/** /**
@ -74,40 +78,20 @@ public class BucketMetadata extends ContainerMetadataImpl {
* <p/> * <p/>
* Not be in an IP address style (e.g., "192.168.5.4") * Not be in an IP address style (e.g., "192.168.5.4")
*/ */
@Override
public void setName(String name) {
// note that we cannot enforce this, as invalid buckets may already exist
super.setName(name);
}
public String getName() { public String getName() {
return name; return name;
} }
@Override public int compareTo(BucketMetadata o) {
public String toString() { return (this == o) ? 0 : getName().compareTo(o.getName());
return "BucketMetadata [canonicalUser=" + canonicalUser + ", creationDate=" + creationDate
+ ", name=" + name + "]";
}
/**
* Every bucket and object in Amazon S3 has an owner, the user that created the bucket or
* object. The owner of a bucket or object cannot be changed. However, if the object is
* overwritten by another user (deleted and rewritten), the new object will have a new owner.
*/
public CanonicalUser getOwner() {
return canonicalUser;
}
public void setOwner(CanonicalUser canonicalUser) {
this.canonicalUser = canonicalUser;
} }
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = super.hashCode(); int result = 1;
result = prime * result + ((canonicalUser == null) ? 0 : canonicalUser.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((owner == null) ? 0 : owner.hashCode());
return result; return result;
} }
@ -115,17 +99,21 @@ public class BucketMetadata extends ContainerMetadataImpl {
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) if (this == obj)
return true; return true;
if (!super.equals(obj)) if (obj == null)
return false; return false;
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
BucketMetadata other = (BucketMetadata) obj; BucketMetadata other = (BucketMetadata) obj;
if (canonicalUser == null) { if (name == null) {
if (other.canonicalUser != null) if (other.name != null)
return false; return false;
} else if (!canonicalUser.equals(other.canonicalUser)) } else if (!name.equals(other.name))
return false;
if (owner == null) {
if (other.owner != null)
return false;
} else if (!owner.equals(other.owner))
return false; return false;
return true; return true;
} }
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -24,10 +24,9 @@
package org.jclouds.aws.s3.domain; package org.jclouds.aws.s3.domain;
/** /**
* Every bucket and object in Amazon S3 has an owner, the user that created the * Every bucket and object in Amazon S3 has an owner, the user that created the bucket or object.
* bucket or object. The owner of a bucket or object cannot be changed. However, * The owner of a bucket or object cannot be changed. However, if the object is overwritten by
* if the object is overwritten by another user (deleted and rewritten), the new * another user (deleted and rewritten), the new object will have a new owner.
* object will have a new owner.
* <p/> * <p/>
* *
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html? * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?
@ -42,19 +41,14 @@ public class CanonicalUser {
this.id = id; this.id = id;
} }
@Override public CanonicalUser(String id, String displayName) {
public String toString() { this(id);
final StringBuilder sb = new StringBuilder(); this.displayName = displayName;
sb.append("S3Owner");
sb.append("{id='").append(id).append('\'');
sb.append(", displayName='").append(displayName).append('\'');
sb.append('}');
return sb.toString();
} }
/** /**
* To locate the CanonicalUser ID for a user, the user must perform the * To locate the CanonicalUser ID for a user, the user must perform the
* {@link org.jclouds.aws.s3.S3BlobStore#listBlobs(String)} and retrieve * {@link org.jclouds.aws.s3.blobstore.S3BlobStore#list(String)} and retrieve
* {@link BucketMetadata#getOwner()} * {@link BucketMetadata#getOwner()}
*/ */
public String getId() { public String getId() {
@ -73,28 +67,28 @@ public class CanonicalUser {
} }
@Override @Override
public boolean equals(Object o) { public int hashCode() {
if (this == o) final int prime = 31;
return true; int result = 1;
if (!(o instanceof CanonicalUser)) result = prime * result + ((id == null) ? 0 : id.hashCode());
return false; return result;
CanonicalUser s3Owner = (CanonicalUser) o;
if (displayName != null ? !displayName.equals(s3Owner.displayName)
: s3Owner.displayName != null)
return false;
if (!id.equals(s3Owner.id))
return false;
return true;
} }
@Override @Override
public int hashCode() { public boolean equals(Object obj) {
int result = id.hashCode(); if (this == obj)
result = 31 * result return true;
+ (displayName != null ? displayName.hashCode() : 0); if (obj == null)
return result; return false;
if (getClass() != obj.getClass())
return false;
CanonicalUser other = (CanonicalUser) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
} }
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -48,7 +48,40 @@ import java.util.SortedSet;
* @author Adrian Cole * @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html" /> * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html" />
*/ */
public interface ListBucketResponse extends org.jclouds.rest.internal.BoundedSortedSet<ObjectMetadata> { public interface ListBucketResponse extends SortedSet<ObjectMetadata> {
/**
* Limits the response to keys which begin with the indicated prefix. You can use prefixes to
* separate a bucket into different sets of keys in a way similar to how a file system uses
* folders.
*/
String getPrefix();
/**
* Indicates where in the bucket to begin listing. The list will only include keys that occur
* lexicographically after marker. This is convenient for pagination: To get the next page of
* results use the last key of the current page as the marker.
*/
String getMarker();
/**
* The maximum number of keys you'd like to see in the response body. The server might return
* fewer than this many keys, but will not return more.
*/
int getMaxKeys();
/**
* There are more then maxKeys available
*/
boolean isTruncated();
/**
* Causes keys that contain the same string between the prefix and the first occurrence of the
* delimiter to be rolled up into a single result element in the CommonPrefixes collection. These
* rolled-up keys are not returned elsewhere in the response.
*
*/
String getDelimiter();
/** /**
* Example: * Example:
@ -65,12 +98,12 @@ public interface ListBucketResponse extends org.jclouds.rest.internal.BoundedSor
* *
* @see org.jclouds.aws.s3.options.ListBucketOptions#getPrefix() * @see org.jclouds.aws.s3.options.ListBucketOptions#getPrefix()
*/ */
public SortedSet<String> getCommonPrefixes(); SortedSet<String> getCommonPrefixes();
public String getBucketName();
public String getDelimiter();
public boolean isTruncated();
/**
* name of the Bucket FIXME Comment this
*
* @return
*/
String getName();
} }

View File

@ -0,0 +1,118 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.domain;
import java.util.Map;
import org.jclouds.aws.s3.domain.internal.MutableObjectMetadataImpl;
import org.joda.time.DateTime;
import com.google.inject.ImplementedBy;
/**
* /** Amazon S3 is designed to store objects. Objects are stored in {@link S3BucketListing buckets}
* and consist of a {@link org.jclouds.aws.s3.domain.S3Object#getData() value}, a
* {@link S3Object#getKey key}, {@link MutableObjectMetadata#getUserMetadata() metadata}, and an
* access control policy.
*
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingObjects.html"
*
* @see <a href= "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingMetadata.html" />
*/
@ImplementedBy(MutableObjectMetadataImpl.class)
public interface MutableObjectMetadata extends ObjectMetadata {
/**
* The key is the handle that you assign to an object that allows you retrieve it later. A key is
* a sequence of Unicode characters whose UTF-8 encoding is at most 1024 bytes long. Each object
* in a bucket must have a unique key.
*
* @see <a href= "http://docs.amazonwebservices.com/AmazonHTTP/2006-03-01/UsingKeys.html" />
*/
void setKey(String key);
/**
* Every bucket and object in Amazon S3 has an owner, the user that created the bucket or object.
* The owner of a bucket or object cannot be changed. However, if the object is overwritten by
* another user (deleted and rewritten), the new object will have a new owner.
*/
void setOwner(CanonicalUser owner);
/**
* Currently defaults to 'STANDARD' and not used.
*/
void setStorageClass(StorageClass storageClass);
/**
* Can be used to specify caching behavior along the request/reply chain.
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.9.
*/
void setCacheControl(String cacheControl);
/**
* Specifies presentational information for the object.
*
* @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html?sec19.5.1."/>
*/
void setContentDisposition(String contentDisposition);
/**
* Specifies what content encodings have been applied to the object and thus what decoding
* mechanisms must be applied in order to obtain the media-type referenced by the Content-Type
* header field.
*
* @see <a href= "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.11" />
*/
void setContentEncoding(String encoding);
/**
*
* A standard MIME type describing the format of the contents. If none is provided, the default
* is binary/octet-stream.
*
* @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17"/>
*/
void setContentType(String type);
/**
* The base64 decoded 128-bit MD5 digest of the message (without the headers) according to RFC
* 1864. This header can be used as a message integrity check to verify that the data is the same
* data that was originally sent. Although it is optional, we recommend using the Content-MD5
* mechanism as an end-to-end integrity check.
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTAuthentication.html"/>
*/
void setContentMD5(byte[] md5);
void setLastModified(DateTime lastModified);
void setETag(String eTag);
void setSize(long size);
void setUserMetadata(Map<String, String> userMetadata);
}

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -23,9 +23,9 @@
*/ */
package org.jclouds.aws.s3.domain; package org.jclouds.aws.s3.domain;
import java.io.Serializable; import java.util.Map;
import org.jclouds.blobstore.internal.BlobMetadataImpl; import org.joda.time.DateTime;
/** /**
* /** Amazon S3 is designed to store objects. Objects are stored in {@link S3BucketListing buckets} * /** Amazon S3 is designed to store objects. Objects are stored in {@link S3BucketListing buckets}
@ -38,160 +38,46 @@ import org.jclouds.blobstore.internal.BlobMetadataImpl;
* *
* @see <a href= "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingMetadata.html" /> * @see <a href= "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingMetadata.html" />
*/ */
public class ObjectMetadata extends BlobMetadataImpl implements Serializable { public interface ObjectMetadata extends Comparable<ObjectMetadata> {
/** The serialVersionUID */ public enum StorageClass {
private static final long serialVersionUID = -4415449798024051115L; STANDARD
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Metadata [accessControlList=").append(accessControlList).append(
", cacheControl=").append(cacheControl).append(", dataDisposition=").append(
dataDisposition).append(", owner=").append(owner).append(", storageClass=").append(
storageClass).append(", allHeaders=").append(allHeaders).append(", dataEncoding=")
.append(dataEncoding).append(", dataType=").append(dataType).append(", eTag=")
.append(eTag).append(", key=").append(name).append(", lastModified=").append(
lastModified).append(", size=").append(size).append(", userMetadata=")
.append(userMetadata).append("]");
return builder.toString();
}
private String cacheControl;
private String dataDisposition;
private AccessControlList accessControlList;
// only parsed on list
private CanonicalUser owner = null;
private String storageClass = null;
protected String dataEncoding;
public ObjectMetadata() {
super();
} }
/** /**
* @param key * The key is the handle that you assign to an object that allows you retrieve it later. A key is
* @see #getKey() * a sequence of Unicode characters whose UTF-8 encoding is at most 1024 bytes long. Each object
* in a bucket must have a unique key.
*
* @see <a href= "http://docs.amazonwebservices.com/AmazonHTTP/2006-03-01/UsingKeys.html" />
*/ */
public ObjectMetadata(String key) { String getKey();
super(key);
}
public void setOwner(CanonicalUser owner) {
this.owner = owner;
}
/** /**
* Every bucket and object in Amazon S3 has an owner, the user that created the bucket or object. * Every bucket and object in Amazon S3 has an owner, the user that created the bucket or object.
* The owner of a bucket or object cannot be changed. However, if the object is overwritten by * The owner of a bucket or object cannot be changed. However, if the object is overwritten by
* another user (deleted and rewritten), the new object will have a new owner. * another user (deleted and rewritten), the new object will have a new owner.
*/ */
public CanonicalUser getOwner() { CanonicalUser getOwner();
return owner;
}
public void setStorageClass(String storageClass) {
this.storageClass = storageClass;
}
/** /**
* Currently defaults to 'STANDARD' and not used. * Currently defaults to 'STANDARD' and not used.
*/ */
public String getStorageClass() { StorageClass getStorageClass();
return storageClass;
}
public void setCacheControl(String cacheControl) {
this.cacheControl = cacheControl;
}
/** /**
* Can be used to specify caching behavior along the request/reply chain. * Can be used to specify caching behavior along the request/reply chain.
* *
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.9. * @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.9.
*/ */
public String getCacheControl() { String getCacheControl();
return cacheControl;
}
public void setContentDisposition(String dataDisposition) {
this.dataDisposition = dataDisposition;
}
/** /**
* Specifies presentational information for the object. * Specifies presentational information for the object.
* *
* @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html?sec19.5.1."/> * @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html?sec19.5.1."/>
*/ */
public String getContentDisposition() { String getContentDisposition();
return dataDisposition;
}
public void setAccessControlList(AccessControlList acl) {
this.accessControlList = acl;
}
public AccessControlList getAccessControlList() {
return this.accessControlList;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((accessControlList == null) ? 0 : accessControlList.hashCode());
result = prime * result + ((cacheControl == null) ? 0 : cacheControl.hashCode());
result = prime * result + ((dataDisposition == null) ? 0 : dataDisposition.hashCode());
result = prime * result + ((owner == null) ? 0 : owner.hashCode());
result = prime * result + ((storageClass == null) ? 0 : storageClass.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;
ObjectMetadata other = (ObjectMetadata) obj;
if (accessControlList == null) {
if (other.accessControlList != null)
return false;
} else if (!accessControlList.equals(other.accessControlList))
return false;
if (cacheControl == null) {
if (other.cacheControl != null)
return false;
} else if (!cacheControl.equals(other.cacheControl))
return false;
if (dataDisposition == null) {
if (other.dataDisposition != null)
return false;
} else if (!dataDisposition.equals(other.dataDisposition))
return false;
if (owner == null) {
if (other.owner != null)
return false;
} else if (!owner.equals(other.owner))
return false;
if (storageClass == null) {
if (other.storageClass != null)
return false;
} else if (!storageClass.equals(other.storageClass))
return false;
return true;
}
public int compareTo(ObjectMetadata o) {
return (this == o) ? 0 : getName().compareTo(o.getName());
}
public void setContentEncoding(String dataEncoding) {
this.dataEncoding = dataEncoding;
}
/** /**
* Specifies what content encodings have been applied to the object and thus what decoding * Specifies what content encodings have been applied to the object and thus what decoding
@ -200,8 +86,33 @@ public class ObjectMetadata extends BlobMetadataImpl implements Serializable {
* *
* @see <a href= "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.11" /> * @see <a href= "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.11" />
*/ */
public String getContentEncoding() { String getContentEncoding();
return dataEncoding;
} /**
*
* A standard MIME type describing the format of the contents. If none is provided, the default
* is binary/octet-stream.
*
* @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17"/>
*/
String getContentType();
/**
* The base64 decoded 128-bit MD5 digest of the message (without the headers) according to RFC
* 1864. This header can be used as a message integrity check to verify that the data is the same
* data that was originally sent. Although it is optional, we recommend using the Content-MD5
* mechanism as an end-to-end integrity check.
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTAuthentication.html"/>
*/
byte[] getContentMD5();
DateTime getLastModified();
String getETag();
Long getSize();
Map<String, String> getUserMetadata();
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -23,41 +23,76 @@
*/ */
package org.jclouds.aws.s3.domain; package org.jclouds.aws.s3.domain;
import javax.inject.Inject; import java.io.IOException;
import org.jclouds.blobstore.internal.BlobImpl; import com.google.common.collect.Multimap;
import com.google.inject.internal.Nullable;
/** /**
* Amazon S3 is designed to store objects. Objects are stored in {@link S3Bucket buckets} and * Amazon S3 is designed to store objects. Objects are stored in buckets and consist of a
* consist of a {@link org.jclouds.aws.s3.domain.S3Object#getData() value}, a * {@link ObjectMetadataS3Object#getData() value}, a {@link ObjectMetadata#getKey key},
* {@link S3Object#getKey key}, {@link S3Object.Metadata#getUserMetadata() metadata}, and an access * {@link ObjectMetadata#getUserMetadata() metadata}, and an access control policy.
* control policy.
* *
* @author Adrian Cole * @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingObjects.html" * @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingObjects.html"
* /> * />
*/ */
public class S3Object extends BlobImpl<ObjectMetadata> { public interface S3Object extends Comparable<S3Object> {
public interface Factory {
public S3Object(ObjectMetadata metadata, Object data) { S3Object create(@Nullable MutableObjectMetadata metadata);
super(metadata, data);
} }
public S3Object(ObjectMetadata metadata) { /**
super(metadata); * Sets entity for the request or the content from the response. If size isn't set, this will
} * attempt to discover it.
*
* @param data
* typically InputStream for downloads, or File, byte [], String, or InputStream for
* uploads.
*/
void setData(Object data);
public S3Object(String key, Object data) { /**
this(new ObjectMetadata(key), data); * @return InputStream, if downloading, or whatever was set during {@link #setData(Object)}
} */
Object getData();
@Inject /**
public S3Object() { * generate an MD5 Hash for the current data.
this(new ObjectMetadata()); * <p/>
} * <h2>Note</h2>
* <p/>
* If this is an InputStream, it will be converted to a byte array first.
*
* @throws IOException
* if there is a problem generating the hash.
*/
void generateMD5() throws IOException;
public S3Object(String key) { void setContentLength(long contentLength);
this(new ObjectMetadata(key));
}
/**
* Returns the total size of the downloaded object, or the chunk that's available.
* <p/>
* Chunking is only used when org.jclouds.http.GetOptions is called with options like tail,
* range, or startAt.
*
* @return the length in bytes that can be be obtained from {@link #getData()}
* @see org.jclouds.http.HttpHeaders#CONTENT_LENGTH
* @see GetObjectOptions
*/
Long getContentLength();
/**
* @return System and User metadata relevant to this object.
*/
MutableObjectMetadata getMetadata();
Multimap<String, String> getAllHeaders();
void setAccessControlList(AccessControlList acl);
AccessControlList getAccessControlList();
void setAllHeaders(Multimap<String, String> allHeaders);
} }

View File

@ -0,0 +1,251 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.domain.internal;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Map;
import org.jclouds.aws.s3.domain.CanonicalUser;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.joda.time.DateTime;
import com.google.common.collect.Maps;
/**
* Returns the metadata parsable from a bucket listing
*
* @author Adrian Cole
*/
public class BucketListObjectMetadata implements Serializable, ObjectMetadata {
/** The serialVersionUID */
private static final long serialVersionUID = -4415449798024051115L;
private final String key;
private final DateTime lastModified;
private final String eTag;
private final long size;
private final CanonicalUser owner;
private final StorageClass storageClass;
private final String contentType;
private final byte[] contentMD5;
private final String cacheControl;
private final String contentDisposition;
private final String contentEncoding;
private final Map<String, String> userMetadata;
public BucketListObjectMetadata(String key, DateTime lastModified, String eTag, byte[] md5,
long size, CanonicalUser owner, StorageClass storageClass) {
this.key = key;
this.lastModified = lastModified;
this.eTag = eTag;
this.size = size;
this.owner = owner;
this.contentMD5 = md5;
this.storageClass = storageClass;
this.contentType = null;
this.cacheControl = null;
this.contentDisposition = null;
this.contentEncoding = null;
this.userMetadata = Maps.newHashMap();
}
/**
*{@inheritDoc}
*/
public String getKey() {
return key;
}
/**
*{@inheritDoc}
*/
public CanonicalUser getOwner() {
return owner;
}
/**
*{@inheritDoc}
*/
public StorageClass getStorageClass() {
return storageClass;
}
/**
*{@inheritDoc}
*/
public String getCacheControl() {
return cacheControl;
}
/**
*{@inheritDoc}
*/
public String getContentDisposition() {
return contentDisposition;
}
/**
*{@inheritDoc}
*/
public String getContentEncoding() {
return contentEncoding;
}
/**
*{@inheritDoc}
*/
public String getContentType() {
return contentType;
}
/**
*{@inheritDoc}
*/
public DateTime getLastModified() {
return lastModified;
}
/**
*{@inheritDoc}
*/
public String getETag() {
return eTag;
}
/**
*{@inheritDoc}
*/
public Long getSize() {
return size;
}
/**
*{@inheritDoc}
*/
public int compareTo(ObjectMetadata o) {
return (this == o) ? 0 : getKey().compareTo(o.getKey());
}
/**
*{@inheritDoc}
*/
public Map<String, String> getUserMetadata() {
return userMetadata;
}
/**
*{@inheritDoc}
*/
public byte[] getContentMD5() {
return contentMD5;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((cacheControl == null) ? 0 : cacheControl.hashCode());
result = prime * result + ((contentDisposition == null) ? 0 : contentDisposition.hashCode());
result = prime * result + ((contentEncoding == null) ? 0 : contentEncoding.hashCode());
result = prime * result + Arrays.hashCode(contentMD5);
result = prime * result + ((contentType == null) ? 0 : contentType.hashCode());
result = prime * result + ((eTag == null) ? 0 : eTag.hashCode());
result = prime * result + ((key == null) ? 0 : key.hashCode());
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
result = prime * result + ((owner == null) ? 0 : owner.hashCode());
result = prime * result + (int) (size ^ (size >>> 32));
result = prime * result + ((storageClass == null) ? 0 : storageClass.hashCode());
result = prime * result + ((userMetadata == null) ? 0 : userMetadata.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;
BucketListObjectMetadata other = (BucketListObjectMetadata) obj;
if (cacheControl == null) {
if (other.cacheControl != null)
return false;
} else if (!cacheControl.equals(other.cacheControl))
return false;
if (contentDisposition == null) {
if (other.contentDisposition != null)
return false;
} else if (!contentDisposition.equals(other.contentDisposition))
return false;
if (contentEncoding == null) {
if (other.contentEncoding != null)
return false;
} else if (!contentEncoding.equals(other.contentEncoding))
return false;
if (!Arrays.equals(contentMD5, other.contentMD5))
return false;
if (contentType == null) {
if (other.contentType != null)
return false;
} else if (!contentType.equals(other.contentType))
return false;
if (eTag == null) {
if (other.eTag != null)
return false;
} else if (!eTag.equals(other.eTag))
return false;
if (key == null) {
if (other.key != null)
return false;
} else if (!key.equals(other.key))
return false;
if (lastModified == null) {
if (other.lastModified != null)
return false;
} else if (!lastModified.equals(other.lastModified))
return false;
if (owner == null) {
if (other.owner != null)
return false;
} else if (!owner.equals(other.owner))
return false;
if (size != other.size)
return false;
if (storageClass == null) {
if (other.storageClass != null)
return false;
} else if (!storageClass.equals(other.storageClass))
return false;
if (userMetadata == null) {
if (other.userMetadata != null)
return false;
} else if (!userMetadata.equals(other.userMetadata))
return false;
return true;
}
}

View File

@ -0,0 +1,252 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.domain.internal;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Map;
import org.jclouds.aws.s3.domain.CanonicalUser;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.joda.time.DateTime;
/**
* Returns the metadata parsable from a bucket listing
*
* @author Adrian Cole
*/
public class CopyObjectResult implements Serializable, ObjectMetadata {
/** The serialVersionUID */
private static final long serialVersionUID = -4415449798024051115L;
private final String key;
private final DateTime lastModified;
private final String eTag;
private final Long size;
private final CanonicalUser owner;
private final StorageClass storageClass;
private final String contentType;
private final byte[] contentMD5;
private final String cacheControl;
private final String contentDisposition;
private final String contentEncoding;
private final Map<String, String> userMetadata;
public CopyObjectResult(DateTime lastModified, String eTag) {
this.key = null;
this.lastModified = lastModified;
this.eTag = eTag;
this.size = null;
this.owner = null;
this.storageClass = StorageClass.STANDARD;
this.contentType = null;
this.contentMD5 = null;
this.cacheControl = null;
this.contentDisposition = null;
this.contentEncoding = null;
this.userMetadata = null;
}
/**
*{@inheritDoc}
*/
public String getKey() {
return key;
}
/**
*{@inheritDoc}
*/
public CanonicalUser getOwner() {
return owner;
}
/**
*{@inheritDoc}
*/
public StorageClass getStorageClass() {
return storageClass;
}
/**
*{@inheritDoc}
*/
public String getCacheControl() {
return cacheControl;
}
/**
*{@inheritDoc}
*/
public String getContentDisposition() {
return contentDisposition;
}
/**
*{@inheritDoc}
*/
public String getContentEncoding() {
return contentEncoding;
}
/**
*{@inheritDoc}
*/
public String getContentType() {
return contentType;
}
/**
*{@inheritDoc}
*/
public DateTime getLastModified() {
return lastModified;
}
/**
*{@inheritDoc}
*/
public String getETag() {
return eTag;
}
/**
*{@inheritDoc}
*/
public Long getSize() {
return size;
}
/**
*{@inheritDoc}
*/
public int compareTo(ObjectMetadata o) {
return (this == o) ? 0 : getKey().compareTo(o.getKey());
}
/**
*{@inheritDoc}
*/
public Map<String, String> getUserMetadata() {
return userMetadata;
}
/**
*{@inheritDoc}
*/
public byte[] getContentMD5() {
return contentMD5;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((cacheControl == null) ? 0 : cacheControl.hashCode());
result = prime * result + ((contentDisposition == null) ? 0 : contentDisposition.hashCode());
result = prime * result + ((contentEncoding == null) ? 0 : contentEncoding.hashCode());
result = prime * result + Arrays.hashCode(contentMD5);
result = prime * result + ((contentType == null) ? 0 : contentType.hashCode());
result = prime * result + ((eTag == null) ? 0 : eTag.hashCode());
result = prime * result + ((key == null) ? 0 : key.hashCode());
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
result = prime * result + ((owner == null) ? 0 : owner.hashCode());
result = prime * result + ((size == null) ? 0 : size.hashCode());
result = prime * result + ((storageClass == null) ? 0 : storageClass.hashCode());
result = prime * result + ((userMetadata == null) ? 0 : userMetadata.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;
CopyObjectResult other = (CopyObjectResult) obj;
if (cacheControl == null) {
if (other.cacheControl != null)
return false;
} else if (!cacheControl.equals(other.cacheControl))
return false;
if (contentDisposition == null) {
if (other.contentDisposition != null)
return false;
} else if (!contentDisposition.equals(other.contentDisposition))
return false;
if (contentEncoding == null) {
if (other.contentEncoding != null)
return false;
} else if (!contentEncoding.equals(other.contentEncoding))
return false;
if (!Arrays.equals(contentMD5, other.contentMD5))
return false;
if (contentType == null) {
if (other.contentType != null)
return false;
} else if (!contentType.equals(other.contentType))
return false;
if (eTag == null) {
if (other.eTag != null)
return false;
} else if (!eTag.equals(other.eTag))
return false;
if (key == null) {
if (other.key != null)
return false;
} else if (!key.equals(other.key))
return false;
if (lastModified == null) {
if (other.lastModified != null)
return false;
} else if (!lastModified.equals(other.lastModified))
return false;
if (owner == null) {
if (other.owner != null)
return false;
} else if (!owner.equals(other.owner))
return false;
if (size == null) {
if (other.size != null)
return false;
} else if (!size.equals(other.size))
return false;
if (storageClass == null) {
if (other.storageClass != null)
return false;
} else if (!storageClass.equals(other.storageClass))
return false;
if (userMetadata == null) {
if (other.userMetadata != null)
return false;
} else if (!userMetadata.equals(other.userMetadata))
return false;
return true;
}
}

View File

@ -0,0 +1,334 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.domain.internal;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Map;
import org.jclouds.aws.s3.domain.CanonicalUser;
import org.jclouds.aws.s3.domain.MutableObjectMetadata;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.joda.time.DateTime;
import com.google.common.collect.Maps;
/**
* Allows you to manipulate metadata.
*
* @author Adrian Cole
*/
public class MutableObjectMetadataImpl implements Serializable, MutableObjectMetadata {
/** The serialVersionUID */
private static final long serialVersionUID = -4648755473986695062L;
private String key;
private DateTime lastModified;
private String eTag;
private long size;
private CanonicalUser owner;
private StorageClass storageClass;
private String contentType;
private byte[] contentMD5;
private String cacheControl;
private String contentDisposition;
private String contentEncoding;
private Map<String, String> userMetadata = Maps.newHashMap();
public MutableObjectMetadataImpl() {
this.storageClass = StorageClass.STANDARD;
}
/**
*{@inheritDoc}
*/
public String getKey() {
return key;
}
/**
*{@inheritDoc}
*/
public CanonicalUser getOwner() {
return owner;
}
/**
*{@inheritDoc}
*/
public StorageClass getStorageClass() {
return storageClass;
}
/**
*{@inheritDoc}
*/
public String getCacheControl() {
return cacheControl;
}
/**
*{@inheritDoc}
*/
public String getContentDisposition() {
return contentDisposition;
}
/**
*{@inheritDoc}
*/
public String getContentEncoding() {
return contentEncoding;
}
/**
*{@inheritDoc}
*/
public String getContentType() {
return contentType;
}
/**
*{@inheritDoc}
*/
public DateTime getLastModified() {
return lastModified;
}
/**
*{@inheritDoc}
*/
public String getETag() {
return eTag;
}
/**
*{@inheritDoc}
*/
public Long getSize() {
return size;
}
/**
*{@inheritDoc}
*/
public int compareTo(ObjectMetadata o) {
return (this == o) ? 0 : getKey().compareTo(o.getKey());
}
/**
*{@inheritDoc}
*/
public Map<String, String> getUserMetadata() {
return userMetadata;
}
/**
*{@inheritDoc}
*/
public byte[] getContentMD5() {
if (contentMD5 != null) {
byte[] retval = new byte[contentMD5.length];
System.arraycopy(this.contentMD5, 0, retval, 0, contentMD5.length);
return retval;
} else {
return null;
}
}
/**
*{@inheritDoc}
*/
public void setCacheControl(String cacheControl) {
this.cacheControl = cacheControl;
}
/**
*{@inheritDoc}
*/
public void setContentDisposition(String contentDisposition) {
this.contentDisposition = contentDisposition;
}
/**
*{@inheritDoc}
*/
public void setContentEncoding(String encoding) {
this.contentEncoding = encoding;
}
/**
*{@inheritDoc}
*/
public void setContentMD5(byte[] md5) {
if (md5 != null) {
byte[] retval = new byte[md5.length];
System.arraycopy(md5, 0, retval, 0, md5.length);
this.contentMD5 = md5;
}
}
/**
*{@inheritDoc}
*/
public void setContentType(String contentType) {
this.contentType = contentType;
}
/**
*{@inheritDoc}
*/
public void setETag(String eTag) {
this.eTag = eTag;
}
/**
*{@inheritDoc}
*/
public void setKey(String key) {
this.key = key;
}
/**
*{@inheritDoc}
*/
public void setLastModified(DateTime lastModified) {
this.lastModified = lastModified;
}
/**
*{@inheritDoc}
*/
public void setOwner(CanonicalUser owner) {
this.owner = owner;
}
/**
*{@inheritDoc}
*/
public void setSize(long size) {
this.size = size;
}
/**
*{@inheritDoc}
*/
public void setStorageClass(StorageClass storageClass) {
this.storageClass = storageClass;
}
/**
*{@inheritDoc}
*/
public void setUserMetadata(Map<String, String> userMetadata) {
this.userMetadata = userMetadata;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((cacheControl == null) ? 0 : cacheControl.hashCode());
result = prime * result + ((contentDisposition == null) ? 0 : contentDisposition.hashCode());
result = prime * result + ((contentEncoding == null) ? 0 : contentEncoding.hashCode());
result = prime * result + Arrays.hashCode(contentMD5);
result = prime * result + ((contentType == null) ? 0 : contentType.hashCode());
result = prime * result + ((eTag == null) ? 0 : eTag.hashCode());
result = prime * result + ((key == null) ? 0 : key.hashCode());
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
result = prime * result + ((owner == null) ? 0 : owner.hashCode());
result = prime * result + (int) (size ^ (size >>> 32));
result = prime * result + ((storageClass == null) ? 0 : storageClass.hashCode());
result = prime * result + ((userMetadata == null) ? 0 : userMetadata.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;
MutableObjectMetadataImpl other = (MutableObjectMetadataImpl) obj;
if (cacheControl == null) {
if (other.cacheControl != null)
return false;
} else if (!cacheControl.equals(other.cacheControl))
return false;
if (contentDisposition == null) {
if (other.contentDisposition != null)
return false;
} else if (!contentDisposition.equals(other.contentDisposition))
return false;
if (contentEncoding == null) {
if (other.contentEncoding != null)
return false;
} else if (!contentEncoding.equals(other.contentEncoding))
return false;
if (!Arrays.equals(contentMD5, other.contentMD5))
return false;
if (contentType == null) {
if (other.contentType != null)
return false;
} else if (!contentType.equals(other.contentType))
return false;
if (eTag == null) {
if (other.eTag != null)
return false;
} else if (!eTag.equals(other.eTag))
return false;
if (key == null) {
if (other.key != null)
return false;
} else if (!key.equals(other.key))
return false;
if (lastModified == null) {
if (other.lastModified != null)
return false;
} else if (!lastModified.equals(other.lastModified))
return false;
if (owner == null) {
if (other.owner != null)
return false;
} else if (!owner.equals(other.owner))
return false;
if (size != other.size)
return false;
if (storageClass == null) {
if (other.storageClass != null)
return false;
} else if (!storageClass.equals(other.storageClass))
return false;
if (userMetadata == null) {
if (other.userMetadata != null)
return false;
} else if (!userMetadata.equals(other.userMetadata))
return false;
return true;
}
}

View File

@ -0,0 +1,210 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.domain.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.io.InputStream;
import javax.inject.Inject;
import org.jclouds.aws.s3.domain.AccessControlList;
import org.jclouds.aws.s3.domain.MutableObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.blobstore.domain.MD5InputStreamResult;
import org.jclouds.blobstore.functions.CalculateSize;
import org.jclouds.blobstore.functions.GenerateMD5;
import org.jclouds.blobstore.functions.GenerateMD5Result;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
/**
* Default Implementation of {@link S3Object}.
*
* @author Adrian Cole
*/
public class S3ObjectImpl implements S3Object, Comparable<S3Object> {
private final GenerateMD5Result generateMD5Result;
private final GenerateMD5 generateMD5;
private final CalculateSize calculateSize;
private final MutableObjectMetadata metadata;
private Object data;
private Multimap<String, String> allHeaders = HashMultimap.create();
private Long contentLength;
@Inject
public S3ObjectImpl(GenerateMD5Result generateMD5Result, GenerateMD5 generateMD5,
CalculateSize calculateSize, MutableObjectMetadata metadata) {
this.generateMD5Result = generateMD5Result;
this.generateMD5 = generateMD5;
this.calculateSize = calculateSize;
this.metadata = metadata;
}
private AccessControlList accessControlList;
/**
* {@inheritDoc}
*/
public void setAccessControlList(AccessControlList acl) {
this.accessControlList = acl;
}
/**
* {@inheritDoc}
*/
public AccessControlList getAccessControlList() {
return this.accessControlList;
}
/**
* {@inheritDoc}
*/
public void generateMD5() {
checkState(data != null, "data");
if (data instanceof InputStream) {
MD5InputStreamResult result = generateMD5Result.apply((InputStream) data);
getMetadata().setContentMD5(result.md5);
setContentLength(result.length);
setData(result.data);
} else {
getMetadata().setContentMD5(generateMD5.apply(data));
}
}
/**
* {@inheritDoc}
*/
public Object getData() {
return data;
}
/**
* {@inheritDoc}
*/
public void setData(Object data) {
this.data = checkNotNull(data, "data");
if (getContentLength() == null) {
Long size = calculateSize.apply(data);
if (size != null)
this.setContentLength(size);
}
}
/**
* {@inheritDoc}
*/
public Long getContentLength() {
return contentLength;
}
/**
* {@inheritDoc}
*/
public void setContentLength(long contentLength) {
this.contentLength = contentLength;
}
/**
* {@inheritDoc}
*/
public MutableObjectMetadata getMetadata() {
return metadata;
}
/**
* {@inheritDoc}
*/
public Multimap<String, String> getAllHeaders() {
return allHeaders;
}
/**
* {@inheritDoc}
*/
public void setAllHeaders(Multimap<String, String> allHeaders) {
this.allHeaders = checkNotNull(allHeaders, "allHeaders");
}
/**
* {@inheritDoc}
*/
public int compareTo(S3Object o) {
if (getMetadata().getKey() == null)
return -1;
return (this == o) ? 0 : getMetadata().getKey().compareTo(o.getMetadata().getKey());
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((accessControlList == null) ? 0 : accessControlList.hashCode());
result = prime * result + ((allHeaders == null) ? 0 : allHeaders.hashCode());
result = prime * result + ((contentLength == null) ? 0 : contentLength.hashCode());
result = prime * result + ((data == null) ? 0 : data.hashCode());
result = prime * result + ((metadata == null) ? 0 : metadata.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;
S3ObjectImpl other = (S3ObjectImpl) obj;
if (accessControlList == null) {
if (other.accessControlList != null)
return false;
} else if (!accessControlList.equals(other.accessControlList))
return false;
if (allHeaders == null) {
if (other.allHeaders != null)
return false;
} else if (!allHeaders.equals(other.allHeaders))
return false;
if (contentLength == null) {
if (other.contentLength != null)
return false;
} else if (!contentLength.equals(other.contentLength))
return false;
if (data == null) {
if (other.data != null)
return false;
} else if (!data.equals(other.data))
return false;
if (metadata == null) {
if (other.metadata != null)
return false;
} else if (!metadata.equals(other.metadata))
return false;
return true;
}
}

View File

@ -0,0 +1,168 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.domain.internal;
import java.util.SortedSet;
import java.util.TreeSet;
import org.jclouds.aws.s3.domain.ListBucketResponse;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import com.google.common.collect.Iterables;
/**
*
* @author Adrian Cole
*
*/
public class TreeSetListBucketResponse extends TreeSet<ObjectMetadata> implements
ListBucketResponse {
/** The serialVersionUID */
private static final long serialVersionUID = -4475709781001190244L;
private final String name;
protected final String prefix;
protected final int maxKeys;
private final String delimiter;
protected final String marker;
private final SortedSet<String> commonPrefixes;
protected final boolean truncated;
public TreeSetListBucketResponse(String name, Iterable<ObjectMetadata> contents, String prefix,
String marker, int maxKeys, String delimiter, boolean isTruncated,
SortedSet<String> commonPrefixes) {
Iterables.addAll(this, contents);
this.name = name;
this.prefix = prefix;
this.marker = marker;
this.maxKeys = maxKeys;
this.truncated = isTruncated;
this.delimiter = delimiter;
this.commonPrefixes = commonPrefixes;
}
/**
* {@inheritDoc}
*/
public SortedSet<String> getCommonPrefixes() {
return commonPrefixes;
}
/**
* {@inheritDoc}
*/
public String getDelimiter() {
return delimiter;
}
/**
* {@inheritDoc}
*/
public String getMarker() {
return marker;
}
/**
* {@inheritDoc}
*/
public int getMaxKeys() {
return maxKeys;
}
/**
* {@inheritDoc}
*/
public String getPrefix() {
return prefix;
}
/**
* {@inheritDoc}
*/
public boolean isTruncated() {
return truncated;
}
/**
* {@inheritDoc}
*/
public String getName() {
return name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((commonPrefixes == null) ? 0 : commonPrefixes.hashCode());
result = prime * result + ((delimiter == null) ? 0 : delimiter.hashCode());
result = prime * result + ((marker == null) ? 0 : marker.hashCode());
result = prime * result + maxKeys;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((prefix == null) ? 0 : prefix.hashCode());
result = prime * result + (truncated ? 1231 : 1237);
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;
TreeSetListBucketResponse other = (TreeSetListBucketResponse) obj;
if (commonPrefixes == null) {
if (other.commonPrefixes != null)
return false;
} else if (!commonPrefixes.equals(other.commonPrefixes))
return false;
if (delimiter == null) {
if (other.delimiter != null)
return false;
} else if (!delimiter.equals(other.delimiter))
return false;
if (marker == null) {
if (other.marker != null)
return false;
} else if (!marker.equals(other.marker))
return false;
if (maxKeys != other.maxKeys)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (prefix == null) {
if (other.prefix != null)
return false;
} else if (!prefix.equals(other.prefix))
return false;
if (truncated != other.truncated)
return false;
return true;
}
}

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,45 +0,0 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.functions;
import javax.inject.Inject;
import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.functions.ClearAndDeleteIfNotEmpty;
import org.jclouds.blobstore.strategy.ClearContainerStrategy;
public class ClearAndDeleteBucketIfNotEmpty extends
ClearAndDeleteIfNotEmpty<BucketMetadata, ObjectMetadata, S3Object> {
@Inject
ClearAndDeleteBucketIfNotEmpty(
ClearContainerStrategy<BucketMetadata, ObjectMetadata, S3Object> clear,
BlobStore<BucketMetadata, ObjectMetadata, S3Object> connection) {
super(clear, connection);
}
}

View File

@ -0,0 +1,40 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.functions;
import org.jclouds.aws.s3.domain.S3Object;
import com.google.common.base.Function;
/**
*
* @author Adrian Cole
*/
public class ObjectKey implements Function<Object, String> {
public String apply(Object from) {
return ((S3Object) from).getMetadata().getKey();
}
}

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -24,11 +24,17 @@
package org.jclouds.aws.s3.functions; package org.jclouds.aws.s3.functions;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Provider; import javax.ws.rs.core.HttpHeaders;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.blobstore.functions.ParseBlobFromHeadersAndHttpContent; import org.jclouds.blobstore.functions.ParseSystemAndUserMetadataFromHeaders;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse;
import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
/** /**
* Parses response headers and creates a new S3Object from them and the HTTP content. * Parses response headers and creates a new S3Object from them and the HTTP content.
@ -36,13 +42,60 @@ import org.jclouds.blobstore.functions.ParseBlobFromHeadersAndHttpContent;
* @see ParseMetadataFromHeaders * @see ParseMetadataFromHeaders
* @author Adrian Cole * @author Adrian Cole
*/ */
public class ParseObjectFromHeadersAndHttpContent extends public class ParseObjectFromHeadersAndHttpContent implements Function<HttpResponse, S3Object>,
ParseBlobFromHeadersAndHttpContent<ObjectMetadata, S3Object> { InvocationContext {
private final ParseObjectMetadataFromHeaders metadataParser;
private final S3Object.Factory objectProvider;
@Inject @Inject
public ParseObjectFromHeadersAndHttpContent(ParseObjectMetadataFromHeaders metadataParser, public ParseObjectFromHeadersAndHttpContent(ParseObjectMetadataFromHeaders metadataParser,
Provider<S3Object> blobFactory) { S3Object.Factory objectProvider) {
super(metadataParser, blobFactory); this.metadataParser = metadataParser;
this.objectProvider = objectProvider;
}
/**
* First, calls {@link ParseSystemAndUserMetadataFromHeaders}.
*
* Then, sets the object size based on the Content-Length header and adds the content to the
* {@link S3Object} result.
*
* @throws org.jclouds.http.HttpException
*/
public S3Object apply(HttpResponse from) {
S3Object object = objectProvider.create(metadataParser.apply(from));
addAllHeadersTo(from, object);
object.setData(from.getContent());
attemptToParseSizeAndRangeFromHeaders(from, object);
return object;
}
@VisibleForTesting
void attemptToParseSizeAndRangeFromHeaders(HttpResponse from, S3Object object)
throws HttpException {
String contentLength = from.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH);
String contentRange = from.getFirstHeaderOrNull("Content-Range");
if (contentLength != null) {
object.setContentLength(Long.parseLong(contentLength));
}
if (contentRange == null && contentLength != null) {
object.getMetadata().setSize(object.getContentLength());
} else if (contentRange != null) {
object.getMetadata().setSize(
Long.parseLong(contentRange.substring(contentRange.lastIndexOf('/') + 1)));
}
}
@VisibleForTesting
void addAllHeadersTo(HttpResponse from, S3Object object) {
object.getAllHeaders().putAll(from.getHeaders());
}
public void setContext(GeneratedHttpRequest<?> request) {
metadataParser.setContext(request);
} }
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -23,45 +23,50 @@
*/ */
package org.jclouds.aws.s3.functions; package org.jclouds.aws.s3.functions;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import org.jclouds.aws.s3.domain.ObjectMetadata; import org.jclouds.aws.s3.blobstore.functions.BlobToObjectMetadata;
import org.jclouds.aws.s3.domain.MutableObjectMetadata;
import org.jclouds.aws.s3.reference.S3Headers; import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.functions.ParseSystemAndUserMetadataFromHeaders; import org.jclouds.blobstore.functions.ParseSystemAndUserMetadataFromHeaders;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.util.DateService; import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
/** /**
* This parses @{link {@link org.jclouds.aws.s3.domain.ObjectMetadata} from HTTP headers. * This parses @{link {@link org.jclouds.aws.s3.domain.internal.MutableObjectMetadata} from HTTP
* headers.
* *
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTObjectGET.html" /> * @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTObjectGET.html" />
* @author Adrian Cole * @author Adrian Cole
*/ */
public class ParseObjectMetadataFromHeaders extends public class ParseObjectMetadataFromHeaders implements
ParseSystemAndUserMetadataFromHeaders<ObjectMetadata> { Function<HttpResponse, MutableObjectMetadata>, InvocationContext {
private final ParseSystemAndUserMetadataFromHeaders blobMetadataParser;
private final BlobToObjectMetadata blobToObjectMetadata;
@Inject @Inject
public ParseObjectMetadataFromHeaders(DateService dateParser, public ParseObjectMetadataFromHeaders(ParseSystemAndUserMetadataFromHeaders blobMetadataParser,
@Named(PROPERTY_USER_METADATA_PREFIX) String metadataPrefix, BlobToObjectMetadata blobToObjectMetadata) {
Provider<ObjectMetadata> metadataFactory) { this.blobMetadataParser = blobMetadataParser;
super(dateParser, metadataPrefix, metadataFactory); this.blobToObjectMetadata = blobToObjectMetadata;
} }
/** /**
* parses the http response headers to create a new * parses the http response headers to create a new
* {@link org.jclouds.aws.s3.domain.ObjectMetadata} object. * {@link org.jclouds.aws.s3.domain.internal.MutableObjectMetadata} object.
*/ */
@Override public MutableObjectMetadata apply(HttpResponse from) {
public ObjectMetadata apply(HttpResponse from) { BlobMetadata base = blobMetadataParser.apply(from);
ObjectMetadata to = super.apply(from); MutableObjectMetadata to = blobToObjectMetadata.apply(base);
addETagTo(from, to);
to.setContentMD5(HttpUtils.fromHexString(to.getETag().replaceAll("\"", "")));
to.setCacheControl(from.getFirstHeaderOrNull(HttpHeaders.CACHE_CONTROL)); to.setCacheControl(from.getFirstHeaderOrNull(HttpHeaders.CACHE_CONTROL));
to.setContentDisposition(from.getFirstHeaderOrNull("Content-Disposition")); to.setContentDisposition(from.getFirstHeaderOrNull("Content-Disposition"));
to.setContentEncoding(from.getFirstHeaderOrNull(HttpHeaders.CONTENT_ENCODING)); to.setContentEncoding(from.getFirstHeaderOrNull(HttpHeaders.CONTENT_ENCODING));
@ -72,15 +77,17 @@ public class ParseObjectMetadataFromHeaders extends
* ETag == Content-MD5 * ETag == Content-MD5
*/ */
@VisibleForTesting @VisibleForTesting
protected void addETagTo(HttpResponse from, ObjectMetadata metadata) { protected void addETagTo(HttpResponse from, MutableObjectMetadata metadata) {
super.addETagTo(from, metadata);
if (metadata.getETag() == null) { if (metadata.getETag() == null) {
String eTagHeader = from.getFirstHeaderOrNull(S3Headers.AMZ_MD5); String eTagHeader = from.getFirstHeaderOrNull(S3Headers.AMZ_MD5);
if (eTagHeader != null) { if (eTagHeader != null) {
metadata.setETag(eTagHeader); metadata.setETag(eTagHeader);
} }
} }
metadata.setContentMD5(HttpUtils.fromHexString(metadata.getETag().replaceAll("\"", ""))); }
public void setContext(GeneratedHttpRequest<?> request) {
blobMetadataParser.setContext(request);
} }
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -23,6 +23,8 @@
*/ */
package org.jclouds.aws.s3.functions; package org.jclouds.aws.s3.functions;
import javax.inject.Singleton;
import org.jclouds.aws.AWSResponseException; import org.jclouds.aws.AWSResponseException;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -31,6 +33,7 @@ import com.google.common.base.Function;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton
public class ReturnTrueIfBucketAlreadyOwnedByYou implements Function<Exception, Boolean> { public class ReturnTrueIfBucketAlreadyOwnedByYou implements Function<Exception, Boolean> {
public Boolean apply(Exception from) { public Boolean apply(Exception from) {

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -23,10 +23,13 @@
*/ */
package org.jclouds.aws.s3.functions; package org.jclouds.aws.s3.functions;
import javax.inject.Singleton;
import org.jclouds.aws.AWSResponseException; import org.jclouds.aws.AWSResponseException;
import com.google.common.base.Function; import com.google.common.base.Function;
@Singleton
public class ReturnTrueOn404FalseIfNotEmpty implements Function<Exception, Boolean> { public class ReturnTrueOn404FalseIfNotEmpty implements Function<Exception, Boolean> {
public Boolean apply(Exception from) { public Boolean apply(Exception from) {

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -62,7 +62,7 @@ public class AWSClientErrorRetryHandler implements HttpRetryHandler {
if (command.getFailureCount() > retryCountLimit) if (command.getFailureCount() > retryCountLimit)
return false; return false;
if (response.getStatusCode() == 400 || response.getStatusCode() == 409) { if (response.getStatusCode() == 400 || response.getStatusCode() == 409) {
byte[] content = Utils.closeConnectionButKeepContentStream(response); byte[] content = Utils.closeClientButKeepContentStream(response);
command.incrementFailureCount(); command.incrementFailureCount();
try { try {
AWSError error = utils.parseAWSErrorFromContent(command, response, new String(content)); AWSError error = utils.parseAWSErrorFromContent(command, response, new String(content));

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -55,7 +55,7 @@ public class AWSRedirectionRetryHandler extends RedirectionRetryHandler {
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) { public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
if (response.getFirstHeaderOrNull(HttpHeaders.LOCATION) == null if (response.getFirstHeaderOrNull(HttpHeaders.LOCATION) == null
&& (response.getStatusCode() == 301 || response.getStatusCode() == 307)) { && (response.getStatusCode() == 301 || response.getStatusCode() == 307)) {
byte[] content = Utils.closeConnectionButKeepContentStream(response); byte[] content = Utils.closeClientButKeepContentStream(response);
if (command.getRequest().getMethod() == HttpMethod.HEAD) { if (command.getRequest().getMethod() == HttpMethod.HEAD) {
command.setMethod(HttpMethod.GET); command.setMethod(HttpMethod.GET);
return true; return true;

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -53,7 +53,7 @@ import com.google.common.collect.Multimap;
* <code> * <code>
* import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.* * import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.*
* <p/> * <p/>
* S3Connection connection = // get connection * S3Client connection = // get connection
* <p/> * <p/>
* Multimap<String,String> metadata = HashMultimap.create(); * Multimap<String,String> metadata = HashMultimap.create();
* metadata.put("x-amz-meta-adrian", "foo"); * metadata.put("x-amz-meta-adrian", "foo");

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -37,7 +37,7 @@ import org.jclouds.http.options.BaseHttpRequestOptions;
* <code> * <code>
* import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.* * import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.*
* <p/> * <p/>
* S3Connection connection = // get connection * S3Client connection = // get connection
* Future<S3Bucket> bucket = connection.listBucket("bucketName",withPrefix("home/users").maxKeys(1000)); * Future<S3Bucket> bucket = connection.listBucket("bucketName",withPrefix("home/users").maxKeys(1000));
* <code> * <code>
* *
@ -60,6 +60,10 @@ public class ListBucketOptions extends BaseHttpRequestOptions {
return this; return this;
} }
public String getPrefix() {
return getFirstQueryOrNull("prefix");
}
/** /**
* Indicates where in the bucket to begin listing. The list will only include keys that occur * Indicates where in the bucket to begin listing. The list will only include keys that occur
* lexicographically after marker. This is convenient for pagination: To get the next page of * lexicographically after marker. This is convenient for pagination: To get the next page of
@ -70,17 +74,25 @@ public class ListBucketOptions extends BaseHttpRequestOptions {
return this; return this;
} }
public String getMarker() {
return getFirstQueryOrNull("marker");
}
/** /**
* The maximum number of keys you'd like to see in the response body. The server might return * The maximum number of keys you'd like to see in the response body. The server might return
* fewer than this many keys, but will not return more. * fewer than this many keys, but will not return more.
*/ */
public ListBucketOptions maxResults(long maxKeys) { public ListBucketOptions maxResults(int maxKeys) {
checkState(maxKeys >= 0, "maxKeys must be >= 0"); checkState(maxKeys >= 0, "maxKeys must be >= 0");
queryParameters.put("max-keys", Long.toString(maxKeys)); queryParameters.put("max-keys", Long.toString(maxKeys));
return this; return this;
} }
public Integer getMaxResults() {
String returnVal = getFirstQueryOrNull("max-keys");
return (returnVal != null) ? new Integer(returnVal) : null;
}
/** /**
* Causes keys that contain the same string between the prefix and the first occurrence of the * Causes keys that contain the same string between the prefix and the first occurrence of the
* delimiter to be rolled up into a single result element in the CommonPrefixes collection. These * delimiter to be rolled up into a single result element in the CommonPrefixes collection. These
@ -92,6 +104,10 @@ public class ListBucketOptions extends BaseHttpRequestOptions {
return this; return this;
} }
public String getDelimiter() {
return getFirstQueryOrNull("delimiter");
}
public static class Builder { public static class Builder {
/** /**
@ -111,9 +127,9 @@ public class ListBucketOptions extends BaseHttpRequestOptions {
} }
/** /**
* @see ListBucketOptions#maxResults(long) * @see ListBucketOptions#maxResults(int)
*/ */
public static ListBucketOptions maxResults(long maxKeys) { public static ListBucketOptions maxResults(int maxKeys) {
ListBucketOptions options = new ListBucketOptions(); ListBucketOptions options = new ListBucketOptions();
return options.maxResults(maxKeys); return options.maxResults(maxKeys);
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -39,9 +39,9 @@ import org.jclouds.http.options.BaseHttpRequestOptions;
* <code> * <code>
* import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.* * import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.*
* import static org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint.*; * import static org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint.*;
* import org.jclouds.aws.s3.S3Connection; * import org.jclouds.aws.s3.S3Client;
* <p/> * <p/>
* S3Connection connection = // get connection * S3Client connection = // get connection
* Future<Boolean> createdInEu = connection.putBucketIfNotExists("bucketName",createIn(EU)); * Future<Boolean> createdInEu = connection.putBucketIfNotExists("bucketName",createIn(EU));
* <code> * <code>
* *

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -39,9 +39,9 @@ import static com.google.common.base.Preconditions.*;
* <p/> * <p/>
* <code> * <code>
* import static org.jclouds.aws.s3.commands.options.PutObjectOptions.Builder.* * import static org.jclouds.aws.s3.commands.options.PutObjectOptions.Builder.*
* import org.jclouds.aws.s3.S3Connection; * import org.jclouds.aws.s3.S3Client;
* *
* S3Connection connection = // get connection * S3Client connection = // get connection
* Future<Boolean> publicly readable = connection.putObject("bucketName",new S3Object("key","value"), withAcl(CannedAccessPolicy.PUBLIC_READ)); * Future<Boolean> publicly readable = connection.putObject("bucketName",new S3Object("key","value"), withAcl(CannedAccessPolicy.PUBLIC_READ));
* <code> * <code>
* *

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -24,14 +24,13 @@
package org.jclouds.aws.s3.reference; package org.jclouds.aws.s3.reference;
import org.jclouds.aws.reference.AWSConstants; import org.jclouds.aws.reference.AWSConstants;
import org.jclouds.blobstore.reference.BlobStoreConstants;
/** /**
* Configuration properties and constants used in S3 connections. * Configuration properties and constants used in S3 connections.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public interface S3Constants extends AWSConstants, S3Headers, BlobStoreConstants { 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.
@ -47,5 +46,6 @@ public interface S3Constants extends AWSConstants, S3Headers, BlobStoreConstants
* how long do we wait before obtaining a new timestamp for requests. * how long do we wait before obtaining a new timestamp for requests.
*/ */
public static final String PROPERTY_S3_SESSIONINTERVAL = "jclouds.s3.sessioninterval"; public static final String PROPERTY_S3_SESSIONINTERVAL = "jclouds.s3.sessioninterval";
public static final String PROPERTY_S3_METADATA_PREFIX = "jclouds.s3.metaprefix";
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -26,8 +26,10 @@ package org.jclouds.aws.s3.xml;
import javax.inject.Inject; import javax.inject.Inject;
import org.jclouds.aws.s3.domain.ObjectMetadata; import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.internal.CopyObjectResult;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
import org.jclouds.util.DateService; import org.jclouds.util.DateService;
import org.joda.time.DateTime;
/** /**
* Parses the response from Amazon S3 COPY Object command. * Parses the response from Amazon S3 COPY Object command.
@ -39,10 +41,12 @@ import org.jclouds.util.DateService;
*/ */
public class CopyObjectHandler extends ParseSax.HandlerWithResult<ObjectMetadata> { public class CopyObjectHandler extends ParseSax.HandlerWithResult<ObjectMetadata> {
private ObjectMetadata metadata = new ObjectMetadata(); private CopyObjectResult metadata;
private StringBuilder currentText = new StringBuilder(); private StringBuilder currentText = new StringBuilder();
@Inject @Inject
private DateService dateParser; private DateService dateParser;
private DateTime currentLastModified;
private String currentETag;
public ObjectMetadata getResult() { public ObjectMetadata getResult() {
return metadata; return metadata;
@ -50,9 +54,11 @@ public class CopyObjectHandler extends ParseSax.HandlerWithResult<ObjectMetadata
public void endElement(String uri, String name, String qName) { public void endElement(String uri, String name, String qName) {
if (qName.equals("ETag")) { if (qName.equals("ETag")) {
metadata.setETag(currentText.toString()); this.currentETag = currentText.toString().trim();
} else if (qName.equals("LastModified")) { } else if (qName.equals("LastModified")) {
metadata.setLastModified(dateParser.iso8601DateParse(currentText.toString())); this.currentLastModified = dateParser.iso8601DateParse(currentText.toString().trim());
} else if (qName.equals("CopyObjectResult")) {
metadata = new CopyObjectResult(currentLastModified, currentETag);
} }
currentText = new StringBuilder(); currentText = new StringBuilder();
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -31,6 +31,7 @@ import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.CanonicalUser; import org.jclouds.aws.s3.domain.CanonicalUser;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
import org.jclouds.util.DateService; import org.jclouds.util.DateService;
import org.joda.time.DateTime;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@ -47,11 +48,12 @@ import com.google.common.collect.Sets;
public class ListAllMyBucketsHandler extends ParseSax.HandlerWithResult<SortedSet<BucketMetadata>> { public class ListAllMyBucketsHandler extends ParseSax.HandlerWithResult<SortedSet<BucketMetadata>> {
private SortedSet<BucketMetadata> buckets = Sets.newTreeSet(); private SortedSet<BucketMetadata> buckets = Sets.newTreeSet();
private BucketMetadata currentS3Bucket;
private CanonicalUser currentOwner; private CanonicalUser currentOwner;
private StringBuilder currentText = new StringBuilder(); private StringBuilder currentText = new StringBuilder();
private final DateService dateParser; private final DateService dateParser;
private String currentName;
private DateTime currentCreationDate;
@Inject @Inject
public ListAllMyBucketsHandler(DateService dateParser) { public ListAllMyBucketsHandler(DateService dateParser) {
@ -64,16 +66,15 @@ public class ListAllMyBucketsHandler extends ParseSax.HandlerWithResult<SortedSe
public void endElement(String uri, String name, String qName) { public void endElement(String uri, String name, String qName) {
if (qName.equals("ID")) { // owner stuff if (qName.equals("ID")) { // owner stuff
currentOwner = new CanonicalUser(currentText.toString()); currentOwner = new CanonicalUser(currentText.toString().trim());
} else if (qName.equals("DisplayName")) { } else if (qName.equals("DisplayName")) {
currentOwner.setDisplayName(currentText.toString()); currentOwner.setDisplayName(currentText.toString().trim());
} else if (qName.equals("Bucket")) { } else if (qName.equals("Bucket")) {
currentS3Bucket.setOwner(currentOwner); buckets.add(new BucketMetadata(currentName, currentCreationDate, currentOwner));
buckets.add(currentS3Bucket);
} else if (qName.equals("Name")) { } else if (qName.equals("Name")) {
currentS3Bucket = new BucketMetadata(currentText.toString()); currentName = currentText.toString().trim();
} else if (qName.equals("CreationDate")) { } else if (qName.equals("CreationDate")) {
currentS3Bucket.setCreationDate(dateParser.iso8601DateParse(currentText.toString())); currentCreationDate = dateParser.iso8601DateParse(currentText.toString().trim());
} }
currentText = new StringBuilder(); currentText = new StringBuilder();
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -30,10 +30,13 @@ import javax.inject.Inject;
import org.jclouds.aws.s3.domain.CanonicalUser; import org.jclouds.aws.s3.domain.CanonicalUser;
import org.jclouds.aws.s3.domain.ListBucketResponse; import org.jclouds.aws.s3.domain.ListBucketResponse;
import org.jclouds.aws.s3.domain.ObjectMetadata; import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.TreeSetListBucketResponse; import org.jclouds.aws.s3.domain.ObjectMetadata.StorageClass;
import org.jclouds.aws.s3.domain.internal.BucketListObjectMetadata;
import org.jclouds.aws.s3.domain.internal.TreeSetListBucketResponse;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
import org.jclouds.util.DateService; import org.jclouds.util.DateService;
import org.joda.time.DateTime;
import org.xml.sax.Attributes; import org.xml.sax.Attributes;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@ -51,7 +54,6 @@ import com.google.common.collect.Sets;
public class ListBucketHandler extends ParseSax.HandlerWithResult<ListBucketResponse> { public class ListBucketHandler extends ParseSax.HandlerWithResult<ListBucketResponse> {
private SortedSet<ObjectMetadata> contents; private SortedSet<ObjectMetadata> contents;
private SortedSet<String> commonPrefixes; private SortedSet<String> commonPrefixes;
private ObjectMetadata currentObjectMetadata;
private CanonicalUser currentOwner; private CanonicalUser currentOwner;
private StringBuilder currentText = new StringBuilder(); private StringBuilder currentText = new StringBuilder();
@ -76,6 +78,12 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult<ListBucketResp
} }
private boolean inCommonPrefixes; private boolean inCommonPrefixes;
private String currentKey;
private DateTime currentLastModified;
private String currentETag;
private byte[] currentMD5;
private long currentSize;
private StorageClass currentStorageClass;
public void startElement(String uri, String name, String qName, Attributes attrs) { public void startElement(String uri, String name, String qName, Attributes attrs) {
if (qName.equals("CommonPrefixes")) { if (qName.equals("CommonPrefixes")) {
@ -85,27 +93,26 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult<ListBucketResp
public void endElement(String uri, String name, String qName) { public void endElement(String uri, String name, String qName) {
if (qName.equals("ID")) { if (qName.equals("ID")) {
currentOwner = new CanonicalUser(currentText.toString()); currentOwner = new CanonicalUser(currentText.toString().trim());
} else if (qName.equals("DisplayName")) { } else if (qName.equals("DisplayName")) {
currentOwner.setDisplayName(currentText.toString()); currentOwner.setDisplayName(currentText.toString().trim());
} else if (qName.equals("Key")) { // content stuff } else if (qName.equals("Key")) { // content stuff
currentObjectMetadata = new ObjectMetadata(currentText.toString()); currentKey = currentText.toString().trim();
} else if (qName.equals("LastModified")) { } else if (qName.equals("LastModified")) {
currentObjectMetadata.setLastModified(dateParser.iso8601DateParse(currentText.toString())); currentLastModified = dateParser.iso8601DateParse(currentText.toString().trim());
} else if (qName.equals("ETag")) { } else if (qName.equals("ETag")) {
currentObjectMetadata.setETag(currentText.toString()); currentETag = currentText.toString().trim();
currentObjectMetadata.setContentMD5(HttpUtils.fromHexString(currentObjectMetadata currentMD5 = HttpUtils.fromHexString(currentETag.replaceAll("\"", ""));
.getETag().replaceAll("\"", "")));
} else if (qName.equals("Size")) { } else if (qName.equals("Size")) {
currentObjectMetadata.setSize(Long.parseLong(currentText.toString())); currentSize = new Long(currentText.toString().trim());
} else if (qName.equals("Owner")) { } else if (qName.equals("Owner")) {
currentObjectMetadata.setOwner(currentOwner);
} else if (qName.equals("StorageClass")) { } else if (qName.equals("StorageClass")) {
currentObjectMetadata.setStorageClass(currentText.toString()); currentStorageClass = ObjectMetadata.StorageClass.valueOf(currentText.toString().trim());
} else if (qName.equals("Contents")) { } else if (qName.equals("Contents")) {
contents.add(currentObjectMetadata); contents.add(new BucketListObjectMetadata(currentKey, currentLastModified, currentETag,
currentMD5, currentSize, currentOwner, currentStorageClass));
} else if (qName.equals("Name")) { } else if (qName.equals("Name")) {
this.bucketName = currentText.toString(); this.bucketName = currentText.toString().trim();
} else if (qName.equals("Prefix")) { } else if (qName.equals("Prefix")) {
String prefix = currentText.toString().trim(); String prefix = currentText.toString().trim();
if (inCommonPrefixes) if (inCommonPrefixes)
@ -117,11 +124,11 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult<ListBucketResp
this.delimiter = currentText.toString().trim(); this.delimiter = currentText.toString().trim();
} else if (qName.equals("Marker")) { } else if (qName.equals("Marker")) {
if (!currentText.toString().equals("")) if (!currentText.toString().equals(""))
this.marker = currentText.toString(); this.marker = currentText.toString().trim();
} else if (qName.equals("MaxKeys")) { } else if (qName.equals("MaxKeys")) {
this.maxResults = Integer.parseInt(currentText.toString()); this.maxResults = Integer.parseInt(currentText.toString().trim());
} else if (qName.equals("IsTruncated")) { } else if (qName.equals("IsTruncated")) {
this.isTruncated = Boolean.parseBoolean(currentText.toString()); this.isTruncated = Boolean.parseBoolean(currentText.toString().trim());
} }
currentText = new StringBuilder(); currentText = new StringBuilder();
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -23,8 +23,8 @@
*/ */
package org.jclouds.aws.s3; package org.jclouds.aws.s3;
import static org.jclouds.aws.s3.internal.StubS3Connection.TEST_ACL_EMAIL; import static org.jclouds.aws.s3.internal.StubS3Client.TEST_ACL_EMAIL;
import static org.jclouds.aws.s3.internal.StubS3Connection.TEST_ACL_ID; import static org.jclouds.aws.s3.internal.StubS3Client.TEST_ACL_ID;
import static org.jclouds.aws.s3.options.CopyObjectOptions.Builder.ifSourceETagDoesntMatch; import static org.jclouds.aws.s3.options.CopyObjectOptions.Builder.ifSourceETagDoesntMatch;
import static org.jclouds.aws.s3.options.CopyObjectOptions.Builder.ifSourceETagMatches; import static org.jclouds.aws.s3.options.CopyObjectOptions.Builder.ifSourceETagMatches;
import static org.jclouds.aws.s3.options.CopyObjectOptions.Builder.ifSourceModifiedSince; import static org.jclouds.aws.s3.options.CopyObjectOptions.Builder.ifSourceModifiedSince;
@ -43,6 +43,7 @@ import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertTrue;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URL; import java.net.URL;
import java.util.Map; import java.util.Map;
@ -76,9 +77,8 @@ import com.google.common.collect.Maps;
* @author James Murty * @author James Murty
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = { "integration", "live" }, testName = "s3.S3ConnectionLiveTest") @Test(groups = { "integration", "live" }, testName = "s3.S3ClientLiveTest")
public class S3ConnectionLiveTest extends public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest<S3Client> {
BaseBlobStoreIntegrationTest<S3Connection, BucketMetadata, ObjectMetadata, S3Object> {
/** /**
* this method overrides containerName to ensure it isn't found * this method overrides containerName to ensure it isn't found
@ -103,8 +103,10 @@ public class S3ConnectionLiveTest extends
String containerName = getContainerName(); String containerName = getContainerName();
try { try {
String key = "hello"; String key = "hello";
S3Object object = context.getApi().newS3Object();
context.getApi().putObject(containerName, new S3Object(key, TEST_STRING), object.getMetadata().setKey(key);
object.setData(TEST_STRING);
context.getApi().putObject(containerName, object,
withAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, TimeUnit.SECONDS); withAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, TimeUnit.SECONDS);
@ -147,12 +149,15 @@ public class S3ConnectionLiveTest extends
final String publicReadWriteObjectKey = "public-read-write-acl"; final String publicReadWriteObjectKey = "public-read-write-acl";
final String containerName = getContainerName(); final String containerName = getContainerName();
try { try {
S3Object object = context.getApi().newS3Object();
object.getMetadata().setKey(publicReadWriteObjectKey);
object.setData("");
// Public Read-Write object // Public Read-Write object
context.getApi().putObject(containerName, new S3Object(publicReadWriteObjectKey, ""), context.getApi().putObject(containerName, object,
new PutObjectOptions().withAcl(CannedAccessPolicy.PUBLIC_READ_WRITE)).get(10, new PutObjectOptions().withAcl(CannedAccessPolicy.PUBLIC_READ_WRITE)).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
assertEventually(new Runnable() { assertConsistencyAware(new Runnable() {
public void run() { public void run() {
try { try {
AccessControlList acl = context.getApi().getObjectACL(containerName, AccessControlList acl = context.getApi().getObjectACL(containerName,
@ -252,11 +257,14 @@ public class S3ConnectionLiveTest extends
final String publicReadObjectKey = "public-read-acl"; final String publicReadObjectKey = "public-read-acl";
final String containerName = getContainerName(); final String containerName = getContainerName();
try { try {
context.getApi().putObject(containerName, new S3Object(publicReadObjectKey, ""), S3Object object = context.getApi().newS3Object();
object.getMetadata().setKey(publicReadObjectKey);
object.setData("");
context.getApi().putObject(containerName, object,
new PutObjectOptions().withAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, new PutObjectOptions().withAcl(CannedAccessPolicy.PUBLIC_READ)).get(10,
TimeUnit.SECONDS); TimeUnit.SECONDS);
assertEventually(new Runnable() { assertConsistencyAware(new Runnable() {
public void run() { public void run() {
try { try {
AccessControlList acl = context.getApi().getObjectACL(containerName, AccessControlList acl = context.getApi().getObjectACL(containerName,
@ -280,17 +288,38 @@ public class S3ConnectionLiveTest extends
} }
protected String addBlobToContainer(String sourceContainer, String key)
throws InterruptedException, ExecutionException, TimeoutException, IOException {
S3Object sourceObject = context.getApi().newS3Object();
sourceObject.getMetadata().setKey(key);
sourceObject.getMetadata().setContentType("text/xml");
sourceObject.setData(TEST_STRING);
return context.getApi().putObject(sourceContainer, sourceObject).get(10, TimeUnit.SECONDS);
}
protected S3Object validateObject(String sourceContainer, String key)
throws InterruptedException, ExecutionException, TimeoutException, IOException {
assertConsistencyAwareContainerSize(sourceContainer, 1);
S3Object newObject = context.getApi().getObject(sourceContainer, key).get(30,
TimeUnit.SECONDS);
assert newObject != null;
assertEquals(Utils.toStringAndClose((InputStream) newObject.getData()), TEST_STRING);
return newObject;
}
public void testMetadataWithCacheControlAndContentDisposition() throws Exception { public void testMetadataWithCacheControlAndContentDisposition() throws Exception {
String key = "hello"; String key = "hello";
S3Object object = context.newBlob(key); S3Object object = context.getApi().newS3Object();
object.getMetadata().setKey(key);
object.setData(TEST_STRING); object.setData(TEST_STRING);
object.getMetadata().setCacheControl("no-cache"); object.getMetadata().setCacheControl("no-cache");
object.getMetadata().setContentDisposition("attachment; filename=hello.txt"); object.getMetadata().setContentDisposition("attachment; filename=hello.txt");
String containerName = getContainerName(); String containerName = getContainerName();
try { try {
addBlobToContainer(containerName, object); context.getApi().putObject(containerName, object).get(10, TimeUnit.SECONDS);
S3Object newObject = validateContent(containerName, key);
S3Object newObject = validateObject(containerName, key);
assertEquals(newObject.getMetadata().getCacheControl(), "no-cache"); assertEquals(newObject.getMetadata().getCacheControl(), "no-cache");
assertEquals(newObject.getMetadata().getContentDisposition(), assertEquals(newObject.getMetadata().getContentDisposition(),
@ -304,13 +333,14 @@ public class S3ConnectionLiveTest extends
public void testMetadataContentEncoding() throws Exception { public void testMetadataContentEncoding() throws Exception {
String key = "hello"; String key = "hello";
S3Object object = context.newBlob(key); S3Object object = context.getApi().newS3Object();
object.getMetadata().setKey(key);
object.setData(TEST_STRING); object.setData(TEST_STRING);
object.getMetadata().setContentEncoding("x-compress"); object.getMetadata().setContentEncoding("x-compress");
String containerName = getContainerName(); String containerName = getContainerName();
try { try {
addBlobToContainer(containerName, object); context.getApi().putObject(containerName, object).get(10, TimeUnit.SECONDS);
S3Object newObject = validateContent(containerName, key); S3Object newObject = validateObject(containerName, key);
assertEquals(newObject.getMetadata().getContentEncoding(), "x-compress"); assertEquals(newObject.getMetadata().getContentEncoding(), "x-compress");
} finally { } finally {
@ -478,44 +508,6 @@ public class S3ConnectionLiveTest extends
} }
} }
public void testListContainerDelimiter() throws InterruptedException, ExecutionException,
TimeoutException, UnsupportedEncodingException {
String containerName = getContainerName();
try {
String prefix = "apps";
addTenObjectsUnderPrefix(containerName, prefix);
add15UnderRoot(containerName);
ListBucketResponse container = context.getApi().listBucket(containerName, delimiter("/"))
.get(10, TimeUnit.SECONDS);
assertEquals(container.getDelimiter(), "/");
assert !container.isTruncated();
assertEquals(container.size(), 15);
assertEquals(container.getCommonPrefixes().size(), 1);
} finally {
returnContainer(containerName);
}
}
public void testListContainerPrefix() throws InterruptedException, ExecutionException,
TimeoutException, UnsupportedEncodingException {
String containerName = getContainerName();
try {
String prefix = "apps";
addTenObjectsUnderPrefix(containerName, prefix);
add15UnderRoot(containerName);
ListBucketResponse container = context.getApi().listBucket(containerName,
withPrefix("apps/")).get(10, TimeUnit.SECONDS);
assert !container.isTruncated();
assertEquals(container.size(), 10);
assertEquals(container.getPrefix(), "apps/");
} finally {
returnContainer(containerName);
}
}
public void testPrivateAclIsDefaultForContainer() throws InterruptedException, public void testPrivateAclIsDefaultForContainer() throws InterruptedException,
ExecutionException, TimeoutException, IOException { ExecutionException, TimeoutException, IOException {
String containerName = getContainerName(); String containerName = getContainerName();
@ -575,36 +567,6 @@ public class S3ConnectionLiveTest extends
acl.addPermission(new CanonicalUserGrantee(ownerId), Permission.WRITE_ACP); acl.addPermission(new CanonicalUserGrantee(ownerId), Permission.WRITE_ACP);
} }
public void testListContainerMarker() throws InterruptedException, ExecutionException,
TimeoutException, UnsupportedEncodingException {
String containerName = getContainerName();
try {
addAlphabetUnderRoot(containerName);
ListBucketResponse container = context.getApi()
.listBucket(containerName, afterMarker("y")).get(10, TimeUnit.SECONDS);
assertEquals(container.getMarker(), "y");
assert !container.isTruncated();
assertEquals(container.size(), 1);
} finally {
returnContainer(containerName);
}
}
public void testListContainerMaxResults() throws InterruptedException, ExecutionException,
TimeoutException, UnsupportedEncodingException {
String containerName = getContainerName();
try {
addAlphabetUnderRoot(containerName);
ListBucketResponse container = context.getApi().listBucket(containerName, maxResults(5))
.get(10, TimeUnit.SECONDS);
assertEquals(container.getMaxResults(), 5);
assert container.isTruncated();
assertEquals(container.size(), 5);
} finally {
returnContainer(containerName);
}
}
public void testPublicReadAccessPolicy() throws Exception { public void testPublicReadAccessPolicy() throws Exception {
String containerName = getScratchContainerName(); String containerName = getScratchContainerName();
try { try {
@ -643,7 +605,7 @@ public class S3ConnectionLiveTest extends
context.getApi().putBucketIfNotExists(containerName + "eu", context.getApi().putBucketIfNotExists(containerName + "eu",
createIn(LocationConstraint.EU).withBucketAcl(CannedAccessPolicy.PUBLIC_READ)) createIn(LocationConstraint.EU).withBucketAcl(CannedAccessPolicy.PUBLIC_READ))
.get(30, TimeUnit.SECONDS); .get(30, TimeUnit.SECONDS);
assertEventually(new Runnable() { assertConsistencyAware(new Runnable() {
public void run() { public void run() {
try { try {
AccessControlList acl = context.getApi().getBucketACL(containerName + "eu").get( AccessControlList acl = context.getApi().getBucketACL(containerName + "eu").get(
@ -667,10 +629,11 @@ public class S3ConnectionLiveTest extends
void containerExists() throws Exception { void containerExists() throws Exception {
String containerName = getContainerName(); String containerName = getContainerName();
try { try {
SortedSet<BucketMetadata> list = context.getApi().listOwnedBuckets(); SortedSet<BucketMetadata> list = context.getApi().listOwnedBuckets().get(10,
TimeUnit.SECONDS);
BucketMetadata firstContainer = list.first(); BucketMetadata firstContainer = list.first();
BucketMetadata toMatch = new BucketMetadata(containerName); BucketMetadata toMatch = new BucketMetadata(containerName, new DateTime(), firstContainer
toMatch.setOwner(firstContainer.getOwner()); .getOwner());
assert list.contains(toMatch); assert list.contains(toMatch);
} finally { } finally {
returnContainer(containerName); returnContainer(containerName);
@ -680,16 +643,86 @@ public class S3ConnectionLiveTest extends
protected void addAlphabetUnderRoot(String containerName) throws InterruptedException, protected void addAlphabetUnderRoot(String containerName) throws InterruptedException,
ExecutionException, TimeoutException { ExecutionException, TimeoutException {
for (char letter = 'a'; letter <= 'z'; letter++) { for (char letter = 'a'; letter <= 'z'; letter++) {
S3Object blob = context.newBlob(letter + ""); S3Object blob = context.getApi().newS3Object();
blob.getMetadata().setKey(letter + "");
blob.setData(letter + "content"); blob.setData(letter + "content");
context.getApi().putObject(containerName, blob).get(10, TimeUnit.SECONDS); context.getApi().putObject(containerName, blob).get(10, TimeUnit.SECONDS);
} }
} }
public void testListContainerMarker() throws InterruptedException, ExecutionException,
TimeoutException, UnsupportedEncodingException {
String containerName = getContainerName();
try {
addAlphabetUnderRoot(containerName);
ListBucketResponse container = context.getApi()
.listBucket(containerName, afterMarker("y")).get(10, TimeUnit.SECONDS);
assertEquals(container.getMarker(), "y");
assert !container.isTruncated();
assertEquals(container.size(), 1);
} finally {
returnContainer(containerName);
}
}
public void testListContainerDelimiter() throws InterruptedException, ExecutionException,
TimeoutException, UnsupportedEncodingException {
String containerName = getContainerName();
try {
String prefix = "apps";
addTenObjectsUnderPrefix(containerName, prefix);
add15UnderRoot(containerName);
ListBucketResponse container = context.getApi().listBucket(containerName, delimiter("/"))
.get(10, TimeUnit.SECONDS);
assertEquals(container.getDelimiter(), "/");
assert !container.isTruncated();
assertEquals(container.size(), 15);
assertEquals(container.getCommonPrefixes().size(), 1);
} finally {
returnContainer(containerName);
}
}
public void testListContainerPrefix() throws InterruptedException, ExecutionException,
TimeoutException, UnsupportedEncodingException {
String containerName = getContainerName();
try {
String prefix = "apps";
addTenObjectsUnderPrefix(containerName, prefix);
add15UnderRoot(containerName);
ListBucketResponse container = context.getApi().listBucket(containerName,
withPrefix("apps/")).get(10, TimeUnit.SECONDS);
assert !container.isTruncated();
assertEquals(container.size(), 10);
assertEquals(container.getPrefix(), "apps/");
} finally {
returnContainer(containerName);
}
}
public void testListContainerMaxResults() throws InterruptedException, ExecutionException,
TimeoutException, UnsupportedEncodingException {
String containerName = getContainerName();
try {
addAlphabetUnderRoot(containerName);
ListBucketResponse container = context.getApi().listBucket(containerName, maxResults(5))
.get(10, TimeUnit.SECONDS);
assertEquals(container.getMaxKeys(), 5);
assert container.isTruncated();
assertEquals(container.size(), 5);
} finally {
returnContainer(containerName);
}
}
protected void add15UnderRoot(String containerName) throws InterruptedException, protected void add15UnderRoot(String containerName) throws InterruptedException,
ExecutionException, TimeoutException { ExecutionException, TimeoutException {
for (int i = 0; i < 15; i++) { for (int i = 0; i < 15; i++) {
S3Object blob = context.newBlob(i + ""); S3Object blob = context.getApi().newS3Object();
blob.getMetadata().setKey(i + "");
blob.setData(i + "content"); blob.setData(i + "content");
context.getApi().putObject(containerName, blob).get(10, TimeUnit.SECONDS); context.getApi().putObject(containerName, blob).get(10, TimeUnit.SECONDS);
} }
@ -698,7 +731,8 @@ public class S3ConnectionLiveTest extends
protected void addTenObjectsUnderPrefix(String containerName, String prefix) protected void addTenObjectsUnderPrefix(String containerName, String prefix)
throws InterruptedException, ExecutionException, TimeoutException { throws InterruptedException, ExecutionException, TimeoutException {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
S3Object blob = context.newBlob(prefix + "/" + i); S3Object blob = context.getApi().newS3Object();
blob.getMetadata().setKey(prefix + "/" + i);
blob.setData(i + "content"); blob.setData(i + "content");
context.getApi().putObject(containerName, blob).get(10, TimeUnit.SECONDS); context.getApi().putObject(containerName, blob).get(10, TimeUnit.SECONDS);
} }

View File

@ -0,0 +1,382 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.net.URI;
import org.jclouds.aws.s3.blobstore.functions.BlobToObject;
import org.jclouds.aws.s3.config.S3ObjectModule;
import org.jclouds.aws.s3.domain.AccessControlList;
import org.jclouds.aws.s3.domain.CannedAccessPolicy;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
import org.jclouds.aws.s3.functions.ParseObjectFromHeadersAndHttpContent;
import org.jclouds.aws.s3.functions.ParseObjectMetadataFromHeaders;
import org.jclouds.aws.s3.functions.ReturnTrueIfBucketAlreadyOwnedByYou;
import org.jclouds.aws.s3.functions.ReturnTrueOn404FalseIfNotEmpty;
import org.jclouds.aws.s3.options.CopyObjectOptions;
import org.jclouds.aws.s3.options.ListBucketOptions;
import org.jclouds.aws.s3.options.PutBucketOptions;
import org.jclouds.aws.s3.options.PutObjectOptions;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.aws.s3.xml.AccessControlListHandler;
import org.jclouds.aws.s3.xml.CopyObjectHandler;
import org.jclouds.aws.s3.xml.ListAllMyBucketsHandler;
import org.jclouds.aws.s3.xml.ListBucketHandler;
import org.jclouds.blobstore.binders.BindBlobToMultipartFormTest;
import org.jclouds.blobstore.config.BlobStoreObjectModule;
import org.jclouds.blobstore.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404;
import org.jclouds.blobstore.functions.ThrowKeyNotFoundOn404;
import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.http.functions.ParseETagHeader;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ReturnFalseOn404;
import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.http.functions.ReturnVoidIf2xx;
import org.jclouds.http.options.GetOptions;
import org.jclouds.logging.Logger;
import org.jclouds.logging.Logger.LoggerFactory;
import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.Jsr330;
import org.jclouds.util.TimeStamp;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.inject.AbstractModule;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of {@code S3Client}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "s3.S3ClientTest")
public class S3ClientTest extends RestClientTest<S3Client> {
public void testListBucket() throws SecurityException, NoSuchMethodException, IOException {
Method method = S3Client.class.getMethod("listBucket", String.class, Array.newInstance(
ListBucketOptions.class, 0).getClass());
GeneratedHttpRequest<S3Client> httpMethod = processor.createRequest(method, "bucket");
assertRequestLineEquals(httpMethod, "GET http://bucket.stub:8080/ HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
assertEntityEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, ListBucketHandler.class);
assertExceptionParserClassEquals(method, null);
checkFilters(httpMethod);
}
public void testBucketExists() throws SecurityException, NoSuchMethodException, IOException {
Method method = S3Client.class.getMethod("bucketExists", String.class);
GeneratedHttpRequest<S3Client> httpMethod = processor.createRequest(method, "bucket");
assertRequestLineEquals(httpMethod, "HEAD http://bucket.stub:8080/?max-keys=0 HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
assertEntityEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ReturnTrueIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnFalseOn404.class);
checkFilters(httpMethod);
}
public void testCopyObject() throws ArrayIndexOutOfBoundsException, SecurityException,
IllegalArgumentException, NoSuchMethodException, IOException {
Method method = S3Client.class
.getMethod("copyObject", String.class, String.class, String.class, String.class,
Array.newInstance(CopyObjectOptions.class, 0).getClass());
GeneratedHttpRequest<S3Client> httpMethod = processor.createRequest(method,
"sourceBucket", "sourceObject", "destinationBucket", "destinationObject");
assertRequestLineEquals(httpMethod,
"PUT http://destinationBucket.stub:8080/destinationObject HTTP/1.1");
assertHeadersEqual(httpMethod,
"Content-Length: 0\nHost: destinationBucket.stub\nx-amz-copy-source: /sourceBucket/sourceObject\n");
assertEntityEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, CopyObjectHandler.class);
assertExceptionParserClassEquals(method, null);
checkFilters(httpMethod);
}
public void testDeleteBucketIfEmpty() throws SecurityException, NoSuchMethodException,
IOException {
Method method = S3Client.class.getMethod("deleteBucketIfEmpty", String.class);
GeneratedHttpRequest<S3Client> httpMethod = processor.createRequest(method, "bucket");
assertRequestLineEquals(httpMethod, "DELETE http://bucket.stub:8080/ HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
assertEntityEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ReturnTrueIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnTrueOn404FalseIfNotEmpty.class);
checkFilters(httpMethod);
}
public void testDeleteObject() throws SecurityException, NoSuchMethodException, IOException {
Method method = S3Client.class.getMethod("deleteObject", String.class, String.class);
GeneratedHttpRequest<S3Client> httpMethod = processor.createRequest(method, "bucket",
"object");
assertRequestLineEquals(httpMethod, "DELETE http://bucket.stub:8080/object HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
assertEntityEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class);
checkFilters(httpMethod);
}
public void testGetBucketACL() throws SecurityException, NoSuchMethodException, IOException {
Method method = S3Client.class.getMethod("getBucketACL", String.class);
GeneratedHttpRequest<S3Client> httpMethod = processor.createRequest(method, "bucket");
assertRequestLineEquals(httpMethod, "GET http://bucket.stub:8080/?acl HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
assertEntityEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, AccessControlListHandler.class);
assertExceptionParserClassEquals(method, ThrowContainerNotFoundOn404.class);
checkFilters(httpMethod);
}
public void testGetObject() throws ArrayIndexOutOfBoundsException, SecurityException,
IllegalArgumentException, NoSuchMethodException, IOException {
Method method = S3Client.class.getMethod("getObject", String.class, String.class, Array
.newInstance(GetOptions.class, 0).getClass());
GeneratedHttpRequest<S3Client> httpMethod = processor.createRequest(method, "bucket",
"object");
assertRequestLineEquals(httpMethod, "GET http://bucket.stub:8080/object HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
assertEntityEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod,
ParseObjectFromHeadersAndHttpContent.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ThrowKeyNotFoundOn404.class);
checkFilters(httpMethod);
}
public void testGetObjectACL() throws SecurityException, NoSuchMethodException, IOException {
Method method = S3Client.class.getMethod("getObjectACL", String.class, String.class);
GeneratedHttpRequest<S3Client> httpMethod = processor.createRequest(method, "bucket",
"object");
assertRequestLineEquals(httpMethod, "GET http://bucket.stub:8080/object?acl HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
assertEntityEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, AccessControlListHandler.class);
assertExceptionParserClassEquals(method, ThrowKeyNotFoundOn404.class);
checkFilters(httpMethod);
}
public void testHeadObject() throws SecurityException, NoSuchMethodException, IOException {
Method method = S3Client.class.getMethod("headObject", String.class, String.class);
GeneratedHttpRequest<S3Client> httpMethod = processor.createRequest(method, "bucket",
"object");
assertRequestLineEquals(httpMethod, "HEAD http://bucket.stub:8080/object HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: bucket.stub\n");
assertEntityEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ParseObjectMetadataFromHeaders.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ThrowKeyNotFoundOn404.class);
checkFilters(httpMethod);
}
public void testListOwnedBuckets() throws SecurityException, NoSuchMethodException, IOException {
Method method = S3Client.class.getMethod("listOwnedBuckets");
GeneratedHttpRequest<S3Client> httpMethod = processor.createRequest(method);
assertRequestLineEquals(httpMethod, "GET http://stub:8080/ HTTP/1.1");
assertHeadersEqual(httpMethod, "Host: stub\n");
assertEntityEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ParseSax.class);
assertSaxResponseParserClassEquals(method, ListAllMyBucketsHandler.class);
assertExceptionParserClassEquals(method, null);
checkFilters(httpMethod);
}
public void testNewS3Object() throws SecurityException, NoSuchMethodException, IOException {
Method method = S3Client.class.getMethod("newS3Object");
assertEquals(method.getReturnType(), S3Object.class);
}
public void testPutBucketACL() throws SecurityException, NoSuchMethodException, IOException {
Method method = S3Client.class.getMethod("putBucketACL", String.class,
AccessControlList.class);
GeneratedHttpRequest<S3Client> httpMethod = processor.createRequest(method, "bucket",
AccessControlList.fromCannedAccessPolicy(CannedAccessPolicy.PRIVATE, "1234"));
assertRequestLineEquals(httpMethod, "PUT http://bucket.stub:8080/?acl HTTP/1.1");
assertHeadersEqual(httpMethod,
"Content-Length: 321\nContent-Type: text/xml\nHost: bucket.stub\n");
assertEntityEquals(
httpMethod,
"<AccessControlPolicy xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Owner><ID>1234</ID></Owner><AccessControlList><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CanonicalUser\"><ID>1234</ID></Grantee><Permission>FULL_CONTROL</Permission></Grant></AccessControlList></AccessControlPolicy>");
assertResponseParserClassEquals(method, httpMethod, ReturnTrueIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpMethod);
}
public void testPutBucketIfNotExists() throws ArrayIndexOutOfBoundsException, SecurityException,
IllegalArgumentException, NoSuchMethodException, IOException {
Method method = S3Client.class.getMethod("putBucketIfNotExists", String.class, Array
.newInstance(PutBucketOptions.class, 0).getClass());
GeneratedHttpRequest<S3Client> httpMethod = processor.createRequest(method, "bucket");
assertRequestLineEquals(httpMethod, "PUT http://bucket.stub:8080/ HTTP/1.1");
assertHeadersEqual(httpMethod, "Content-Length: 0\nHost: bucket.stub\n");
assertEntityEquals(httpMethod, null);
assertResponseParserClassEquals(method, httpMethod, ReturnTrueIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnTrueIfBucketAlreadyOwnedByYou.class);
checkFilters(httpMethod);
}
public void testPutObject() throws ArrayIndexOutOfBoundsException, SecurityException,
IllegalArgumentException, NoSuchMethodException, IOException {
Method method = S3Client.class.getMethod("putObject", String.class, S3Object.class, Array
.newInstance(PutObjectOptions.class, 0).getClass());
GeneratedHttpRequest<S3Client> httpMethod = processor.createRequest(method, "bucket",
blobToS3Object.apply(BindBlobToMultipartFormTest.TEST_BLOB));
assertRequestLineEquals(httpMethod, "PUT http://bucket.stub:8080/hello HTTP/1.1");
assertHeadersEqual(httpMethod,
"Content-Length: 5\nContent-Type: text/plain\nHost: bucket.stub\n");
assertEntityEquals(httpMethod, "hello");
assertResponseParserClassEquals(method, httpMethod, ParseETagHeader.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpMethod);
}
public void testPutObjectACL() throws SecurityException, NoSuchMethodException, IOException {
Method method = S3Client.class.getMethod("putObjectACL", String.class, String.class,
AccessControlList.class);
GeneratedHttpRequest<S3Client> httpMethod = processor.createRequest(method, "bucket",
"key", AccessControlList.fromCannedAccessPolicy(CannedAccessPolicy.PRIVATE, "1234"));
assertRequestLineEquals(httpMethod, "PUT http://bucket.stub:8080/key?acl HTTP/1.1");
assertHeadersEqual(httpMethod,
"Content-Length: 321\nContent-Type: text/xml\nHost: bucket.stub\n");
assertEntityEquals(
httpMethod,
"<AccessControlPolicy xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Owner><ID>1234</ID></Owner><AccessControlList><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CanonicalUser\"><ID>1234</ID></Grantee><Permission>FULL_CONTROL</Permission></Grant></AccessControlList></AccessControlPolicy>");
assertResponseParserClassEquals(method, httpMethod, ReturnTrueIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpMethod);
}
BlobToObject blobToS3Object;
@Override
protected void checkFilters(GeneratedHttpRequest<S3Client> httpMethod) {
assertEquals(httpMethod.getFilters().size(), 1);
assertEquals(httpMethod.getFilters().get(0).getClass(), RequestAuthorizeSignature.class);
}
@Override
protected TypeLiteral<RestAnnotationProcessor<S3Client>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<S3Client>>() {
};
}
@BeforeClass
@Override
protected void setupFactory() {
super.setupFactory();
blobToS3Object = injector.getInstance(BlobToObject.class);
}
@Override
protected Module createModule() {
return new AbstractModule() {
@Override
protected void configure() {
install(new BlobStoreObjectModule());
install(new S3ObjectModule());
bind(URI.class).annotatedWith(S3.class).toInstance(URI.create("http://stub:8080"));
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to(
"user");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY))
.to("key");
bindConstant().annotatedWith(
Jsr330.named(BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX)).to("prefix");
bindConstant().annotatedWith(TimeStamp.class).to("timestamp");
bind(Logger.LoggerFactory.class).toInstance(new LoggerFactory() {
public Logger getLogger(String category) {
return Logger.NULL;
}
});
}
};
}
}

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -25,23 +25,28 @@ package org.jclouds.aws.s3;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID; import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY; import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.jclouds.aws.s3.config.RestS3ConnectionModule;
import org.jclouds.aws.s3.config.S3ContextModule; import org.jclouds.aws.s3.config.S3ContextModule;
import org.jclouds.aws.s3.config.StubS3BlobStoreModule; import org.jclouds.aws.s3.config.S3RestClientModule;
import org.jclouds.aws.s3.config.S3ContextModule.S3ContextImpl; import org.jclouds.aws.s3.config.S3StubClientModule;
import org.jclouds.aws.s3.internal.StubS3Connection; import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.blobstore.integration.internal.StubBlobStore; import org.jclouds.aws.s3.domain.internal.S3ObjectImpl;
import org.jclouds.aws.s3.internal.StubS3Client;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.RestContextImpl;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module; import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/** /**
* Tests behavior of modules configured in S3ContextBuilder * Tests behavior of modules configured in S3ContextBuilder
@ -52,43 +57,49 @@ import com.google.inject.Module;
public class S3ContextBuilderTest { public class S3ContextBuilderTest {
public void testNewBuilder() { public void testNewBuilder() {
S3ContextBuilder builder = new S3ContextBuilder("id", "secret"); S3ContextBuilder builder = new S3ContextBuilder(new S3PropertiesBuilder("id", "secret")
assertEquals(builder.getProperties().getProperty(PROPERTY_USER_METADATA_PREFIX), .build());
assertEquals(builder.getProperties().getProperty(S3Constants.PROPERTY_S3_METADATA_PREFIX),
"x-amz-meta-"); "x-amz-meta-");
assertEquals(builder.getProperties().getProperty(PROPERTY_AWS_ACCESSKEYID), "id"); assertEquals(builder.getProperties().getProperty(PROPERTY_AWS_ACCESSKEYID), "id");
assertEquals(builder.getProperties().getProperty(PROPERTY_AWS_SECRETACCESSKEY), "secret"); assertEquals(builder.getProperties().getProperty(PROPERTY_AWS_SECRETACCESSKEY), "secret");
} }
public void testBuildContext() { public void testBuildContext() {
S3Context context = new S3ContextBuilder("id", "secret").withModules( RestContext<S3Client> context = new S3ContextBuilder(new S3PropertiesBuilder("id", "secret")
new StubS3BlobStoreModule()).buildContext(); .build()).withModules(new S3StubClientModule()).buildContext();
assertEquals(context.getClass(), S3ContextImpl.class); assertEquals(context.getClass(), RestContextImpl.class);
assertEquals(context.getApi().getClass(), StubS3Connection.class); assertEquals(context.getApi().getClass(), StubS3Client.class);
assertEquals(context.getBlobStore().getClass(), StubBlobStore.class); assertEquals(context.getApi().newS3Object().getClass(), S3ObjectImpl.class);
assertEquals(context.getAccount(), "id"); assertEquals(context.getAccount(), "id");
assertEquals(context.getEndPoint(), URI.create("https://localhost/s3stub")); assertEquals(context.getEndPoint(), URI.create("https://localhost/s3stub"));
} }
public void testBuildInjector() { public void testBuildInjector() {
Injector i = new S3ContextBuilder("id", "secret").withModules(new StubS3BlobStoreModule()) Injector i = new S3ContextBuilder(new S3PropertiesBuilder("id", "secret").build())
.buildInjector(); .withModules(new S3StubClientModule()).buildInjector();
assert i.getInstance(S3Context.class) != null; assert i.getInstance(Key.get(new TypeLiteral<RestContext<S3Client>>() {
})) != null;
assert i.getInstance(S3Object.class) != null;
assert i.getInstance(Blob.class) != null;
} }
protected void testAddContextModule() { protected void testAddContextModule() {
List<Module> modules = new ArrayList<Module>(); List<Module> modules = new ArrayList<Module>();
S3ContextBuilder builder = new S3ContextBuilder("id", "secret"); S3ContextBuilder builder = new S3ContextBuilder(new S3PropertiesBuilder("id", "secret")
.build());
builder.addContextModule(modules); builder.addContextModule(modules);
assertEquals(modules.size(), 1); assertEquals(modules.size(), 1);
assertEquals(modules.get(0).getClass(), S3ContextModule.class); assertEquals(modules.get(0).getClass(), S3ContextModule.class);
} }
protected void addConnectionModule() { protected void addClientModule() {
List<Module> modules = new ArrayList<Module>(); List<Module> modules = new ArrayList<Module>();
S3ContextBuilder builder = new S3ContextBuilder("id", "secret"); S3ContextBuilder builder = new S3ContextBuilder(new S3PropertiesBuilder("id", "secret")
builder.addConnectionModule(modules); .build());
builder.addClientModule(modules);
assertEquals(modules.size(), 1); assertEquals(modules.size(), 1);
assertEquals(modules.get(0).getClass(), RestS3ConnectionModule.class); assertEquals(modules.get(0).getClass(), S3RestClientModule.class);
} }
} }

View File

@ -0,0 +1,110 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.blobstore;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_ACCESSKEYID;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AWS_SECRETACCESSKEY;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.blobstore.config.S3BlobStoreContextModule;
import org.jclouds.aws.s3.config.S3RestClientModule;
import org.jclouds.aws.s3.config.S3StubClientModule;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.internal.S3ObjectImpl;
import org.jclouds.aws.s3.internal.StubS3Client;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.internal.BlobImpl;
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
import org.testng.annotations.Test;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of modules configured in S3ContextBuilder
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "s3.S3ContextBuilderTest")
public class S3BlobStoreContextBuilderTest {
public void testNewBuilder() {
S3BlobStoreContextBuilder builder = new S3BlobStoreContextBuilder(
new S3BlobStorePropertiesBuilder("id", "secret").build());
assertEquals(builder.getProperties().getProperty(PROPERTY_USER_METADATA_PREFIX),
"x-amz-meta-");
assertEquals(builder.getProperties().getProperty(PROPERTY_AWS_ACCESSKEYID), "id");
assertEquals(builder.getProperties().getProperty(PROPERTY_AWS_SECRETACCESSKEY), "secret");
}
public void testBuildContext() {
BlobStoreContext<S3Client> context = new S3BlobStoreContextBuilder(
new S3BlobStorePropertiesBuilder("id", "secret").build()).withModules(
new S3StubClientModule()).buildContext();
assertEquals(context.getClass(), BlobStoreContextImpl.class);
assertEquals(context.getApi().getClass(), StubS3Client.class);
assertEquals(context.getBlobStore().getClass(), S3BlobStore.class);
assertEquals(context.getApi().newS3Object().getClass(), S3ObjectImpl.class);
assertEquals(context.getBlobStore().newBlob().getClass(), BlobImpl.class);
assertEquals(context.getAccount(), "id");
assertEquals(context.getEndPoint(), URI.create("https://localhost/s3stub"));
}
public void testBuildInjector() {
Injector i = new S3BlobStoreContextBuilder(new S3BlobStorePropertiesBuilder("id", "secret")
.build()).withModules(new S3StubClientModule()).buildInjector();
assert i.getInstance(Key.get(new TypeLiteral<BlobStoreContext<S3Client>>() {
})) != null;
assert i.getInstance(S3Object.class) != null;
assert i.getInstance(Blob.class) != null;
}
protected void testAddContextModule() {
List<Module> modules = new ArrayList<Module>();
S3BlobStoreContextBuilder builder = new S3BlobStoreContextBuilder(
new S3BlobStorePropertiesBuilder("id", "secret").build());
builder.addContextModule(modules);
assertEquals(modules.size(), 1);
assertEquals(modules.get(0).getClass(), S3BlobStoreContextModule.class);
}
protected void addClientModule() {
List<Module> modules = new ArrayList<Module>();
S3BlobStoreContextBuilder builder = new S3BlobStoreContextBuilder(
new S3BlobStorePropertiesBuilder("id", "secret").build());
builder.addClientModule(modules);
assertEquals(modules.size(), 1);
assertEquals(modules.get(0).getClass(), S3RestClientModule.class);
}
}

View File

@ -0,0 +1,74 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.blobstore.config;
import static org.testng.Assert.assertEquals;
import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.config.S3StubClientModule;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
import org.jclouds.concurrent.WithinThreadExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.util.Jsr330;
import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "s3.S3BlobStoreModuleTest")
public class S3BlobStoreModuleTest {
Injector createInjector() {
return Guice.createInjector(new ExecutorServiceModule(new WithinThreadExecutorService()),
new JDKLoggingModule(), new S3StubClientModule(), new S3BlobStoreContextModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(
Jsr330.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to("user");
bindConstant().annotatedWith(
Jsr330.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY)).to("key");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_S3_ENDPOINT))
.to("http://localhost");
super.configure();
}
});
}
@Test
void testContextImpl() {
BlobStoreContext<S3Client> context = createInjector().getInstance(
Key.get(new TypeLiteral<BlobStoreContext<S3Client>>() {
}));
assertEquals(context.getClass(), BlobStoreContextImpl.class);
}
}

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -21,12 +21,9 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.aws.s3.integration; package org.jclouds.aws.s3.blobstore.integration;
import org.jclouds.aws.s3.S3Connection; import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.blobstore.integration.internal.BaseBlobIntegrationTest; import org.jclouds.blobstore.integration.internal.BaseBlobIntegrationTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -36,7 +33,6 @@ import org.testng.annotations.Test;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = { "integration", "live" }, testName = "s3.S3BlobIntegrationTest") @Test(groups = { "integration", "live" }, testName = "s3.S3BlobIntegrationTest")
public class S3BlobIntegrationTest extends public class S3BlobIntegrationTest extends BaseBlobIntegrationTest<S3Client> {
BaseBlobIntegrationTest<S3Connection, BucketMetadata, ObjectMetadata, S3Object> {
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -21,12 +21,9 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.aws.s3.integration; package org.jclouds.aws.s3.blobstore.integration;
import org.jclouds.aws.s3.S3Connection; import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.blobstore.integration.internal.BaseBlobLiveTest; import org.jclouds.blobstore.integration.internal.BaseBlobLiveTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -36,7 +33,6 @@ import org.testng.annotations.Test;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = { "live" }, testName = "s3.S3BlobLiveTest") @Test(groups = { "live" }, testName = "s3.S3BlobLiveTest")
public class S3BlobLiveTest extends public class S3BlobLiveTest extends BaseBlobLiveTest<S3Client> {
BaseBlobLiveTest<S3Connection, BucketMetadata, ObjectMetadata, S3Object> {
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -21,12 +21,9 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.aws.s3.integration; package org.jclouds.aws.s3.blobstore.integration;
import org.jclouds.aws.s3.S3Connection; import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.blobstore.integration.internal.BaseBlobMapIntegrationTest; import org.jclouds.blobstore.integration.internal.BaseBlobMapIntegrationTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -34,7 +31,6 @@ import org.testng.annotations.Test;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = { "integration", "live" }, testName = "s3.S3BlobMapIntegrationTest") @Test(groups = { "integration", "live" }, testName = "s3.S3BlobMapIntegrationTest")
public class S3BlobMapIntegrationTest extends public class S3BlobMapIntegrationTest extends BaseBlobMapIntegrationTest<S3Client> {
BaseBlobMapIntegrationTest<S3Connection, BucketMetadata, ObjectMetadata, S3Object> {
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -21,12 +21,9 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.aws.s3.integration; package org.jclouds.aws.s3.blobstore.integration;
import org.jclouds.aws.s3.S3Connection; import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.blobstore.integration.internal.BaseContainerIntegrationTest; import org.jclouds.blobstore.integration.internal.BaseContainerIntegrationTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -35,7 +32,6 @@ import org.testng.annotations.Test;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = { "integration", "live" }, testName = "s3.S3ContainerIntegrationTest") @Test(groups = { "integration", "live" }, testName = "s3.S3ContainerIntegrationTest")
public class S3ContainerIntegrationTest extends public class S3ContainerIntegrationTest extends BaseContainerIntegrationTest<S3Client> {
BaseContainerIntegrationTest<S3Connection, BucketMetadata, ObjectMetadata, S3Object> {
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -21,12 +21,9 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.aws.s3.integration; package org.jclouds.aws.s3.blobstore.integration;
import org.jclouds.aws.s3.S3Connection; import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.blobstore.integration.internal.BaseContainerLiveTest; import org.jclouds.blobstore.integration.internal.BaseContainerLiveTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -35,7 +32,6 @@ import org.testng.annotations.Test;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = { "live" }, testName = "s3.S3ContainerLiveTest") @Test(groups = { "live" }, testName = "s3.S3ContainerLiveTest")
public class S3ContainerLiveTest extends public class S3ContainerLiveTest extends BaseContainerLiveTest<S3Client> {
BaseContainerLiveTest<S3Connection, BucketMetadata, ObjectMetadata, S3Object> {
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com> * Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* *
* ==================================================================== * ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one * Licensed to the Apache Software Foundation (ASF) under one
@ -21,12 +21,9 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.aws.s3.integration; package org.jclouds.aws.s3.blobstore.integration;
import org.jclouds.aws.s3.S3Connection; import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.blobstore.integration.internal.BaseInputStreamMapIntegrationTest; import org.jclouds.blobstore.integration.internal.BaseInputStreamMapIntegrationTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -35,6 +32,6 @@ import org.testng.annotations.Test;
*/ */
@Test(groups = { "integration", "live" }, testName = "s3.S3InputStreamMapIntegrationTest") @Test(groups = { "integration", "live" }, testName = "s3.S3InputStreamMapIntegrationTest")
public class S3InputStreamMapIntegrationTest extends public class S3InputStreamMapIntegrationTest extends
BaseInputStreamMapIntegrationTest<S3Connection, BucketMetadata, ObjectMetadata, S3Object> { BaseInputStreamMapIntegrationTest<S3Client> {
} }

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