mirror of https://github.com/apache/jclouds.git
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:
parent
3d41d6b107
commit
fd3c3841ee
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue