Issue 47: Added metadata fields to S3Object for CannedAccessPolicy and AccessControlList, and modified metadata header parser to identify the x-amz-acl header if present and set the corresponding canned policy on an object.

git-svn-id: http://jclouds.googlecode.com/svn/trunk@1430 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
jamurty 2009-06-13 01:00:33 +00:00
parent b8275fda10
commit 41be68b3a9
4 changed files with 115 additions and 0 deletions

View File

@ -27,6 +27,7 @@ import java.util.Map.Entry;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.S3Object.Metadata;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.aws.util.DateService;
@ -63,6 +64,7 @@ public class ParseMetadataFromHeaders extends HttpFutureCommand.ResponseCallable
addUserMetadataTo(metadata);
addMd5To(metadata);
addCannedAccessPolicyTo(metadata);
parseLastModifiedOrThrowException(metadata);
setContentTypeOrThrowException(metadata);
@ -122,6 +124,13 @@ public class ParseMetadataFromHeaders extends HttpFutureCommand.ResponseCallable
}
}
private void addCannedAccessPolicyTo(S3Object.Metadata metadata) {
String aclHeader = getResponse().getFirstHeaderOrNull(S3Headers.CANNED_ACL);
if (aclHeader != null) {
metadata.setCannedAccessPolicy(CannedAccessPolicy.fromHeader(aclHeader));
}
}
public void setKey(String key) {
this.key = key;
}

View File

@ -27,6 +27,7 @@ import static com.google.common.base.Preconditions.*;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import org.jclouds.aws.s3.commands.options.GetObjectOptions;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.aws.s3.util.S3Utils.Md5InputStreamResult;
import org.jclouds.http.ContentTypes;
@ -96,6 +97,8 @@ public class S3Object {
private String cacheControl;
private String dataDisposition;
private String dataEncoding;
private CannedAccessPolicy cannedAccessPolicy;
private AccessControlList accessControlList;
// only parsed on list
private CanonicalUser owner = null;
@ -319,6 +322,22 @@ public class S3Object {
public void setAllHeaders(Multimap<String, String> allHeaders) {
this.allHeaders = allHeaders;
}
public void setCannedAccessPolicy(CannedAccessPolicy policy) {
this.cannedAccessPolicy = policy;
}
public CannedAccessPolicy getCannedAccessPolicy() {
return this.cannedAccessPolicy;
}
public void setAccessControlList(AccessControlList acl) {
this.accessControlList = acl;
}
public AccessControlList getAccessControlList() {
return this.accessControlList;
}
/**
* @return all http response headers associated with this S3Object

View File

@ -77,4 +77,28 @@ public enum CannedAccessPolicy {
public String toString() {
return policyName;
}
/**
* @param capHeader
* The value of the x-amz-acl HTTP Header returned by S3 when an
* object has a canned access policy.
*
* @return
* the canned access policy object corresponding to the header value,
* or null if the given header value does not represent a valid canned
* policy.
*/
public static CannedAccessPolicy fromHeader(String capHeader) {
if ("private".equals(capHeader)) {
return CannedAccessPolicy.PRIVATE;
} else if ("public-read".equals(capHeader)) {
return CannedAccessPolicy.PUBLIC_READ;
} else if ("public-read-write".equals(capHeader)) {
return CannedAccessPolicy.PUBLIC_READ_WRITE;
} else if ("authenticated-read".equals(capHeader)) {
return CannedAccessPolicy.AUTHENTICATED_READ;
} else {
return null;
}
}
}

View File

@ -25,17 +25,25 @@ package org.jclouds.aws.s3.commands.callables;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.reset;
import static org.testng.Assert.assertEquals;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.S3Object.Metadata;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.util.DateService;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpHeaders;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
/**
* @author Adrian Cole
*/
@ -86,5 +94,60 @@ public class ParseObjectFromHeadersAndHttpContentTest {
assertEquals(object.getContentRange(), "0-10485759/20232760");
}
@Test
public void testParseObjectFromHeadersWithCannedAccessPolicy() throws HttpException {
DateService dateService = new DateService();
ParseMetadataFromHeaders metadataParser = new ParseMetadataFromHeaders(dateService);
metadataParser.setKey("object-key");
ParseObjectFromHeadersAndHttpContent callable = new ParseObjectFromHeadersAndHttpContent(
metadataParser);
HttpResponse response = createNiceMock(HttpResponse.class);
callable.setResponse(response);
S3Object object;
// Test with no policy
buildDefaultResponseMock(response);
expect(response.getFirstHeaderOrNull(S3Headers.CANNED_ACL)).andReturn(null);
replay(response);
object = callable.call();
assertEquals(object.getMetadata().getCannedAccessPolicy(), null);
// Test setting the "private" policy
buildDefaultResponseMock(response);
expect(response.getFirstHeaderOrNull(S3Headers.CANNED_ACL)).andReturn(
CannedAccessPolicy.PRIVATE.toString());
replay(response);
object = callable.call();
assertEquals(object.getMetadata().getCannedAccessPolicy(), CannedAccessPolicy.PRIVATE);
// Test setting the "authenticated read" policy
buildDefaultResponseMock(response);
expect(response.getFirstHeaderOrNull(S3Headers.CANNED_ACL)).andReturn(
CannedAccessPolicy.AUTHENTICATED_READ.toString());
replay(response);
object = callable.call();
assertEquals(object.getMetadata().getCannedAccessPolicy(),
CannedAccessPolicy.AUTHENTICATED_READ);
}
private void buildDefaultResponseMock(HttpResponse response) {
reset(response);
// Headers required for the parse classes to work, but we don't care about this data.
String data = "test data";
expect(response.getStatusCode()).andReturn(200).atLeastOnce();
Multimap<String, String> emptyHeaders = HashMultimap.create();
expect(response.getHeaders()).andReturn(emptyHeaders).atLeastOnce();
expect(response.getContent()).andReturn(IOUtils.toInputStream(data)).atLeastOnce();
expect(response.getFirstHeaderOrNull(HttpHeaders.LAST_MODIFIED))
.andReturn(new DateService().rfc822DateFormat()).atLeastOnce();
expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE))
.andReturn("text/plain").atLeastOnce();
expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH))
.andReturn("" + data.length()).atLeastOnce();
}
}