From 7366d5c1cc9a88e325db9aed83d5f74d382382ba Mon Sep 17 00:00:00 2001 From: jamurty Date: Tue, 30 Jun 2009 20:19:14 +0000 Subject: [PATCH] Issue 15: Added ACL get/put implementation to JetS3t plugin git-svn-id: http://jclouds.googlecode.com/svn/trunk@1597 3d8758e0-26b5-11de-8745-db77d3ebf521 --- .../aws/s3/internal/StubS3Connection.java | 2 +- .../aws/s3/jets3t/JCloudsS3Service.java | 48 +++-- .../java/org/jclouds/aws/s3/jets3t/Util.java | 100 ++++++++- .../JCloudsS3ServiceIntegrationTest.java | 190 +++++++++++++++--- 4 files changed, 293 insertions(+), 47 deletions(-) diff --git a/aws/s3/core/src/test/java/org/jclouds/aws/s3/internal/StubS3Connection.java b/aws/s3/core/src/test/java/org/jclouds/aws/s3/internal/StubS3Connection.java index 92f4554211..165dfc62b2 100644 --- a/aws/s3/core/src/test/java/org/jclouds/aws/s3/internal/StubS3Connection.java +++ b/aws/s3/core/src/test/java/org/jclouds/aws/s3/internal/StubS3Connection.java @@ -421,7 +421,7 @@ public class StubS3Connection implements S3Connection { S3Object sourceS3 = source.get(sourceObject); S3Object.Metadata newMd = copy(sourceS3.getMetadata(), destinationObject); if (options.getAcl() != null) - keyToAcl.put(destinationBucket + destinationObject, options.getAcl()); + keyToAcl.put(destinationBucket + "/" + destinationObject, options.getAcl()); if (options.getMetadata() != null) { newMd.setUserMetadata(options.getMetadata()); } diff --git a/aws/s3/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java b/aws/s3/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java index 144a3401c9..f404ae2d9e 100644 --- a/aws/s3/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java +++ b/aws/s3/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java @@ -175,8 +175,15 @@ public class JCloudsS3Service extends S3Service { @Override protected AccessControlList getBucketAclImpl(String bucketName) throws S3ServiceException { - // TODO Unimplemented - throw new UnsupportedOperationException(); + try { + org.jclouds.aws.s3.domain.AccessControlList jcACL = + connection.getBucketACL(bucketName) + .get(requestTimeoutMilliseconds,TimeUnit.MILLISECONDS); + return Util.convertAccessControlList(jcACL); + } catch (Exception e) { + Utils. rethrowIfRuntimeOrSameType(e); + throw new S3ServiceException("error getting bucket's ACL: " + bucketName, e); + } } @Override @@ -195,8 +202,15 @@ public class JCloudsS3Service extends S3Service { @Override protected AccessControlList getObjectAclImpl(String bucketName, String objectKey) throws S3ServiceException { - // TODO Unimplemented - throw new UnsupportedOperationException(); + try { + org.jclouds.aws.s3.domain.AccessControlList jcACL = + connection.getObjectACL(bucketName, objectKey) + .get(requestTimeoutMilliseconds,TimeUnit.MILLISECONDS); + return Util.convertAccessControlList(jcACL); + } catch (Exception e) { + Utils. rethrowIfRuntimeOrSameType(e); + throw new S3ServiceException("error getting object's ACL", e); + } } @Override @@ -310,19 +324,29 @@ public class JCloudsS3Service extends S3Service { } @Override - protected void putBucketAclImpl(String bucketName, AccessControlList acl) + protected void putBucketAclImpl(String bucketName, AccessControlList jsACL) throws S3ServiceException { - // TODO Unimplemented - throw new UnsupportedOperationException(); - + try { + org.jclouds.aws.s3.domain.AccessControlList jcACL = Util.convertAccessControlList(jsACL); + connection.putBucketACL(bucketName, jcACL) + .get(requestTimeoutMilliseconds,TimeUnit.MILLISECONDS); + } catch (Exception e) { + Utils. rethrowIfRuntimeOrSameType(e); + throw new S3ServiceException("error putting bucket's ACL: " + bucketName, e); + } } @Override - protected void putObjectAclImpl(String bucketName, String objectKey, AccessControlList acl) + protected void putObjectAclImpl(String bucketName, String objectKey, AccessControlList jsACL) throws S3ServiceException { - // TODO Unimplemented - throw new UnsupportedOperationException(); - + try { + org.jclouds.aws.s3.domain.AccessControlList jcACL = Util.convertAccessControlList(jsACL); + connection.putObjectACL(bucketName, objectKey, jcACL) + .get(requestTimeoutMilliseconds,TimeUnit.MILLISECONDS); + } catch (Exception e) { + Utils. rethrowIfRuntimeOrSameType(e); + throw new S3ServiceException("error putting object's ACL", e); + } } @Override diff --git a/aws/s3/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/Util.java b/aws/s3/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/Util.java index 1b559625dc..a626dc33f1 100644 --- a/aws/s3/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/Util.java +++ b/aws/s3/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/Util.java @@ -29,6 +29,7 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Date; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -47,6 +48,12 @@ import org.jclouds.http.ContentTypes; import org.jclouds.util.Utils; import org.jets3t.service.S3ServiceException; import org.jets3t.service.acl.AccessControlList; +import org.jets3t.service.acl.CanonicalGrantee; +import org.jets3t.service.acl.EmailAddressGrantee; +import org.jets3t.service.acl.GrantAndPermission; +import org.jets3t.service.acl.GranteeInterface; +import org.jets3t.service.acl.GroupGrantee; +import org.jets3t.service.acl.Permission; import org.jets3t.service.model.S3Bucket; import org.jets3t.service.model.S3Object; import org.jets3t.service.model.S3Owner; @@ -239,7 +246,7 @@ public class Util { return options; } - public static CannedAccessPolicy convertAcl(AccessControlList acl) { + public static CannedAccessPolicy convertACLToCannedAccessPolicy(AccessControlList acl) { if (acl == null) { return null; } else if (acl == AccessControlList.REST_CANNED_AUTHENTICATED_READ) { @@ -255,10 +262,97 @@ public class Util { "Only 'canned' AccessControlList options are supported: " + acl); } + public static AccessControlList convertAccessControlList( + org.jclouds.aws.s3.domain.AccessControlList jcACL) + { + AccessControlList jsACL = new AccessControlList(); + if (jcACL.getOwner() != null) { + jsACL.setOwner(new S3Owner(jcACL.getOwner().getId(), jcACL.getOwner().getDisplayName())); + } + for (org.jclouds.aws.s3.domain.AccessControlList.Grant jcGrant : jcACL.getGrants()) { + Permission jsPermission = null; + org.jclouds.aws.s3.domain.AccessControlList.Permission jcPerm = jcGrant.getPermission(); + if (org.jclouds.aws.s3.domain.AccessControlList.Permission.FULL_CONTROL == jcPerm) { + jsPermission = Permission.PERMISSION_FULL_CONTROL; + } else if (org.jclouds.aws.s3.domain.AccessControlList.Permission.READ == jcPerm) { + jsPermission = Permission.PERMISSION_READ; + } else if (org.jclouds.aws.s3.domain.AccessControlList.Permission.READ_ACP == jcPerm) { + jsPermission = Permission.PERMISSION_READ_ACP; + } else if (org.jclouds.aws.s3.domain.AccessControlList.Permission.WRITE == jcPerm) { + jsPermission = Permission.PERMISSION_WRITE; + } else if (org.jclouds.aws.s3.domain.AccessControlList.Permission.WRITE_ACP == jcPerm) { + jsPermission = Permission.PERMISSION_WRITE_ACP; + } + + GranteeInterface jsGrantee = null; + org.jclouds.aws.s3.domain.AccessControlList.Grantee jcGrantee = jcGrant.getGrantee(); + if (jcGrantee instanceof + org.jclouds.aws.s3.domain.AccessControlList.EmailAddressGrantee) { + jsGrantee = new EmailAddressGrantee(jcGrantee.getIdentifier()); + } else if (jcGrantee instanceof + org.jclouds.aws.s3.domain.AccessControlList.CanonicalUserGrantee) { + jsGrantee = new CanonicalGrantee(jcGrantee.getIdentifier()); + } else if (jcGrantee instanceof + org.jclouds.aws.s3.domain.AccessControlList.GroupGrantee) { + jsGrantee = new GroupGrantee(jcGrantee.getIdentifier()); + } + + jsACL.grantPermission(jsGrantee, jsPermission); + } + return jsACL; + } + + @SuppressWarnings("unchecked") + public static org.jclouds.aws.s3.domain.AccessControlList convertAccessControlList( + AccessControlList jsACL) + { + org.jclouds.aws.s3.domain.AccessControlList jcACL = + new org.jclouds.aws.s3.domain.AccessControlList(); + if (jsACL.getOwner() != null) { + jcACL.setOwner(new org.jclouds.aws.s3.domain.CanonicalUser(jsACL.getOwner().getId())); + } + Iterator jsGrantAndPermissionIter = jsACL.getGrants().iterator(); + while (jsGrantAndPermissionIter.hasNext()) { + GrantAndPermission jsGrantAndPermission = + (GrantAndPermission) jsGrantAndPermissionIter.next(); + + org.jclouds.aws.s3.domain.AccessControlList.Permission jcPermission = null; + Permission jsPerm = jsGrantAndPermission.getPermission(); + if (Permission.PERMISSION_FULL_CONTROL == jsPerm) { + jcPermission = org.jclouds.aws.s3.domain.AccessControlList.Permission.FULL_CONTROL; + } else if (Permission.PERMISSION_READ == jsPerm) { + jcPermission = org.jclouds.aws.s3.domain.AccessControlList.Permission.READ; + } else if (Permission.PERMISSION_READ_ACP == jsPerm) { + jcPermission = org.jclouds.aws.s3.domain.AccessControlList.Permission.READ_ACP; + } else if (Permission.PERMISSION_WRITE == jsPerm) { + jcPermission = org.jclouds.aws.s3.domain.AccessControlList.Permission.WRITE; + } else if (Permission.PERMISSION_WRITE_ACP == jsPerm) { + jcPermission = org.jclouds.aws.s3.domain.AccessControlList.Permission.WRITE_ACP; + } + + org.jclouds.aws.s3.domain.AccessControlList.Grantee jcGrantee = null; + GranteeInterface jsGrantee = jsGrantAndPermission.getGrantee(); + if (jsGrantee instanceof EmailAddressGrantee) { + jcGrantee = new org.jclouds.aws.s3.domain.AccessControlList.EmailAddressGrantee( + jsGrantee.getIdentifier()); + } else if (jsGrantee instanceof CanonicalGrantee) { + jcGrantee = new org.jclouds.aws.s3.domain.AccessControlList.CanonicalUserGrantee( + jsGrantee.getIdentifier()); + } else if (jsGrantee instanceof GroupGrantee) { + jcGrantee = new org.jclouds.aws.s3.domain.AccessControlList.GroupGrantee( + org.jclouds.aws.s3.domain.AccessControlList.GroupGranteeURI.fromURI( + jsGrantee.getIdentifier())); + } + + jcACL.addPermission(jcGrantee, jcPermission); + } + return jcACL; + } + public static PutObjectOptions convertPutObjectOptions(AccessControlList acl) { PutObjectOptions options = new PutObjectOptions(); if (acl != null) { - options.withAcl(convertAcl(acl)); + options.withAcl(convertACLToCannedAccessPolicy(acl)); } return options; } @@ -270,7 +364,7 @@ public class Util { { CopyObjectOptions options = new CopyObjectOptions(); if (acl != null) { - options.overrideAcl(convertAcl(acl)); + options.overrideAcl(convertACLToCannedAccessPolicy(acl)); } if (ifModifiedSince != null) { options.ifSourceModifiedSince(new DateTime(ifModifiedSince)); diff --git a/aws/s3/extensions/jets3t/src/test/java/org/jclouds/aws/s3/jets3t/JCloudsS3ServiceIntegrationTest.java b/aws/s3/extensions/jets3t/src/test/java/org/jclouds/aws/s3/jets3t/JCloudsS3ServiceIntegrationTest.java index f271d96cd4..0e03f04b76 100644 --- a/aws/s3/extensions/jets3t/src/test/java/org/jclouds/aws/s3/jets3t/JCloudsS3ServiceIntegrationTest.java +++ b/aws/s3/extensions/jets3t/src/test/java/org/jclouds/aws/s3/jets3t/JCloudsS3ServiceIntegrationTest.java @@ -43,6 +43,8 @@ import java.util.concurrent.TimeoutException; import org.apache.commons.io.IOUtils; import org.jclouds.aws.s3.S3IntegrationTest; import org.jclouds.aws.s3.config.StubS3ConnectionModule; +import org.jclouds.aws.s3.domain.AccessControlList.GroupGranteeURI; +import org.jclouds.aws.s3.domain.AccessControlList.Permission; import org.jclouds.aws.s3.reference.S3Constants; import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.http.ContentTypes; @@ -50,12 +52,15 @@ import org.jets3t.service.S3ObjectsChunk; import org.jets3t.service.S3Service; import org.jets3t.service.S3ServiceException; import org.jets3t.service.acl.AccessControlList; +import org.jets3t.service.acl.GrantAndPermission; +import org.jets3t.service.acl.GroupGrantee; import org.jets3t.service.model.S3Bucket; import org.jets3t.service.model.S3Object; import org.jets3t.service.security.AWSCredentials; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; +import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Iterators; @@ -394,14 +399,15 @@ public class JCloudsS3ServiceIntegrationTest extends S3IntegrationTest { assertEquals(jsResultObject .getMetadata(S3Constants.USER_METADATA_PREFIX + "my-metadata-1"), "value-1"); - // Upload object with public-read ACL + // Upload object with canned public-read ACL requestObject = new S3Object(objectKey); requestObject.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ); jsResultObject = service.putObject(new S3Bucket(bucketName), requestObject); - jcObject = client.getObject(bucketName, objectKey).get(10, TimeUnit.SECONDS); - // TODO: No way yet to get/lookup ACL from jClouds object - // assertEquals(jcObject.getAcl(), CannedAccessPolicy.PUBLIC_READ); - assertEquals(jsResultObject.getAcl(), AccessControlList.REST_CANNED_PUBLIC_READ); + org.jclouds.aws.s3.domain.AccessControlList jcACL = + client.getObjectACL(bucketName, objectKey).get(10, TimeUnit.SECONDS); + assertTrue(jcACL.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ)); + assertTrue(jcACL.hasPermission(jcACL.getOwner().getId(), Permission.FULL_CONTROL)); + assertEquals(jcACL.getGrants().size(), 2); // TODO : Any way to test a URL lookup that works for live and stub testing? // URL publicUrl = new URL( @@ -455,8 +461,12 @@ public class JCloudsS3ServiceIntegrationTest extends S3IntegrationTest { 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) + .getMd5())); + // Test destination ACL is unchanged (ie private) + org.jclouds.aws.s3.domain.AccessControlList jcACL = + client.getObjectACL(bucketName, destinationObject.getKey()).get(10, TimeUnit.SECONDS); + assertEquals(jcACL.getGrants().size(), 1); + assertTrue(jcACL.hasPermission(jcACL.getOwner().getId(), Permission.FULL_CONTROL)); // Copy with metadata replaced destinationObject = new S3Object(destinationObjectKey); @@ -469,16 +479,154 @@ public class JCloudsS3ServiceIntegrationTest extends S3IntegrationTest { assertEquals(Iterators.getLast(jcDestinationObject.getMetadata().getUserMetadata().get( S3Constants.USER_METADATA_PREFIX + metadataName).iterator()), destinationMetadataValue); - // TODO: Test destination ACL is unchanged (ie private) + // Test destination ACL is unchanged (ie private) + jcACL = client.getObjectACL(bucketName, destinationObject.getKey()) + .get(10, TimeUnit.SECONDS); + assertEquals(jcACL.getGrants().size(), 1); + assertTrue(jcACL.hasPermission(jcACL.getOwner().getId(), Permission.FULL_CONTROL)); // Copy with ACL modified destinationObject = new S3Object(destinationObjectKey); destinationObject.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ); copyResult = service.copyObject(bucketName, sourceObjectKey, bucketName, destinationObject, false); - jcDestinationObject = client.getObject(bucketName, destinationObject.getKey()).get(10, - TimeUnit.SECONDS); - // TODO: Test destination ACL is changed (ie public-read) + // Test destination ACL is changed (ie public-read) + jcACL = client.getObjectACL(bucketName, destinationObject.getKey()) + .get(10, TimeUnit.SECONDS); + assertEquals(jcACL.getGrants().size(), 2); + assertTrue(jcACL.hasPermission(jcACL.getOwner().getId(), Permission.FULL_CONTROL)); + assertTrue(jcACL.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ)); + + } finally { + returnBucket(bucketName); + } + } + + @Test(dependsOnMethods = "testCreateBucketImpl") + @SuppressWarnings("unchecked") + public void testPutAndGetBucketAclImpl() throws InterruptedException, ExecutionException, + TimeoutException, S3ServiceException + { + String bucketName = getScratchBucketName(); + try { + S3Bucket bucket = new S3Bucket(bucketName); + AccessControlList acl = null; + + // Confirm bucket is created private by default. + acl = service.getBucketAcl(bucket); + final String ownerId = acl.getOwner().getId(); + assertEquals(acl.getGrants().size(), 1); + GrantAndPermission gap = (GrantAndPermission) + Iterables.find(acl.getGrants(), new Predicate() { + public boolean apply(GrantAndPermission gap) { + return gap.getGrantee().getIdentifier().equals(ownerId); + } + }); + assertNotNull(gap); + assertEquals(gap.getPermission(), + org.jets3t.service.acl.Permission.PERMISSION_FULL_CONTROL); + + // Add read access for public, and read-acp access for authenticated users. + acl.grantPermission(GroupGrantee.ALL_USERS, + org.jets3t.service.acl.Permission.PERMISSION_READ); + acl.grantPermission(GroupGrantee.AUTHENTICATED_USERS, + org.jets3t.service.acl.Permission.PERMISSION_READ_ACP); + service.putBucketAcl(bucketName, acl); + acl = service.getBucketAcl(bucket); + assertEquals(acl.getGrants().size(), 3); + gap = (GrantAndPermission) + Iterables.find(acl.getGrants(), new Predicate() { + public boolean apply(GrantAndPermission gap) { + return gap.getGrantee().getIdentifier().equals(ownerId); + } + }); + assertEquals(gap.getPermission(), + org.jets3t.service.acl.Permission.PERMISSION_FULL_CONTROL); + gap = (GrantAndPermission) + Iterables.find(acl.getGrants(), new Predicate() { + public boolean apply(GrantAndPermission gap) { + return gap.getGrantee().getIdentifier().equals( + GroupGrantee.ALL_USERS.getIdentifier()); + } + }); + assertEquals(gap.getPermission(), + org.jets3t.service.acl.Permission.PERMISSION_READ); + gap = (GrantAndPermission) + Iterables.find(acl.getGrants(), new Predicate() { + public boolean apply(GrantAndPermission gap) { + return gap.getGrantee().getIdentifier().equals( + GroupGrantee.AUTHENTICATED_USERS.getIdentifier()); + } + }); + assertEquals(gap.getPermission(), + org.jets3t.service.acl.Permission.PERMISSION_READ_ACP); + } finally { + returnScratchBucket(bucketName); + } + } + + @Test(dependsOnMethods = "testCreateBucketImpl") + @SuppressWarnings("unchecked") + public void testGetAndPutObjectAclImpl() throws InterruptedException, ExecutionException, + TimeoutException, S3ServiceException, NoSuchAlgorithmException, IOException + { + String bucketName = getBucketName(); + try { + S3Bucket bucket = new S3Bucket(bucketName); + S3Object object = new S3Object("testGetAndPutObjectAclImpl", "my data"); + AccessControlList acl = null; + + // Create default object. + service.putObject(bucket, object); + + // Confirm object is created private by default. + acl = service.getObjectAcl(bucket, object.getKey()); + final String ownerId = acl.getOwner().getId(); + assertEquals(acl.getGrants().size(), 1); + GrantAndPermission gap = (GrantAndPermission) + Iterables.find(acl.getGrants(), new Predicate() { + public boolean apply(GrantAndPermission gap) { + return gap.getGrantee().getIdentifier().equals(ownerId); + } + }); + assertNotNull(gap); + assertEquals(gap.getPermission(), + org.jets3t.service.acl.Permission.PERMISSION_FULL_CONTROL); + + // Add read access for public, and read-acp access for authenticated users. + acl.grantPermission(GroupGrantee.ALL_USERS, + org.jets3t.service.acl.Permission.PERMISSION_READ); + acl.grantPermission(GroupGrantee.AUTHENTICATED_USERS, + org.jets3t.service.acl.Permission.PERMISSION_READ_ACP); + service.putObjectAcl(bucketName, object.getKey(), acl); + acl = service.getObjectAcl(bucket, object.getKey()); + assertEquals(acl.getGrants().size(), 3); + gap = (GrantAndPermission) + Iterables.find(acl.getGrants(), new Predicate() { + public boolean apply(GrantAndPermission gap) { + return gap.getGrantee().getIdentifier().equals(ownerId); + } + }); + assertEquals(gap.getPermission(), + org.jets3t.service.acl.Permission.PERMISSION_FULL_CONTROL); + gap = (GrantAndPermission) + Iterables.find(acl.getGrants(), new Predicate() { + public boolean apply(GrantAndPermission gap) { + return gap.getGrantee().getIdentifier().equals( + GroupGrantee.ALL_USERS.getIdentifier()); + } + }); + assertEquals(gap.getPermission(), + org.jets3t.service.acl.Permission.PERMISSION_READ); + gap = (GrantAndPermission) + Iterables.find(acl.getGrants(), new Predicate() { + public boolean apply(GrantAndPermission gap) { + return gap.getGrantee().getIdentifier().equals( + GroupGrantee.AUTHENTICATED_USERS.getIdentifier()); + } + }); + assertEquals(gap.getPermission(), + org.jets3t.service.acl.Permission.PERMISSION_READ_ACP); } finally { returnBucket(bucketName); } @@ -489,11 +637,6 @@ public class JCloudsS3ServiceIntegrationTest extends S3IntegrationTest { fail("Not yet implemented"); } - @Test(enabled = false) - public void testGetBucketAclImpl() { - fail("Not yet implemented"); - } - @Test(enabled = false) public void testGetBucketLocationImpl() { fail("Not yet implemented"); @@ -504,21 +647,6 @@ public class JCloudsS3ServiceIntegrationTest extends S3IntegrationTest { fail("Not yet implemented"); } - @Test(enabled = false) - public void testGetObjectAclImpl() { - fail("Not yet implemented"); - } - - @Test(enabled = false) - public void testPutBucketAclImpl() { - fail("Not yet implemented"); - } - - @Test(enabled = false) - public void testPutObjectAclImpl() { - fail("Not yet implemented"); - } - @Test(enabled = false) public void testSetBucketLoggingStatusImpl() { fail("Not yet implemented");