mirror of https://github.com/apache/jclouds.git
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:
parent
373f643ce8
commit
8c1861f73d
|
@ -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";
|
||||
|
||||
}
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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!");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
|
@ -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 + "");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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()));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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()),
|
||||
|
|
|
@ -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));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()));
|
||||
|
|
Loading…
Reference in New Issue