diff --git a/core/src/main/java/org/jclouds/http/ContentTypes.java b/core/src/main/java/org/jclouds/http/ContentTypes.java new file mode 100644 index 0000000000..c036aa71e8 --- /dev/null +++ b/core/src/main/java/org/jclouds/http/ContentTypes.java @@ -0,0 +1,32 @@ +/** + * + * Copyright (C) 2009 Adrian Cole + * + * ==================================================================== + * 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.http; + +public interface ContentTypes { + + public static final String BINARY = "application/octet-stream"; + public static final String PLAIN = "text/plain"; + public static final String UNKNOWN_MIME_TYPE = "application/x-unknown-mime-type"; + +} \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/http/HttpConstants.java b/core/src/main/java/org/jclouds/http/HttpConstants.java index cfaf8bb5ac..305751eb39 100644 --- a/core/src/main/java/org/jclouds/http/HttpConstants.java +++ b/core/src/main/java/org/jclouds/http/HttpConstants.java @@ -28,15 +28,7 @@ package org.jclouds.http; * * @author Adrian Cole */ -public interface HttpConstants { - public static final String CONTENT_LENGTH = "Content-Length"; - public static final String CONTENT_TYPE = "Content-Type"; - public static final String CONTENT_MD5 = "Content-MD5"; - public static final String HOST = "Host"; - public static final String DATE = "Date"; - public static final String BINARY = "application/octet-stream"; - public static final String PLAIN = "text/plain"; - public static final String TRANSFER_ENCODING = "Transfer-Encoding"; +public interface HttpConstants extends HttpHeaders, ContentTypes { public static final String PROPERTY_HTTP_SECURE = "jclouds.http.secure"; public static final String PROPERTY_HTTP_PORT = "jclouds.http.port"; public static final String PROPERTY_HTTP_ADDRESS = "jclouds.http.address"; diff --git a/core/src/main/java/org/jclouds/http/HttpHeaders.java b/core/src/main/java/org/jclouds/http/HttpHeaders.java new file mode 100644 index 0000000000..d1b201f3c7 --- /dev/null +++ b/core/src/main/java/org/jclouds/http/HttpHeaders.java @@ -0,0 +1,82 @@ +/** + * + * Copyright (C) 2009 Adrian Cole + * + * ==================================================================== + * 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.http; + +public interface HttpHeaders { + + /** + * Can be used to specify caching behavior along the request/reply chain. Go + * to http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9. + */ + public static final String CACHE_CONTROL = "Cache-Control"; + /** + * Specifies presentational information for the object. Go to + * http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.5.1. + */ + public static final String CONTENT_DISPOSITION = "Content-Disposition"; + /** + * 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. Go to + * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11. + */ + public static final String CONTENT_ENCODING = "Content-Encoding"; + /** + * The size of the object, in bytes. This is required. Go to + * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13. + */ + public static final String CONTENT_LENGTH = "Content-Length"; + /** + * A standard MIME type describing the format of the contents. If none is + * provided, the default is binary/octet-stream. Go to + * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17. + */ + public static final String CONTENT_TYPE = "Content-Type"; + /** + * The base64 encoded 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. + */ + public static final String CONTENT_MD5 = "Content-MD5"; + /** + * A user agent that wishes to authenticate itself with a server-- usually, + * but not necessarily, after receiving a 401 response--does so by including + * an Authorization request-header field with the request. The Authorization + * field value consists of credentials containing the authentication + * information of the user agent for the realm of the resource being + * requested. + * + * Authorization = "Authorization" ":" credentials + * + * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html + */ + public static final String AUTHORIZATION = "Authorization"; + public static final String HOST = "Host"; + public static final String DATE = "Date"; + public static final String TRANSFER_ENCODING = "Transfer-Encoding"; + public static final String LAST_MODIFIED = "Last-Modified"; + public static final String SERVER = "Server"; + +} \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/http/HttpMessage.java b/core/src/main/java/org/jclouds/http/HttpMessage.java new file mode 100644 index 0000000000..4c83c4ac71 --- /dev/null +++ b/core/src/main/java/org/jclouds/http/HttpMessage.java @@ -0,0 +1,53 @@ +/** + * + * Copyright (C) 2009 Adrian Cole + * + * ==================================================================== + * 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.http; + +import java.util.Collection; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; + +public class HttpMessage { + + protected Multimap headers = HashMultimap.create(); + + public HttpMessage() { + super(); + } + + public Multimap getHeaders() { + return headers; + } + + public void setHeaders(Multimap headers) { + this.headers = headers; + } + + public String getFirstHeaderOrNull(String string) { + Collection values = headers.get(string); + return (values != null && values.size() >= 1) ? values.iterator() + .next() : null; + } + +} \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/http/HttpRequest.java b/core/src/main/java/org/jclouds/http/HttpRequest.java index 0d44d03918..c4bbccac78 100644 --- a/core/src/main/java/org/jclouds/http/HttpRequest.java +++ b/core/src/main/java/org/jclouds/http/HttpRequest.java @@ -26,28 +26,22 @@ package org.jclouds.http; import static com.google.common.base.Preconditions.checkNotNull; import java.io.InputStream; -import java.util.Collection; import javax.annotation.Resource; import org.jclouds.logging.Logger; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; - /** - * // TODO: Adrian: Document this! + * Represents a request that can be executed within + * {@link HttpFutureCommandClient} * * @author Adrian Cole */ -public class HttpRequest { +public class HttpRequest extends HttpMessage { private final String method; private final String uri; - Multimap headers = HashMultimap.create(); - Object content; - String contentType; - long contentLength = -1; + Object payload; @Resource protected Logger logger = Logger.NULL; @@ -64,9 +58,7 @@ public class HttpRequest { sb.append("{method='").append(method).append('\''); sb.append(", uri='").append(uri).append('\''); sb.append(", headers=").append(headers); - sb.append(", content set=").append(content != null); - sb.append(", contentType='").append(contentType).append('\''); - sb.append(", contentLength=").append(contentLength); + sb.append(", payload set=").append(payload != null); sb.append('}'); return sb.toString(); } @@ -79,16 +71,8 @@ public class HttpRequest { return uri; } - public Multimap getHeaders() { - return headers; - } - - public void setHeaders(Multimap headers) { - this.headers = headers; - } - public boolean isReplayable() { - Object content = getContent(); + Object content = getPayload(); if (content != null && content instanceof InputStream) { logger.warn("%1s: InputStreams are not replayable", toString()); return false; @@ -96,33 +80,12 @@ public class HttpRequest { return true; } - public Object getContent() { - return content; + public Object getPayload() { + return payload; } - public void setContent(Object content) { - this.content = content; + public void setPayload(Object content) { + this.payload = content; } - public String getContentType() { - return contentType; - } - - public void setContentType(String contentType) { - this.contentType = contentType; - } - - public long getContentLength() { - return contentLength; - } - - public void setContentLength(long contentLength) { - this.contentLength = contentLength; - } - - public String getFirstHeaderOrNull(String string) { - Collection values = headers.get(string); - return (values != null && values.size() >= 1) ? values.iterator() - .next() : null; - } } diff --git a/core/src/main/java/org/jclouds/http/HttpResponse.java b/core/src/main/java/org/jclouds/http/HttpResponse.java index 0f7a52fcc8..54027b9b5e 100644 --- a/core/src/main/java/org/jclouds/http/HttpResponse.java +++ b/core/src/main/java/org/jclouds/http/HttpResponse.java @@ -24,22 +24,17 @@ package org.jclouds.http; import java.io.InputStream; -import java.util.Collection; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; /** - * // TODO: Adrian: Document this! + * Represents a response produced from {@link HttpFutureCommandClient} * * @author Adrian Cole */ -public class HttpResponse { - int statusCode; - Multimap headers = HashMultimap.create(); - String message; - InputStream content; - String contentType; +public class HttpResponse extends HttpMessage { + private int statusCode; + private String message; + private InputStream content; @Override public String toString() { @@ -49,7 +44,6 @@ public class HttpResponse { sb.append(", headers=").append(headers); sb.append(", message='").append(message).append('\''); sb.append(", content set=").append(content != null); - sb.append(", contentType='").append(contentType).append('\''); sb.append('}'); return sb.toString(); } @@ -62,14 +56,6 @@ public class HttpResponse { this.statusCode = statusCode; } - public Multimap getHeaders() { - return headers; - } - - public void setHeaders(Multimap headers) { - this.headers = headers; - } - public String getMessage() { return message; } @@ -85,18 +71,4 @@ public class HttpResponse { public void setContent(InputStream content) { this.content = content; } - - public String getContentType() { - return contentType; - } - - public void setContentType(String contentType) { - this.contentType = contentType; - } - - public String getFirstHeaderOrNull(String string) { - Collection values = headers.get(string); - return (values != null && values.size() >= 1) ? values.iterator() - .next() : null; - } } \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/http/JavaUrlHttpFutureCommandClient.java b/core/src/main/java/org/jclouds/http/JavaUrlHttpFutureCommandClient.java index b37c792e0c..6de20fa532 100644 --- a/core/src/main/java/org/jclouds/http/JavaUrlHttpFutureCommandClient.java +++ b/core/src/main/java/org/jclouds/http/JavaUrlHttpFutureCommandClient.java @@ -23,8 +23,6 @@ */ package org.jclouds.http; -import static com.google.common.base.Preconditions.checkNotNull; - import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -116,8 +114,6 @@ public class JavaUrlHttpFutureCommandClient implements HttpFutureCommandClient { } if (in != null) { response.setContent(in); - response.setContentType(connection - .getHeaderField(HttpConstants.CONTENT_TYPE)); } response.setStatusCode(connection.getResponseCode()); for (String header : connection.getHeaderFields().keySet()) { @@ -135,33 +131,30 @@ public class JavaUrlHttpFutureCommandClient implements HttpFutureCommandClient { HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoOutput(true); connection.setAllowUserInteraction(false); - connection.setInstanceFollowRedirects(false); + connection.setInstanceFollowRedirects(true); connection.setRequestMethod(request.getMethod()); for (String header : request.getHeaders().keySet()) { for (String value : request.getHeaders().get(header)) connection.setRequestProperty(header, value); } - if (request.getContent() != null) { - connection.setRequestProperty(HttpConstants.CONTENT_TYPE, - checkNotNull(request.getContentType(), - "request.getContentType()")); + if (request.getPayload() != null) { OutputStream out = connection.getOutputStream(); try { - if (request.getContent() instanceof String) { + if (request.getPayload() instanceof String) { OutputStreamWriter writer = new OutputStreamWriter(out); - writer.write((String) request.getContent()); + writer.write((String) request.getPayload()); writer.close(); - } else if (request.getContent() instanceof InputStream) { - IOUtils.copy((InputStream) request.getContent(), out); - } else if (request.getContent() instanceof File) { + } else if (request.getPayload() instanceof InputStream) { + IOUtils.copy((InputStream) request.getPayload(), out); + } else if (request.getPayload() instanceof File) { IOUtils.copy(new FileInputStream((File) request - .getContent()), out); - } else if (request.getContent() instanceof byte[]) { - IOUtils.write((byte[]) request.getContent(), out); + .getPayload()), out); + } else if (request.getPayload() instanceof byte[]) { + IOUtils.write((byte[]) request.getPayload(), out); } else { throw new UnsupportedOperationException( "Content not supported " - + request.getContent().getClass()); + + request.getPayload().getClass()); } } finally { IOUtils.closeQuietly(out); diff --git a/core/src/main/java/org/jclouds/http/commands/callables/xml/ParseSax.java b/core/src/main/java/org/jclouds/http/commands/callables/xml/ParseSax.java index 7c2f619c6c..cdd66684f1 100644 --- a/core/src/main/java/org/jclouds/http/commands/callables/xml/ParseSax.java +++ b/core/src/main/java/org/jclouds/http/commands/callables/xml/ParseSax.java @@ -113,7 +113,8 @@ public class ParseSax extends HttpFutureCommand.ResponseCallable { } /** - * // TODO: Adrian: Document this! + * Handler that produces a useable domain object accessible after parsing + * completes. * * @author Adrian Cole */ diff --git a/core/src/main/java/org/jclouds/http/options/BaseHttpRequestOptions.java b/core/src/main/java/org/jclouds/http/options/BaseHttpRequestOptions.java new file mode 100644 index 0000000000..12b110af9a --- /dev/null +++ b/core/src/main/java/org/jclouds/http/options/BaseHttpRequestOptions.java @@ -0,0 +1,89 @@ +/** + * + * Copyright (C) 2009 Adrian Cole + * + * ==================================================================== + * 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.http.options; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; + +/** + * + * @see HttpRequestOptions + * @author Adrian Cole + * + */ +public class BaseHttpRequestOptions implements HttpRequestOptions { + + protected Map options = new HashMap(); + protected Multimap headers = HashMultimap.create(); + protected String payload; + + public String buildPayload() { + return payload; + } + + protected String getFirstHeaderOrNull(String string) { + Collection values = headers.get(string); + return (values != null && values.size() >= 1) ? values.iterator() + .next() : null; + } + + protected void replaceHeader(String key, String value) { + headers.removeAll(key); + headers.put(key, value); + } + + /** + * {@inheritDoc} + */ + public Multimap buildRequestHeaders() { + return headers; + } + + /** + * {@inheritDoc} + */ + public String buildQueryString() { + StringBuilder builder = new StringBuilder(""); + if (options.size() > 0) { + builder.append("?"); + for (Iterator> i = options.entrySet() + .iterator(); i.hasNext();) { + Entry entry = i.next(); + builder.append(entry.getKey()).append("=").append( + entry.getValue()); + if (i.hasNext()) + builder.append("&"); + } + } + String returnVal = builder.toString(); + return returnVal; + } + +} \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/http/options/HttpRequestOptions.java b/core/src/main/java/org/jclouds/http/options/HttpRequestOptions.java new file mode 100644 index 0000000000..b18e43d9bd --- /dev/null +++ b/core/src/main/java/org/jclouds/http/options/HttpRequestOptions.java @@ -0,0 +1,51 @@ +/** + * + * Copyright (C) 2009 Adrian Cole + * + * ==================================================================== + * 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.http.options; + +import com.google.common.collect.Multimap; + +/** + * Builds options that override or append to HttpRequests. + * + * @author Adrian Cole + * + */ +public interface HttpRequestOptions { + + /** + * Builds headers representing options. + * + * @return object that may contain headers. + */ + Multimap buildRequestHeaders(); + + /** + * Builds a query string, ex. ?marker=toast + * + * @return an http query string representing these options, or empty string + * if none are present. + */ + String buildQueryString(); + +} \ No newline at end of file diff --git a/extensions/httpnio/src/main/java/org/jclouds/http/httpnio/HttpNioUtils.java b/extensions/httpnio/src/main/java/org/jclouds/http/httpnio/HttpNioUtils.java index d72dd947cc..fa3a645620 100644 --- a/extensions/httpnio/src/main/java/org/jclouds/http/httpnio/HttpNioUtils.java +++ b/extensions/httpnio/src/main/java/org/jclouds/http/httpnio/HttpNioUtils.java @@ -36,6 +36,7 @@ import org.apache.http.message.BasicHttpEntityEnclosingRequest; import org.apache.http.nio.entity.NByteArrayEntity; import org.apache.http.nio.entity.NFileEntity; import org.apache.http.nio.entity.NStringEntity; +import org.jclouds.http.HttpHeaders; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; @@ -48,10 +49,15 @@ public class HttpNioUtils { for (String value : object.getHeaders().get(header)) apacheRequest.addHeader(header, value); } - Object content = object.getContent(); + Object content = object.getPayload(); if (content != null) { - addEntityForContent(apacheRequest, content, - object.getContentType(), object.getContentLength()); + addEntityForContent( + apacheRequest, + content, + object.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE), + Long + .parseLong(object + .getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH))); } return apacheRequest; } diff --git a/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java b/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java index 35687d2465..f5c0e139e9 100644 --- a/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java +++ b/extensions/jets3t/src/main/java/org/jclouds/aws/s3/jets3t/JCloudsS3Service.java @@ -207,12 +207,12 @@ public class JCloudsS3Service extends S3Service { @Override protected S3Bucket[] listAllBucketsImpl() throws S3ServiceException { try { - List jcBucketList = connection - .getMetaDataOfOwnedBuckets().get( + List jcBucketList = connection + .getOwnedBuckets().get( requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); ArrayList jsBucketList = new ArrayList(); - for (org.jclouds.aws.s3.domain.S3Bucket.MetaData jcBucket : jcBucketList) { + for (org.jclouds.aws.s3.domain.S3Bucket.Metadata jcBucket : jcBucketList) { org.jets3t.service.model.S3Bucket jsBucket = new org.jets3t.service.model.S3Bucket( jcBucket.getName()); jsBucket.setOwner(new org.jets3t.service.model.S3Owner(jcBucket diff --git a/extensions/jets3t/src/test/java/org/jclouds/aws/s3/jets3t/JCloudsS3ServiceTest.java b/extensions/jets3t/src/test/java/org/jclouds/aws/s3/jets3t/JCloudsS3ServiceTest.java index 40840bf767..5bbc97f663 100644 --- a/extensions/jets3t/src/test/java/org/jclouds/aws/s3/jets3t/JCloudsS3ServiceTest.java +++ b/extensions/jets3t/src/test/java/org/jclouds/aws/s3/jets3t/JCloudsS3ServiceTest.java @@ -107,7 +107,7 @@ public class JCloudsS3ServiceTest extends S3IntegrationTest { private void createBucket(String bucketName) throws InterruptedException, ExecutionException, TimeoutException { - client.createBucketIfNotExists(bucketName).get(10, TimeUnit.SECONDS); + client.putBucketIfNotExists(bucketName).get(10, TimeUnit.SECONDS); } @Test @@ -121,7 +121,7 @@ public class JCloudsS3ServiceTest extends S3IntegrationTest { service.deleteObject(bucketName, objectKey); - assertEquals(client.getObjectMetaData(bucketName, objectKey).get(10, + assertEquals(client.headObject(bucketName, objectKey).get(10, TimeUnit.SECONDS), org.jclouds.aws.s3.domain.S3Object.NOT_FOUND); } @@ -131,7 +131,7 @@ public class JCloudsS3ServiceTest extends S3IntegrationTest { org.jclouds.aws.s3.domain.S3Object jcloudsObject = new org.jclouds.aws.s3.domain.S3Object( objectKey); jcloudsObject.setData(objectValue); - client.addObject(name, jcloudsObject).get(10, TimeUnit.SECONDS); + client.putObject(name, jcloudsObject).get(10, TimeUnit.SECONDS); } @Test @@ -183,17 +183,17 @@ public class JCloudsS3ServiceTest extends S3IntegrationTest { S3Bucket[] jsBuckets = service.listAllBuckets(); - List jcBuckets = client - .getMetaDataOfOwnedBuckets().get(10, TimeUnit.SECONDS); + List jcBuckets = client + .getOwnedBuckets().get(10, TimeUnit.SECONDS); assert jsBuckets.length == jcBuckets.size(); - Iterator jcBucketsIter = jcBuckets + Iterator jcBucketsIter = jcBuckets .iterator(); for (S3Bucket jsBucket : jsBuckets) { assert jcBucketsIter.hasNext(); - org.jclouds.aws.s3.domain.S3Bucket.MetaData jcBucket = jcBucketsIter + org.jclouds.aws.s3.domain.S3Bucket.Metadata jcBucket = jcBucketsIter .next(); assert jsBucket.getName().equals(jcBucket.getName()); assert jsBucket.getOwner().getId().equals( diff --git a/gae/src/main/java/org/jclouds/gae/URLFetchServiceClient.java b/gae/src/main/java/org/jclouds/gae/URLFetchServiceClient.java index 2148bd11c4..0b6e69f453 100644 --- a/gae/src/main/java/org/jclouds/gae/URLFetchServiceClient.java +++ b/gae/src/main/java/org/jclouds/gae/URLFetchServiceClient.java @@ -38,7 +38,6 @@ import java.util.List; import javax.annotation.Resource; import org.apache.commons.io.IOUtils; -import org.jclouds.http.HttpConstants; import org.jclouds.http.HttpFutureCommand; import org.jclouds.http.HttpFutureCommandClient; import org.jclouds.http.HttpRequest; @@ -126,17 +125,17 @@ public class URLFetchServiceClient implements HttpFutureCommandClient { */ @VisibleForTesting void changeRequestContentToBytes(HttpRequest request) throws IOException { - Object content = request.getContent(); + Object content = request.getPayload(); if (content == null || content instanceof byte[]) { return; } else if (content instanceof String) { String string = (String) content; - request.setContent(string.getBytes()); + request.setPayload(string.getBytes()); } else if (content instanceof InputStream || content instanceof File) { InputStream i = content instanceof InputStream ? (InputStream) content : new FileInputStream((File) content); try { - request.setContent(IOUtils.toByteArray(i)); + request.setPayload(IOUtils.toByteArray(i)); } finally { IOUtils.closeQuietly(i); } @@ -157,8 +156,6 @@ public class URLFetchServiceClient implements HttpFutureCommandClient { if (gaeResponse.getContent() != null) { response.setContent(new ByteArrayInputStream(gaeResponse .getContent())); - response.setContentType(response - .getFirstHeaderOrNull(HttpConstants.CONTENT_TYPE)); } return response; } @@ -167,17 +164,14 @@ public class URLFetchServiceClient implements HttpFutureCommandClient { HTTPRequest convert(HttpRequest request) throws IOException { URL url = new URL(target, request.getUri()); HTTPRequest gaeRequest = new HTTPRequest(url, HTTPMethod - .valueOf(request.getMethod()), disallowTruncate() - .doNotFollowRedirects()); + .valueOf(request.getMethod()), disallowTruncate()); for (String header : request.getHeaders().keySet()) { for (String value : request.getHeaders().get(header)) gaeRequest.addHeader(new HTTPHeader(header, value)); } - if (request.getContent() != null) { + if (request.getPayload() != null) { changeRequestContentToBytes(request); - gaeRequest.addHeader(new HTTPHeader(HttpConstants.CONTENT_TYPE, - request.getContentType())); - gaeRequest.setPayload((byte[]) request.getContent()); + gaeRequest.setPayload((byte[]) request.getPayload()); } return gaeRequest; } diff --git a/gae/src/test/java/org/jclouds/gae/URLFetchServiceClientTest.java b/gae/src/test/java/org/jclouds/gae/URLFetchServiceClientTest.java index 0d9300473c..439dd10829 100644 --- a/gae/src/test/java/org/jclouds/gae/URLFetchServiceClientTest.java +++ b/gae/src/test/java/org/jclouds/gae/URLFetchServiceClientTest.java @@ -39,7 +39,7 @@ import java.util.Date; import java.util.List; import org.apache.commons.io.IOUtils; -import org.jclouds.http.HttpConstants; +import org.jclouds.http.HttpHeaders; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpResponse; @@ -73,7 +73,7 @@ public class URLFetchServiceClientTest { HTTPResponse gaeResponse = createMock(HTTPResponse.class); expect(gaeResponse.getResponseCode()).andReturn(200); List headers = new ArrayList(); - headers.add(new HTTPHeader(HttpConstants.CONTENT_TYPE, "text/xml")); + headers.add(new HTTPHeader(HttpHeaders.CONTENT_TYPE, "text/xml")); expect(gaeResponse.getHeaders()).andReturn(headers); expect(gaeResponse.getContent()).andReturn(null).atLeastOnce(); replay(gaeResponse); @@ -81,7 +81,7 @@ public class URLFetchServiceClientTest { assertEquals(response.getStatusCode(), 200); assertEquals(response.getContent(), null); assertEquals(response.getHeaders().size(), 1); - assertEquals(response.getFirstHeaderOrNull(HttpConstants.CONTENT_TYPE), + assertEquals(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE), "text/xml"); } @@ -90,7 +90,7 @@ public class URLFetchServiceClientTest { HTTPResponse gaeResponse = createMock(HTTPResponse.class); expect(gaeResponse.getResponseCode()).andReturn(200); List headers = new ArrayList(); - headers.add(new HTTPHeader(HttpConstants.CONTENT_TYPE, "text/xml")); + headers.add(new HTTPHeader(HttpHeaders.CONTENT_TYPE, "text/xml")); expect(gaeResponse.getHeaders()).andReturn(headers); expect(gaeResponse.getContent()).andReturn("hello".getBytes()) .atLeastOnce(); @@ -99,7 +99,7 @@ public class URLFetchServiceClientTest { assertEquals(response.getStatusCode(), 200); assertEquals(IOUtils.toString(response.getContent()), "hello"); assertEquals(response.getHeaders().size(), 1); - assertEquals(response.getFirstHeaderOrNull(HttpConstants.CONTENT_TYPE), + assertEquals(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE), "text/xml"); } @@ -137,28 +137,28 @@ public class URLFetchServiceClientTest { @Test void testConvertRequestStringContent() throws IOException { HttpRequest request = new HttpRequest("GET", "foo"); - request.setContent("hoot!"); + request.setPayload("hoot!"); testHoot(request); } @Test void testConvertRequestInputStreamContent() throws IOException { HttpRequest request = new HttpRequest("GET", "foo"); - request.setContent(IOUtils.toInputStream("hoot!")); + request.setPayload(IOUtils.toInputStream("hoot!")); testHoot(request); } @Test void testConvertRequestBytesContent() throws IOException { HttpRequest request = new HttpRequest("GET", "foo"); - request.setContent("hoot!".getBytes()); + request.setPayload("hoot!".getBytes()); testHoot(request); } @Test(expectedExceptions = UnsupportedOperationException.class) void testConvertRequestBadContent() throws IOException { HttpRequest request = new HttpRequest("GET", "foo"); - request.setContent(new Date()); + request.setPayload(new Date()); client.convert(request); } @@ -179,15 +179,15 @@ public class URLFetchServiceClientTest { file.getParentFile().mkdirs(); IOUtils.write("hoot!", new FileOutputStream(file)); HttpRequest request = new HttpRequest("GET", "foo"); - request.setContent(file); + request.setPayload(file); testHoot(request); } private void testHoot(HttpRequest request) throws IOException { - request.setContentType("text/plain"); + request.getHeaders().put(HttpHeaders.CONTENT_TYPE,"text/plain"); HTTPRequest gaeRequest = client.convert(request); assertEquals(gaeRequest.getHeaders().get(0).getName(), - HttpConstants.CONTENT_TYPE); + HttpHeaders.CONTENT_TYPE); assertEquals(gaeRequest.getHeaders().get(0).getValue(), "text/plain"); assertEquals(new String(gaeRequest.getPayload()), "hoot!"); } diff --git a/s3/perftest/src/test/java/com/amazon/s3/BaseJCloudsPerformance.java b/s3/perftest/src/test/java/com/amazon/s3/BaseJCloudsPerformance.java index 68b04d12bd..306acefd98 100644 --- a/s3/perftest/src/test/java/com/amazon/s3/BaseJCloudsPerformance.java +++ b/s3/perftest/src/test/java/com/amazon/s3/BaseJCloudsPerformance.java @@ -58,7 +58,7 @@ public abstract class BaseJCloudsPerformance extends BasePerformance { key); object.getMetaData().setContentType(contentType); object.setData(data); - return client.addObject(bucket, object).get(120, TimeUnit.SECONDS) != null; + return client.putObject(bucket, object).get(120, TimeUnit.SECONDS) != null; } @Override @@ -68,7 +68,7 @@ public abstract class BaseJCloudsPerformance extends BasePerformance { key); object.getMetaData().setContentType(contentType); object.setData(data); - return client.addObject(bucket, object).get(120, TimeUnit.SECONDS) != null; + return client.putObject(bucket, object).get(120, TimeUnit.SECONDS) != null; } @Override @@ -79,7 +79,7 @@ public abstract class BaseJCloudsPerformance extends BasePerformance { object.getMetaData().setContentType(contentType); object.setData(data); object.getMetaData().setSize(data.available()); - return client.addObject(bucket, object).get(120, TimeUnit.SECONDS) != null; + return client.putObject(bucket, object).get(120, TimeUnit.SECONDS) != null; } @Override @@ -89,6 +89,6 @@ public abstract class BaseJCloudsPerformance extends BasePerformance { key); object.getMetaData().setContentType(contentType); object.setData(data); - return client.addObject(bucket, object).get(120, TimeUnit.SECONDS) != null; + return client.putObject(bucket, object).get(120, TimeUnit.SECONDS) != null; } } diff --git a/s3/perftest/src/test/java/com/amazon/s3/BasePerformance.java b/s3/perftest/src/test/java/com/amazon/s3/BasePerformance.java index c3d2ce9ae3..f77da7e423 100644 --- a/s3/perftest/src/test/java/com/amazon/s3/BasePerformance.java +++ b/s3/perftest/src/test/java/com/amazon/s3/BasePerformance.java @@ -90,7 +90,7 @@ public abstract class BasePerformance extends S3IntegrationTest { @Optional String AWSSecretAccessKey) throws Exception { super.setUpClient(AWSAccessKeyId, AWSSecretAccessKey); for (String bucket : BUCKETS) { - client.createBucketIfNotExists(bucket).get(10, TimeUnit.SECONDS); + client.putBucketIfNotExists(bucket).get(10, TimeUnit.SECONDS); } } diff --git a/s3/src/main/java/org/jclouds/aws/s3/S3Connection.java b/s3/src/main/java/org/jclouds/aws/s3/S3Connection.java index d8dabe5edd..e3f8b562b4 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/S3Connection.java +++ b/s3/src/main/java/org/jclouds/aws/s3/S3Connection.java @@ -24,10 +24,14 @@ package org.jclouds.aws.s3; import java.util.List; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; -import org.jclouds.aws.s3.commands.options.GetBucketOptions; +import org.jclouds.aws.s3.commands.options.CopyObjectOptions; +import org.jclouds.aws.s3.commands.options.GetObjectOptions; +import org.jclouds.aws.s3.commands.options.ListBucketOptions; import org.jclouds.aws.s3.commands.options.PutBucketOptions; +import org.jclouds.aws.s3.commands.options.PutObjectOptions; import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Object; @@ -54,6 +58,21 @@ public interface S3Connection { */ Future getObject(String bucketName, String key); + /** + * Retrieves the object and metadata associated with the key. + * + * @param bucketName + * namespace of the object you are retrieving + * + * @param key + * unique key in the s3Bucket identifying the object + * @param options + * options for retrieving the object + * @return fully populated S3Object containing data stored in S3 + */ + Future getObject(String bucketName, String key, + GetObjectOptions options); + /** * Retrieves the metadata of the object associated with the key. * @@ -64,7 +83,7 @@ public interface S3Connection { * unique key in the s3Bucket identifying the object * @return metadata associated with the key */ - Future getObjectMetaData(String bucketName, String key); + Future headObject(String bucketName, String key); /** * Removes the object and metadata associated with the key. @@ -84,16 +103,30 @@ public interface S3Connection { * namespace of the object you are storing * @param object * contains the data and metadata to create or overwrite - * @return ETAG which is a hex MD5 hash of the content uploaded + * @return MD5 hash of the content uploaded */ - Future addObject(String bucketName, S3Object object); + Future putObject(String bucketName, S3Object object); + + /** + * Store data by creating or overwriting an object. + * + * @param bucketName + * namespace of the object you are storing + * @param object + * contains the data and metadata to create or overwrite + * @param options + * options for creating the object + * @return MD5 hash of the content uploaded + */ + Future putObject(String bucketName, S3Object object, + PutObjectOptions options); /** * Create and name your own bucket in which to store your objects. * * @return true, if the bucket was created */ - Future createBucketIfNotExists(String name); + Future putBucketIfNotExists(String name); /** * Create and name your own bucket in which to store your objects. @@ -103,8 +136,7 @@ public interface S3Connection { * @return true, if the bucket was created * @see PutBucketOptions */ - Future createBucketIfNotExists(String name, - PutBucketOptions options); + Future putBucketIfNotExists(String name, PutBucketOptions options); /** * Deletes the bucket, if it is empty. @@ -120,10 +152,20 @@ public interface S3Connection { * * @return metaData populated with lastModified and etag of the new object */ - Future copyObject(String sourceBucket, + Future copyObject(String sourceBucket, String sourceObject, String destinationBucket, String destinationObject); + /** + * Copies one object to another bucket using the specifid options + * + * @return metaData populated with lastModified and etag of the new object + * @see CopyObjectOptions + */ + Future copyObject(String sourceBucket, + String sourceObject, String destinationBucket, + String destinationObject, CopyObjectOptions options); + Future bucketExists(String name); /** @@ -131,9 +173,9 @@ public interface S3Connection { * @param s3Bucket * @return */ - Future getBucket(String name); + Future listBucket(String name); - Future getBucket(String name, GetBucketOptions options); + Future listBucket(String name, ListBucketOptions options); - Future> getMetaDataOfOwnedBuckets(); + Future> getOwnedBuckets(); } diff --git a/s3/src/main/java/org/jclouds/aws/s3/S3Constants.java b/s3/src/main/java/org/jclouds/aws/s3/S3Constants.java index a4a5b4246e..d845687999 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/S3Constants.java +++ b/s3/src/main/java/org/jclouds/aws/s3/S3Constants.java @@ -31,8 +31,8 @@ import org.jclouds.http.HttpConstants; * * @author Adrian Cole */ -public interface S3Constants extends HttpConstants, PoolConstants { - public static final String AUTH = "Authorization"; +public interface S3Constants extends HttpConstants, PoolConstants, S3Headers { + public static final String PROPERTY_AWS_SECRETACCESSKEY = "jclouds.aws.secretaccesskey"; public static final String PROPERTY_AWS_ACCESSKEYID = "jclouds.aws.accesskeyid"; public static final String PROPERTY_AWS_MAP_TIMEOUT = "jclouds.aws.map.timeout"; diff --git a/s3/src/main/java/org/jclouds/aws/s3/S3Headers.java b/s3/src/main/java/org/jclouds/aws/s3/S3Headers.java new file mode 100644 index 0000000000..dbb8df0bb6 --- /dev/null +++ b/s3/src/main/java/org/jclouds/aws/s3/S3Headers.java @@ -0,0 +1,49 @@ +/** + * + * Copyright (C) 2009 Adrian Cole + * + * ==================================================================== + * 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; + +public interface S3Headers { + + /** + * The canned ACL to apply to the object. Options include private, + * public-read, public-read-write, and authenticated-read. For more + * information, see REST Access Control Policy. + */ + public static final String CANNED_ACL = "x-amz-acl"; + /** + * Any header starting with this prefix is considered user metadata. It will + * be stored with the object and returned when you retrieve the object. The + * total size of the HTTP request, not including the body, must be less than + * 8 KB. + */ + public static final String USER_METADATA_PREFIX = "x-amz-meta-"; + public static final String ETAG = "ETag"; + public static final String AMZ_MD5 = "x-amz-meta-object-md5"; + public static final String RANGE = "Range"; + public static final String OBJECT_IF_MODIFIED_SINCE = "If-Modified-Since"; + public static final String OBJECT_IF_UNMODIFIED_SINCE = "If-Unmodified-Since"; + public static final String OBJECT_IF_MATCH = "If-Match"; + public static final String OBJECT_IF_NONE_MATCH = "If-None-Match"; + +} \ No newline at end of file diff --git a/s3/src/main/java/org/jclouds/aws/s3/S3ResponseException.java b/s3/src/main/java/org/jclouds/aws/s3/S3ResponseException.java index 455d80b28b..ea58972cdf 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/S3ResponseException.java +++ b/s3/src/main/java/org/jclouds/aws/s3/S3ResponseException.java @@ -24,16 +24,16 @@ package org.jclouds.aws.s3; import org.jclouds.aws.s3.domain.S3Error; -import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpMessage; public class S3ResponseException extends RuntimeException { private static final long serialVersionUID = 1L; private S3Error error; - private HttpResponse response; + private HttpMessage response; - public S3ResponseException(S3Error error, HttpResponse response) { + public S3ResponseException(S3Error error, HttpMessage response) { super(error.toString()); this.setError(error); this.setResponse(response); @@ -47,11 +47,11 @@ public class S3ResponseException extends RuntimeException { return error; } - public void setResponse(HttpResponse response) { + public void setResponse(HttpMessage response) { this.response = response; } - public HttpResponse getResponse() { + public HttpMessage getResponse() { return response; } } diff --git a/s3/src/main/java/org/jclouds/aws/s3/S3Utils.java b/s3/src/main/java/org/jclouds/aws/s3/S3Utils.java index 34483c69d4..801708aa51 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/S3Utils.java +++ b/s3/src/main/java/org/jclouds/aws/s3/S3Utils.java @@ -79,7 +79,7 @@ public class S3Utils extends Utils { hmac.init(new KeyParameter(keyBytes)); hmac.update(plainBytes, 0, plainBytes.length); hmac.doFinal(resBuf, 0); - return new String(Base64.encode(resBuf)); + return toBase64String(resBuf); } public static String md5Hex(byte[] toEncode) @@ -93,6 +93,10 @@ public class S3Utils extends Utils { throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException { byte[] resBuf = md5(toEncode); + return toBase64String(resBuf); + } + + public static String toBase64String(byte[] resBuf) { return new String(Base64.encode(resBuf)); } diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/BucketExists.java b/s3/src/main/java/org/jclouds/aws/s3/commands/BucketExists.java index faf66170a8..e7ca1583da 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/BucketExists.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/BucketExists.java @@ -23,7 +23,7 @@ */ package org.jclouds.aws.s3.commands; -import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.maxKeys; +import static org.jclouds.aws.s3.commands.options.ListBucketOptions.Builder.maxResults; import org.jclouds.http.commands.callables.ReturnTrueIf200; import com.google.inject.Inject; @@ -35,7 +35,7 @@ public class BucketExists extends S3FutureCommand { @Inject public BucketExists(@Named("jclouds.http.address") String amazonHost, ReturnTrueIf200 callable, @Assisted String s3Bucket) { - super("HEAD", "/" + maxKeys(0).toQueryString(), callable, amazonHost, + super("HEAD", "/" + maxResults(0).buildQueryString(), callable, amazonHost, s3Bucket); } } \ No newline at end of file diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/CopyObject.java b/s3/src/main/java/org/jclouds/aws/s3/commands/CopyObject.java index 51c439f0ae..2b57bc88a8 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/CopyObject.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/CopyObject.java @@ -25,6 +25,7 @@ package org.jclouds.aws.s3.commands; import static com.google.common.base.Preconditions.checkNotNull; +import org.jclouds.aws.s3.commands.options.CopyObjectOptions; import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.xml.CopyObjectHandler; import org.jclouds.http.commands.callables.xml.ParseSax; @@ -33,15 +34,16 @@ import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import com.google.inject.name.Named; -public class CopyObject extends S3FutureCommand { +public class CopyObject extends S3FutureCommand { @Inject public CopyObject(@Named("jclouds.http.address") String amazonHost, - ParseSax callable, + ParseSax callable, @Assisted("sourceBucket") String sourceBucket, @Assisted("sourceObject") String sourceObject, @Assisted("destinationBucket") String destinationBucket, - @Assisted("destinationObject") String destinationObject) { + @Assisted("destinationObject") String destinationObject, + @Assisted CopyObjectOptions options) { super("PUT", "/" + checkNotNull(destinationObject, "destinationObject"), callable, amazonHost, destinationBucket); @@ -52,5 +54,6 @@ public class CopyObject extends S3FutureCommand { String.format("/%1s/%2s", checkNotNull(sourceBucket, "sourceBucket").toLowerCase(), checkNotNull( sourceObject, "sourceObject"))); + getRequest().getHeaders().putAll(options.buildRequestHeaders()); } } \ No newline at end of file diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/GetMetaDataForOwnedBuckets.java b/s3/src/main/java/org/jclouds/aws/s3/commands/GetMetaDataForOwnedBuckets.java index 59f05185b3..1595989c4c 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/GetMetaDataForOwnedBuckets.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/GetMetaDataForOwnedBuckets.java @@ -38,11 +38,11 @@ import com.google.inject.name.Named; * @author Adrian Cole * */ -public class GetMetaDataForOwnedBuckets extends S3FutureCommand> { +public class GetMetaDataForOwnedBuckets extends S3FutureCommand> { @Inject public GetMetaDataForOwnedBuckets(@Named("jclouds.http.address") String amazonHost, - ParseSax> callable) { + ParseSax> callable) { super("GET", "/", callable, amazonHost); } diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/GetObject.java b/s3/src/main/java/org/jclouds/aws/s3/commands/GetObject.java index ae3d9d34e2..ba6cc3444c 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/GetObject.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/GetObject.java @@ -31,6 +31,7 @@ import java.util.concurrent.TimeoutException; import org.jclouds.aws.s3.S3ResponseException; import org.jclouds.aws.s3.commands.callables.GetObjectCallable; +import org.jclouds.aws.s3.commands.options.GetObjectOptions; import org.jclouds.aws.s3.domain.S3Object; import com.google.common.annotations.VisibleForTesting; @@ -50,8 +51,10 @@ public class GetObject extends S3FutureCommand { @Inject public GetObject(@Named("jclouds.http.address") String amazonHost, GetObjectCallable callable, - @Assisted("bucketName") String s3Bucket, @Assisted("key") String key) { + @Assisted("bucketName") String s3Bucket, + @Assisted("key") String key, @Assisted GetObjectOptions options) { super("GET", "/" + checkNotNull(key), callable, amazonHost, s3Bucket); + this.getRequest().getHeaders().putAll(options.buildRequestHeaders()); callable.setKey(key); } @@ -65,8 +68,7 @@ public class GetObject extends S3FutureCommand { } @VisibleForTesting - S3Object attemptNotFound(ExecutionException e) - throws ExecutionException { + S3Object attemptNotFound(ExecutionException e) throws ExecutionException { if (e.getCause() != null && e.getCause() instanceof S3ResponseException) { S3ResponseException responseException = (S3ResponseException) e .getCause(); diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/HeadMetaData.java b/s3/src/main/java/org/jclouds/aws/s3/commands/HeadMetaData.java index 41dc38a65c..6adfc414b0 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/HeadMetaData.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/HeadMetaData.java @@ -34,12 +34,12 @@ import com.google.inject.name.Named; /** * Retrieves the metadata associated with the Key or - * {@link S3Object.MetaData#NOT_FOUND} if not available; + * {@link S3Object.Metadata#NOT_FOUND} if not available; * * @author Adrian Cole * */ -public class HeadMetaData extends S3FutureCommand { +public class HeadMetaData extends S3FutureCommand { @Inject public HeadMetaData(@Named("jclouds.http.address") String amazonHost, diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/GetBucket.java b/s3/src/main/java/org/jclouds/aws/s3/commands/ListBucket.java similarity index 73% rename from s3/src/main/java/org/jclouds/aws/s3/commands/GetBucket.java rename to s3/src/main/java/org/jclouds/aws/s3/commands/ListBucket.java index 9733bc942d..9dad66827f 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/GetBucket.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/ListBucket.java @@ -23,30 +23,23 @@ */ package org.jclouds.aws.s3.commands; -import org.jclouds.aws.s3.commands.options.GetBucketOptions; +import org.jclouds.aws.s3.commands.options.ListBucketOptions; import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.xml.ListBucketHandler; import org.jclouds.http.commands.callables.xml.ParseSax; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; - import com.google.inject.name.Named; -public class GetBucket extends S3FutureCommand { +public class ListBucket extends S3FutureCommand { @Inject - public GetBucket(@Named("jclouds.http.address") String amazonHost, - ParseSax bucketParser, @Assisted String bucket) { - this(amazonHost, bucketParser, bucket, new GetBucketOptions()); - } - - @Inject - public GetBucket(@Named("jclouds.http.address") String amazonHost, + public ListBucket(@Named("jclouds.http.address") String amazonHost, ParseSax bucketParser, @Assisted String bucket, - @Assisted GetBucketOptions options) { - super("GET", "/" + options.toQueryString(), bucketParser, amazonHost, - bucket); + @Assisted ListBucketOptions options) { + super("GET", "/" + options.buildQueryString(), bucketParser, + amazonHost, bucket); ListBucketHandler handler = (ListBucketHandler) bucketParser .getHandler(); handler.setBucketName(bucket); diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/PutBucket.java b/s3/src/main/java/org/jclouds/aws/s3/commands/PutBucket.java index b6fefe0562..1f3f6140e9 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/PutBucket.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/PutBucket.java @@ -24,6 +24,8 @@ package org.jclouds.aws.s3.commands; import org.jclouds.aws.s3.commands.callables.PutBucketCallable; +import org.jclouds.aws.s3.commands.options.PutBucketOptions; +import org.jclouds.http.HttpHeaders; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; @@ -39,8 +41,16 @@ public class PutBucket extends S3FutureCommand { @Inject public PutBucket(@Named("jclouds.http.address") String amazonHost, - PutBucketCallable callable, @Assisted String s3Bucket) { + PutBucketCallable callable, @Assisted String s3Bucket, + @Assisted PutBucketOptions options) { super("PUT", "/", callable, amazonHost, s3Bucket); + getRequest().getHeaders().putAll(options.buildRequestHeaders()); + String payload = options.buildPayload(); + if (payload != null) { + getRequest().setPayload(payload); + getRequest().getHeaders().put(HttpHeaders.CONTENT_LENGTH, + payload.getBytes().length + ""); + } } } \ No newline at end of file diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/PutObject.java b/s3/src/main/java/org/jclouds/aws/s3/commands/PutObject.java index 0b42338a90..174b5ee93b 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/PutObject.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/PutObject.java @@ -25,27 +25,55 @@ package org.jclouds.aws.s3.commands; import static com.google.common.base.Preconditions.checkNotNull; +import org.jclouds.aws.s3.S3Utils; import org.jclouds.aws.s3.commands.callables.PutObjectCallable; +import org.jclouds.aws.s3.commands.options.PutObjectOptions; import org.jclouds.aws.s3.domain.S3Object; +import org.jclouds.http.HttpHeaders; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import com.google.inject.name.Named; -public class PutObject extends S3FutureCommand { +public class PutObject extends S3FutureCommand { @Inject public PutObject(@Named("jclouds.http.address") String amazonHost, PutObjectCallable callable, @Assisted String s3Bucket, - @Assisted S3Object object) { + @Assisted S3Object object, @Assisted PutObjectOptions options) { super("PUT", "/" + checkNotNull(object.getKey()), callable, amazonHost, s3Bucket); - getRequest().setContent( + getRequest().setPayload( checkNotNull(object.getData(), "object.getContent()")); - getRequest().setContentType( + + getRequest().getHeaders().put( + HttpHeaders.CONTENT_TYPE, checkNotNull(object.getMetaData().getContentType(), "object.metaData.contentType()")); - getRequest().setContentLength(object.getMetaData().getSize()); + getRequest().getHeaders().put(HttpHeaders.CONTENT_LENGTH, + object.getMetaData().getSize() + ""); + + if (object.getMetaData().getCacheControl() != null) { + getRequest().getHeaders().put(HttpHeaders.CACHE_CONTROL, + object.getMetaData().getCacheControl()); + } + if (object.getMetaData().getContentDisposition() != null) { + getRequest().getHeaders().put(HttpHeaders.CONTENT_DISPOSITION, + object.getMetaData().getContentDisposition()); + } + if (object.getMetaData().getContentEncoding() != null) { + getRequest().getHeaders().put(HttpHeaders.CONTENT_ENCODING, + object.getMetaData().getContentEncoding()); + } + + if (object.getMetaData().getMd5() != null) + getRequest().getHeaders().put(HttpHeaders.CONTENT_MD5, + S3Utils.toBase64String(object.getMetaData().getMd5())); + + getRequest().getHeaders() + .putAll(object.getMetaData().getUserMetadata()); + getRequest().getHeaders().putAll(options.buildRequestHeaders()); + } } \ No newline at end of file diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/S3CommandFactory.java b/s3/src/main/java/org/jclouds/aws/s3/commands/S3CommandFactory.java index c5a1fa0e7f..517885ac34 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/S3CommandFactory.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/S3CommandFactory.java @@ -23,8 +23,11 @@ */ package org.jclouds.aws.s3.commands; -import org.jclouds.aws.s3.commands.options.GetBucketOptions; +import org.jclouds.aws.s3.commands.options.CopyObjectOptions; +import org.jclouds.aws.s3.commands.options.GetObjectOptions; +import org.jclouds.aws.s3.commands.options.ListBucketOptions; import org.jclouds.aws.s3.commands.options.PutBucketOptions; +import org.jclouds.aws.s3.commands.options.PutObjectOptions; import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.aws.s3.xml.S3ParserFactory; @@ -76,20 +79,9 @@ public class S3CommandFactory { } @Inject - private PutBucketFactory putBucketFactory; + private PutBucketFactory putBucketFactoryOptions; public static interface PutBucketFactory { - PutBucket create(String bucket); - } - - public PutBucket createPutBucket(String bucket) { - return putBucketFactory.create(bucket); - } - - @Inject - private PutBucketFactoryOptions putBucketFactoryOptions; - - public static interface PutBucketFactoryOptions { PutBucket create(String bucket, PutBucketOptions options); } @@ -101,11 +93,13 @@ public class S3CommandFactory { private PutObjectFactory putObjectFactory; public static interface PutObjectFactory { - PutObject create(String bucket, S3Object object); + PutObject create(String bucket, S3Object object, + PutObjectOptions options); } - public PutObject createPutObject(String bucket, S3Object s3Object) { - return putObjectFactory.create(bucket, s3Object); + public PutObject createPutObject(String bucket, S3Object s3Object, + PutObjectOptions options) { + return putObjectFactory.create(bucket, s3Object, options); } @Inject @@ -113,11 +107,12 @@ public class S3CommandFactory { public static interface GetObjectFactory { GetObject create(@Assisted("bucketName") String bucket, - @Assisted("key") String key); + @Assisted("key") String key, GetObjectOptions options); } - public GetObject createGetObject(String bucket, String key) { - return getObjectFactory.create(bucket, key); + public GetObject createGetObject(String bucket, String key, + GetObjectOptions options) { + return getObjectFactory.create(bucket, key, options); } @Inject @@ -141,24 +136,17 @@ public class S3CommandFactory { .createListBucketsParser()); } - public GetBucket createGetBucket(String bucket) { - return new GetBucket(amazonHost, - parserFactory.createListBucketParser(), bucket); + public ListBucket createListBucket(String bucket, ListBucketOptions options) { + return new ListBucket(amazonHost, parserFactory + .createListBucketParser(), bucket, options); } - - public GetBucket createGetBucket(String bucket, GetBucketOptions options) { - return new GetBucket(amazonHost, - parserFactory.createListBucketParser(), bucket, options); - } - + public CopyObject createCopyObject(String sourceBucket, String sourceObject, String destinationBucket, - String destinationObject) { + String destinationObject, CopyObjectOptions options) { return new CopyObject(amazonHost, parserFactory .createCopyObjectParser(), sourceBucket, sourceObject, - destinationBucket, destinationObject); + destinationBucket, destinationObject, options); } - - } \ No newline at end of file diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/callables/GetObjectCallable.java b/s3/src/main/java/org/jclouds/aws/s3/commands/callables/GetObjectCallable.java index 6135798a83..c4fa649830 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/callables/GetObjectCallable.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/callables/GetObjectCallable.java @@ -53,11 +53,11 @@ public class GetObjectCallable extends */ public S3Object call() throws HttpException { metaDataParser.setResponse(getResponse()); - S3Object.MetaData metaData = metaDataParser.call(); - if (metaData == S3Object.MetaData.NOT_FOUND) + S3Object.Metadata metaData = metaDataParser.call(); + if (metaData == S3Object.Metadata.NOT_FOUND) return S3Object.NOT_FOUND; if (getResponse().getContent() != null) { - return new S3Object(metaData,getResponse().getContent()); + return new S3Object(metaData, getResponse().getContent()); } else { String reason = null; try { diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/callables/HeadMetaDataCallable.java b/s3/src/main/java/org/jclouds/aws/s3/commands/callables/HeadMetaDataCallable.java index 5e0fe86e28..4b1d9b5032 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/callables/HeadMetaDataCallable.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/callables/HeadMetaDataCallable.java @@ -24,24 +24,27 @@ package org.jclouds.aws.s3.commands.callables; import java.io.IOException; +import java.util.Map.Entry; import org.jclouds.Utils; import org.jclouds.aws.s3.DateService; +import org.jclouds.aws.s3.S3Headers; import org.jclouds.aws.s3.S3Utils; import org.jclouds.aws.s3.domain.S3Object; import org.jclouds.http.HttpException; import org.jclouds.http.HttpFutureCommand; +import org.jclouds.http.HttpHeaders; import com.google.inject.Inject; /** - * This parses @{link {@link S3Object.MetaData} from http headers or returns - * {@link S3Object.MetaData#NOT_FOUND} on 404. + * This parses @{link {@link S3Object.Metadata} from http headers or returns + * {@link S3Object.Metadata#NOT_FOUND} on 404. * * @author Adrian Cole */ public class HeadMetaDataCallable extends - HttpFutureCommand.ResponseCallable { + HttpFutureCommand.ResponseCallable { private final DateService dateParser; private String key; @@ -54,31 +57,29 @@ public class HeadMetaDataCallable extends * @return S3Content.NOT_FOUND, if not found. * @throws org.jclouds.http.HttpException */ - public S3Object.MetaData call() throws HttpException { + public S3Object.Metadata call() throws HttpException { if (getResponse().getStatusCode() == 200) { - S3Object.MetaData metaData = new S3Object.MetaData(key); - String md5Header = getResponse().getFirstHeaderOrNull( - "x-amz-meta-object-md5"); - if (md5Header != null) { - metaData.setMd5(S3Utils.fromHexString(md5Header)); - } + S3Object.Metadata metaData = new S3Object.Metadata(key); + + extractUserMetadata(metaData); + addMd5(metaData); metaData.setLastModified(dateParser .dateTimeFromHeaderFormat(getResponse() - .getFirstHeaderOrNull("Last-Modified"))); - String eTag = getResponse().getFirstHeaderOrNull("ETag"); - if (eTag != null) { - metaData.setMd5(S3Utils - .fromHexString(eTag.replaceAll("\"", ""))); - } + .getFirstHeaderOrNull(HttpHeaders.LAST_MODIFIED))); metaData.setContentType(getResponse().getFirstHeaderOrNull( - "Content-Type")); + HttpHeaders.CONTENT_TYPE)); metaData.setSize(Long.parseLong(getResponse().getFirstHeaderOrNull( - "Content-Length"))); - metaData.setServer(getResponse().getFirstHeaderOrNull("Server")); + HttpHeaders.CONTENT_LENGTH))); + metaData.setCacheControl(getResponse().getFirstHeaderOrNull( + HttpHeaders.CACHE_CONTROL)); + metaData.setContentDisposition(getResponse().getFirstHeaderOrNull( + HttpHeaders.CONTENT_DISPOSITION)); + metaData.setContentEncoding(getResponse().getFirstHeaderOrNull( + HttpHeaders.CONTENT_ENCODING)); return metaData; } else if (getResponse().getStatusCode() == 404) { - return S3Object.MetaData.NOT_FOUND; + return S3Object.Metadata.NOT_FOUND; } else { String reason = null; try { @@ -91,6 +92,29 @@ public class HeadMetaDataCallable extends } } + private void addMd5(S3Object.Metadata metaData) { + String md5Header = getResponse() + .getFirstHeaderOrNull(S3Headers.AMZ_MD5); + if (md5Header != null) { + metaData.setMd5(S3Utils.fromHexString(md5Header)); + } + String eTag = getResponse().getFirstHeaderOrNull(S3Headers.ETAG); + if (metaData.getMd5() == null && eTag != null) { + metaData.setMd5(S3Utils.fromHexString(eTag.replaceAll("\"", ""))); + } + } + + private void extractUserMetadata(S3Object.Metadata metaData) { + for (Entry header : getResponse().getHeaders() + .entries()) { + if (header.getKey() != null + && header.getKey().startsWith( + S3Headers.USER_METADATA_PREFIX)) + metaData.getUserMetadata().put(header.getKey(), + header.getValue()); + } + } + public void setKey(String key) { this.key = key; } diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/callables/PutObjectCallable.java b/s3/src/main/java/org/jclouds/aws/s3/commands/callables/PutObjectCallable.java index 65a23981d9..3acaea2c79 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/callables/PutObjectCallable.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/callables/PutObjectCallable.java @@ -35,16 +35,21 @@ import org.jclouds.http.HttpFutureCommand; * @author Adrian Cole */ public class PutObjectCallable extends - HttpFutureCommand.ResponseCallable { + HttpFutureCommand.ResponseCallable { - public String call() throws HttpException { + public byte [] call() throws HttpException { if (getResponse().getStatusCode() == 200) { try { getResponse().getContent().close(); } catch (IOException e) { logger.error(e, "error consuming content"); } - return getResponse().getHeaders().get("ETag").iterator().next(); + String eTag = getResponse().getFirstHeaderOrNull("ETag"); + if (eTag != null) { + return S3Utils + .fromHexString(eTag.replaceAll("\"", "")); + } + throw new HttpException("did not receive ETag"); } else { try { String reason = S3Utils.toStringAndClose(getResponse() diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/config/S3CommandsModule.java b/s3/src/main/java/org/jclouds/aws/s3/commands/config/S3CommandsModule.java index c92e639b1d..ce1d882cbd 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/config/S3CommandsModule.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/config/S3CommandsModule.java @@ -66,11 +66,6 @@ public class S3CommandsModule extends AbstractModule { S3CommandFactory.PutBucketFactory.class, PutBucket.class)); - bind(S3CommandFactory.PutBucketFactoryOptions.class).toProvider( - FactoryProvider.newFactory( - S3CommandFactory.PutBucketFactoryOptions.class, - PutBucket.class)); - bind(S3CommandFactory.PutObjectFactory.class).toProvider( FactoryProvider.newFactory( S3CommandFactory.PutObjectFactory.class, diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/options/CopyObjectOptions.java b/s3/src/main/java/org/jclouds/aws/s3/commands/options/CopyObjectOptions.java index 6b7f392508..bb2044660c 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/options/CopyObjectOptions.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/options/CopyObjectOptions.java @@ -31,9 +31,11 @@ import java.io.UnsupportedEncodingException; import org.jclouds.aws.s3.DateService; import org.jclouds.aws.s3.S3Utils; +import org.jclouds.http.options.BaseHttpRequestOptions; import org.joda.time.DateTime; import com.google.common.base.Preconditions; +import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; /** @@ -56,7 +58,7 @@ import com.google.common.collect.Multimap; * Future object = connection.copyObject("sourceBucket", "objectName", * "destinationBucket", "destinationName", * overrideMetadataWith(meta). - * ifUnmodifiedSince(new DateTime().minusDays(1)) + * ifSourceModifiedSince(new DateTime().minusDays(1)) * ); * * @@ -66,13 +68,11 @@ import com.google.common.collect.Multimap; * * */ -public class CopyObjectOptions { +public class CopyObjectOptions extends BaseHttpRequestOptions { private final static DateService dateService = new DateService(); - private String ifModifiedSince; - private String ifUnmodifiedSince; - private String ifMatch; - private String ifNoneMatch; + public static final CopyObjectOptions NONE = new CopyObjectOptions(); + private Multimap metadata; /** @@ -88,7 +88,7 @@ public class CopyObjectOptions { * @see CopyObjectOptions#ifSourceModifiedSince(DateTime) */ public String getIfModifiedSince() { - return ifModifiedSince; + return getFirstHeaderOrNull("x-amz-copy-source-if-modified-since"); } /** @@ -105,7 +105,7 @@ public class CopyObjectOptions { * @see CopyObjectOptions#ifSourceUnmodifiedSince(DateTime) */ public String getIfUnmodifiedSince() { - return ifUnmodifiedSince; + return getFirstHeaderOrNull("x-amz-copy-source-if-unmodified-since"); } /** @@ -120,7 +120,7 @@ public class CopyObjectOptions { * @see CopyObjectOptions#ifSourceMd5Matches(String) */ public String getIfMatch() { - return ifMatch; + return getFirstHeaderOrNull("x-amz-copy-source-if-match"); } /** @@ -135,7 +135,7 @@ public class CopyObjectOptions { * @see CopyObjectOptions#ifSourceMd5DoesntMatch(String) */ public String getIfNoneMatch() { - return ifNoneMatch; + return getFirstHeaderOrNull("x-amz-copy-source-if-none-match"); } /** @@ -156,12 +156,13 @@ public class CopyObjectOptions { * {@link #ifSourceUnmodifiedSince(DateTime)} */ public CopyObjectOptions ifSourceModifiedSince(DateTime ifModifiedSince) { - checkState(ifMatch == null, + checkState(getIfMatch() == null, "ifMd5Matches() is not compatible with ifModifiedSince()"); - checkState(ifUnmodifiedSince == null, + checkState(getIfUnmodifiedSince() == null, "ifUnmodifiedSince() is not compatible with ifModifiedSince()"); - this.ifModifiedSince = dateService.toHeaderString(checkNotNull( - ifModifiedSince, "ifModifiedSince")); + replaceHeader("x-amz-copy-source-if-modified-since", + dateService.toHeaderString(checkNotNull(ifModifiedSince, + "ifModifiedSince"))); return this; } @@ -172,12 +173,13 @@ public class CopyObjectOptions { * {@link #ifSourceModifiedSince(DateTime)} */ public CopyObjectOptions ifSourceUnmodifiedSince(DateTime ifUnmodifiedSince) { - checkState(ifNoneMatch == null, + checkState(getIfNoneMatch() == null, "ifMd5DoesntMatch() is not compatible with ifUnmodifiedSince()"); - checkState(ifModifiedSince == null, + checkState(getIfModifiedSince() == null, "ifModifiedSince() is not compatible with ifUnmodifiedSince()"); - this.ifUnmodifiedSince = dateService.toHeaderString(checkNotNull( - ifUnmodifiedSince, "ifUnmodifiedSince")); + replaceHeader("x-amz-copy-source-if-unmodified-since", dateService + .toHeaderString(checkNotNull(ifUnmodifiedSince, + "ifUnmodifiedSince"))); return this; } @@ -195,12 +197,12 @@ public class CopyObjectOptions { */ public CopyObjectOptions ifSourceMd5Matches(byte[] md5) throws UnsupportedEncodingException { - checkState(ifNoneMatch == null, + checkState(getIfNoneMatch() == null, "ifMd5DoesntMatch() is not compatible with ifMd5Matches()"); - checkState(ifModifiedSince == null, + checkState(getIfModifiedSince() == null, "ifModifiedSince() is not compatible with ifMd5Matches()"); - this.ifMatch = String.format("\"%1s\"", S3Utils - .toHexString(checkNotNull(md5, "md5"))); + replaceHeader("x-amz-copy-source-if-match", String.format("\"%1s\"", + S3Utils.toHexString(checkNotNull(md5, "md5")))); return this; } @@ -218,16 +220,26 @@ public class CopyObjectOptions { */ public CopyObjectOptions ifSourceMd5DoesntMatch(byte[] md5) throws UnsupportedEncodingException { - checkState(ifMatch == null, + checkState(getIfMatch() == null, "ifMd5Matches() is not compatible with ifMd5DoesntMatch()"); Preconditions - .checkState(ifUnmodifiedSince == null, + .checkState(getIfUnmodifiedSince() == null, "ifUnmodifiedSince() is not compatible with ifMd5DoesntMatch()"); - this.ifNoneMatch = String.format("\"%1s\"", S3Utils - .toHexString(checkNotNull(md5, "ifMd5DoesntMatch"))); + replaceHeader("x-amz-copy-source-if-none-match", String.format( + "\"%1s\"", S3Utils.toHexString(checkNotNull(md5, + "ifMd5DoesntMatch")))); return this; } + @Override + public Multimap buildRequestHeaders() { + Multimap returnVal = HashMultimap.create(); + returnVal.putAll(headers); + if (metadata != null) + returnVal.putAll(metadata); + return returnVal; + } + /** * Use the provided metadata instead of what is on the source object. */ diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/options/GetObjectOptions.java b/s3/src/main/java/org/jclouds/aws/s3/commands/options/GetObjectOptions.java index d15116da53..da471e7931 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/options/GetObjectOptions.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/options/GetObjectOptions.java @@ -29,7 +29,9 @@ import static com.google.common.base.Preconditions.checkState; import java.io.UnsupportedEncodingException; import org.jclouds.aws.s3.DateService; +import org.jclouds.aws.s3.S3Headers; import org.jclouds.aws.s3.S3Utils; +import org.jclouds.http.options.BaseHttpRequestOptions; import org.joda.time.DateTime; /** @@ -53,14 +55,9 @@ import org.joda.time.DateTime; * * */ -public class GetObjectOptions { +public class GetObjectOptions extends BaseHttpRequestOptions { private final static DateService dateService = new DateService(); - - private String range; - private String ifModifiedSince; - private String ifUnmodifiedSince; - private String ifMatch; - private String ifNoneMatch; + public static final GetObjectOptions NONE = new GetObjectOptions(); /** * Only download the specified range of the object. @@ -68,7 +65,9 @@ public class GetObjectOptions { public GetObjectOptions range(long start, long end) { checkState(start >= 0, "start must be >= 0"); checkState(end >= 0, "end must be >= 0"); - this.range = String.format("bytes=%1d-%2d", start, end); + headers + .put(S3Headers.RANGE, String + .format("bytes=%1d-%2d", start, end)); return this; } @@ -79,7 +78,7 @@ public class GetObjectOptions { * @see GetObjectOptions#range(long, long) */ public String getRange() { - return range; + return this.getFirstHeaderOrNull(S3Headers.RANGE); } /** @@ -89,12 +88,13 @@ public class GetObjectOptions { * {@link #ifUnmodifiedSince(DateTime)} */ public GetObjectOptions ifModifiedSince(DateTime ifModifiedSince) { - checkState(ifMatch == null, + checkState(getIfMatch() == null, "ifMd5Matches() is not compatible with ifModifiedSince()"); - checkState(ifUnmodifiedSince == null, + checkState(getIfUnmodifiedSince() == null, "ifUnmodifiedSince() is not compatible with ifModifiedSince()"); - this.ifModifiedSince = dateService.toHeaderString(checkNotNull( - ifModifiedSince, "ifModifiedSince")); + this.headers.put(S3Headers.OBJECT_IF_MODIFIED_SINCE, + dateService.toHeaderString(checkNotNull(ifModifiedSince, + "ifModifiedSince"))); return this; } @@ -107,7 +107,7 @@ public class GetObjectOptions { * @see GetObjectOptions#ifModifiedSince(DateTime) */ public String getIfModifiedSince() { - return ifModifiedSince; + return this.getFirstHeaderOrNull(S3Headers.OBJECT_IF_MODIFIED_SINCE); } /** @@ -117,12 +117,13 @@ public class GetObjectOptions { * {@link #ifModifiedSince(DateTime)} */ public GetObjectOptions ifUnmodifiedSince(DateTime ifUnmodifiedSince) { - checkState(ifNoneMatch == null, + checkState(getIfNoneMatch() == null, "ifMd5DoesntMatch() is not compatible with ifUnmodifiedSince()"); - checkState(ifModifiedSince == null, + checkState(getIfModifiedSince() == null, "ifModifiedSince() is not compatible with ifUnmodifiedSince()"); - this.ifUnmodifiedSince = dateService.toHeaderString(checkNotNull( - ifUnmodifiedSince, "ifUnmodifiedSince")); + this.headers.put(S3Headers.OBJECT_IF_UNMODIFIED_SINCE, dateService + .toHeaderString(checkNotNull(ifUnmodifiedSince, + "ifUnmodifiedSince"))); return this; } @@ -135,7 +136,7 @@ public class GetObjectOptions { * @see GetObjectOptions#ifUnmodifiedSince(DateTime) */ public String getIfUnmodifiedSince() { - return ifUnmodifiedSince; + return this.getFirstHeaderOrNull(S3Headers.OBJECT_IF_UNMODIFIED_SINCE); } /** @@ -152,12 +153,12 @@ public class GetObjectOptions { */ public GetObjectOptions ifMd5Matches(byte[] md5) throws UnsupportedEncodingException { - checkState(ifNoneMatch == null, + checkState(getIfNoneMatch() == null, "ifMd5DoesntMatch() is not compatible with ifMd5Matches()"); - checkState(ifModifiedSince == null, + checkState(getIfModifiedSince() == null, "ifModifiedSince() is not compatible with ifMd5Matches()"); - this.ifMatch = String.format("\"%1s\"", S3Utils - .toHexString(checkNotNull(md5, "md5"))); + this.headers.put(S3Headers.OBJECT_IF_MATCH, String.format("\"%1s\"", + S3Utils.toHexString(checkNotNull(md5, "md5")))); return this; } @@ -170,7 +171,7 @@ public class GetObjectOptions { * @see GetObjectOptions#ifMd5Matches(String) */ public String getIfMatch() { - return ifMatch; + return this.getFirstHeaderOrNull(S3Headers.OBJECT_IF_MATCH); } /** @@ -187,12 +188,13 @@ public class GetObjectOptions { */ public GetObjectOptions ifMd5DoesntMatch(byte[] md5) throws UnsupportedEncodingException { - checkState(ifMatch == null, + checkState(getIfMatch() == null, "ifMd5Matches() is not compatible with ifMd5DoesntMatch()"); - checkState(ifUnmodifiedSince == null, + checkState(getIfUnmodifiedSince() == null, "ifUnmodifiedSince() is not compatible with ifMd5DoesntMatch()"); - this.ifNoneMatch = String.format("\"%1s\"", S3Utils - .toHexString(checkNotNull(md5, "ifMd5DoesntMatch"))); + this.headers.put(S3Headers.OBJECT_IF_NONE_MATCH, String.format( + "\"%1s\"", S3Utils.toHexString(checkNotNull(md5, + "ifMd5DoesntMatch")))); return this; } @@ -205,7 +207,7 @@ public class GetObjectOptions { * @see GetObjectOptions#ifMd5DoesntMatch(String) */ public String getIfNoneMatch() { - return ifNoneMatch; + return this.getFirstHeaderOrNull(S3Headers.OBJECT_IF_NONE_MATCH); } public static class Builder { diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/options/GetBucketOptions.java b/s3/src/main/java/org/jclouds/aws/s3/commands/options/ListBucketOptions.java similarity index 67% rename from s3/src/main/java/org/jclouds/aws/s3/commands/options/GetBucketOptions.java rename to s3/src/main/java/org/jclouds/aws/s3/commands/options/ListBucketOptions.java index 510d9452f7..707fedc30a 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/options/GetBucketOptions.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/options/ListBucketOptions.java @@ -28,10 +28,9 @@ import static com.google.common.base.Preconditions.checkState; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; + +import org.jclouds.http.options.BaseHttpRequestOptions; + /** * Contains options supported in the REST API for the GET bucket operation.

@@ -43,7 +42,7 @@ import java.util.Map.Entry; * import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.* * * S3Connection connection = // get connection - * Future bucket = connection.getBucket("bucketName",prefix("/home/users").maxKeys(1000)); + * Future bucket = connection.listBucket("bucketName",withPrefix("home/users").maxKeys(1000)); * * * Description of parameters taken from {@link http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET.html} @@ -52,31 +51,8 @@ import java.util.Map.Entry; * * */ -public class GetBucketOptions { - private Map options = new HashMap(); - - /** - * Builds a query string, ex. ?marker=toast - * - * @return an http query string representing these options, or empty string - * if none are present. - */ - public String toQueryString() { - StringBuilder builder = new StringBuilder(""); - if (options.size() > 0) { - builder.append("?"); - for (Iterator> i = options.entrySet() - .iterator(); i.hasNext();) { - Entry entry = i.next(); - builder.append(entry.getKey()).append("=").append( - entry.getValue()); - if (i.hasNext()) - builder.append("&"); - } - } - String returnVal = builder.toString(); - return returnVal; - } +public class ListBucketOptions extends BaseHttpRequestOptions { + public static final ListBucketOptions NONE = new ListBucketOptions(); /** * Limits the response to keys which begin with the indicated prefix. You @@ -85,7 +61,7 @@ public class GetBucketOptions { * * @throws UnsupportedEncodingException */ - public GetBucketOptions prefix(String prefix) + public ListBucketOptions withPrefix(String prefix) throws UnsupportedEncodingException { options.put("prefix", URLEncoder.encode(checkNotNull(prefix, "prefix"), "UTF-8")); @@ -93,7 +69,7 @@ public class GetBucketOptions { } /** - * @see GetBucketOptions#prefix(String) + * @see ListBucketOptions#prefix(String) */ public String getPrefix() { return options.get("prefix"); @@ -107,7 +83,7 @@ public class GetBucketOptions { * * @throws UnsupportedEncodingException */ - public GetBucketOptions marker(String marker) + public ListBucketOptions afterMarker(String marker) throws UnsupportedEncodingException { options.put("marker", URLEncoder.encode(checkNotNull(marker, "marker"), "UTF-8")); @@ -115,7 +91,7 @@ public class GetBucketOptions { } /** - * @see GetBucketOptions#marker(String) + * @see ListBucketOptions#marker(String) */ public String getMarker() { return options.get("marker"); @@ -125,14 +101,14 @@ public class GetBucketOptions { * 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. */ - public GetBucketOptions maxKeys(long maxKeys) { + public ListBucketOptions maxResults(long maxKeys) { checkState(maxKeys >= 0, "maxKeys must be >= 0"); options.put("max-keys", Long.toString(maxKeys)); return this; } /** - * @see GetBucketOptions#maxKeys(String) + * @see ListBucketOptions#maxKeys(String) */ public String getMaxKeys() { return options.get("max-keys"); @@ -146,7 +122,7 @@ public class GetBucketOptions { * * @throws UnsupportedEncodingException */ - public GetBucketOptions delimiter(String delimiter) + public ListBucketOptions setDelimiter(String delimiter) throws UnsupportedEncodingException { options.put("delimiter", URLEncoder.encode(checkNotNull(delimiter, "delimiter"), "UTF-8")); @@ -154,7 +130,7 @@ public class GetBucketOptions { } /** - * @see GetBucketOptions#delimiter(String) + * @see ListBucketOptions#setDelimiter(String) */ public String getDelimiter() { return options.get("delimiter"); @@ -164,40 +140,40 @@ public class GetBucketOptions { /** * @throws UnsupportedEncodingException - * @see GetBucketOptions#prefix + * @see ListBucketOptions#withPrefix */ - public static GetBucketOptions prefix(String prefix) + public static ListBucketOptions withPrefix(String prefix) throws UnsupportedEncodingException { - GetBucketOptions options = new GetBucketOptions(); - return options.prefix(prefix); + ListBucketOptions options = new ListBucketOptions(); + return options.withPrefix(prefix); } /** * @throws UnsupportedEncodingException - * @see GetBucketOptions#marker + * @see ListBucketOptions#afterMarker */ - public static GetBucketOptions marker(String marker) + public static ListBucketOptions afterMarker(String marker) throws UnsupportedEncodingException { - GetBucketOptions options = new GetBucketOptions(); - return options.marker(marker); + ListBucketOptions options = new ListBucketOptions(); + return options.afterMarker(marker); } /** - * @see GetBucketOptions#maxKeys + * @see ListBucketOptions#maxResults */ - public static GetBucketOptions maxKeys(long maxKeys) { - GetBucketOptions options = new GetBucketOptions(); - return options.maxKeys(maxKeys); + public static ListBucketOptions maxResults(long maxKeys) { + ListBucketOptions options = new ListBucketOptions(); + return options.maxResults(maxKeys); } /** * @throws UnsupportedEncodingException - * @see GetBucketOptions#delimiter + * @see ListBucketOptions#delimiter */ - public static GetBucketOptions delimiter(String delimiter) + public static ListBucketOptions delimiter(String delimiter) throws UnsupportedEncodingException { - GetBucketOptions options = new GetBucketOptions(); - return options.delimiter(delimiter); + ListBucketOptions options = new ListBucketOptions(); + return options.setDelimiter(delimiter); } } diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/options/PutBucketOptions.java b/s3/src/main/java/org/jclouds/aws/s3/commands/options/PutBucketOptions.java index ac8f1864b8..f198978d01 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/commands/options/PutBucketOptions.java +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/options/PutBucketOptions.java @@ -23,14 +23,18 @@ */ package org.jclouds.aws.s3.commands.options; -import org.jclouds.aws.s3.domain.S3Bucket.MetaData.LocationConstraint; +import org.jclouds.aws.s3.S3Headers; +import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint; +import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; +import org.jclouds.http.options.BaseHttpRequestOptions; -import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.*; /** - * Contains options supported in the REST API for the PUT bucket operation. - *

Usage

- * The recommended way to instantiate a PutBucketOptions object is to statically import PutBucketOptions.Builder.* and invoke a static creation method followed by an instance mutator (if needed): + * Contains options supported in the REST API for the PUT bucket operation.

+ * Usage

The recommended way to instantiate a PutBucketOptions object is to + * statically import PutBucketOptions.Builder.* and invoke a static creation + * method followed by an instance mutator (if needed): *

* * import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.* @@ -38,7 +42,7 @@ import static com.google.common.base.Preconditions.checkNotNull; * import org.jclouds.aws.s3.S3Connection; * * S3Connection connection = // get connection - * Future createdInEu = connection.createBucketIfNotExists("bucketName",locationConstraint(EU)); + * Future createdInEu = connection.putBucketIfNotExists("bucketName",createIn(EU)); * * * Description of parameters taken from {@link http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketPUT.html} @@ -46,7 +50,9 @@ import static com.google.common.base.Preconditions.checkNotNull; * @author Adrian Cole * */ -public class PutBucketOptions { +public class PutBucketOptions extends BaseHttpRequestOptions { + public static final PutBucketOptions NONE = new PutBucketOptions(); + private CannedAccessPolicy acl = CannedAccessPolicy.PRIVATE; private LocationConstraint constraint; /** @@ -54,13 +60,36 @@ public class PutBucketOptions { * location constraint that will affect where your data physically resides. * You can currently specify a Europe (EU) location constraint. */ - public PutBucketOptions locationConstraint(LocationConstraint constraint) { + public PutBucketOptions createIn(LocationConstraint constraint) { this.constraint = checkNotNull(constraint, "constraint"); + this.payload = String + .format( + "%1s", + constraint.toString()); return this; } /** - * @see PutBucketOptions#locationConstraint(LocationConstraint) + * Override the default ACL (private) with the specified one. + * + * @see CannedAccessPolicy + */ + public PutBucketOptions withBucketAcl(CannedAccessPolicy acl) { + this.acl = checkNotNull(acl, "acl"); + if (!acl.equals(CannedAccessPolicy.PRIVATE)) + this.replaceHeader(S3Headers.CANNED_ACL, acl.toString()); + return this; + } + + /** + * @see PutBucketOptions#withBucketAcl(CannedAccessPolicy) + */ + public CannedAccessPolicy getAcl() { + return acl; + } + + /** + * @see PutBucketOptions#createIn(LocationConstraint) */ public LocationConstraint getLocationConstraint() { return constraint; @@ -68,12 +97,19 @@ public class PutBucketOptions { public static class Builder { /** - * @see PutBucketOptions#locationConstraint(LocationConstraint) + * @see PutBucketOptions#createIn(LocationConstraint) */ - public static PutBucketOptions locationConstraint( - LocationConstraint constraint) { + public static PutBucketOptions createIn(LocationConstraint constraint) { PutBucketOptions options = new PutBucketOptions(); - return options.locationConstraint(constraint); + return options.createIn(constraint); + } + + /** + * @see PutBucketOptions#withBucketAcl(CannedAccessPolicy) + */ + public static PutBucketOptions withBucketAcl(CannedAccessPolicy acl) { + PutBucketOptions options = new PutBucketOptions(); + return options.withBucketAcl(acl); } } } diff --git a/s3/src/main/java/org/jclouds/aws/s3/commands/options/PutObjectOptions.java b/s3/src/main/java/org/jclouds/aws/s3/commands/options/PutObjectOptions.java new file mode 100644 index 0000000000..eb627719d8 --- /dev/null +++ b/s3/src/main/java/org/jclouds/aws/s3/commands/options/PutObjectOptions.java @@ -0,0 +1,87 @@ +/** + * + * Copyright (C) 2009 Adrian Cole + * + * ==================================================================== + * 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.commands.options; + +import org.jclouds.aws.s3.S3Headers; +import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; +import org.jclouds.http.options.BaseHttpRequestOptions; + +import static com.google.common.base.Preconditions.*; + +/** + * Contains options supported in the REST API for the PUT object operation. + *

+ *

+ * Usage

The recommended way to instantiate a PutObjectOptions object is to + * statically import PutObjectOptions.Builder.* and invoke a static creation + * method followed by an instance mutator (if needed): + *

+ * + * import static org.jclouds.aws.s3.commands.options.PutObjectOptions.Builder.* + * import org.jclouds.aws.s3.S3Connection; + * + * S3Connection connection = // get connection + * Future publicly readable = connection.putObject("bucketName",new S3Object("key","value"), withAcl(CannedAccessPolicy.PUBLIC_READ)); + * + * + * Description of parameters taken from {@link http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectPUT.html} + * + * @author Adrian Cole + * + */ +public class PutObjectOptions extends BaseHttpRequestOptions { + public static final PutObjectOptions NONE = new PutObjectOptions(); + + private CannedAccessPolicy acl = CannedAccessPolicy.PRIVATE; + + /** + * Override the default ACL (private) with the specified one. + * + * @see CannedAccessPolicy + */ + public PutObjectOptions withAcl(CannedAccessPolicy acl) { + this.acl = checkNotNull(acl, "acl"); + if (!acl.equals(CannedAccessPolicy.PRIVATE)) + this.replaceHeader(S3Headers.CANNED_ACL, acl.toString()); + return this; + } + + /** + * @see PutObjectOptions#withAcl(CannedAccessPolicy) + */ + public CannedAccessPolicy getAcl() { + return acl; + } + + public static class Builder { + + /** + * @see PutObjectOptions#withAcl(CannedAccessPolicy) + */ + public static PutObjectOptions withAcl(CannedAccessPolicy acl) { + PutObjectOptions options = new PutObjectOptions(); + return options.withAcl(acl); + } + } +} diff --git a/s3/src/main/java/org/jclouds/aws/s3/domain/S3Bucket.java b/s3/src/main/java/org/jclouds/aws/s3/domain/S3Bucket.java index a898658fb2..603edbd94b 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/domain/S3Bucket.java +++ b/s3/src/main/java/org/jclouds/aws/s3/domain/S3Bucket.java @@ -75,7 +75,7 @@ public class S3Bucket { return result; } - public static class MetaData { + public static class Metadata { @Override public String toString() { final StringBuilder sb = new StringBuilder(); @@ -83,7 +83,6 @@ public class S3Bucket { sb.append("{name='").append(name).append('\''); sb.append(", creationDate=").append(creationDate); sb.append(", canonicalUser=").append(canonicalUser); - sb.append(", locationConstraint=").append(locationConstraint); sb.append('}'); return sb.toString(); } @@ -92,10 +91,10 @@ public class S3Bucket { public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof MetaData)) + if (!(o instanceof Metadata)) return false; - MetaData metaData = (MetaData) o; + Metadata metaData = (Metadata) o; if (canonicalUser != null ? !canonicalUser .equals(metaData.canonicalUser) @@ -105,8 +104,6 @@ public class S3Bucket { .equals(metaData.creationDate) : metaData.creationDate != null) return false; - if (locationConstraint != metaData.locationConstraint) - return false; if (!name.equals(metaData.name)) return false; @@ -120,10 +117,6 @@ public class S3Bucket { + (creationDate != null ? creationDate.hashCode() : 0); result = 31 * result + (canonicalUser != null ? canonicalUser.hashCode() : 0); - result = 31 - * result - + (locationConstraint != null ? locationConstraint - .hashCode() : 0); return result; } @@ -134,9 +127,8 @@ public class S3Bucket { private final String name; private DateTime creationDate; private S3Owner canonicalUser; - private LocationConstraint locationConstraint; - public MetaData(String name) { + public Metadata(String name) { this.name = checkNotNull(name, "name").toLowerCase(); } @@ -160,44 +152,37 @@ public class S3Bucket { this.canonicalUser = canonicalUser; } - public LocationConstraint getLocationConstraint() { - return locationConstraint; - } - - public void setLocationConstraint(LocationConstraint locationConstraint) { - this.locationConstraint = locationConstraint; - } } public static final S3Bucket NOT_FOUND = new S3Bucket("NOT_FOUND"); - private Set objects = new HashSet(); + private Set objects = new HashSet(); private Set commonPrefixes = new HashSet(); private String prefix; private String marker; private String delimiter; private long maxKeys; - private final MetaData metaData; + private final Metadata metaData; private boolean isComplete; public S3Bucket(String name) { - this.metaData = new MetaData(name); + this.metaData = new Metadata(name); } public String getName() { return this.metaData.getName(); } - public S3Bucket(MetaData metaData) { + public S3Bucket(Metadata metaData) { this.metaData = checkNotNull(metaData, "metaData"); } - public Set getContents() { + public Set getContents() { return objects; } - public void setContents(Set objects) { + public void setContents(Set objects) { this.objects = objects; } @@ -209,7 +194,7 @@ public class S3Bucket { isComplete = complete; } - public MetaData getMetaData() { + public Metadata getMetaData() { return metaData; } diff --git a/s3/src/main/java/org/jclouds/aws/s3/domain/S3Object.java b/s3/src/main/java/org/jclouds/aws/s3/domain/S3Object.java index 6e74b9c638..2891642f3a 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/domain/S3Object.java +++ b/s3/src/main/java/org/jclouds/aws/s3/domain/S3Object.java @@ -23,17 +23,230 @@ */ package org.jclouds.aws.s3.domain; -import static com.google.common.base.Preconditions.*; -import org.joda.time.DateTime; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; import java.util.Arrays; +import org.jclouds.http.ContentTypes; +import org.joda.time.DateTime; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; + /** * // TODO: Adrian: Document this! * * @author Adrian Cole */ public class S3Object { + public static final S3Object NOT_FOUND = new S3Object(Metadata.NOT_FOUND); + + private Object data; + private Metadata metaData; + + public S3Object(String key) { + this(new Metadata(key)); + } + + public S3Object(Metadata metaData) { + this.metaData = metaData; + } + + public S3Object(Metadata metaData, Object data) { + this(metaData); + this.data = data; + } + + public S3Object(String key, Object data) { + this(key); + this.data = data; + } + + public static class Metadata { + public static final Metadata NOT_FOUND = new Metadata("NOT_FOUND"); + + // parsed during list, head, or get + private final String key; + private byte[] md5; + private long size = -1; + + // only parsed during head or get + private Multimap userMetadata = HashMultimap.create(); + private DateTime lastModified; + private String contentType = ContentTypes.UNKNOWN_MIME_TYPE; + private String cacheControl; + private String contentDisposition; + private String contentEncoding; + + // only parsed on list + private S3Owner owner = null; + private String storageClass = null; + + public Metadata(String key) { + checkNotNull(key, "key"); + checkArgument(!key.startsWith("/"), "keys cannot start with /"); + this.key = key; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("MetaData"); + sb.append("{key='").append(key).append('\''); + sb.append(", lastModified=").append(lastModified); + sb.append(", md5=").append( + getMd5() == null ? "null" : Arrays.asList(getMd5()) + .toString()); + sb.append(", size=").append(size); + sb.append(", contentType='").append(contentType).append('\''); + sb.append('}'); + return sb.toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof Metadata)) + return false; + + Metadata metaData = (Metadata) o; + + if (size != metaData.size) + return false; + if (contentType != null ? !contentType.equals(metaData.contentType) + : metaData.contentType != null) + return false; + if (!key.equals(metaData.key)) + return false; + if (lastModified != null ? !lastModified + .equals(metaData.lastModified) + : metaData.lastModified != null) + return false; + if (!Arrays.equals(getMd5(), metaData.getMd5())) + return false; + return true; + } + + @Override + public int hashCode() { + int result = key.hashCode(); + result = 31 * result + + (lastModified != null ? lastModified.hashCode() : 0); + result = 31 * result + + (getMd5() != null ? Arrays.hashCode(getMd5()) : 0); + result = 31 * result + (int) (size ^ (size >>> 32)); + result = 31 * result + + (contentType != null ? contentType.hashCode() : 0); + return result; + } + + public String getKey() { + return key; + } + + public DateTime getLastModified() { + return lastModified; + } + + public void setLastModified(DateTime lastModified) { + this.lastModified = lastModified; + } + + public long getSize() { + return size; + } + + public void setSize(long size) { + this.size = size; + } + + public String getContentType() { + return contentType; + } + + public void setContentType(String contentType) { + this.contentType = contentType; + } + + public void setMd5(byte[] md5) { + this.md5 = md5; + } + + public byte[] getMd5() { + return md5; + } + + public void setUserMetadata(Multimap userMetadata) { + this.userMetadata = userMetadata; + } + + public Multimap getUserMetadata() { + return userMetadata; + } + + public void setOwner(S3Owner owner) { + this.owner = owner; + } + + public S3Owner getOwner() { + return owner; + } + + public void setStorageClass(String storageClass) { + this.storageClass = storageClass; + } + + public String getStorageClass() { + return storageClass; + } + + public void setCacheControl(String cacheControl) { + this.cacheControl = cacheControl; + } + + public String getCacheControl() { + return cacheControl; + } + + public void setContentDisposition(String contentDisposition) { + this.contentDisposition = contentDisposition; + } + + public String getContentDisposition() { + return contentDisposition; + } + + public void setContentEncoding(String contentEncoding) { + this.contentEncoding = contentEncoding; + } + + public String getContentEncoding() { + return contentEncoding; + } + } + + public String getKey() { + return metaData.getKey(); + } + + public void setData(Object data) { + this.data = data; + } + + public Object getData() { + return data; + } + + public void setMetaData(Metadata metaData) { + this.metaData = metaData; + } + + public Metadata getMetaData() { + return metaData; + } + @Override public String toString() { final StringBuilder sb = new StringBuilder(); @@ -43,8 +256,6 @@ public class S3Object { return sb.toString(); } - public static final S3Object NOT_FOUND = new S3Object(MetaData.NOT_FOUND); - @Override public boolean equals(Object o) { if (this == o) @@ -69,187 +280,4 @@ public class S3Object { return result; } - public static class MetaData { - public static final MetaData NOT_FOUND = new MetaData("NOT_FOUND"); - public static final String UNKNOWN_MIME_TYPE = "application/x-unknown-mime-type"; - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append("MetaData"); - sb.append("{key='").append(key).append('\''); - sb.append(", lastModified=").append(lastModified); - sb.append(", md5=").append( - getMd5() == null ? "null" : Arrays.asList(getMd5()) - .toString()); - sb.append(", size=").append(size); - sb.append(", owner=").append(owner); - sb.append(", contentType='").append(contentType).append('\''); - sb.append(", storageClass='").append(storageClass).append('\''); - sb.append(", server='").append(server).append('\''); - sb.append('}'); - return sb.toString(); - } - - private final String key; - private DateTime lastModified; - private byte[] md5; - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (!(o instanceof MetaData)) - return false; - - MetaData metaData = (MetaData) o; - - if (size != metaData.size) - return false; - if (contentType != null ? !contentType.equals(metaData.contentType) - : metaData.contentType != null) - return false; - if (!key.equals(metaData.key)) - return false; - if (lastModified != null ? !lastModified - .equals(metaData.lastModified) - : metaData.lastModified != null) - return false; - if (!Arrays.equals(getMd5(), metaData.getMd5())) - return false; - if (owner != null ? !owner.equals(metaData.owner) - : metaData.owner != null) - return false; - - return true; - } - - @Override - public int hashCode() { - int result = key.hashCode(); - result = 31 * result - + (lastModified != null ? lastModified.hashCode() : 0); - result = 31 * result - + (getMd5() != null ? Arrays.hashCode(getMd5()) : 0); - result = 31 * result + (int) (size ^ (size >>> 32)); - result = 31 * result + (owner != null ? owner.hashCode() : 0); - result = 31 * result - + (contentType != null ? contentType.hashCode() : 0); - return result; - } - - private long size = -1; - private S3Owner owner; - private String contentType = UNKNOWN_MIME_TYPE; - private String storageClass = "STANDARD"; - private String server; - - public MetaData(String key) { - checkNotNull(key, "key"); - checkArgument(!key.startsWith("/"), "keys cannot start with /"); - this.key = key; - } - - public String getKey() { - return key; - } - - public DateTime getLastModified() { - return lastModified; - } - - public void setLastModified(DateTime lastModified) { - this.lastModified = lastModified; - } - - public long getSize() { - return size; - } - - public void setSize(long size) { - this.size = size; - } - - public S3Owner getOwner() { - return owner; - } - - public void setOwner(S3Owner owner) { - this.owner = owner; - } - - public String getContentType() { - return contentType; - } - - public void setContentType(String contentType) { - this.contentType = contentType; - } - - public String getStorageClass() { - return storageClass; - } - - public void setStorageClass(String storageClass) { - this.storageClass = storageClass; - } - - public String getServer() { - return server; - } - - public void setServer(String server) { - this.server = server; - } - - public void setMd5(byte[] md5) { - this.md5 = md5; - } - - public byte[] getMd5() { - return md5; - } - } - - private Object data; - private MetaData metaData; - - public S3Object(String key) { - this(new MetaData(key)); - } - - public S3Object(MetaData metaData) { - this.metaData = metaData; - } - - public S3Object(MetaData metaData, Object data) { - this(metaData); - this.data = data; - } - - public S3Object(String key, Object data) { - this(key); - this.data = data; - } - - public String getKey() { - return metaData.getKey(); - } - - public void setData(Object data) { - this.data = data; - } - - public Object getData() { - return data; - } - - public void setMetaData(MetaData metaData) { - this.metaData = metaData; - } - - public MetaData getMetaData() { - return metaData; - } - } diff --git a/s3/src/main/java/org/jclouds/aws/s3/domain/acl/CannedAccessPolicy.java b/s3/src/main/java/org/jclouds/aws/s3/domain/acl/CannedAccessPolicy.java new file mode 100644 index 0000000000..8aec9b3677 --- /dev/null +++ b/s3/src/main/java/org/jclouds/aws/s3/domain/acl/CannedAccessPolicy.java @@ -0,0 +1,80 @@ +/** + * + * Copyright (C) 2009 Adrian Cole + * + * ==================================================================== + * 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.acl; + +/** + * Description from Amazon's documentation: + * + *

+ * Because of restrictions in what can be sent via http headers, Amazon S3 + * supports the concept of canned access policies for REST. A canned access + * policy can be included with the x-amz-acl header as part of a PUT operation + * to provide shorthand representation of a full access policy. When Amazon S3 + * sees the x-amz-acl header as part of a PUT operation, it will assign the + * respective access policy to the resource created as a result of the PUT. If + * no x-amz-acl header is included with a PUT request, then the bucket or object + * is written with the private access control policy (even if, in the case of an + * object, the object already exists with some other pre-existing access control + * policy). + * + * @see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html? + * RESTAccessPolicy.html + * @author Adrian Cole + * + */ +public enum CannedAccessPolicy { + + /** + * Owner gets FULL_CONTROL. No one else has access rights (default). + */ + PRIVATE("private"), + /** + * Owner gets FULL_CONTROL and the anonymous principal is granted READ + * access. If this policy is used on an object, it can be read from a + * browser with no authentication. + */ + PUBLIC_READ("public-read"), + /** + * Owner gets FULL_CONTROL, the anonymous principal is granted READ and + * WRITE access. This can be a useful policy to apply to a bucket, but is + * generally not recommended. + */ + PUBLIC_READ_WRITE("public-read-write"), + /** + * Owner gets FULL_CONTROL, and any principal authenticated as a registered + * Amazon S3 user is granted READ access. + */ + AUTHENTICATED_READ("authenticated-read"); + + private String policyName; + + CannedAccessPolicy(String policyName) { + this.policyName = policyName; + } + + @Override + public String toString() { + return policyName; + } +} diff --git a/s3/src/main/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignature.java b/s3/src/main/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignature.java index 0353566504..2ab4eca3a6 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignature.java +++ b/s3/src/main/java/org/jclouds/aws/s3/filters/RequestAuthorizeSignature.java @@ -32,8 +32,8 @@ import java.util.concurrent.atomic.AtomicReference; import org.jclouds.aws.s3.DateService; import org.jclouds.aws.s3.S3Constants; import org.jclouds.aws.s3.S3Utils; -import org.jclouds.http.HttpConstants; import org.jclouds.http.HttpException; +import org.jclouds.http.HttpHeaders; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequestFilter; import org.joda.time.DateTime; @@ -43,8 +43,8 @@ import com.google.inject.name.Named; public class RequestAuthorizeSignature implements HttpRequestFilter { private static final String[] firstHeadersToSign = new String[] { - HttpConstants.CONTENT_MD5, HttpConstants.CONTENT_TYPE, - HttpConstants.DATE }; + HttpHeaders.CONTENT_MD5, HttpHeaders.CONTENT_TYPE, + HttpHeaders.DATE }; private final String accessKey; private final String secretKey; @@ -113,7 +113,6 @@ public class RequestAuthorizeSignature implements HttpRequestFilter { // re-sign the request removeOldHeaders(request); - addContentTypeHeader(request); addDateHeader(request); StringBuilder toSign = new StringBuilder(); @@ -127,9 +126,9 @@ public class RequestAuthorizeSignature implements HttpRequestFilter { } private void removeOldHeaders(HttpRequest request) { - request.getHeaders().removeAll(S3Constants.AUTH); - request.getHeaders().removeAll(HttpConstants.CONTENT_TYPE); - request.getHeaders().removeAll(HttpConstants.DATE); + request.getHeaders().removeAll(S3Constants.AUTHORIZATION); + request.getHeaders().removeAll(HttpHeaders.CONTENT_TYPE); + request.getHeaders().removeAll(HttpHeaders.DATE); } private void addAuthHeader(HttpRequest request, StringBuilder toSign) @@ -141,23 +140,16 @@ public class RequestAuthorizeSignature implements HttpRequestFilter { } catch (Exception e) { throw new HttpException("error signing request", e); } - request.getHeaders().put(S3Constants.AUTH, + request.getHeaders().put(S3Constants.AUTHORIZATION, "AWS " + accessKey + ":" + signature); } - private void addContentTypeHeader(HttpRequest request) { - if (request.getContent() != null && request.getContentType() != null) { - request.getHeaders().put(HttpConstants.CONTENT_TYPE, - request.getContentType()); - } - } - private void appendMethod(HttpRequest request, StringBuilder toSign) { toSign.append(request.getMethod()).append("\n"); } private void addDateHeader(HttpRequest request) { - request.getHeaders().put(HttpConstants.DATE, + request.getHeaders().put(HttpHeaders.DATE, dateService.timestampAsHeaderString()); } @@ -180,7 +172,7 @@ public class RequestAuthorizeSignature implements HttpRequestFilter { } private void appendBucketName(HttpRequest request, StringBuilder toSign) { - String hostHeader = request.getHeaders().get(HttpConstants.HOST) + String hostHeader = request.getHeaders().get(HttpHeaders.HOST) .iterator().next(); if (hostHeader.endsWith(".s3.amazonaws.com")) toSign.append("/").append( diff --git a/s3/src/main/java/org/jclouds/aws/s3/internal/BaseS3Map.java b/s3/src/main/java/org/jclouds/aws/s3/internal/BaseS3Map.java index de0727d858..224c0fe26b 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/internal/BaseS3Map.java +++ b/s3/src/main/java/org/jclouds/aws/s3/internal/BaseS3Map.java @@ -74,7 +74,7 @@ public abstract class BaseS3Map implements Map, S3Map { public int size() { try { S3Bucket bucket = refreshBucket(); - Set contents = bucket.getContents(); + Set contents = bucket.getContents(); return contents.size(); } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); @@ -85,7 +85,7 @@ public abstract class BaseS3Map implements Map, S3Map { protected boolean containsMd5(byte[] md5) throws InterruptedException, ExecutionException, TimeoutException { - for (S3Object.MetaData metaData : refreshBucket().getContents()) { + for (S3Object.Metadata metaData : refreshBucket().getContents()) { if (Arrays.equals(md5, metaData.getMd5())) return true; } @@ -190,7 +190,7 @@ public abstract class BaseS3Map implements Map, S3Map { protected S3Bucket refreshBucket() throws InterruptedException, ExecutionException, TimeoutException { - S3Bucket currentBucket = connection.getBucket(bucket).get( + S3Bucket currentBucket = connection.listBucket(bucket).get( requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); if (currentBucket == S3Bucket.NOT_FOUND) throw new S3RuntimeException("bucket not found: " + bucket); @@ -201,7 +201,7 @@ public abstract class BaseS3Map implements Map, S3Map { public Set keySet() { try { Set keys = new HashSet(); - for (S3Object.MetaData object : refreshBucket().getContents()) + for (S3Object.Metadata object : refreshBucket().getContents()) keys.add(object.getKey()); return keys; } catch (Exception e) { @@ -213,8 +213,8 @@ public abstract class BaseS3Map implements Map, S3Map { public boolean containsKey(Object key) { try { - return connection.getObjectMetaData(bucket, key.toString()).get( - requestTimeoutMilliseconds, TimeUnit.MILLISECONDS) != S3Object.MetaData.NOT_FOUND; + return connection.headObject(bucket, key.toString()).get( + requestTimeoutMilliseconds, TimeUnit.MILLISECONDS) != S3Object.Metadata.NOT_FOUND; } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); throw new S3RuntimeException(String.format( diff --git a/s3/src/main/java/org/jclouds/aws/s3/internal/GuiceS3Context.java b/s3/src/main/java/org/jclouds/aws/s3/internal/GuiceS3Context.java index a1632875ce..a95a7e6413 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/internal/GuiceS3Context.java +++ b/s3/src/main/java/org/jclouds/aws/s3/internal/GuiceS3Context.java @@ -79,7 +79,7 @@ public class GuiceS3Context implements S3Context { * {@inheritDoc} */ public S3InputStreamMap createInputStreamMap(String bucket) { - getConnection().createBucketIfNotExists(bucket); + getConnection().putBucketIfNotExists(bucket); return s3InputStreamMapFactory.createMapView(bucket); } @@ -87,7 +87,7 @@ public class GuiceS3Context implements S3Context { * {@inheritDoc} */ public S3ObjectMap createS3ObjectMap(String bucket) { - getConnection().createBucketIfNotExists(bucket); + getConnection().putBucketIfNotExists(bucket); return s3ObjectMapFactory.createMapView(bucket); } diff --git a/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3Connection.java b/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3Connection.java index 3fbd43c161..246cc3cad1 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3Connection.java +++ b/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3Connection.java @@ -31,18 +31,21 @@ import org.jclouds.aws.s3.commands.BucketExists; import org.jclouds.aws.s3.commands.CopyObject; import org.jclouds.aws.s3.commands.DeleteBucket; import org.jclouds.aws.s3.commands.DeleteObject; -import org.jclouds.aws.s3.commands.GetBucket; import org.jclouds.aws.s3.commands.GetMetaDataForOwnedBuckets; import org.jclouds.aws.s3.commands.GetObject; import org.jclouds.aws.s3.commands.HeadMetaData; +import org.jclouds.aws.s3.commands.ListBucket; import org.jclouds.aws.s3.commands.PutBucket; import org.jclouds.aws.s3.commands.PutObject; import org.jclouds.aws.s3.commands.S3CommandFactory; -import org.jclouds.aws.s3.commands.options.GetBucketOptions; +import org.jclouds.aws.s3.commands.options.CopyObjectOptions; +import org.jclouds.aws.s3.commands.options.GetObjectOptions; +import org.jclouds.aws.s3.commands.options.ListBucketOptions; import org.jclouds.aws.s3.commands.options.PutBucketOptions; +import org.jclouds.aws.s3.commands.options.PutObjectOptions; import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Object; -import org.jclouds.aws.s3.domain.S3Bucket.MetaData; +import org.jclouds.aws.s3.domain.S3Bucket.Metadata; import org.jclouds.http.HttpFutureCommandClient; import com.google.inject.Inject; @@ -75,7 +78,17 @@ public class LiveS3Connection implements S3Connection { * @see GetObject */ public Future getObject(String s3Bucket, String key) { - GetObject getObject = factory.createGetObject(s3Bucket, key); + return getObject(s3Bucket, key, GetObjectOptions.NONE); + } + + /** + * {@inheritDoc} + * + * @see GetObject + */ + public Future getObject(String s3Bucket, String key, + GetObjectOptions options) { + GetObject getObject = factory.createGetObject(s3Bucket, key, options); client.submit(getObject); return getObject; } @@ -85,8 +98,7 @@ public class LiveS3Connection implements S3Connection { * * @see HeadMetaData */ - public Future getObjectMetaData(String s3Bucket, - String key) { + public Future headObject(String s3Bucket, String key) { HeadMetaData headMetaData = factory.createHeadMetaData(s3Bucket, key); client.submit(headMetaData); return headMetaData; @@ -108,8 +120,19 @@ public class LiveS3Connection implements S3Connection { * * @see PutObject */ - public Future addObject(String s3Bucket, S3Object object) { - PutObject putObject = factory.createPutObject(s3Bucket, object); + public Future putObject(String s3Bucket, S3Object object) { + return putObject(s3Bucket, object, PutObjectOptions.NONE); + } + + /** + * {@inheritDoc} + * + * @see PutObject + */ + public Future putObject(String bucketName, S3Object object, + PutObjectOptions options) { + PutObject putObject = factory.createPutObject(bucketName, object, + options); client.submit(putObject); return putObject; } @@ -119,10 +142,8 @@ public class LiveS3Connection implements S3Connection { * * @see PutBucket */ - public Future createBucketIfNotExists(String s3Bucket) { - PutBucket putBucket = factory.createPutBucket(s3Bucket); - client.submit(putBucket); - return putBucket; + public Future putBucketIfNotExists(String s3Bucket) { + return putBucketIfNotExists(s3Bucket, PutBucketOptions.NONE); } /** @@ -130,7 +151,7 @@ public class LiveS3Connection implements S3Connection { * * @see PutBucket */ - public Future createBucketIfNotExists(String s3Bucket, + public Future putBucketIfNotExists(String s3Bucket, PutBucketOptions options) { PutBucket putBucket = factory.createPutBucket(s3Bucket, options); client.submit(putBucket); @@ -153,11 +174,23 @@ public class LiveS3Connection implements S3Connection { * * @see CopyObject */ - public Future copyObject(String sourceBucket, + public Future copyObject(String sourceBucket, String sourceObject, String destinationBucket, String destinationObject) { + return copyObject(sourceBucket, sourceObject, destinationBucket, + destinationObject, new CopyObjectOptions()); + } + + /** + * {@inheritDoc} + * + * @see CopyObject + */ + public Future copyObject(String sourceBucket, + String sourceObject, String destinationBucket, + String destinationObject, CopyObjectOptions options) { CopyObject copy = factory.createCopyObject(sourceBucket, sourceObject, - destinationBucket, destinationObject); + destinationBucket, destinationObject, options); client.submit(copy); return copy; } @@ -176,10 +209,20 @@ public class LiveS3Connection implements S3Connection { /** * {@inheritDoc} * - * @see GetBucket + * @see ListBucket */ - public Future getBucket(String s3Bucket) { - GetBucket getBucket = factory.createGetBucket(s3Bucket); + public Future listBucket(String s3Bucket) { + return listBucket(s3Bucket, ListBucketOptions.NONE); + } + + /** + * {@inheritDoc} + * + * @see ListBucket + */ + public Future listBucket(String s3Bucket, + ListBucketOptions options) { + ListBucket getBucket = factory.createListBucket(s3Bucket, options); client.submit(getBucket); return getBucket; } @@ -187,21 +230,13 @@ public class LiveS3Connection implements S3Connection { /** * {@inheritDoc} * - * @see GetBucket + * @see GetMetaDataForOwnedBuckets */ - public Future getBucket(String s3Bucket, GetBucketOptions options) { - GetBucket getBucket = factory.createGetBucket(s3Bucket, options); - client.submit(getBucket); - return getBucket; - } - - /** - * {@inheritDoc} - */ - public Future> getMetaDataOfOwnedBuckets() { + public Future> getOwnedBuckets() { GetMetaDataForOwnedBuckets listRequest = factory .createGetMetaDataForOwnedBuckets(); client.submit(listRequest); return listRequest; } + } diff --git a/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3InputStreamMap.java b/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3InputStreamMap.java index 0f3af00bf5..f2733f77df 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3InputStreamMap.java +++ b/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3InputStreamMap.java @@ -152,7 +152,7 @@ public class LiveS3InputStreamMap extends BaseS3Map implements InputStream returnVal = containsKey(s) ? get(s) : null; object.setData(o); setSizeIfContentIsInputStream(object); - connection.addObject(bucket, object).get( + connection.putObject(bucket, object).get( requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); return returnVal; } catch (Exception e) { @@ -185,14 +185,14 @@ public class LiveS3InputStreamMap extends BaseS3Map implements private void putAllInternal(Map map) { try { - List> puts = new ArrayList>(); + List> puts = new ArrayList>(); for (String key : map.keySet()) { S3Object object = new S3Object(key); object.setData(map.get(key)); setSizeIfContentIsInputStream(object); - puts.add(connection.addObject(bucket, object)); + puts.add(connection.putObject(bucket, object)); } - for (Future put : puts) + for (Future put : puts) // this will throw an exception if there was a problem put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); } catch (Exception e) { diff --git a/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3ObjectMap.java b/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3ObjectMap.java index b2f9c57960..894340130c 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3ObjectMap.java +++ b/s3/src/main/java/org/jclouds/aws/s3/internal/LiveS3ObjectMap.java @@ -99,7 +99,7 @@ public class LiveS3ObjectMap extends BaseS3Map implements S3ObjectMap public S3Object put(String key, S3Object value) { S3Object returnVal = get(key); try { - connection.addObject(bucket, value).get(requestTimeoutMilliseconds, + connection.putObject(bucket, value).get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); } catch (Exception e) { Utils. rethrowIfRuntimeOrSameType(e); @@ -111,11 +111,11 @@ public class LiveS3ObjectMap extends BaseS3Map implements S3ObjectMap public void putAll(Map map) { try { - List> puts = new ArrayList>(); + List> puts = new ArrayList>(); for (S3Object object : map.values()) { - puts.add(connection.addObject(bucket, object)); + puts.add(connection.putObject(bucket, object)); } - for (Future put : puts) + for (Future put : puts) // this will throw an exception if there was a problem put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); } catch (Exception e) { diff --git a/s3/src/main/java/org/jclouds/aws/s3/xml/CopyObjectHandler.java b/s3/src/main/java/org/jclouds/aws/s3/xml/CopyObjectHandler.java index 0b81980700..11891aa84a 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/xml/CopyObjectHandler.java +++ b/s3/src/main/java/org/jclouds/aws/s3/xml/CopyObjectHandler.java @@ -36,18 +36,18 @@ import com.google.inject.Inject; * @author Adrian Cole */ public class CopyObjectHandler extends - ParseSax.HandlerWithResult { + ParseSax.HandlerWithResult { - private S3Object.MetaData metaData; + private S3Object.Metadata metaData; private StringBuilder currentText = new StringBuilder(); @Inject private DateService dateParser; public void setKey(String key) { - metaData = new S3Object.MetaData(key); + metaData = new S3Object.Metadata(key); } - public S3Object.MetaData getResult() { + public S3Object.Metadata getResult() { return metaData; } diff --git a/s3/src/main/java/org/jclouds/aws/s3/xml/ListAllMyBucketsHandler.java b/s3/src/main/java/org/jclouds/aws/s3/xml/ListAllMyBucketsHandler.java index 277a02d91f..a6fa09fcbd 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/xml/ListAllMyBucketsHandler.java +++ b/s3/src/main/java/org/jclouds/aws/s3/xml/ListAllMyBucketsHandler.java @@ -40,10 +40,10 @@ import com.google.inject.Inject; * @author Adrian Cole */ public class ListAllMyBucketsHandler extends - ParseSax.HandlerWithResult> { + ParseSax.HandlerWithResult> { - private List buckets = new ArrayList(); - private S3Bucket.MetaData currentS3Bucket; + private List buckets = new ArrayList(); + private S3Bucket.Metadata currentS3Bucket; private S3Owner currentOwner; private StringBuilder currentText = new StringBuilder(); @@ -54,7 +54,7 @@ public class ListAllMyBucketsHandler extends this.dateParser = dateParser; } - public List getResult() { + public List getResult() { return buckets; } @@ -75,7 +75,7 @@ public class ListAllMyBucketsHandler extends currentS3Bucket.setCanonicalUser(currentOwner); buckets.add(currentS3Bucket); } else if (qName.equals("Name")) { - currentS3Bucket = new S3Bucket.MetaData(currentText.toString()); + currentS3Bucket = new S3Bucket.Metadata(currentText.toString()); } else if (qName.equals("CreationDate")) { currentS3Bucket.setCreationDate(dateParser .dateTimeFromXMLFormat(currentText.toString())); diff --git a/s3/src/main/java/org/jclouds/aws/s3/xml/ListBucketHandler.java b/s3/src/main/java/org/jclouds/aws/s3/xml/ListBucketHandler.java index 6dda6fed2e..d0ccf4cbd0 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/xml/ListBucketHandler.java +++ b/s3/src/main/java/org/jclouds/aws/s3/xml/ListBucketHandler.java @@ -52,7 +52,7 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult { } private S3Bucket s3Bucket; - private S3Object.MetaData currentObjectMetaData; + private S3Object.Metadata currentObjectMetaData; private S3Owner currentOwner; private StringBuilder currentText = new StringBuilder(); @Inject @@ -84,7 +84,7 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult { } else if (qName.equals("DisplayName")) { currentOwner.setDisplayName(currentText.toString()); } else if (qName.equals("Key")) { // content stuff - currentObjectMetaData = new S3Object.MetaData(currentText + currentObjectMetaData = new S3Object.Metadata(currentText .toString()); } else if (qName.equals("LastModified")) { currentObjectMetaData.setLastModified(dateParser diff --git a/s3/src/main/java/org/jclouds/aws/s3/xml/S3ParserFactory.java b/s3/src/main/java/org/jclouds/aws/s3/xml/S3ParserFactory.java index cf1f5825c6..a0c2556cd1 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/xml/S3ParserFactory.java +++ b/s3/src/main/java/org/jclouds/aws/s3/xml/S3ParserFactory.java @@ -42,7 +42,7 @@ import com.google.inject.Provider; public class S3ParserFactory { @Inject - private GenericParseFactory> parseListAllMyBucketsFactory; + private GenericParseFactory> parseListAllMyBucketsFactory; public static interface GenericParseFactory { ParseSax create(ParseSax.HandlerWithResult handler); @@ -52,7 +52,7 @@ public class S3ParserFactory { Provider ListAllMyBucketsHandlerprovider; @VisibleForTesting - public ParseSax> createListBucketsParser() { + public ParseSax> createListBucketsParser() { return parseListAllMyBucketsFactory .create(ListAllMyBucketsHandlerprovider.get()); } @@ -69,13 +69,13 @@ public class S3ParserFactory { } @Inject - private GenericParseFactory parseCopyObjectFactory; + private GenericParseFactory parseCopyObjectFactory; @Inject Provider copyObjectHandlerProvider; @VisibleForTesting - public ParseSax createCopyObjectParser() { + public ParseSax createCopyObjectParser() { return parseCopyObjectFactory.create(copyObjectHandlerProvider.get()); } diff --git a/s3/src/main/java/org/jclouds/aws/s3/xml/config/S3ParserModule.java b/s3/src/main/java/org/jclouds/aws/s3/xml/config/S3ParserModule.java index 0e1dc71a36..aa62aa2301 100644 --- a/s3/src/main/java/org/jclouds/aws/s3/xml/config/S3ParserModule.java +++ b/s3/src/main/java/org/jclouds/aws/s3/xml/config/S3ParserModule.java @@ -50,18 +50,18 @@ public class S3ParserModule extends AbstractModule { protected void configure() { install(new SaxModule()); - final TypeLiteral>> listBucketsTypeLiteral = new TypeLiteral>>() { + final TypeLiteral>> listBucketsTypeLiteral = new TypeLiteral>>() { }; final TypeLiteral> bucketTypeLiteral = new TypeLiteral>() { }; - final TypeLiteral> objectMetaDataTypeLiteral = new TypeLiteral>() { + final TypeLiteral> objectMetaDataTypeLiteral = new TypeLiteral>() { }; final TypeLiteral> errorTypeLiteral = new TypeLiteral>() { }; bind(listBucketsTypeLiteral).toProvider( FactoryProvider.newFactory(listBucketsTypeLiteral, - new TypeLiteral>>() { + new TypeLiteral>>() { })); bind(bucketTypeLiteral).toProvider( FactoryProvider.newFactory(bucketTypeLiteral, @@ -69,7 +69,7 @@ public class S3ParserModule extends AbstractModule { })); bind(objectMetaDataTypeLiteral).toProvider( FactoryProvider.newFactory(objectMetaDataTypeLiteral, - new TypeLiteral>() { + new TypeLiteral>() { })); bind(errorTypeLiteral).toProvider( FactoryProvider.newFactory(errorTypeLiteral, @@ -78,11 +78,11 @@ public class S3ParserModule extends AbstractModule { // Bind the implementations of handlers to the interfaces they implement bind( - new TypeLiteral>>() { + new TypeLiteral>>() { }).to(ListAllMyBucketsHandler.class); bind(new TypeLiteral>() { }).to(ListBucketHandler.class); - bind(new TypeLiteral>() { + bind(new TypeLiteral>() { }).to(CopyObjectHandler.class); bind(new TypeLiteral>() { }).to(ErrorHandler.class); diff --git a/s3/src/test/java/org/jclouds/aws/s3/AmazonS3SSLTest.java b/s3/src/test/java/org/jclouds/aws/s3/AmazonS3SSLTest.java index a4cfd1d6e3..75dd61a881 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/AmazonS3SSLTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/AmazonS3SSLTest.java @@ -33,7 +33,7 @@ import java.util.Properties; * @author Adrian Cole */ @Test(groups = "unit", sequential = true, testName = "s3.AmazonS3SSLTest") -public class AmazonS3SSLTest extends AmazonS3Test { +public class AmazonS3SSLTest extends S3ConnectionTest { @Override protected Properties buildS3Properties(String AWSAccessKeyId, String AWSSecretAccessKey) { Properties properties = super.buildS3Properties(AWSAccessKeyId, AWSSecretAccessKey); diff --git a/s3/src/test/java/org/jclouds/aws/s3/AmazonS3Test.java b/s3/src/test/java/org/jclouds/aws/s3/AmazonS3Test.java deleted file mode 100644 index 1102cab279..0000000000 --- a/s3/src/test/java/org/jclouds/aws/s3/AmazonS3Test.java +++ /dev/null @@ -1,251 +0,0 @@ -/** - * - * Copyright (C) 2009 Adrian Cole - * - * ==================================================================== - * 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 static org.testng.Assert.assertNotNull; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.List; -import java.util.Properties; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import org.apache.commons.io.IOUtils; -import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.*; -import org.jclouds.aws.s3.domain.S3Bucket; -import org.jclouds.aws.s3.domain.S3Object; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -@Test(groups = "unit", sequential = true, testName = "s3.AmazonS3Test") -public class AmazonS3Test extends S3IntegrationTest { - - private String returnedString; - - List listAllMyBuckets() throws Exception { - return client.getMetaDataOfOwnedBuckets().get(10, TimeUnit.SECONDS); - } - - S3Object getObject() throws Exception { - return client.getObject(bucketPrefix + "adrianjbosstest", "3366").get( - 10, TimeUnit.SECONDS); - } - - String putFileObject() throws Exception { - S3Object object = new S3Object("meat"); - object.getMetaData().setContentType("text/xml"); - object.setData(new File("pom.xml")); - return client.addObject(bucketPrefix + "adrianjbosstest", object).get( - 10, TimeUnit.SECONDS); - } - - @DataProvider(name = "putTests") - public Object[][] createData1() throws IOException { - - String realObject = IOUtils.toString(new FileInputStream("pom.xml")); - - return new Object[][] { - { "file", "text/xml", new File("pom.xml"), realObject }, - { "string", "text/xml", realObject, realObject }, - { "bytes", "application/octet-stream", realObject.getBytes(), - realObject } }; - } - - @Test(dataProvider = "putTests") - void testPutObject(String key, String type, Object content, - Object realObject) throws Exception { - String bucketName = bucketPrefix + "filetestsforadrian"; - client.createBucketIfNotExists(bucketName).get(10, TimeUnit.SECONDS); - context.createS3ObjectMap(bucketName).clear(); - assertEquals(client.getBucket(bucketName).get(10, TimeUnit.SECONDS) - .getContents().size(), 0); - S3Object object = new S3Object(key); - object.getMetaData().setContentType(type); - object.setData(content); - assertNotNull(client.addObject(bucketName, object).get(10, - TimeUnit.SECONDS)); - object = client.getObject(bucketName, object.getKey()).get(10, - TimeUnit.SECONDS); - returnedString = S3Utils.getContentAsStringAndClose(object); - assertEquals(returnedString, realObject); - assertEquals(client.getBucket(bucketName).get(10, TimeUnit.SECONDS) - .getContents().size(), 1); - } - - @Test() - void testCopyObject() throws Exception { - String realObject = IOUtils.toString(new FileInputStream("pom.xml")); - - String sourceBucket = bucketPrefix + "copysource"; - client.createBucketIfNotExists(sourceBucket).get(10, TimeUnit.SECONDS); - assertEquals(client.getBucket(sourceBucket).get(10, TimeUnit.SECONDS) - .getContents().size(), 0); - - S3Object sourceObject = new S3Object("file"); - sourceObject.getMetaData().setContentType("text/xml"); - sourceObject.setData(new File("pom.xml")); - - client.addObject(sourceBucket, sourceObject).get(10, TimeUnit.SECONDS); - assertEquals(client.getBucket(sourceBucket).get(10, TimeUnit.SECONDS) - .getContents().size(), 1); - - sourceObject = client.getObject(sourceBucket, sourceObject.getKey()) - .get(10, TimeUnit.SECONDS); - assertEquals(S3Utils.getContentAsStringAndClose(sourceObject), - realObject); - - String destinationBucket = bucketPrefix + "copydestination"; - client.createBucketIfNotExists(destinationBucket).get(10, - TimeUnit.SECONDS); - assertEquals(client.getBucket(destinationBucket).get(10, - TimeUnit.SECONDS).getContents().size(), 0); - - client.copyObject(sourceBucket, sourceObject.getKey(), - destinationBucket, sourceObject.getKey()).get(10, - TimeUnit.SECONDS); - assertEquals(client.getBucket(destinationBucket).get(10, - TimeUnit.SECONDS).getContents().size(), 1); - // todo compare etag - - S3Object destinationObject = client.getObject(destinationBucket, - sourceObject.getKey()).get(10, TimeUnit.SECONDS); - assertEquals(S3Utils.getContentAsStringAndClose(destinationObject), - realObject); - - } - - S3Object.MetaData headObject() throws Exception { - String bucketName = bucketPrefix + "adrianjbosstest"; - return client.getObjectMetaData(bucketName, "3366").get(10, - TimeUnit.SECONDS); - } - - @Test() - void testGetBucketDelimiter() throws InterruptedException, - ExecutionException, TimeoutException, UnsupportedEncodingException { - String bucketName = bucketPrefix + "delimiter"; - assert client.createBucketIfNotExists(bucketName).get(10, - TimeUnit.SECONDS); - String prefix = "apps"; - addTenObjectsUnderPrefix(bucketName, prefix); - add15UnderRoot(bucketName); - S3Bucket bucket = client.getBucket(bucketName, delimiter("/")).get(10, - TimeUnit.SECONDS); - assertEquals(bucket.getDelimiter(), "/"); - assertEquals(bucket.getContents().size(), 15); - assertEquals(bucket.getCommonPrefixes().size(), 1); - } - - private void addAlphabetUnderRoot(String bucketName) - throws InterruptedException, ExecutionException, TimeoutException { - for (char letter = 'a'; letter <= 'z'; letter++) { - client.addObject(bucketName, - new S3Object(letter + "", letter + "content")).get(10, - TimeUnit.SECONDS); - } - } - - @Test - void testGetBucketMarker() throws InterruptedException, ExecutionException, - TimeoutException, UnsupportedEncodingException { - String bucketName = bucketPrefix + "marker"; - assert client.createBucketIfNotExists(bucketName).get(10, - TimeUnit.SECONDS); - addAlphabetUnderRoot(bucketName); - S3Bucket bucket = client.getBucket(bucketName, marker("y")).get(10, - TimeUnit.SECONDS); - assertEquals(bucket.getMarker(), "y"); - assertEquals(bucket.getContents().size(), 1); - } - - @Test() - void testGetBucketPrefix() throws InterruptedException, ExecutionException, - TimeoutException, UnsupportedEncodingException { - String bucketName = bucketPrefix + "prefix"; - assert client.createBucketIfNotExists(bucketName).get(10, - TimeUnit.SECONDS); - String prefix = "apps"; - addTenObjectsUnderPrefix(bucketName, prefix); - add15UnderRoot(bucketName); - - S3Bucket bucket = client.getBucket(bucketName, prefix("apps/")).get(10, - TimeUnit.SECONDS); - assertEquals(bucket.getContents().size(), 10); - assertEquals(bucket.getPrefix(), "apps/"); - - } - - private void add15UnderRoot(String bucketName) throws InterruptedException, - ExecutionException, TimeoutException { - for (int i = 0; i < 15; i++) - client.addObject(bucketName, new S3Object(i + "", i + "content")) - .get(10, TimeUnit.SECONDS); - } - - private void addTenObjectsUnderPrefix(String bucketName, String prefix) - throws InterruptedException, ExecutionException, TimeoutException { - for (int i = 0; i < 10; i++) - client.addObject(bucketName, - new S3Object(prefix + "/" + i, i + "content")).get(10, - TimeUnit.SECONDS); - } - - @Test() - void bucketExists() throws Exception { - String bucketName = bucketPrefix + "needstoexist"; - assert !client.bucketExists(bucketName).get(10, TimeUnit.SECONDS); - assert client.createBucketIfNotExists(bucketName).get(10, - TimeUnit.SECONDS); - assert client.bucketExists(bucketName).get(10, TimeUnit.SECONDS); - - } - - Boolean deleteBucket() throws Exception { - String bucketName = bucketPrefix + "adrianjbosstest"; - return client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS); - } - - Boolean deleteObject() throws Exception { - String bucketName = bucketPrefix + "adrianjbosstest"; - return client.deleteObject(bucketName, "3366") - .get(10, TimeUnit.SECONDS); - } - - Boolean createBucketIfNotExists() throws Exception { - String bucketName = bucketPrefix + "adrianjbosstest"; - return client.createBucketIfNotExists(bucketName).get(10, - TimeUnit.SECONDS); - } - - S3Bucket getBucket() throws Exception { - String bucketName = bucketPrefix + "adrianjbosstest"; - return client.getBucket(bucketName).get(10, TimeUnit.SECONDS); - } - -} \ No newline at end of file diff --git a/s3/src/test/java/org/jclouds/aws/s3/BaseS3MapTest.java b/s3/src/test/java/org/jclouds/aws/s3/BaseS3MapTest.java index aa30d83bbc..14d34526dc 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/BaseS3MapTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/BaseS3MapTest.java @@ -89,7 +89,7 @@ public abstract class BaseS3MapTest extends S3IntegrationTest { .toInputStream("dogma"), "five", IOUtils .toInputStream("emma")); bucket = (bucketPrefix + ".mimi").toLowerCase(); - client.createBucketIfNotExists(bucket).get(10, TimeUnit.SECONDS); + client.putBucketIfNotExists(bucket).get(10, TimeUnit.SECONDS); map = createMap(context, bucket); map.clear(); } diff --git a/s3/src/test/java/org/jclouds/aws/s3/S3ConnectionTest.java b/s3/src/test/java/org/jclouds/aws/s3/S3ConnectionTest.java new file mode 100644 index 0000000000..a8393771da --- /dev/null +++ b/s3/src/test/java/org/jclouds/aws/s3/S3ConnectionTest.java @@ -0,0 +1,72 @@ +/** + * + * Copyright (C) 2009 Adrian Cole + * + * ==================================================================== + * 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.List; +import java.util.concurrent.TimeUnit; + +import org.jclouds.aws.s3.domain.S3Bucket; +import org.jclouds.aws.s3.domain.S3Object; +import org.testng.annotations.Test; + +@Test(groups = "unit", testName = "s3.AmazonS3Test") +public class S3ConnectionTest extends S3IntegrationTest { + + @Test + void testListBuckets() throws Exception { + listAllMyBuckets(); + } + + List listAllMyBuckets() throws Exception { + return client.getOwnedBuckets().get(10, TimeUnit.SECONDS); + } + + S3Object getObject() throws Exception { + return client.getObject(bucketPrefix + "adrianjbosstest", "3366").get( + 10, TimeUnit.SECONDS); + } + + S3Object.Metadata headObject() throws Exception { + String bucketName = bucketPrefix + "adrianjbosstest"; + return client.headObject(bucketName, "3366").get(10, + TimeUnit.SECONDS); + } + + Boolean deleteBucket() throws Exception { + String bucketName = bucketPrefix + "adrianjbosstest"; + return client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS); + } + + Boolean deleteObject() throws Exception { + String bucketName = bucketPrefix + "adrianjbosstest"; + return client.deleteObject(bucketName, "3366") + .get(10, TimeUnit.SECONDS); + } + + S3Bucket getBucket() throws Exception { + String bucketName = bucketPrefix + "adrianjbosstest"; + return client.listBucket(bucketName).get(10, TimeUnit.SECONDS); + } + +} \ No newline at end of file diff --git a/s3/src/test/java/org/jclouds/aws/s3/S3IntegrationTest.java b/s3/src/test/java/org/jclouds/aws/s3/S3IntegrationTest.java index 63532c8a7f..94caa41744 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/S3IntegrationTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/S3IntegrationTest.java @@ -24,15 +24,19 @@ package org.jclouds.aws.s3; import static com.google.common.base.Preconditions.checkNotNull; +import static org.testng.Assert.assertEquals; +import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.logging.ConsoleHandler; import java.util.logging.Formatter; import java.util.logging.Handler; @@ -52,8 +56,44 @@ import org.testng.annotations.Test; import com.google.inject.Module; -@Test(sequential = true) +@Test public class S3IntegrationTest { + + protected void createBucketAndEnsureEmpty(String sourceBucket) + throws InterruptedException, ExecutionException, TimeoutException { + client.putBucketIfNotExists(sourceBucket).get(10, TimeUnit.SECONDS); + assertEquals(client.listBucket(sourceBucket).get(10, TimeUnit.SECONDS) + .getContents().size(), 0); + } + + protected static final String TEST_STRING = ""; + + protected void addObjectToBucket(String sourceBucket, String key) + throws InterruptedException, ExecutionException, TimeoutException, + IOException { + S3Object sourceObject = new S3Object(key); + sourceObject.getMetaData().setContentType("text/xml"); + sourceObject.setData(TEST_STRING); + addObjectToBucket(sourceBucket, sourceObject); + } + + protected void addObjectToBucket(String sourceBucket, S3Object object) + throws InterruptedException, ExecutionException, TimeoutException, + IOException { + ; + client.putObject(sourceBucket, object).get(10, TimeUnit.SECONDS); + } + + protected S3Object validateContent(String sourceBucket, String key) throws InterruptedException, ExecutionException, + TimeoutException, IOException { + assertEquals(client.listBucket(sourceBucket).get(10, TimeUnit.SECONDS) + .getContents().size(), 1); + S3Object newObject = client.getObject(sourceBucket, key).get(10, + TimeUnit.SECONDS); + assertEquals(S3Utils.getContentAsStringAndClose(newObject), TEST_STRING); + return newObject; + } + @BeforeTest void enableDebug() { if (debugEnabled()) { @@ -86,7 +126,7 @@ public class S3IntegrationTest { protected S3Context context = null; protected String bucketPrefix = System.getProperty("user.name") + "." - + this.getClass().getName(); + + this.getClass().getSimpleName(); private static final String sysAWSAccessKeyId = System .getProperty(S3Constants.PROPERTY_AWS_ACCESSKEYID); @@ -136,14 +176,14 @@ public class S3IntegrationTest { protected void deleteEverything() throws Exception { try { - List metaData = client - .getMetaDataOfOwnedBuckets().get(10, TimeUnit.SECONDS); + List metaData = client + .getOwnedBuckets().get(10, TimeUnit.SECONDS); List> results = new ArrayList>(); - for (S3Bucket.MetaData metaDatum : metaData) { + for (S3Bucket.Metadata metaDatum : metaData) { if (metaDatum.getName().startsWith(bucketPrefix.toLowerCase())) { - S3Bucket bucket = client.getBucket(metaDatum.getName()) + S3Bucket bucket = client.listBucket(metaDatum.getName()) .get(10, TimeUnit.SECONDS); - for (S3Object.MetaData objectMeta : bucket.getContents()) { + for (S3Object.Metadata objectMeta : bucket.getContents()) { results.add(client.deleteObject(metaDatum.getName(), objectMeta.getKey())); } diff --git a/s3/src/test/java/org/jclouds/aws/s3/StubS3Connection.java b/s3/src/test/java/org/jclouds/aws/s3/StubS3Connection.java index 926a5495bf..ca0b8f35b2 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/StubS3Connection.java +++ b/s3/src/test/java/org/jclouds/aws/s3/StubS3Connection.java @@ -34,11 +34,14 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import org.jclouds.aws.s3.commands.options.GetBucketOptions; +import org.jclouds.aws.s3.commands.options.CopyObjectOptions; +import org.jclouds.aws.s3.commands.options.GetObjectOptions; +import org.jclouds.aws.s3.commands.options.ListBucketOptions; import org.jclouds.aws.s3.commands.options.PutBucketOptions; +import org.jclouds.aws.s3.commands.options.PutObjectOptions; import org.jclouds.aws.s3.domain.S3Bucket; import org.jclouds.aws.s3.domain.S3Object; -import org.jclouds.aws.s3.domain.S3Bucket.MetaData; +import org.jclouds.aws.s3.domain.S3Bucket.Metadata; /** * // TODO: Adrian: Document this! @@ -65,18 +68,18 @@ public class StubS3Connection implements S3Connection { }; } - public Future getObjectMetaData(final String s3Bucket, + public Future headObject(final String s3Bucket, final String key) { - return new FutureBase() { - public S3Object.MetaData get() throws InterruptedException, + return new FutureBase() { + public S3Object.Metadata get() throws InterruptedException, ExecutionException { if (!bucketToContents.containsKey(s3Bucket)) - return S3Object.MetaData.NOT_FOUND; + return S3Object.Metadata.NOT_FOUND; Map realContents = bucketToContents .get(s3Bucket); if (!realContents.containsKey(key)) - return S3Object.MetaData.NOT_FOUND; - S3Object.MetaData metaData = new S3Object.MetaData(key); + return S3Object.Metadata.NOT_FOUND; + S3Object.Metadata metaData = new S3Object.Metadata(key); return metaData; } }; @@ -94,21 +97,21 @@ public class StubS3Connection implements S3Connection { }; } - public Future addObject(final String s3Bucket, final S3Object object) { - return new FutureBase() { - public String get() throws InterruptedException, ExecutionException { + public Future putObject(final String s3Bucket, final S3Object object) { + return new FutureBase() { + public byte[] get() throws InterruptedException, ExecutionException { if (!bucketToContents.containsKey(s3Bucket)) { throw new ExecutionException(new RuntimeException( "bucket not found: " + s3Bucket)); } bucketToContents.get(s3Bucket).put(object.getKey(), object.getClass()); - return object.getKey(); + return object.getKey().getBytes();// todo actually md5 } }; } - public Future createBucketIfNotExists(final String s3Bucket) { + public Future putBucketIfNotExists(final String s3Bucket) { return new FutureBase() { public Boolean get() throws InterruptedException, ExecutionException { @@ -134,20 +137,20 @@ public class StubS3Connection implements S3Connection { }; } - public Future copyObject(final String sourceBucket, + public Future copyObject(final String sourceBucket, final String sourceObject, final String destinationBucket, final String destinationObject) { - return new FutureBase() { - public S3Object.MetaData get() throws InterruptedException, + return new FutureBase() { + public S3Object.Metadata get() throws InterruptedException, ExecutionException { Map source = bucketToContents.get(sourceBucket); Map dest = bucketToContents .get(destinationBucket); if (source.containsKey(sourceObject)) { dest.put(destinationObject, source.get(sourceObject)); - return new S3Object.MetaData(destinationObject); + return new S3Object.Metadata(destinationObject); } - return S3Object.MetaData.NOT_FOUND; + return S3Object.Metadata.NOT_FOUND; } }; } @@ -161,16 +164,16 @@ public class StubS3Connection implements S3Connection { }; } - public Future getBucket(final String s3Bucket) { + public Future listBucket(final String s3Bucket) { return new FutureBase() { public S3Bucket get() throws InterruptedException, ExecutionException { - Set contents = new HashSet(); + Set contents = new HashSet(); Map realContents = bucketToContents .get(s3Bucket); if (realContents != null) { for (String key : realContents.keySet()) { - S3Object.MetaData metaData = new S3Object.MetaData(key); + S3Object.Metadata metaData = new S3Object.Metadata(key); contents.add(metaData); } } @@ -202,25 +205,44 @@ public class StubS3Connection implements S3Connection { } } - public Future> getMetaDataOfOwnedBuckets() { - return new FutureBase>() { - public List get() throws InterruptedException, + public Future> getOwnedBuckets() { + return new FutureBase>() { + public List get() throws InterruptedException, ExecutionException { - List list = new ArrayList(); + List list = new ArrayList(); for (String name : bucketToContents.keySet()) - list.add(new S3Bucket.MetaData(name)); + list.add(new S3Bucket.Metadata(name)); return list; } }; } - public Future createBucketIfNotExists(String name, + public Future putBucketIfNotExists(String name, PutBucketOptions options) { throw new UnsupportedOperationException("todo"); } - public Future getBucket(String name, GetBucketOptions options) { + public Future listBucket(String name, ListBucketOptions options) { throw new UnsupportedOperationException("todo"); } + public Future copyObject( + String sourceBucket, String sourceObject, String destinationBucket, + String destinationObject, CopyObjectOptions options) { + // TODO Auto-generated method stub + return null; + } + + public Future putObject(String bucketName, S3Object object, + PutObjectOptions options) { + // TODO Auto-generated method stub + return null; + } + + public Future getObject(String bucketName, String key, + GetObjectOptions options) { + // TODO Auto-generated method stub + return null; + } + } diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/BucketExistsIntegrationTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/BucketExistsIntegrationTest.java new file mode 100644 index 0000000000..eab0cae5c1 --- /dev/null +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/BucketExistsIntegrationTest.java @@ -0,0 +1,57 @@ +/** + * + * Copyright (C) 2009 Adrian Cole + * + * ==================================================================== + * 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.commands; + +import java.util.concurrent.TimeUnit; + +import org.jclouds.aws.s3.S3IntegrationTest; +import org.testng.annotations.Test; + +/** + * Tests integrated functionality of all bucketExists commands. + *

+ * Each test uses a different bucket name, so it should be perfectly fine to run + * in parallel. + * + * @author Adrian Cole + * + */ +@Test(groups = "integration", testName = "s3.BucketExistsIntegrationTest") +public class BucketExistsIntegrationTest extends S3IntegrationTest { + + @Test() + void bucketDoesntExist() throws Exception { + String bucketName = bucketPrefix + "shouldntexist"; + assert !client.bucketExists(bucketName).get(10, TimeUnit.SECONDS); + } + + @Test() + void bucketExists() throws Exception { + String bucketName = bucketPrefix + "needstoexist"; + assert client.putBucketIfNotExists(bucketName).get(10, + TimeUnit.SECONDS); + assert client.bucketExists(bucketName).get(10, TimeUnit.SECONDS); + + } +} \ No newline at end of file diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/CopyObjectIntegrationTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/CopyObjectIntegrationTest.java new file mode 100644 index 0000000000..aff8348745 --- /dev/null +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/CopyObjectIntegrationTest.java @@ -0,0 +1,96 @@ +/** + * + * Copyright (C) 2009 Adrian Cole + * + * ==================================================================== + * 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.commands; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.jclouds.aws.s3.S3IntegrationTest; +import org.testng.annotations.Test; + +/** + * Tests integrated functionality of all copyObject commands. + *

+ * Each test uses a different bucket name, so it should be perfectly fine to run + * in parallel. + * + * @author Adrian Cole + * + */ +@Test(groups = "integration", testName = "s3.CopyObjectIntegrationTest") +public class CopyObjectIntegrationTest extends S3IntegrationTest { + + @Test() + void testCopyObject() throws Exception { + String sourceBucket = bucketPrefix + "testCopyObject"; + String sourceKey = "apples"; + String destinationBucket = bucketPrefix + "testCopyObjectDestination"; + String destinationKey = "pears"; + + setupSourceBucket(sourceBucket, sourceKey); + + createBucketAndEnsureEmpty(destinationBucket); + client.copyObject(sourceBucket, sourceKey, destinationBucket, + destinationKey).get(10, TimeUnit.SECONDS); + + validateContent(destinationBucket, destinationKey); + + } + + private void setupSourceBucket(String sourceBucket, String sourceKey) + throws InterruptedException, ExecutionException, TimeoutException, + IOException { + createBucketAndEnsureEmpty(sourceBucket); + addObjectToBucket(sourceBucket, sourceKey); + validateContent(sourceBucket, sourceKey); + } + + @Test + void testCopyIfModifiedSince() { + // TODO + } + + @Test + void testCopyIfUnmodifiedSince() { + // TODO + } + + @Test + void testCopyIfMatch() { + // TODO + } + + @Test + void testCopyIfNoneMatch() { + // TODO + } + + @Test + void testCopyWithMetadata() { + + } + +} \ No newline at end of file diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/GetObjectIntegrationTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/GetObjectIntegrationTest.java new file mode 100644 index 0000000000..3e79dbe605 --- /dev/null +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/GetObjectIntegrationTest.java @@ -0,0 +1,70 @@ +/** + * + * Copyright (C) 2009 Adrian Cole + * + * ==================================================================== + * 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.commands; + +import org.jclouds.aws.s3.S3IntegrationTest; +import org.testng.annotations.Test; + +/** + * Tests integrated functionality of all GetObject commands. + *

+ * Each test uses a different bucket name, so it should be perfectly fine to run + * in parallel. + * + * @author Adrian Cole + * + */ +@Test(groups = "integration", testName = "s3.GetObjectIntegrationTest") +public class GetObjectIntegrationTest extends S3IntegrationTest { + + @Test + void testGetIfModifiedSince() { + // TODO + } + + @Test + void testGetIfUnmodifiedSince() { + // TODO + } + + @Test + void testGetIfMatch() { + // TODO + } + + @Test + void testGetIfNoneMatch() { + // TODO + } + + @Test + void testGetWithMetadata() { + // TODO + } + + @Test + void testGetRange() { + // TODO + } +} \ No newline at end of file diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/ListBucketIntegrationTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/ListBucketIntegrationTest.java new file mode 100644 index 0000000000..e3bdf21677 --- /dev/null +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/ListBucketIntegrationTest.java @@ -0,0 +1,138 @@ +/** + * + * Copyright (C) 2009 Adrian Cole + * + * ==================================================================== + * 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.commands; + +import static org.jclouds.aws.s3.commands.options.ListBucketOptions.Builder.delimiter; +import static org.jclouds.aws.s3.commands.options.ListBucketOptions.Builder.afterMarker; +import static org.jclouds.aws.s3.commands.options.ListBucketOptions.Builder.withPrefix; +import static org.jclouds.aws.s3.commands.options.ListBucketOptions.Builder.maxResults; + +import static org.testng.Assert.assertEquals; + +import java.io.UnsupportedEncodingException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.jclouds.aws.s3.S3IntegrationTest; +import org.jclouds.aws.s3.domain.S3Bucket; +import org.jclouds.aws.s3.domain.S3Object; +import org.testng.annotations.Test; + +/** + * Tests integrated functionality of all getBucket commands. + *

+ * Each test uses a different bucket name, so it should be perfectly fine to run + * in parallel. + * + * @author Adrian Cole + * + */ +@Test(groups = "integration", testName = "s3.ListBucketIntegrationTest") +public class ListBucketIntegrationTest extends S3IntegrationTest { + + @Test() + void testListBucketDelimiter() throws InterruptedException, + ExecutionException, TimeoutException, UnsupportedEncodingException { + String bucketName = bucketPrefix + "delimiter"; + assert client.putBucketIfNotExists(bucketName).get(10, + TimeUnit.SECONDS); + String prefix = "apps"; + addTenObjectsUnderPrefix(bucketName, prefix); + add15UnderRoot(bucketName); + S3Bucket bucket = client.listBucket(bucketName, delimiter("/")).get(10, + TimeUnit.SECONDS); + assertEquals(bucket.getDelimiter(), "/"); + assertEquals(bucket.getContents().size(), 15); + assertEquals(bucket.getCommonPrefixes().size(), 1); + } + + private void addAlphabetUnderRoot(String bucketName) + throws InterruptedException, ExecutionException, TimeoutException { + for (char letter = 'a'; letter <= 'z'; letter++) { + client.putObject(bucketName, + new S3Object(letter + "", letter + "content")).get(10, + TimeUnit.SECONDS); + } + } + + @Test + void testListBucketMarker() throws InterruptedException, + ExecutionException, TimeoutException, UnsupportedEncodingException { + String bucketName = bucketPrefix + "marker"; + assert client.putBucketIfNotExists(bucketName).get(10, + TimeUnit.SECONDS); + addAlphabetUnderRoot(bucketName); + S3Bucket bucket = client.listBucket(bucketName, afterMarker("y")).get( + 10, TimeUnit.SECONDS); + assertEquals(bucket.getMarker(), "y"); + assertEquals(bucket.getContents().size(), 1); + } + + @Test + void testListBucketMaxResults() throws InterruptedException, + ExecutionException, TimeoutException, UnsupportedEncodingException { + String bucketName = bucketPrefix + "max"; + assert client.putBucketIfNotExists(bucketName).get(10, + TimeUnit.SECONDS); + addAlphabetUnderRoot(bucketName); + S3Bucket bucket = client.listBucket(bucketName, maxResults(5)).get(10, + TimeUnit.SECONDS); + assertEquals(bucket.getMaxKeys(), 5); + assertEquals(bucket.getContents().size(), 5); + } + + @Test() + void testListBucketPrefix() throws InterruptedException, + ExecutionException, TimeoutException, UnsupportedEncodingException { + String bucketName = bucketPrefix + "prefix"; + assert client.putBucketIfNotExists(bucketName).get(10, + TimeUnit.SECONDS); + String prefix = "apps"; + addTenObjectsUnderPrefix(bucketName, prefix); + add15UnderRoot(bucketName); + + S3Bucket bucket = client.listBucket(bucketName, withPrefix("apps/")) + .get(10, TimeUnit.SECONDS); + assertEquals(bucket.getContents().size(), 10); + assertEquals(bucket.getPrefix(), "apps/"); + + } + + private void add15UnderRoot(String bucketName) throws InterruptedException, + ExecutionException, TimeoutException { + for (int i = 0; i < 15; i++) + client.putObject(bucketName, new S3Object(i + "", i + "content")) + .get(10, TimeUnit.SECONDS); + } + + private void addTenObjectsUnderPrefix(String bucketName, String prefix) + throws InterruptedException, ExecutionException, TimeoutException { + for (int i = 0; i < 10; i++) + client.putObject(bucketName, + new S3Object(prefix + "/" + i, i + "content")).get(10, + TimeUnit.SECONDS); + } + +} \ No newline at end of file diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/PutBucketIntegrationTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/PutBucketIntegrationTest.java new file mode 100644 index 0000000000..b58a6372ab --- /dev/null +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/PutBucketIntegrationTest.java @@ -0,0 +1,86 @@ +/** + * + * Copyright (C) 2009 Adrian Cole + * + * ==================================================================== + * 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.commands; + +import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.createIn; +import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.withBucketAcl; + +import java.io.IOException; +import java.net.URL; +import java.util.concurrent.TimeUnit; + +import org.jclouds.aws.s3.S3IntegrationTest; +import org.jclouds.aws.s3.S3Utils; +import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint; +import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; +import org.testng.annotations.Test; + +/** + * Tests integrated functionality of all PutBucket commands. + *

+ * Each test uses a different bucket name, so it should be perfectly fine to run + * in parallel. + * + * @author Adrian Cole + * + */ +@Test(groups = "integration", testName = "s3.PutBucketIntegrationTest") +public class PutBucketIntegrationTest extends S3IntegrationTest { + + @Test() + void testPublicReadAccessPolicy() throws Exception { + String bucketName = bucketPrefix + "public"; + + client.putBucketIfNotExists(bucketName, + withBucketAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, + TimeUnit.SECONDS); + URL url = new URL(String.format("http://%1s.s3.amazonaws.com", + bucketName)); + S3Utils.toStringAndClose(url.openStream()); + } + + @Test(expectedExceptions = IOException.class) + void testDefaultAccessPolicy() throws Exception { + String bucketName = bucketPrefix + "private"; + + client.putBucketIfNotExists(bucketName).get(10, TimeUnit.SECONDS); + URL url = new URL(String.format("http://%1s.s3.amazonaws.com", + bucketName)); + S3Utils.toStringAndClose(url.openStream()); + } + + @Test() + void testEu() throws Exception { + String bucketName = (bucketPrefix + "wow").toLowerCase(); + client.putBucketIfNotExists( + bucketName, + createIn(LocationConstraint.EU).withBucketAcl( + CannedAccessPolicy.PUBLIC_READ)).get(10, + TimeUnit.SECONDS); + + URL url = new URL(String.format("http://%1s.s3.amazonaws.com", + bucketName)); + S3Utils.toStringAndClose(url.openStream()); + } +} \ No newline at end of file diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/PutObjectIntegrationTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/PutObjectIntegrationTest.java new file mode 100644 index 0000000000..45b83b9500 --- /dev/null +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/PutObjectIntegrationTest.java @@ -0,0 +1,143 @@ +/** + * + * Copyright (C) 2009 Adrian Cole + * + * ==================================================================== + * 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.commands; + +import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.withBucketAcl; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URL; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.io.IOUtils; +import org.jclouds.aws.s3.S3Headers; +import org.jclouds.aws.s3.S3IntegrationTest; +import org.jclouds.aws.s3.S3Utils; +import static org.jclouds.aws.s3.commands.options.PutObjectOptions.Builder.*; +import org.jclouds.aws.s3.domain.S3Object; +import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * Tests integrated functionality of all PutObject commands. + *

+ * Each test uses a different bucket name, so it should be perfectly fine to run + * in parallel. + * + * @author Adrian Cole + * + */ +@Test(groups = "integration", testName = "s3.PutObjectIntegrationTest") +public class PutObjectIntegrationTest extends S3IntegrationTest { + @DataProvider(name = "putTests") + public Object[][] createData1() throws IOException { + + String realObject = IOUtils.toString(new FileInputStream("pom.xml")); + + return new Object[][] { + { "file", "text/xml", new File("pom.xml"), realObject }, + { "string", "text/xml", realObject, realObject }, + { "bytes", "application/octet-stream", realObject.getBytes(), + realObject } }; + } + + @Test(dataProvider = "putTests") + void testPutObject(String key, String type, Object content, + Object realObject) throws Exception { + String bucketName = bucketPrefix + "filetestsforadrian"; + client.putBucketIfNotExists(bucketName).get(10, TimeUnit.SECONDS); + context.createS3ObjectMap(bucketName).clear(); + assertEquals(client.listBucket(bucketName).get(10, TimeUnit.SECONDS) + .getContents().size(), 0); + S3Object object = new S3Object(key); + object.getMetaData().setContentType(type); + object.setData(content); + assertNotNull(client.putObject(bucketName, object).get(10, + TimeUnit.SECONDS)); + object = client.getObject(bucketName, object.getKey()).get(10, + TimeUnit.SECONDS); + String returnedString = S3Utils.getContentAsStringAndClose(object); + assertEquals(returnedString, realObject); + assertEquals(client.listBucket(bucketName).get(10, TimeUnit.SECONDS) + .getContents().size(), 1); + } + + @Test + void testMetaData() throws Exception { + String bucketName = bucketPrefix + "header"; + createBucketAndEnsureEmpty(bucketName); + String key = "hello"; + + S3Object object = new S3Object(key, TEST_STRING); + object.getMetaData().setCacheControl("no-cache"); + object.getMetaData().setContentType("text/plain"); + object.getMetaData().setContentEncoding("x-compress"); + object.getMetaData().setSize(TEST_STRING.length()); + object.getMetaData().setContentDisposition( + "attachment; filename=hello.txt"); + object.getMetaData().getUserMetadata().put( + S3Headers.USER_METADATA_PREFIX + "adrian", "powderpuff"); + object.getMetaData().setMd5(S3Utils.md5(TEST_STRING.getBytes())); + + addObjectToBucket(bucketName, object); + object = validateContent(bucketName, key); + + // TODO.. why does this come back as binary/octetstring + assertEquals(object.getMetaData().getContentType(), + "binary/octet-stream"); + assertEquals(object.getMetaData().getContentEncoding(), "x-compress"); + assertEquals(object.getMetaData().getContentDisposition(), + "attachment; filename=hello.txt"); + assertEquals(object.getMetaData().getCacheControl(), "no-cache"); + assertEquals(object.getMetaData().getSize(), TEST_STRING.length()); + assertEquals(object.getMetaData().getUserMetadata().values().iterator() + .next(), "powderpuff"); + assertEquals(object.getMetaData().getMd5(), S3Utils.md5(TEST_STRING + .getBytes())); + } + + @Test() + void testCannedAccessPolicyPublic() throws Exception { + String bucketName = bucketPrefix + "aclpublic"; + createBucketAndEnsureEmpty(bucketName); + String key = "hello"; + + client.putBucketIfNotExists(bucketName, + withBucketAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, + TimeUnit.SECONDS); + client.putObject(bucketName, new S3Object(key, TEST_STRING), + + withAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, TimeUnit.SECONDS); + + URL url = new URL(String.format("http://%1s.s3.amazonaws.com/%1s", + bucketName, key)); + S3Utils.toStringAndClose(url.openStream()); + + } + +} \ No newline at end of file diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/S3CommandFactoryTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/S3CommandFactoryTest.java index a4a5f8c2a2..e6b6bc0906 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/commands/S3CommandFactoryTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/S3CommandFactoryTest.java @@ -28,9 +28,13 @@ import static org.easymock.classextension.EasyMock.createMock; import static org.easymock.classextension.EasyMock.replay; import org.jclouds.aws.s3.commands.config.S3CommandsModule; +import org.jclouds.aws.s3.commands.options.CopyObjectOptions; +import org.jclouds.aws.s3.commands.options.GetObjectOptions; +import org.jclouds.aws.s3.commands.options.ListBucketOptions; import org.jclouds.aws.s3.commands.options.PutBucketOptions; +import org.jclouds.aws.s3.commands.options.PutObjectOptions; import org.jclouds.aws.s3.domain.S3Object; -import org.jclouds.aws.s3.domain.S3Bucket.MetaData.LocationConstraint; +import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -73,7 +77,13 @@ public class S3CommandFactoryTest { @Test void testCreateCopyObject() { assert commandFactory.createCopyObject("sourceBucket", "sourceObject", - "destBucket", "destObject") != null; + "destBucket", "destObject", CopyObjectOptions.NONE) != null; + } + + @Test + void testCreateCopyObjectOptions() { + assert commandFactory.createCopyObject("sourceBucket", "sourceObject", + "destBucket", "destObject", new CopyObjectOptions()) != null; } @Test @@ -93,18 +103,18 @@ public class S3CommandFactoryTest { @Test void testCreatePutBucket() { - assert commandFactory.createPutBucket("test") != null; + assert commandFactory.createPutBucket("test", PutBucketOptions.NONE) != null; } @Test void testCreatePutBucketOptions() { assert commandFactory.createPutBucket("test", PutBucketOptions.Builder - .locationConstraint(LocationConstraint.EU)) != null; + .createIn(LocationConstraint.EU)) != null; } @Test void testCreatePutObject() { - S3Object.MetaData metaData = createMock(S3Object.MetaData.class); + S3Object.Metadata metaData = createMock(S3Object.Metadata.class); S3Object object = new S3Object(metaData); object.setData(""); expect(metaData.getKey()).andReturn("rawr"); @@ -113,12 +123,14 @@ public class S3CommandFactoryTest { replay(metaData); - assert commandFactory.createPutObject("test", object) != null; + assert commandFactory.createPutObject("test", object, + PutObjectOptions.NONE) != null; } @Test void testCreateGetObject() { - assert commandFactory.createGetObject("test", "blah") != null; + assert commandFactory.createGetObject("test", "blah", + GetObjectOptions.NONE) != null; } @Test @@ -133,7 +145,7 @@ public class S3CommandFactoryTest { @Test void testCreateListBucket() { - assert commandFactory.createGetBucket("test") != null; + assert commandFactory.createListBucket("test", ListBucketOptions.NONE) != null; } } \ No newline at end of file diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/S3ParserTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/S3ParserTest.java index 43e7de7d2e..1aefebc661 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/commands/S3ParserTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/S3ParserTest.java @@ -86,7 +86,7 @@ public class S3ParserTest extends PerformanceTest { runParseListAllMyBuckets(); } - private List runParseListAllMyBuckets() + private List runParseListAllMyBuckets() throws HttpException { return parserFactory.createListBucketsParser().parse( IOUtils.toInputStream(listAllMyBucketsResultOn200)); @@ -95,11 +95,11 @@ public class S3ParserTest extends PerformanceTest { @Test void testParseListAllMyBucketsParallelResponseTime() throws InterruptedException, ExecutionException { - CompletionService> completer = new ExecutorCompletionService>( + CompletionService> completer = new ExecutorCompletionService>( exec); for (int i = 0; i < LOOP_COUNT; i++) - completer.submit(new Callable>() { - public List call() throws IOException, + completer.submit(new Callable>() { + public List call() throws IOException, SAXException, HttpException { return runParseListAllMyBuckets(); } @@ -110,13 +110,13 @@ public class S3ParserTest extends PerformanceTest { @Test public void testCanParseListAllMyBuckets() throws HttpException { - List s3Buckets = runParseListAllMyBuckets(); - S3Bucket.MetaData bucket1 = s3Buckets.get(0); + List s3Buckets = runParseListAllMyBuckets(); + S3Bucket.Metadata bucket1 = s3Buckets.get(0); assert bucket1.getName().equals("adrianjbosstest"); DateTime expectedDate1 = new DateTime("2009-03-12T02:00:07.000Z"); DateTime date1 = bucket1.getCreationDate(); assert date1.equals(expectedDate1); - S3Bucket.MetaData bucket2 = s3Buckets.get(1); + S3Bucket.Metadata bucket2 = s3Buckets.get(1); assert bucket2.getName().equals("adrianjbosstest2"); DateTime expectedDate2 = new DateTime("2009-03-12T02:00:09.000Z"); DateTime date2 = bucket2.getCreationDate(); @@ -137,7 +137,7 @@ public class S3ParserTest extends PerformanceTest { assert bucket.isComplete(); assert bucket.getName().equals("adrianjbosstest"); assert bucket.getContents().size() == 1; - S3Object.MetaData object = bucket.getContents().iterator().next(); + S3Object.Metadata object = bucket.getContents().iterator().next(); assert object.getKey().equals("3366"); DateTime expected = new DateTime("2009-03-12T02:00:13.000Z"); assert object.getLastModified().equals(expected) : String @@ -163,8 +163,8 @@ public class S3ParserTest extends PerformanceTest { public static final String successfulCopyObject200 = "2009-03-19T13:23:27.000Z\"92836a3ea45a6984d1b4d23a747d46bb\""; - private S3Object.MetaData runParseCopyObjectResult() throws HttpException { - ParseSax parser = parserFactory + private S3Object.Metadata runParseCopyObjectResult() throws HttpException { + ParseSax parser = parserFactory .createCopyObjectParser(); CopyObjectHandler handler = (CopyObjectHandler) parser.getHandler(); handler.setKey("adrianjbosstest"); @@ -173,7 +173,7 @@ public class S3ParserTest extends PerformanceTest { public void testCanParseCopyObjectResult() throws HttpException, UnsupportedEncodingException { - S3Object.MetaData metadata = runParseCopyObjectResult(); + S3Object.Metadata metadata = runParseCopyObjectResult(); DateTime expected = new DateTime("2009-03-19T13:23:27.000Z"); assertEquals(metadata.getLastModified(), expected); assertEquals(S3Utils.toHexString(metadata.getMd5()), diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/options/CopyObjectOptionsTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/options/CopyObjectOptionsTest.java index 711e2da1cc..1db399e25e 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/commands/options/CopyObjectOptionsTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/options/CopyObjectOptionsTest.java @@ -30,6 +30,7 @@ import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSo import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.overrideMetadataWith; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; import java.io.UnsupportedEncodingException; @@ -285,4 +286,25 @@ public class CopyObjectOptionsTest { throws UnsupportedEncodingException { ifSourceMd5Matches(testBytes).ifSourceMd5DoesntMatch(testBytes); } + + @Test + void testBuildRequestHeadersWhenMetadataNull() + throws UnsupportedEncodingException { + assert new CopyObjectOptions().buildRequestHeaders() != null; + } + + @Test + void testBuildRequestHeaders() throws UnsupportedEncodingException { + + Multimap headers = ifSourceModifiedSince(now) + .ifSourceMd5DoesntMatch(testBytes).overrideMetadataWith( + goodMeta).buildRequestHeaders(); + assertEquals(headers.get("x-amz-copy-source-if-modified-since") + .iterator().next(), new DateService().toHeaderString(now)); + assertEquals(headers.get("x-amz-copy-source-if-none-match").iterator() + .next(), "\"" + S3Utils.toHexString(testBytes) + "\""); + for (String value : goodMeta.values()) + assertTrue(headers.containsValue(value)); + + } } diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/options/GetBucketOptionsTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/options/ListBucketOptionsTest.java similarity index 71% rename from s3/src/test/java/org/jclouds/aws/s3/commands/options/GetBucketOptionsTest.java rename to s3/src/test/java/org/jclouds/aws/s3/commands/options/ListBucketOptionsTest.java index 316eaeadde..3f47b7a905 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/commands/options/GetBucketOptionsTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/options/ListBucketOptionsTest.java @@ -24,49 +24,47 @@ package org.jclouds.aws.s3.commands.options; import static com.google.common.base.Preconditions.checkNotNull; -import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.delimiter; -import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.marker; -import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.maxKeys; -import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.prefix; +import static org.jclouds.aws.s3.commands.options.ListBucketOptions.Builder.*; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; import java.io.UnsupportedEncodingException; +import org.jclouds.http.options.HttpRequestOptions; import org.testng.annotations.Test; /** - * Tests possible uses of GetBucketOptions and GetBucketOptions.Builder.* + * Tests possible uses of ListBucketOptions and ListBucketOptions.Builder.* * * @author Adrian Cole */ -public class GetBucketOptionsTest { +public class ListBucketOptionsTest { @Test public void testPrefix() throws UnsupportedEncodingException { - GetBucketOptions options = new GetBucketOptions(); - options.prefix("test"); + ListBucketOptions options = new ListBucketOptions(); + options.withPrefix("test"); assertEquals(options.getPrefix(), "test"); } @Test public void testNoOptionsQueryString() { - GetBucketOptions options = new GetBucketOptions(); - assertEquals(options.toQueryString(), ""); + HttpRequestOptions options = new ListBucketOptions(); + assertEquals(options.buildQueryString(), ""); } @Test public void testOneOptionQueryString() throws UnsupportedEncodingException { - GetBucketOptions options = new GetBucketOptions(); - options.prefix("test"); - assertEquals(options.toQueryString(), "?prefix=test"); + ListBucketOptions options = new ListBucketOptions(); + options.withPrefix("test"); + assertEquals(options.buildQueryString(), "?prefix=test"); } @Test public void testTwoOptionQueryString() throws UnsupportedEncodingException { - GetBucketOptions options = new GetBucketOptions(); - options.prefix("test").maxKeys(1); - String query = options.toQueryString(); + ListBucketOptions options = new ListBucketOptions(); + options.withPrefix("test").maxResults(1); + String query = options.buildQueryString(); checkQuery(query); checkQuery(checkNotNull(query)); @@ -83,9 +81,9 @@ public class GetBucketOptionsTest { @Test public void testPrefixAndDelimiterUrlEncodingQueryString() throws UnsupportedEncodingException { - GetBucketOptions options = new GetBucketOptions(); - options.prefix("/test").delimiter("/"); - String query = options.toQueryString(); + ListBucketOptions options = new ListBucketOptions(); + options.withPrefix("/test").setDelimiter("/"); + String query = options.buildQueryString(); checkEncodedQuery(query); checkEncodedQuery(checkNotNull(query)); @@ -101,85 +99,85 @@ public class GetBucketOptionsTest { @Test public void testNullPrefix() { - GetBucketOptions options = new GetBucketOptions(); + ListBucketOptions options = new ListBucketOptions(); assertNull(options.getPrefix()); } @Test public void testPrefixStatic() throws UnsupportedEncodingException { - GetBucketOptions options = prefix("test"); + ListBucketOptions options = withPrefix("test"); assertEquals(options.getPrefix(), "test"); } @Test(expectedExceptions = NullPointerException.class) public void testPrefixNPE() throws UnsupportedEncodingException { - prefix(null); + withPrefix(null); } @Test public void testMarker() throws UnsupportedEncodingException { - GetBucketOptions options = new GetBucketOptions(); - options.marker("test"); + ListBucketOptions options = new ListBucketOptions(); + options.afterMarker("test"); assertEquals(options.getMarker(), "test"); } @Test public void testNullMarker() { - GetBucketOptions options = new GetBucketOptions(); + ListBucketOptions options = new ListBucketOptions(); assertNull(options.getMarker()); } @Test public void testMarkerStatic() throws UnsupportedEncodingException { - GetBucketOptions options = marker("test"); + ListBucketOptions options = afterMarker("test"); assertEquals(options.getMarker(), "test"); } @Test(expectedExceptions = NullPointerException.class) public void testMarkerNPE() throws UnsupportedEncodingException { - marker(null); + afterMarker(null); } @Test public void testMaxKeys() { - GetBucketOptions options = new GetBucketOptions(); - options.maxKeys(1000); + ListBucketOptions options = new ListBucketOptions(); + options.maxResults(1000); assertEquals(options.getMaxKeys(), "1000"); } @Test public void testNullMaxKeys() { - GetBucketOptions options = new GetBucketOptions(); + ListBucketOptions options = new ListBucketOptions(); assertNull(options.getMaxKeys()); } @Test public void testMaxKeysStatic() { - GetBucketOptions options = maxKeys(1000); + ListBucketOptions options = maxResults(1000); assertEquals(options.getMaxKeys(), "1000"); } @Test(expectedExceptions = IllegalStateException.class) public void testMaxKeysNegative() { - maxKeys(-1); + maxResults(-1); } @Test public void testDelimiter() throws UnsupportedEncodingException { - GetBucketOptions options = new GetBucketOptions(); - options.delimiter("test"); + ListBucketOptions options = new ListBucketOptions(); + options.setDelimiter("test"); assertEquals(options.getDelimiter(), "test"); } @Test public void testNullDelimiter() { - GetBucketOptions options = new GetBucketOptions(); + ListBucketOptions options = new ListBucketOptions(); assertNull(options.getDelimiter()); } @Test public void testDelimiterStatic() throws UnsupportedEncodingException { - GetBucketOptions options = delimiter("test"); + ListBucketOptions options = delimiter("test"); assertEquals(options.getDelimiter(), "test"); } diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/options/PutBucketOptionsTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/options/PutBucketOptionsTest.java index 07628a93bf..f92aadac8c 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/commands/options/PutBucketOptionsTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/options/PutBucketOptionsTest.java @@ -23,15 +23,22 @@ */ package org.jclouds.aws.s3.commands.options; -import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.locationConstraint; +import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.createIn; +import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.withBucketAcl; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; -import org.jclouds.aws.s3.domain.S3Bucket.MetaData.LocationConstraint; +import java.io.UnsupportedEncodingException; + +import org.jclouds.aws.s3.S3Headers; +import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint; +import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; import org.testng.annotations.Test; +import com.google.common.collect.Multimap; + /** - * Tests possible uses of GetBucketOptions and GetBucketOptions.Builder.* + * Tests possible uses of PutBucketOptions and PutBucketOptions.Builder.* * * @author Adrian Cole */ @@ -40,10 +47,19 @@ public class PutBucketOptionsTest { @Test public void testLocationConstraint() { PutBucketOptions options = new PutBucketOptions(); - options.locationConstraint(LocationConstraint.EU); + options.createIn(LocationConstraint.EU); assertEquals(options.getLocationConstraint(), LocationConstraint.EU); } + @Test + public void testPayload() { + PutBucketOptions options = new PutBucketOptions(); + options.createIn(LocationConstraint.EU); + assertEquals( + options.buildPayload(), + "EU"); + } + @Test public void testNullLocationConstraint() { PutBucketOptions options = new PutBucketOptions(); @@ -52,13 +68,33 @@ public class PutBucketOptionsTest { @Test public void testLocationConstraintStatic() { - PutBucketOptions options = locationConstraint(LocationConstraint.EU); + PutBucketOptions options = createIn(LocationConstraint.EU); assertEquals(options.getLocationConstraint(), LocationConstraint.EU); } @Test(expectedExceptions = NullPointerException.class) public void testNPE() { - locationConstraint(null); + createIn(null); } + @Test + public void testAclDefault() { + PutBucketOptions options = new PutBucketOptions(); + assertEquals(options.getAcl(), CannedAccessPolicy.PRIVATE); + } + + @Test + public void testAclStatic() { + PutBucketOptions options = withBucketAcl(CannedAccessPolicy.AUTHENTICATED_READ); + assertEquals(options.getAcl(), CannedAccessPolicy.AUTHENTICATED_READ); + } + + @Test + void testBuildRequestHeaders() throws UnsupportedEncodingException { + + Multimap headers = withBucketAcl( + CannedAccessPolicy.AUTHENTICATED_READ).buildRequestHeaders(); + assertEquals(headers.get(S3Headers.CANNED_ACL).iterator().next(), + CannedAccessPolicy.AUTHENTICATED_READ.toString()); + } } diff --git a/s3/src/test/java/org/jclouds/aws/s3/commands/options/PutObjectOptionsTest.java b/s3/src/test/java/org/jclouds/aws/s3/commands/options/PutObjectOptionsTest.java new file mode 100644 index 0000000000..2a5e323e8a --- /dev/null +++ b/s3/src/test/java/org/jclouds/aws/s3/commands/options/PutObjectOptionsTest.java @@ -0,0 +1,64 @@ +/** + * + * Copyright (C) 2009 Adrian Cole + * + * ==================================================================== + * 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.commands.options; + +import static org.jclouds.aws.s3.commands.options.PutObjectOptions.Builder.withAcl; +import static org.testng.Assert.assertEquals; + +import java.io.UnsupportedEncodingException; + +import org.jclouds.aws.s3.S3Headers; +import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy; +import org.testng.annotations.Test; + +import com.google.common.collect.Multimap; + +/** + * Tests possible uses of PutObjectOptions and PutObjectOptions.Builder.* + * + * @author Adrian Cole + */ +public class PutObjectOptionsTest { + + @Test + public void testAclDefault() { + PutObjectOptions options = new PutObjectOptions(); + assertEquals(options.getAcl(), CannedAccessPolicy.PRIVATE); + } + + @Test + public void testAclStatic() { + PutObjectOptions options = withAcl(CannedAccessPolicy.AUTHENTICATED_READ); + assertEquals(options.getAcl(), CannedAccessPolicy.AUTHENTICATED_READ); + } + + @Test + void testBuildRequestHeaders() throws UnsupportedEncodingException { + + Multimap headers = withAcl( + CannedAccessPolicy.AUTHENTICATED_READ).buildRequestHeaders(); + assertEquals(headers.get(S3Headers.CANNED_ACL).iterator().next(), + CannedAccessPolicy.AUTHENTICATED_READ.toString()); + } +} diff --git a/s3/src/test/java/org/jclouds/aws/s3/domain/S3ObjectTest.java b/s3/src/test/java/org/jclouds/aws/s3/domain/S3ObjectTest.java index eb256a5dff..015e4e4d3d 100644 --- a/s3/src/test/java/org/jclouds/aws/s3/domain/S3ObjectTest.java +++ b/s3/src/test/java/org/jclouds/aws/s3/domain/S3ObjectTest.java @@ -28,6 +28,7 @@ import java.io.File; import static org.testng.Assert.*; import org.jclouds.aws.s3.domain.S3Object; +import org.jclouds.http.ContentTypes; import org.testng.annotations.Test; @Test @@ -39,6 +40,6 @@ public class S3ObjectTest { File file = new File("hello.txt"); object.setData(file); assertEquals(object.getMetaData().getContentType(), - S3Object.MetaData.UNKNOWN_MIME_TYPE); + ContentTypes.UNKNOWN_MIME_TYPE); } } diff --git a/samples/googleappengine/src/main/java/org/jclouds/samples/googleappengine/JCloudsServlet.java b/samples/googleappengine/src/main/java/org/jclouds/samples/googleappengine/JCloudsServlet.java index 954fca5b22..66b36ec2fa 100644 --- a/samples/googleappengine/src/main/java/org/jclouds/samples/googleappengine/JCloudsServlet.java +++ b/samples/googleappengine/src/main/java/org/jclouds/samples/googleappengine/JCloudsServlet.java @@ -58,10 +58,10 @@ public class JCloudsServlet extends HttpServlet { httpServletResponse.setContentType("text/plain"); Writer writer = httpServletResponse.getWriter(); try { - List myBuckets = context.getConnection() - .getMetaDataOfOwnedBuckets().get(10, TimeUnit.SECONDS); + List myBuckets = context.getConnection() + .getOwnedBuckets().get(10, TimeUnit.SECONDS); writer.write("List:\n"); - for (S3Bucket.MetaData bucket : myBuckets) { + for (S3Bucket.Metadata bucket : myBuckets) { writer.write(String.format(" %1s: %2s entries%n", bucket .getName(), context.createInputStreamMap( bucket.getName()).size()));