Added copyObject to JetS3t impl

git-svn-id: http://jclouds.googlecode.com/svn/trunk@882 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
jamurty 2009-05-30 06:58:35 +00:00
parent 3d41d6b107
commit fd3c3841ee
3 changed files with 147 additions and 17 deletions

View File

@ -26,6 +26,7 @@ package org.jclouds.aws.s3.jets3t;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -33,9 +34,11 @@ import java.util.concurrent.TimeUnit;
import org.jclouds.aws.s3.S3Connection; import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.S3Context; import org.jclouds.aws.s3.S3Context;
import org.jclouds.aws.s3.S3ContextFactory; import org.jclouds.aws.s3.S3ContextFactory;
import org.jclouds.aws.s3.commands.options.CopyObjectOptions;
import org.jclouds.aws.s3.commands.options.GetObjectOptions; import org.jclouds.aws.s3.commands.options.GetObjectOptions;
import org.jclouds.aws.s3.commands.options.ListBucketOptions; import org.jclouds.aws.s3.commands.options.ListBucketOptions;
import org.jclouds.aws.s3.commands.options.PutObjectOptions; import org.jclouds.aws.s3.commands.options.PutObjectOptions;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import org.jets3t.service.S3ObjectsChunk; import org.jets3t.service.S3ObjectsChunk;
import org.jets3t.service.S3Service; import org.jets3t.service.S3Service;
@ -95,9 +98,26 @@ public class JCloudsS3Service extends S3Service {
protected Map copyObjectImpl(String sourceBucketName, String sourceObjectKey, protected Map copyObjectImpl(String sourceBucketName, String sourceObjectKey,
String destinationBucketName, String destinationObjectKey, AccessControlList acl, String destinationBucketName, String destinationObjectKey, AccessControlList acl,
Map destinationMetadata, Calendar ifModifiedSince, Calendar ifUnmodifiedSince, Map destinationMetadata, Calendar ifModifiedSince, Calendar ifUnmodifiedSince,
String[] ifMatchTags, String[] ifNoneMatchTags) throws S3ServiceException { String[] ifMatchTags, String[] ifNoneMatchTags) throws S3ServiceException
// TODO Unimplemented {
throw new UnsupportedOperationException(); try {
CopyObjectOptions options = Util.convertCopyObjectOptions(acl,
destinationMetadata, ifModifiedSince, ifUnmodifiedSince,
ifMatchTags, ifNoneMatchTags);
org.jclouds.aws.s3.domain.S3Object.Metadata jcObjectMetadata =
connection.copyObject(sourceBucketName, sourceObjectKey,
destinationBucketName, destinationObjectKey, options)
.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
Map map = new HashMap();
// Result fields returned when copy is successful.
map.put("Last-Modified", jcObjectMetadata.getLastModified().toDate());
map.put("ETag", S3Utils.toHexString(jcObjectMetadata.getMd5()));
return map;
} catch (Exception e) {
Utils.<S3ServiceException> rethrowIfRuntimeOrSameType(e);
throw new S3ServiceException("error copying object", e);
}
} }
@Override @Override
@ -109,7 +129,8 @@ public class JCloudsS3Service extends S3Service {
throw new UnsupportedOperationException("Bucket ACL is not yet supported"); throw new UnsupportedOperationException("Bucket ACL is not yet supported");
try { try {
if (connection.putBucketIfNotExists(bucketName).get()) { if (connection.putBucketIfNotExists(bucketName)
.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)) {
// Bucket created. // Bucket created.
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -30,9 +30,11 @@ import java.util.Calendar;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.jclouds.aws.s3.commands.options.CopyObjectOptions;
import org.jclouds.aws.s3.commands.options.GetObjectOptions; import org.jclouds.aws.s3.commands.options.GetObjectOptions;
import org.jclouds.aws.s3.commands.options.ListBucketOptions; import org.jclouds.aws.s3.commands.options.ListBucketOptions;
import org.jclouds.aws.s3.commands.options.PutObjectOptions; import org.jclouds.aws.s3.commands.options.PutObjectOptions;
@ -42,6 +44,7 @@ import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.aws.util.DateService; import org.jclouds.aws.util.DateService;
import org.jclouds.http.ContentTypes; import org.jclouds.http.ContentTypes;
import org.jclouds.util.Utils;
import org.jets3t.service.S3ServiceException; import org.jets3t.service.S3ServiceException;
import org.jets3t.service.acl.AccessControlList; import org.jets3t.service.acl.AccessControlList;
import org.jets3t.service.model.S3Bucket; import org.jets3t.service.model.S3Bucket;
@ -50,7 +53,9 @@ import org.jets3t.service.model.S3Owner;
import org.jets3t.service.utils.RestUtils; import org.jets3t.service.utils.RestUtils;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
/** /**
* Convert between jCloud and JetS3t objects. * Convert between jCloud and JetS3t objects.
@ -137,6 +142,7 @@ public class Util {
return (S3Object[]) jsObjects.toArray(new S3Object[jsObjects.size()]); return (S3Object[]) jsObjects.toArray(new S3Object[jsObjects.size()]);
} }
@SuppressWarnings("unchecked")
public static org.jclouds.aws.s3.domain.S3Object convertObject(S3Object jsObject) public static org.jclouds.aws.s3.domain.S3Object convertObject(S3Object jsObject)
throws S3ServiceException throws S3ServiceException
{ {
@ -205,11 +211,11 @@ public class Util {
} }
// TODO: options.ifMd5Matches should accept multiple match tags // TODO: options.ifMd5Matches should accept multiple match tags
if (ifMatchTags != null && ifMatchTags.length > 0) { if (ifMatchTags != null && ifMatchTags.length > 0) {
options.ifMd5Matches(ifMatchTags[0].getBytes()); options.ifMd5Matches(Utils.encodeString(ifMatchTags[0]));
} }
// TODO: options.ifMd5DoesntMatch should accept multiple match tags // TODO: options.ifMd5DoesntMatch should accept multiple match tags
if (ifNoneMatchTags != null && ifNoneMatchTags.length > 0) { if (ifNoneMatchTags != null && ifNoneMatchTags.length > 0) {
options.ifMd5DoesntMatch(ifNoneMatchTags[0].getBytes()); options.ifMd5DoesntMatch(Utils.encodeString(ifNoneMatchTags[0]));
} }
return options; return options;
} }
@ -233,16 +239,62 @@ public class Util {
return options; return options;
} }
public static CannedAccessPolicy convertAcl(AccessControlList acl) {
if (acl == null) {
return null;
} else if (acl == AccessControlList.REST_CANNED_AUTHENTICATED_READ) {
return CannedAccessPolicy.AUTHENTICATED_READ;
} else if (acl == AccessControlList.REST_CANNED_PRIVATE) {
return CannedAccessPolicy.PRIVATE;
} else if (acl == AccessControlList.REST_CANNED_PUBLIC_READ) {
return CannedAccessPolicy.PUBLIC_READ;
} else if (acl == AccessControlList.REST_CANNED_PUBLIC_READ_WRITE) {
return CannedAccessPolicy.PUBLIC_READ_WRITE;
}
throw new IllegalArgumentException(
"Only 'canned' AccessControlList options are supported: " + acl);
}
public static PutObjectOptions convertPutObjectOptions(AccessControlList acl) { public static PutObjectOptions convertPutObjectOptions(AccessControlList acl) {
PutObjectOptions options = new PutObjectOptions(); PutObjectOptions options = new PutObjectOptions();
if (acl == AccessControlList.REST_CANNED_AUTHENTICATED_READ) { if (acl != null) {
options.withAcl(CannedAccessPolicy.AUTHENTICATED_READ); options.withAcl(convertAcl(acl));
} else if (acl == AccessControlList.REST_CANNED_PRIVATE) { }
options.withAcl(CannedAccessPolicy.PRIVATE); return options;
} else if (acl == AccessControlList.REST_CANNED_PUBLIC_READ) { }
options.withAcl(CannedAccessPolicy.PUBLIC_READ);
} else if (acl == AccessControlList.REST_CANNED_PUBLIC_READ_WRITE) { @SuppressWarnings("unchecked")
options.withAcl(CannedAccessPolicy.PUBLIC_READ_WRITE); public static CopyObjectOptions convertCopyObjectOptions(AccessControlList acl,
Map destinationMetadata, Calendar ifModifiedSince, Calendar ifUnmodifiedSince,
String[] ifMatchTags, String[] ifNoneMatchTags) throws UnsupportedEncodingException
{
CopyObjectOptions options = new CopyObjectOptions();
if (acl != null) {
options.overrideAcl(convertAcl(acl));
}
if (ifModifiedSince != null) {
options.ifSourceModifiedSince(new DateTime(ifModifiedSince));
}
if (ifUnmodifiedSince != null) {
options.ifSourceUnmodifiedSince(new DateTime(ifUnmodifiedSince));
}
// TODO: options.ifMd5Matches should accept multiple match tags
if (ifMatchTags != null && ifMatchTags.length > 0) {
options.ifSourceMd5Matches(Utils.encodeString(ifMatchTags[0]));
}
// TODO: options.ifMd5DoesntMatch should accept multiple match tags
if (ifNoneMatchTags != null && ifNoneMatchTags.length > 0) {
options.ifSourceMd5DoesntMatch(Utils.encodeString(ifNoneMatchTags[0]));
}
if (destinationMetadata != null) {
Multimap<String, String> newMetadata = HashMultimap.create();
for (Object maybeUserMetadataObj : destinationMetadata.entrySet())
{
String name = ((Entry<String, String>) maybeUserMetadataObj).getKey();
String value = ((Entry<String, String>) maybeUserMetadataObj).getValue();
newMetadata.put(name, value);
}
options.overrideMetadataWith(newMetadata);
} }
return options; return options;
} }

View File

@ -35,6 +35,7 @@ import java.io.IOException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
@ -57,6 +58,7 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
/** /**
* Tests to cover JCloudsS3Service * Tests to cover JCloudsS3Service
@ -416,9 +418,64 @@ public class JCloudsS3ServiceIntegrationTest extends S3IntegrationTest {
emptyBucket(commonTestingBucketName); emptyBucket(commonTestingBucketName);
} }
@Test(enabled = false) @Test(dependsOnMethods = "testCreateBucketImpl")
public void testCopyObjectImpl() { @SuppressWarnings("unchecked")
fail("Not yet implemented"); public void testCopyObjectImpl() throws InterruptedException, ExecutionException,
TimeoutException, IOException, S3ServiceException
{
String data = "This is my data";
String sourceObjectKey = "šriginalObject"; // Notice the use of non-ASCII
String destinationObjectKey = "dŽstinationObject"; // characters here.
String metadataName = "metadata-name";
String sourceMetadataValue = "souce-metadata-value";
String destinationMetadataValue = "destination-metadata-value";
org.jclouds.aws.s3.domain.S3Object sourceObject =
new org.jclouds.aws.s3.domain.S3Object(sourceObjectKey, data);
sourceObject.getMetadata().getUserMetadata().put(
S3Constants.USER_METADATA_PREFIX + metadataName, sourceMetadataValue);
addObjectToBucket(commonTestingBucketName, sourceObject);
S3Object destinationObject;
Map copyResult;
org.jclouds.aws.s3.domain.S3Object jcDestinationObject;
// Copy with metadata and ACL retained
destinationObject = new S3Object(destinationObjectKey);
copyResult = service.copyObject(commonTestingBucketName, sourceObjectKey,
commonTestingBucketName, destinationObject, false);
jcDestinationObject = client.getObject(commonTestingBucketName, destinationObject.getKey())
.get(10, TimeUnit.SECONDS);
assertEquals(jcDestinationObject.getKey(), destinationObjectKey);
assertEquals(Iterators.getLast(jcDestinationObject.getMetadata().getUserMetadata().get(
S3Constants.USER_METADATA_PREFIX + metadataName).iterator()), sourceMetadataValue);
assertEquals(copyResult.get("ETag"),
S3Utils.toHexString(jcDestinationObject.getMetadata().getMd5()));
// TODO: Test destination ACL is unchanged (ie private)
// Copy with metadata replaced
destinationObject = new S3Object(destinationObjectKey);
destinationObject.addMetadata(S3Constants.USER_METADATA_PREFIX + metadataName,
destinationMetadataValue);
copyResult = service.copyObject(commonTestingBucketName, sourceObjectKey,
commonTestingBucketName, destinationObject, true);
jcDestinationObject = client.getObject(commonTestingBucketName, destinationObject.getKey())
.get(10, TimeUnit.SECONDS);
assertEquals(Iterators.getLast(jcDestinationObject.getMetadata().getUserMetadata().get(
S3Constants.USER_METADATA_PREFIX + metadataName).iterator()),
destinationMetadataValue);
// TODO: Test destination ACL is unchanged (ie private)
// Copy with ACL modified
destinationObject = new S3Object(destinationObjectKey);
destinationObject.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ);
copyResult = service.copyObject(commonTestingBucketName, sourceObjectKey,
commonTestingBucketName, destinationObject, false);
jcDestinationObject = client.getObject(commonTestingBucketName, destinationObject.getKey())
.get(10, TimeUnit.SECONDS);
// TODO: Test destination ACL is changed (ie public-read)
emptyBucket(commonTestingBucketName);
} }
@Test(enabled = false) @Test(enabled = false)