Issue 6, Issue 11, Issue 12, Issue 18: support eu, acls, rest options, cleaned up api

git-svn-id: http://jclouds.googlecode.com/svn/trunk@483 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-05-08 17:45:35 +00:00
parent 373f643ce8
commit 8c1861f73d
74 changed files with 2244 additions and 1034 deletions

View File

@ -0,0 +1,32 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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";
}

View File

@ -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";

View File

@ -0,0 +1,82 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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";
}

View File

@ -0,0 +1,53 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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<String, String> headers = HashMultimap.create();
public HttpMessage() {
super();
}
public Multimap<String, String> getHeaders() {
return headers;
}
public void setHeaders(Multimap<String, String> headers) {
this.headers = headers;
}
public String getFirstHeaderOrNull(String string) {
Collection<String> values = headers.get(string);
return (values != null && values.size() >= 1) ? values.iterator()
.next() : null;
}
}

View File

@ -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<String, String> 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<String, String> getHeaders() {
return headers;
}
public void setHeaders(Multimap<String, String> 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<String> values = headers.get(string);
return (values != null && values.size() >= 1) ? values.iterator()
.next() : null;
}
}

View File

@ -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<String, String> 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<String, String> getHeaders() {
return headers;
}
public void setHeaders(Multimap<String, String> 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<String> values = headers.get(string);
return (values != null && values.size() >= 1) ? values.iterator()
.next() : null;
}
}

View File

@ -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);

View File

@ -113,7 +113,8 @@ public class ParseSax<T> extends HttpFutureCommand.ResponseCallable<T> {
}
/**
* // TODO: Adrian: Document this!
* Handler that produces a useable domain object accessible after parsing
* completes.
*
* @author Adrian Cole
*/

View File

@ -0,0 +1,89 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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<String, String> options = new HashMap<String, String>();
protected Multimap<String, String> headers = HashMultimap.create();
protected String payload;
public String buildPayload() {
return payload;
}
protected String getFirstHeaderOrNull(String string) {
Collection<String> 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<String, String> buildRequestHeaders() {
return headers;
}
/**
* {@inheritDoc}
*/
public String buildQueryString() {
StringBuilder builder = new StringBuilder("");
if (options.size() > 0) {
builder.append("?");
for (Iterator<Entry<String, String>> i = options.entrySet()
.iterator(); i.hasNext();) {
Entry<String, String> entry = i.next();
builder.append(entry.getKey()).append("=").append(
entry.getValue());
if (i.hasNext())
builder.append("&");
}
}
String returnVal = builder.toString();
return returnVal;
}
}

View File

@ -0,0 +1,51 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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<String, String> 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();
}

View File

@ -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;
}

View File

@ -207,12 +207,12 @@ public class JCloudsS3Service extends S3Service {
@Override
protected S3Bucket[] listAllBucketsImpl() throws S3ServiceException {
try {
List<org.jclouds.aws.s3.domain.S3Bucket.MetaData> jcBucketList = connection
.getMetaDataOfOwnedBuckets().get(
List<org.jclouds.aws.s3.domain.S3Bucket.Metadata> jcBucketList = connection
.getOwnedBuckets().get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
ArrayList<org.jets3t.service.model.S3Bucket> jsBucketList = new ArrayList<org.jets3t.service.model.S3Bucket>();
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

View File

@ -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<org.jclouds.aws.s3.domain.S3Bucket.MetaData> jcBuckets = client
.getMetaDataOfOwnedBuckets().get(10, TimeUnit.SECONDS);
List<org.jclouds.aws.s3.domain.S3Bucket.Metadata> jcBuckets = client
.getOwnedBuckets().get(10, TimeUnit.SECONDS);
assert jsBuckets.length == jcBuckets.size();
Iterator<org.jclouds.aws.s3.domain.S3Bucket.MetaData> jcBucketsIter = jcBuckets
Iterator<org.jclouds.aws.s3.domain.S3Bucket.Metadata> 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(

View File

@ -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;
}

View File

@ -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<HTTPHeader> headers = new ArrayList<HTTPHeader>();
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<HTTPHeader> headers = new ArrayList<HTTPHeader>();
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!");
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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<S3Object> 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<S3Object> 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<S3Object.MetaData> getObjectMetaData(String bucketName, String key);
Future<S3Object.Metadata> 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<String> addObject(String bucketName, S3Object object);
Future<byte[]> 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<byte[]> 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<Boolean> createBucketIfNotExists(String name);
Future<Boolean> 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<Boolean> createBucketIfNotExists(String name,
PutBucketOptions options);
Future<Boolean> 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<S3Object.MetaData> copyObject(String sourceBucket,
Future<S3Object.Metadata> 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<S3Object.Metadata> copyObject(String sourceBucket,
String sourceObject, String destinationBucket,
String destinationObject, CopyObjectOptions options);
Future<Boolean> bucketExists(String name);
/**
@ -131,9 +173,9 @@ public interface S3Connection {
* @param s3Bucket
* @return
*/
Future<S3Bucket> getBucket(String name);
Future<S3Bucket> listBucket(String name);
Future<S3Bucket> getBucket(String name, GetBucketOptions options);
Future<S3Bucket> listBucket(String name, ListBucketOptions options);
Future<List<S3Bucket.MetaData>> getMetaDataOfOwnedBuckets();
Future<List<S3Bucket.Metadata>> getOwnedBuckets();
}

View File

@ -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";

View File

@ -0,0 +1,49 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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";
}

View File

@ -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;
}
}

View File

@ -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));
}

View File

@ -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<Boolean> {
@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);
}
}

View File

@ -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<S3Object.MetaData> {
public class CopyObject extends S3FutureCommand<S3Object.Metadata> {
@Inject
public CopyObject(@Named("jclouds.http.address") String amazonHost,
ParseSax<S3Object.MetaData> callable,
ParseSax<S3Object.Metadata> 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<S3Object.MetaData> {
String.format("/%1s/%2s", checkNotNull(sourceBucket,
"sourceBucket").toLowerCase(), checkNotNull(
sourceObject, "sourceObject")));
getRequest().getHeaders().putAll(options.buildRequestHeaders());
}
}

View File

@ -38,11 +38,11 @@ import com.google.inject.name.Named;
* @author Adrian Cole
*
*/
public class GetMetaDataForOwnedBuckets extends S3FutureCommand<List<S3Bucket.MetaData>> {
public class GetMetaDataForOwnedBuckets extends S3FutureCommand<List<S3Bucket.Metadata>> {
@Inject
public GetMetaDataForOwnedBuckets(@Named("jclouds.http.address") String amazonHost,
ParseSax<List<S3Bucket.MetaData>> callable) {
ParseSax<List<S3Bucket.Metadata>> callable) {
super("GET", "/", callable, amazonHost);
}

View File

@ -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<S3Object> {
@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<S3Object> {
}
@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();

View File

@ -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<S3Object.MetaData> {
public class HeadMetaData extends S3FutureCommand<S3Object.Metadata> {
@Inject
public HeadMetaData(@Named("jclouds.http.address") String amazonHost,

View File

@ -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<S3Bucket> {
public class ListBucket extends S3FutureCommand<S3Bucket> {
@Inject
public GetBucket(@Named("jclouds.http.address") String amazonHost,
ParseSax<S3Bucket> 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<S3Bucket> 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);

View File

@ -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<Boolean> {
@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 + "");
}
}
}

View File

@ -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<String> {
public class PutObject extends S3FutureCommand<byte[]> {
@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());
}
}

View File

@ -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);
}
}

View File

@ -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 {

View File

@ -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<S3Object.MetaData> {
HttpFutureCommand.ResponseCallable<S3Object.Metadata> {
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<String, String> 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;
}

View File

@ -35,16 +35,21 @@ import org.jclouds.http.HttpFutureCommand;
* @author Adrian Cole
*/
public class PutObjectCallable extends
HttpFutureCommand.ResponseCallable<String> {
HttpFutureCommand.ResponseCallable<byte []> {
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()

View File

@ -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,

View File

@ -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<S3Object.MetaData> object = connection.copyObject("sourceBucket", "objectName",
* "destinationBucket", "destinationName",
* overrideMetadataWith(meta).
* ifUnmodifiedSince(new DateTime().minusDays(1))
* ifSourceModifiedSince(new DateTime().minusDays(1))
* );
* <code>
*
@ -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<String, String> 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<String, String> buildRequestHeaders() {
Multimap<String, String> 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.
*/

View File

@ -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 {

View File

@ -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. <h2>
@ -43,7 +42,7 @@ import java.util.Map.Entry;
* import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.*
*
* S3Connection connection = // get connection
* Future<S3Bucket> bucket = connection.getBucket("bucketName",prefix("/home/users").maxKeys(1000));
* Future<S3Bucket> bucket = connection.listBucket("bucketName",withPrefix("home/users").maxKeys(1000));
* <code>
*
* 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<String, String> options = new HashMap<String, String>();
/**
* 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<Entry<String, String>> i = options.entrySet()
.iterator(); i.hasNext();) {
Entry<String, String> 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);
}
}

View File

@ -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.
* <h2>Usage</h2>
* 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. <h2>
* Usage</h2> 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):
* <p/>
* <code>
* 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<Boolean> createdInEu = connection.createBucketIfNotExists("bucketName",locationConstraint(EU));
* Future<Boolean> createdInEu = connection.putBucketIfNotExists("bucketName",createIn(EU));
* <code>
*
* 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(
"<CreateBucketConfiguration><LocationConstraint>%1s</LocationConstraint></CreateBucketConfiguration>",
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);
}
}
}

View File

@ -0,0 +1,87 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* <p/>
* <h2>
* Usage</h2> 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):
* <p/>
* <code>
* import static org.jclouds.aws.s3.commands.options.PutObjectOptions.Builder.*
* import org.jclouds.aws.s3.S3Connection;
*
* S3Connection connection = // get connection
* Future<Boolean> publicly readable = connection.putObject("bucketName",new S3Object("key","value"), withAcl(CannedAccessPolicy.PUBLIC_READ));
* <code>
*
* 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);
}
}
}

View File

@ -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<S3Object.MetaData> objects = new HashSet<S3Object.MetaData>();
private Set<S3Object.Metadata> objects = new HashSet<S3Object.Metadata>();
private Set<String> commonPrefixes = new HashSet<String>();
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<S3Object.MetaData> getContents() {
public Set<S3Object.Metadata> getContents() {
return objects;
}
public void setContents(Set<S3Object.MetaData> objects) {
public void setContents(Set<S3Object.Metadata> objects) {
this.objects = objects;
}
@ -209,7 +194,7 @@ public class S3Bucket {
isComplete = complete;
}
public MetaData getMetaData() {
public Metadata getMetaData() {
return metaData;
}

View File

@ -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<String, String> 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<String, String> userMetadata) {
this.userMetadata = userMetadata;
}
public Multimap<String, String> 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;
}
}

View File

@ -0,0 +1,80 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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:
*
* <p />
* 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;
}
}

View File

@ -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(

View File

@ -74,7 +74,7 @@ public abstract class BaseS3Map<T> implements Map<String, T>, S3Map {
public int size() {
try {
S3Bucket bucket = refreshBucket();
Set<S3Object.MetaData> contents = bucket.getContents();
Set<S3Object.Metadata> contents = bucket.getContents();
return contents.size();
} catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
@ -85,7 +85,7 @@ public abstract class BaseS3Map<T> implements Map<String, T>, 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<T> implements Map<String, T>, 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<T> implements Map<String, T>, S3Map {
public Set<String> keySet() {
try {
Set<String> keys = new HashSet<String>();
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<T> implements Map<String, T>, 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.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format(

View File

@ -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);
}

View File

@ -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<S3Object> getObject(String s3Bucket, String key) {
GetObject getObject = factory.createGetObject(s3Bucket, key);
return getObject(s3Bucket, key, GetObjectOptions.NONE);
}
/**
* {@inheritDoc}
*
* @see GetObject
*/
public Future<S3Object> 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<S3Object.MetaData> getObjectMetaData(String s3Bucket,
String key) {
public Future<S3Object.Metadata> 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<String> addObject(String s3Bucket, S3Object object) {
PutObject putObject = factory.createPutObject(s3Bucket, object);
public Future<byte[]> putObject(String s3Bucket, S3Object object) {
return putObject(s3Bucket, object, PutObjectOptions.NONE);
}
/**
* {@inheritDoc}
*
* @see PutObject
*/
public Future<byte[]> 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<Boolean> createBucketIfNotExists(String s3Bucket) {
PutBucket putBucket = factory.createPutBucket(s3Bucket);
client.submit(putBucket);
return putBucket;
public Future<Boolean> putBucketIfNotExists(String s3Bucket) {
return putBucketIfNotExists(s3Bucket, PutBucketOptions.NONE);
}
/**
@ -130,7 +151,7 @@ public class LiveS3Connection implements S3Connection {
*
* @see PutBucket
*/
public Future<Boolean> createBucketIfNotExists(String s3Bucket,
public Future<Boolean> 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<S3Object.MetaData> copyObject(String sourceBucket,
public Future<S3Object.Metadata> copyObject(String sourceBucket,
String sourceObject, String destinationBucket,
String destinationObject) {
return copyObject(sourceBucket, sourceObject, destinationBucket,
destinationObject, new CopyObjectOptions());
}
/**
* {@inheritDoc}
*
* @see CopyObject
*/
public Future<S3Object.Metadata> 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<S3Bucket> getBucket(String s3Bucket) {
GetBucket getBucket = factory.createGetBucket(s3Bucket);
public Future<S3Bucket> listBucket(String s3Bucket) {
return listBucket(s3Bucket, ListBucketOptions.NONE);
}
/**
* {@inheritDoc}
*
* @see ListBucket
*/
public Future<S3Bucket> 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<S3Bucket> getBucket(String s3Bucket, GetBucketOptions options) {
GetBucket getBucket = factory.createGetBucket(s3Bucket, options);
client.submit(getBucket);
return getBucket;
}
/**
* {@inheritDoc}
*/
public Future<List<MetaData>> getMetaDataOfOwnedBuckets() {
public Future<List<Metadata>> getOwnedBuckets() {
GetMetaDataForOwnedBuckets listRequest = factory
.createGetMetaDataForOwnedBuckets();
client.submit(listRequest);
return listRequest;
}
}

View File

@ -152,7 +152,7 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> 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<InputStream> implements
private void putAllInternal(Map<? extends String, ? extends Object> map) {
try {
List<Future<String>> puts = new ArrayList<Future<String>>();
List<Future<byte[]>> puts = new ArrayList<Future<byte[]>>();
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<String> put : puts)
for (Future<byte[]> put : puts)
// this will throw an exception if there was a problem
put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) {

View File

@ -99,7 +99,7 @@ public class LiveS3ObjectMap extends BaseS3Map<S3Object> 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.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
@ -111,11 +111,11 @@ public class LiveS3ObjectMap extends BaseS3Map<S3Object> implements S3ObjectMap
public void putAll(Map<? extends String, ? extends S3Object> map) {
try {
List<Future<String>> puts = new ArrayList<Future<String>>();
List<Future<byte[]>> puts = new ArrayList<Future<byte[]>>();
for (S3Object object : map.values()) {
puts.add(connection.addObject(bucket, object));
puts.add(connection.putObject(bucket, object));
}
for (Future<String> put : puts)
for (Future<byte[]> put : puts)
// this will throw an exception if there was a problem
put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) {

View File

@ -36,18 +36,18 @@ import com.google.inject.Inject;
* @author Adrian Cole
*/
public class CopyObjectHandler extends
ParseSax.HandlerWithResult<S3Object.MetaData> {
ParseSax.HandlerWithResult<S3Object.Metadata> {
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;
}

View File

@ -40,10 +40,10 @@ import com.google.inject.Inject;
* @author Adrian Cole
*/
public class ListAllMyBucketsHandler extends
ParseSax.HandlerWithResult<List<S3Bucket.MetaData>> {
ParseSax.HandlerWithResult<List<S3Bucket.Metadata>> {
private List<S3Bucket.MetaData> buckets = new ArrayList<S3Bucket.MetaData>();
private S3Bucket.MetaData currentS3Bucket;
private List<S3Bucket.Metadata> buckets = new ArrayList<S3Bucket.Metadata>();
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<S3Bucket.MetaData> getResult() {
public List<S3Bucket.Metadata> 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()));

View File

@ -52,7 +52,7 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult<S3Bucket> {
}
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<S3Bucket> {
} 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

View File

@ -42,7 +42,7 @@ import com.google.inject.Provider;
public class S3ParserFactory {
@Inject
private GenericParseFactory<List<S3Bucket.MetaData>> parseListAllMyBucketsFactory;
private GenericParseFactory<List<S3Bucket.Metadata>> parseListAllMyBucketsFactory;
public static interface GenericParseFactory<T> {
ParseSax<T> create(ParseSax.HandlerWithResult<T> handler);
@ -52,7 +52,7 @@ public class S3ParserFactory {
Provider<ListAllMyBucketsHandler> ListAllMyBucketsHandlerprovider;
@VisibleForTesting
public ParseSax<List<S3Bucket.MetaData>> createListBucketsParser() {
public ParseSax<List<S3Bucket.Metadata>> createListBucketsParser() {
return parseListAllMyBucketsFactory
.create(ListAllMyBucketsHandlerprovider.get());
}
@ -69,13 +69,13 @@ public class S3ParserFactory {
}
@Inject
private GenericParseFactory<S3Object.MetaData> parseCopyObjectFactory;
private GenericParseFactory<S3Object.Metadata> parseCopyObjectFactory;
@Inject
Provider<CopyObjectHandler> copyObjectHandlerProvider;
@VisibleForTesting
public ParseSax<S3Object.MetaData> createCopyObjectParser() {
public ParseSax<S3Object.Metadata> createCopyObjectParser() {
return parseCopyObjectFactory.create(copyObjectHandlerProvider.get());
}

View File

@ -50,18 +50,18 @@ public class S3ParserModule extends AbstractModule {
protected void configure() {
install(new SaxModule());
final TypeLiteral<S3ParserFactory.GenericParseFactory<List<S3Bucket.MetaData>>> listBucketsTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<List<S3Bucket.MetaData>>>() {
final TypeLiteral<S3ParserFactory.GenericParseFactory<List<S3Bucket.Metadata>>> listBucketsTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<List<S3Bucket.Metadata>>>() {
};
final TypeLiteral<S3ParserFactory.GenericParseFactory<S3Bucket>> bucketTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<S3Bucket>>() {
};
final TypeLiteral<S3ParserFactory.GenericParseFactory<S3Object.MetaData>> objectMetaDataTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<S3Object.MetaData>>() {
final TypeLiteral<S3ParserFactory.GenericParseFactory<S3Object.Metadata>> objectMetaDataTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<S3Object.Metadata>>() {
};
final TypeLiteral<S3ParserFactory.GenericParseFactory<S3Error>> errorTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<S3Error>>() {
};
bind(listBucketsTypeLiteral).toProvider(
FactoryProvider.newFactory(listBucketsTypeLiteral,
new TypeLiteral<ParseSax<List<S3Bucket.MetaData>>>() {
new TypeLiteral<ParseSax<List<S3Bucket.Metadata>>>() {
}));
bind(bucketTypeLiteral).toProvider(
FactoryProvider.newFactory(bucketTypeLiteral,
@ -69,7 +69,7 @@ public class S3ParserModule extends AbstractModule {
}));
bind(objectMetaDataTypeLiteral).toProvider(
FactoryProvider.newFactory(objectMetaDataTypeLiteral,
new TypeLiteral<ParseSax<S3Object.MetaData>>() {
new TypeLiteral<ParseSax<S3Object.Metadata>>() {
}));
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<ParseSax.HandlerWithResult<List<S3Bucket.MetaData>>>() {
new TypeLiteral<ParseSax.HandlerWithResult<List<S3Bucket.Metadata>>>() {
}).to(ListAllMyBucketsHandler.class);
bind(new TypeLiteral<ParseSax.HandlerWithResult<S3Bucket>>() {
}).to(ListBucketHandler.class);
bind(new TypeLiteral<ParseSax.HandlerWithResult<S3Object.MetaData>>() {
bind(new TypeLiteral<ParseSax.HandlerWithResult<S3Object.Metadata>>() {
}).to(CopyObjectHandler.class);
bind(new TypeLiteral<ParseSax.HandlerWithResult<S3Error>>() {
}).to(ErrorHandler.class);

View File

@ -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);

View File

@ -1,251 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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<S3Bucket.MetaData> 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);
}
}

View File

@ -89,7 +89,7 @@ public abstract class BaseS3MapTest<T> 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();
}

View File

@ -0,0 +1,72 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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<S3Bucket.Metadata> 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);
}
}

View File

@ -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 = "<apples><apple name=\"fuji\" /></apples>";
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<S3Bucket.MetaData> metaData = client
.getMetaDataOfOwnedBuckets().get(10, TimeUnit.SECONDS);
List<S3Bucket.Metadata> metaData = client
.getOwnedBuckets().get(10, TimeUnit.SECONDS);
List<Future<Boolean>> results = new ArrayList<Future<Boolean>>();
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()));
}

View File

@ -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<S3Object.MetaData> getObjectMetaData(final String s3Bucket,
public Future<S3Object.Metadata> headObject(final String s3Bucket,
final String key) {
return new FutureBase<S3Object.MetaData>() {
public S3Object.MetaData get() throws InterruptedException,
return new FutureBase<S3Object.Metadata>() {
public S3Object.Metadata get() throws InterruptedException,
ExecutionException {
if (!bucketToContents.containsKey(s3Bucket))
return S3Object.MetaData.NOT_FOUND;
return S3Object.Metadata.NOT_FOUND;
Map<String, Object> 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<String> addObject(final String s3Bucket, final S3Object object) {
return new FutureBase<String>() {
public String get() throws InterruptedException, ExecutionException {
public Future<byte[]> putObject(final String s3Bucket, final S3Object object) {
return new FutureBase<byte[]>() {
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<Boolean> createBucketIfNotExists(final String s3Bucket) {
public Future<Boolean> putBucketIfNotExists(final String s3Bucket) {
return new FutureBase<Boolean>() {
public Boolean get() throws InterruptedException,
ExecutionException {
@ -134,20 +137,20 @@ public class StubS3Connection implements S3Connection {
};
}
public Future<S3Object.MetaData> copyObject(final String sourceBucket,
public Future<S3Object.Metadata> copyObject(final String sourceBucket,
final String sourceObject, final String destinationBucket,
final String destinationObject) {
return new FutureBase<S3Object.MetaData>() {
public S3Object.MetaData get() throws InterruptedException,
return new FutureBase<S3Object.Metadata>() {
public S3Object.Metadata get() throws InterruptedException,
ExecutionException {
Map<String, Object> source = bucketToContents.get(sourceBucket);
Map<String, Object> 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<S3Bucket> getBucket(final String s3Bucket) {
public Future<S3Bucket> listBucket(final String s3Bucket) {
return new FutureBase<S3Bucket>() {
public S3Bucket get() throws InterruptedException,
ExecutionException {
Set<S3Object.MetaData> contents = new HashSet<S3Object.MetaData>();
Set<S3Object.Metadata> contents = new HashSet<S3Object.Metadata>();
Map<String, Object> 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<List<MetaData>> getMetaDataOfOwnedBuckets() {
return new FutureBase<List<S3Bucket.MetaData>>() {
public List<S3Bucket.MetaData> get() throws InterruptedException,
public Future<List<Metadata>> getOwnedBuckets() {
return new FutureBase<List<S3Bucket.Metadata>>() {
public List<S3Bucket.Metadata> get() throws InterruptedException,
ExecutionException {
List<S3Bucket.MetaData> list = new ArrayList<S3Bucket.MetaData>();
List<S3Bucket.Metadata> list = new ArrayList<S3Bucket.Metadata>();
for (String name : bucketToContents.keySet())
list.add(new S3Bucket.MetaData(name));
list.add(new S3Bucket.Metadata(name));
return list;
}
};
}
public Future<Boolean> createBucketIfNotExists(String name,
public Future<Boolean> putBucketIfNotExists(String name,
PutBucketOptions options) {
throw new UnsupportedOperationException("todo");
}
public Future<S3Bucket> getBucket(String name, GetBucketOptions options) {
public Future<S3Bucket> listBucket(String name, ListBucketOptions options) {
throw new UnsupportedOperationException("todo");
}
public Future<org.jclouds.aws.s3.domain.S3Object.Metadata> copyObject(
String sourceBucket, String sourceObject, String destinationBucket,
String destinationObject, CopyObjectOptions options) {
// TODO Auto-generated method stub
return null;
}
public Future<byte[]> putObject(String bucketName, S3Object object,
PutObjectOptions options) {
// TODO Auto-generated method stub
return null;
}
public Future<S3Object> getObject(String bucketName, String key,
GetObjectOptions options) {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -0,0 +1,57 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* <p/>
* 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);
}
}

View File

@ -0,0 +1,96 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* <p/>
* 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() {
}
}

View File

@ -0,0 +1,70 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* <p/>
* 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
}
}

View File

@ -0,0 +1,138 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* <p/>
* 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);
}
}

View File

@ -0,0 +1,86 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* <p/>
* 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());
}
}

View File

@ -0,0 +1,143 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* <p/>
* 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());
}
}

View File

@ -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("<a></a>");
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;
}
}

View File

@ -86,7 +86,7 @@ public class S3ParserTest extends PerformanceTest {
runParseListAllMyBuckets();
}
private List<S3Bucket.MetaData> runParseListAllMyBuckets()
private List<S3Bucket.Metadata> 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<List<S3Bucket.MetaData>> completer = new ExecutorCompletionService<List<S3Bucket.MetaData>>(
CompletionService<List<S3Bucket.Metadata>> completer = new ExecutorCompletionService<List<S3Bucket.Metadata>>(
exec);
for (int i = 0; i < LOOP_COUNT; i++)
completer.submit(new Callable<List<S3Bucket.MetaData>>() {
public List<S3Bucket.MetaData> call() throws IOException,
completer.submit(new Callable<List<S3Bucket.Metadata>>() {
public List<S3Bucket.Metadata> call() throws IOException,
SAXException, HttpException {
return runParseListAllMyBuckets();
}
@ -110,13 +110,13 @@ public class S3ParserTest extends PerformanceTest {
@Test
public void testCanParseListAllMyBuckets() throws HttpException {
List<S3Bucket.MetaData> s3Buckets = runParseListAllMyBuckets();
S3Bucket.MetaData bucket1 = s3Buckets.get(0);
List<S3Bucket.Metadata> 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 = "<CopyObjectResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><LastModified>2009-03-19T13:23:27.000Z</LastModified><ETag>\"92836a3ea45a6984d1b4d23a747d46bb\"</ETag></CopyObjectResult>";
private S3Object.MetaData runParseCopyObjectResult() throws HttpException {
ParseSax<S3Object.MetaData> parser = parserFactory
private S3Object.Metadata runParseCopyObjectResult() throws HttpException {
ParseSax<S3Object.Metadata> 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()),

View File

@ -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<String, String> 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));
}
}

View File

@ -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");
}

View File

@ -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(),
"<CreateBucketConfiguration><LocationConstraint>EU</LocationConstraint></CreateBucketConfiguration>");
}
@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<String, String> headers = withBucketAcl(
CannedAccessPolicy.AUTHENTICATED_READ).buildRequestHeaders();
assertEquals(headers.get(S3Headers.CANNED_ACL).iterator().next(),
CannedAccessPolicy.AUTHENTICATED_READ.toString());
}
}

View File

@ -0,0 +1,64 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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<String, String> headers = withAcl(
CannedAccessPolicy.AUTHENTICATED_READ).buildRequestHeaders();
assertEquals(headers.get(S3Headers.CANNED_ACL).iterator().next(),
CannedAccessPolicy.AUTHENTICATED_READ.toString());
}
}

View File

@ -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);
}
}

View File

@ -58,10 +58,10 @@ public class JCloudsServlet extends HttpServlet {
httpServletResponse.setContentType("text/plain");
Writer writer = httpServletResponse.getWriter();
try {
List<S3Bucket.MetaData> myBuckets = context.getConnection()
.getMetaDataOfOwnedBuckets().get(10, TimeUnit.SECONDS);
List<S3Bucket.Metadata> 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()));