mirror of https://github.com/apache/jclouds.git
finished creating integration tests for all functionality needed for beta. fixed bad logging formats, added javadoc
git-svn-id: http://jclouds.googlecode.com/svn/trunk@643 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
parent
589c37ec04
commit
67683084ff
|
@ -73,7 +73,7 @@ public abstract class FutureCommandConnectionHandle<C, O extends FutureCommand<?
|
|||
if (isCompleted()) {
|
||||
return;
|
||||
}
|
||||
logger.trace("%1s - %2d - releasing to pool", conn, conn.hashCode());
|
||||
logger.trace("%1$s - %2$d - releasing to pool", conn, conn.hashCode());
|
||||
available.put(conn);
|
||||
conn = null;
|
||||
command = null;
|
||||
|
@ -85,7 +85,7 @@ public abstract class FutureCommandConnectionHandle<C, O extends FutureCommand<?
|
|||
return;
|
||||
}
|
||||
if (conn != null) {
|
||||
logger.trace("%1s - %2d - cancelled; shutting down connection",
|
||||
logger.trace("%1$s - %2$d - cancelled; shutting down connection",
|
||||
conn, conn.hashCode());
|
||||
try {
|
||||
shutdownConnection();
|
||||
|
|
|
@ -83,23 +83,23 @@ public abstract class FutureCommandConnectionPool<C, O extends FutureCommand<?,
|
|||
hitBottom = available.size() == 0
|
||||
&& allConnections.availablePermits() == 0;
|
||||
if (hitBottom)
|
||||
logger.warn("%1s - saturated connection pool", this);
|
||||
logger.warn("%1$s - saturated connection pool", this);
|
||||
}
|
||||
logger
|
||||
.debug(
|
||||
"%1s - attempting to acquire connection; %d currently available",
|
||||
"%1$s - attempting to acquire connection; %d currently available",
|
||||
this, available.size());
|
||||
C conn = available.poll(5, TimeUnit.SECONDS);
|
||||
if (conn == null)
|
||||
throw new TimeoutException(
|
||||
"could not obtain a pooled connection within 5 seconds");
|
||||
|
||||
logger.trace("%1s - %2d - aquired", conn, conn.hashCode());
|
||||
logger.trace("%1$s - %2$d - aquired", conn, conn.hashCode());
|
||||
if (connectionValid(conn)) {
|
||||
logger.debug("%1s - %2d - reusing", conn, conn.hashCode());
|
||||
logger.debug("%1$s - %2$d - reusing", conn, conn.hashCode());
|
||||
return conn;
|
||||
} else {
|
||||
logger.debug("%1s - %2d - unusable", conn, conn.hashCode());
|
||||
logger.debug("%1$s - %2$d - unusable", conn, conn.hashCode());
|
||||
shutdownConnection(conn);
|
||||
allConnections.release();
|
||||
return getConnection();
|
||||
|
@ -130,7 +130,7 @@ public abstract class FutureCommandConnectionPool<C, O extends FutureCommand<?,
|
|||
O command = getCommandFromConnection(connection);
|
||||
if (command != null) {
|
||||
if (isReplayable(command)) {
|
||||
logger.info("resubmitting command: %1s", command);
|
||||
logger.info("resubmitting command: %1$s", command);
|
||||
commandQueue.add(command);
|
||||
} else {
|
||||
command.setException(e);
|
||||
|
@ -151,7 +151,7 @@ public abstract class FutureCommandConnectionPool<C, O extends FutureCommand<?,
|
|||
protected void setExceptionOnCommand(C connection, Exception e) {
|
||||
FutureCommand<?, ?, ?> command = getCommandFromConnection(connection);
|
||||
if (command != null) {
|
||||
logger.warn(e, "exception in command: %1s", command);
|
||||
logger.warn(e, "exception in command: %1$s", command);
|
||||
command.setException(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,13 +104,13 @@ public class FutureCommandConnectionPoolClient<C, O extends FutureCommand<?, ?,
|
|||
logger
|
||||
.warn(
|
||||
e,
|
||||
"Interrupted getting a connection for command %1s; retrying",
|
||||
"Interrupted getting a connection for command %1$s; retrying",
|
||||
command);
|
||||
commandQueue.add(command);
|
||||
return;
|
||||
} catch (TimeoutException e) {
|
||||
logger.warn(e,
|
||||
"Timeout getting a connection for command %1s; retrying",
|
||||
"Timeout getting a connection for command %1$s; retrying",
|
||||
command);
|
||||
commandQueue.add(command);
|
||||
return;
|
||||
|
@ -118,7 +118,7 @@ public class FutureCommandConnectionPoolClient<C, O extends FutureCommand<?, ?,
|
|||
|
||||
if (connectionHandle == null) {
|
||||
logger.error(
|
||||
"Failed to obtain connection for command %1s; retrying",
|
||||
"Failed to obtain connection for command %1$s; retrying",
|
||||
command);
|
||||
commandQueue.add(command);
|
||||
return;
|
||||
|
|
|
@ -64,7 +64,7 @@ public abstract class BaseHttpFutureCommandClient implements HttpFutureCommandC
|
|||
HttpResponse response) {
|
||||
int code = response.getStatusCode();
|
||||
if (command.getRequest().isReplayable() && code >= 500) {
|
||||
logger.info("resubmitting command: %1s", command);
|
||||
logger.info("resubmitting command: %1$s", command);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -25,7 +25,7 @@ package org.jclouds.http;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jclouds.Utils;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -34,9 +34,13 @@ import org.apache.commons.io.IOUtils;
|
|||
public class CloseContentAndSetExceptionHandler implements HttpResponseHandler {
|
||||
|
||||
public void handle(HttpFutureCommand<?> command, HttpResponse response) {
|
||||
String message = String.format("Command: %2s failed; response: %1s",
|
||||
response, command);
|
||||
command.setException(new IOException(message));
|
||||
IOUtils.closeQuietly(response.getContent());
|
||||
String content;
|
||||
try {
|
||||
content = Utils.toStringAndClose(response.getContent());
|
||||
command.setException(new HttpResponseException(command, response,
|
||||
content));
|
||||
} catch (IOException e) {
|
||||
command.setException(new HttpResponseException(command, response));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,5 +78,12 @@ public interface HttpHeaders {
|
|||
public static final String TRANSFER_ENCODING = "Transfer-Encoding";
|
||||
public static final String LAST_MODIFIED = "Last-Modified";
|
||||
public static final String SERVER = "Server";
|
||||
public static final String ETAG = "ETag";
|
||||
public static final String RANGE = "Range";
|
||||
public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
|
||||
public static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since";
|
||||
public static final String IF_MATCH = "If-Match";
|
||||
public static final String IF_NONE_MATCH = "If-None-Match";
|
||||
public static final String CONTENT_RANGE = "Content-Range";
|
||||
|
||||
}
|
|
@ -74,7 +74,7 @@ public class HttpRequest extends HttpMessage {
|
|||
public boolean isReplayable() {
|
||||
Object content = getPayload();
|
||||
if (content != null && content instanceof InputStream) {
|
||||
logger.warn("%1s: InputStreams are not replayable", toString());
|
||||
logger.warn("%1$s: InputStreams are not replayable", toString());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
package org.jclouds.http;
|
||||
|
||||
/**
|
||||
* Represents an error obtained from an HttpResponse.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public class HttpResponseException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
protected final HttpFutureCommand<?> command;
|
||||
protected final HttpResponse response;
|
||||
private String content;
|
||||
|
||||
public HttpResponseException(String message, HttpFutureCommand<?> command,
|
||||
HttpResponse response, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.command = command;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
public HttpResponseException(String message, HttpFutureCommand<?> command,
|
||||
HttpResponse response, String content, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.command = command;
|
||||
this.response = response;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public HttpResponseException(HttpFutureCommand<?> command,
|
||||
HttpResponse response, Throwable cause) {
|
||||
this(String.format("command: %1$s failed with response: %2$s", command,
|
||||
response), command, response, cause);
|
||||
}
|
||||
|
||||
public HttpResponseException(HttpFutureCommand<?> command,
|
||||
HttpResponse response, String content, Throwable cause) {
|
||||
this(String.format(
|
||||
"command: %1$s failed with response: %2$s; content: [%3$s]",
|
||||
command, response), command, response, content, cause);
|
||||
}
|
||||
|
||||
public HttpResponseException(String message, HttpFutureCommand<?> command,
|
||||
HttpResponse response) {
|
||||
super(message);
|
||||
this.command = command;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
public HttpResponseException(String message, HttpFutureCommand<?> command,
|
||||
HttpResponse response, String content) {
|
||||
super(message);
|
||||
this.command = command;
|
||||
this.response = response;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public HttpResponseException(HttpFutureCommand<?> command,
|
||||
HttpResponse response) {
|
||||
this(String.format("command: %1$s failed with response: %2$s", command,
|
||||
response), command, response);
|
||||
}
|
||||
|
||||
public HttpResponseException(HttpFutureCommand<?> command,
|
||||
HttpResponse response, String content) {
|
||||
this(String.format(
|
||||
"command: %1$s failed with response: %2$s; content: [%3$s]",
|
||||
command, response, content), command, response, content);
|
||||
}
|
||||
|
||||
public HttpFutureCommand<?> getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public HttpResponse getResponse() {
|
||||
return response;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
}
|
|
@ -59,13 +59,13 @@ public class JavaUrlHttpFutureCommandClient extends BaseHttpFutureCommandClient
|
|||
for (HttpRequestFilter filter : requestFilters) {
|
||||
filter.filter(request);
|
||||
}
|
||||
logger.trace("%1s - converting request %2s", target, request);
|
||||
logger.trace("%1$s - converting request %2$s", target, request);
|
||||
connection = openJavaConnection(request);
|
||||
logger
|
||||
.trace("%1s - submitting request %2s", target,
|
||||
.trace("%1$s - submitting request %2$s", target,
|
||||
connection);
|
||||
response = getResponse(connection);
|
||||
logger.trace("%1s - received response %2s", target, response);
|
||||
logger.trace("%1$s - received response %2$s", target, response);
|
||||
if (isRetryable(command, response))
|
||||
continue;
|
||||
break;
|
||||
|
|
|
@ -56,13 +56,13 @@ public class ReturnStringIf200 extends
|
|||
toReturn = Utils.toStringAndClose(entity);
|
||||
} catch (IOException e) {
|
||||
throw new HttpException(String.format(
|
||||
"Couldn't receive response %1s, entity: %2s ",
|
||||
"Couldn't receive response %1$s, entity: %2$s ",
|
||||
getResponse(), toReturn), e);
|
||||
}
|
||||
return toReturn;
|
||||
} else {
|
||||
throw new HttpException(String.format(
|
||||
"Unhandled status code - %1s", getResponse()));
|
||||
"Unhandled status code - %1$s", getResponse()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -70,7 +70,7 @@ public abstract class BaseLifeCycle implements Runnable, LifeCycle {
|
|||
this.status = Status.SHUTTING_DOWN;
|
||||
doShutdown();
|
||||
this.status = Status.SHUT_DOWN;
|
||||
logger.info("%1s", this);
|
||||
logger.info("%1$s", this);
|
||||
}
|
||||
|
||||
protected abstract void doWork() throws Exception;
|
||||
|
@ -88,7 +88,7 @@ public abstract class BaseLifeCycle implements Runnable, LifeCycle {
|
|||
|
||||
@PostConstruct
|
||||
public void start() {
|
||||
logger.info("starting %1s", this);
|
||||
logger.info("starting %1$s", this);
|
||||
synchronized (this.statusLock) {
|
||||
if (this.status.compareTo(Status.SHUTDOWN_REQUEST) >= 0) {
|
||||
doShutdown();
|
||||
|
@ -116,7 +116,7 @@ public abstract class BaseLifeCycle implements Runnable, LifeCycle {
|
|||
for (BaseLifeCycle dependency : dependencies) {
|
||||
if (dependency.status.compareTo(Status.ACTIVE) != 0) {
|
||||
throw new IllegalStateException(String.format(
|
||||
"Illegal state: %1s for component: %2s",
|
||||
"Illegal state: %1$s for component: %2$s",
|
||||
dependency.status, dependency));
|
||||
}
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ public abstract class BaseLifeCycle implements Runnable, LifeCycle {
|
|||
|
||||
protected void exceptionIfNotActive() {
|
||||
if (!status.equals(Status.ACTIVE))
|
||||
throw new IllegalStateException(String.format("not active: %1s",
|
||||
throw new IllegalStateException(String.format("not active: %1$s",
|
||||
this));
|
||||
}
|
||||
|
||||
|
|
|
@ -165,7 +165,7 @@ public abstract class BaseHttpFutureCommandClientTest {
|
|||
get.getRequest().getHeaders().put("filterme", "filterme");
|
||||
client.submit(get);
|
||||
assert get.get(10, TimeUnit.SECONDS).trim().equals("test") : String
|
||||
.format("expected: [%1s], but got [%2s]", "test", get.get(10,
|
||||
.format("expected: [%1$s], but got [%2$s]", "test", get.get(10,
|
||||
TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,7 @@ public abstract class BaseHttpFutureCommandClientTest {
|
|||
get.getRequest().getHeaders().put("test", "test");
|
||||
client.submit(get);
|
||||
assert get.get(10, TimeUnit.SECONDS).trim().equals("test") : String
|
||||
.format("expected: [%1s], but got [%2s]", "test", get.get(10,
|
||||
.format("expected: [%1$s], but got [%2$s]", "test", get.get(10,
|
||||
TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
|
@ -187,7 +187,7 @@ public abstract class BaseHttpFutureCommandClientTest {
|
|||
assert get != null;
|
||||
client.submit(get);
|
||||
assert get.get(10, TimeUnit.SECONDS).trim().equals(XML) : String
|
||||
.format("expected: [%1s], but got [%2s]", XML, get.get(10,
|
||||
.format("expected: [%1$s], but got [%2$s]", XML, get.get(10,
|
||||
TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ public class HttpNioFutureCommandConnectionHandle extends
|
|||
|
||||
public void startConnection() {
|
||||
conn.getContext().setAttribute("command", command);
|
||||
logger.trace("invoking %1s on connection %2s", command, conn);
|
||||
logger.trace("invoking %1$s on connection %2$s", command, conn);
|
||||
conn.requestOutput();
|
||||
}
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ public class HttpNioFutureCommandConnectionPool extends
|
|||
ioReactor.execute(dispatch);
|
||||
} catch (IOException e) {
|
||||
exception.set(e);
|
||||
logger.error(e, "Error dispatching %1s", dispatch);
|
||||
logger.error(e, "Error dispatching %1$s", dispatch);
|
||||
status = Status.SHUTDOWN_REQUEST;
|
||||
}
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ public class HttpNioFutureCommandConnectionPool extends
|
|||
public void shutdownConnection(NHttpConnection conn) {
|
||||
if (conn.getMetrics().getRequestCount() >= maxConnectionReuse)
|
||||
logger.debug(
|
||||
"%1s - %2d - closing connection due to overuse %1s/%2s",
|
||||
"%1$s - %2$d - closing connection due to overuse %1$s/%2$s",
|
||||
conn, conn.hashCode(), conn.getMetrics().getRequestCount(),
|
||||
maxConnectionReuse);
|
||||
if (conn.getStatus() == NHttpConnection.ACTIVE) {
|
||||
|
@ -155,7 +155,7 @@ public class HttpNioFutureCommandConnectionPool extends
|
|||
boolean acquired = allConnections.tryAcquire(1, TimeUnit.SECONDS);
|
||||
if (acquired) {
|
||||
if (shouldDoWork()) {
|
||||
logger.debug("%1s - opening new connection", target);
|
||||
logger.debug("%1$s - opening new connection", target);
|
||||
ioReactor.connect(target, null, null, sessionCallback);
|
||||
} else {
|
||||
allConnections.release();
|
||||
|
@ -181,13 +181,13 @@ public class HttpNioFutureCommandConnectionPool extends
|
|||
SessionRequestCallback {
|
||||
|
||||
public void completed(SessionRequest request) {
|
||||
logger.trace("%1s->%2s[%3s] - SessionRequest complete", request
|
||||
logger.trace("%1$s->%2$s[%3$s] - SessionRequest complete", request
|
||||
.getLocalAddress(), request.getRemoteAddress(), request
|
||||
.getAttachment());
|
||||
}
|
||||
|
||||
public void cancelled(SessionRequest request) {
|
||||
logger.trace("%1s->%2s[%3s] - SessionRequest cancelled", request
|
||||
logger.trace("%1$s->%2$s[%3$s] - SessionRequest cancelled", request
|
||||
.getLocalAddress(), request.getRemoteAddress(), request
|
||||
.getAttachment());
|
||||
releaseConnectionAndCancelResponse(request);
|
||||
|
@ -198,7 +198,7 @@ public class HttpNioFutureCommandConnectionPool extends
|
|||
FutureCommand<?, ?, ?> frequest = (FutureCommand<?, ?, ?>) request
|
||||
.getAttachment();
|
||||
if (frequest != null) {
|
||||
logger.error("%1s->%2s[%3s] - Cancelling FutureCommand",
|
||||
logger.error("%1$s->%2$s[%3$s] - Cancelling FutureCommand",
|
||||
request.getLocalAddress(), request.getRemoteAddress(),
|
||||
frequest);
|
||||
frequest.cancel(true);
|
||||
|
@ -212,7 +212,7 @@ public class HttpNioFutureCommandConnectionPool extends
|
|||
.getAttachment();
|
||||
if (frequest != null) {
|
||||
logger.error(e,
|
||||
"%1s->%2s[%3s] - Setting Exception on FutureCommand",
|
||||
"%1$s->%2$s[%3$s] - Setting Exception on FutureCommand",
|
||||
request.getLocalAddress(), request.getRemoteAddress(),
|
||||
frequest);
|
||||
frequest.setException(e);
|
||||
|
@ -221,7 +221,7 @@ public class HttpNioFutureCommandConnectionPool extends
|
|||
|
||||
public void failed(SessionRequest request) {
|
||||
int count = currentSessionFailures.getAndIncrement();
|
||||
logger.warn("%1s->%2s[%3s] - SessionRequest failed", request
|
||||
logger.warn("%1$s->%2$s[%3$s] - SessionRequest failed", request
|
||||
.getLocalAddress(), request.getRemoteAddress(), request
|
||||
.getAttachment());
|
||||
releaseConnectionAndSetResponseException(request, request
|
||||
|
@ -230,7 +230,7 @@ public class HttpNioFutureCommandConnectionPool extends
|
|||
logger
|
||||
.error(
|
||||
request.getException(),
|
||||
"%1s->%2s[%3s] - SessionRequest failures: %4s, Disabling pool for %5s",
|
||||
"%1$s->%2$s[%3$s] - SessionRequest failures: %4$s, Disabling pool for %5$s",
|
||||
request.getLocalAddress(), request
|
||||
.getRemoteAddress(),
|
||||
maxSessionFailures, target);
|
||||
|
@ -240,7 +240,7 @@ public class HttpNioFutureCommandConnectionPool extends
|
|||
}
|
||||
|
||||
public void timeout(SessionRequest request) {
|
||||
logger.warn("%1s->%2s[%3s] - SessionRequest timeout", request
|
||||
logger.warn("%1$s->%2$s[%3$s] - SessionRequest timeout", request
|
||||
.getLocalAddress(), request.getRemoteAddress(), request
|
||||
.getAttachment());
|
||||
releaseConnectionAndCancelResponse(request);
|
||||
|
@ -251,28 +251,28 @@ public class HttpNioFutureCommandConnectionPool extends
|
|||
public void connectionOpen(NHttpConnection conn) {
|
||||
conn.setSocketTimeout(0);
|
||||
available.offer(conn);
|
||||
logger.trace("%1s - %2d - open", conn, conn.hashCode());
|
||||
logger.trace("%1$s - %2$d - open", conn, conn.hashCode());
|
||||
}
|
||||
|
||||
public void connectionTimeout(NHttpConnection conn) {
|
||||
String message = String.format("%1s - %2d - timeout %2d", conn, conn
|
||||
String message = String.format("%1$s - %2$d - timeout %2$d", conn, conn
|
||||
.hashCode(), conn.getSocketTimeout());
|
||||
logger.warn(message);
|
||||
resubmitIfRequestIsReplayable(conn, new TimeoutException(message));
|
||||
}
|
||||
|
||||
public void connectionClosed(NHttpConnection conn) {
|
||||
logger.trace("%1s - %2d - closed", conn, conn.hashCode());
|
||||
logger.trace("%1$s - %2$d - closed", conn, conn.hashCode());
|
||||
}
|
||||
|
||||
public void fatalIOException(IOException ex, NHttpConnection conn) {
|
||||
logger.error(ex, "%3s-%1d{%2s} - io error", conn, conn.hashCode(),
|
||||
logger.error(ex, "%3$s-%1$d{%2$s} - io error", conn, conn.hashCode(),
|
||||
target);
|
||||
resubmitIfRequestIsReplayable(conn, ex);
|
||||
}
|
||||
|
||||
public void fatalProtocolException(HttpException ex, NHttpConnection conn) {
|
||||
logger.error(ex, "%3s-%1d{%2s} - http error", conn, conn.hashCode(),
|
||||
logger.error(ex, "%3$s-%1$d{%2$s} - http error", conn, conn.hashCode(),
|
||||
target);
|
||||
setExceptionOnCommand(conn, ex);
|
||||
}
|
||||
|
|
|
@ -134,13 +134,13 @@ public class HttpNioFutureCommandExecutionHandler implements
|
|||
}
|
||||
} else {
|
||||
throw new IllegalStateException(String.format(
|
||||
"No command-handle associated with command %1s", context));
|
||||
"No command-handle associated with command %1$s", context));
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isRetryable(HttpFutureCommand<?> command) {
|
||||
if (command.getRequest().isReplayable()) {
|
||||
logger.info("resubmitting command: %1s", command);
|
||||
logger.info("resubmitting command: %1$s", command);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -151,14 +151,14 @@ public class HttpNioFutureCommandExecutionHandler implements
|
|||
try {
|
||||
handle.release();
|
||||
} catch (InterruptedException e) {
|
||||
logger.error(e, "Interrupted releasing handle %1s", handle);
|
||||
logger.error(e, "Interrupted releasing handle %1$s", handle);
|
||||
}
|
||||
}
|
||||
|
||||
protected void processResponse(org.jclouds.http.HttpResponse response,
|
||||
HttpFutureCommand<?> command) throws IOException {
|
||||
command.getResponseFuture().setResponse(response);
|
||||
logger.trace("submitting response task %1s", command
|
||||
logger.trace("submitting response task %1$s", command
|
||||
.getResponseFuture());
|
||||
executor.submit(command.getResponseFuture());
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ public class HttpNioFutureCommandExecutionHandler implements
|
|||
try {
|
||||
handle.cancel();
|
||||
} catch (Exception e) {
|
||||
logger.error(e, "Error cancelling handle %1s", handle);
|
||||
logger.error(e, "Error cancelling handle %1$s", handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,7 +140,8 @@ public class JCloudsS3Service extends S3Service {
|
|||
} catch (Exception e) {
|
||||
Utils.<S3ServiceException> rethrowIfRuntimeOrSameType(e);
|
||||
throw new S3ServiceException(String.format(
|
||||
"error deleting object: %1s:%2s", bucketName, objectKey), e);
|
||||
"error deleting object: %1$s:%2$s", bucketName, objectKey),
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,16 +209,16 @@ public class JCloudsS3Service extends S3Service {
|
|||
protected S3Bucket[] listAllBucketsImpl() throws S3ServiceException {
|
||||
try {
|
||||
List<org.jclouds.aws.s3.domain.S3Bucket.Metadata> jcBucketList = connection
|
||||
.getOwnedBuckets().get(
|
||||
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
|
||||
.listOwnedBuckets().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) {
|
||||
org.jets3t.service.model.S3Bucket jsBucket = new org.jets3t.service.model.S3Bucket(
|
||||
jcBucket.getName());
|
||||
jsBucket.setOwner(new org.jets3t.service.model.S3Owner(jcBucket
|
||||
.getCanonicalUser().getId(), jcBucket
|
||||
.getCanonicalUser().getDisplayName()));
|
||||
.getOwner().getId(), jcBucket.getOwner()
|
||||
.getDisplayName()));
|
||||
jsBucketList.add(jsBucket);
|
||||
}
|
||||
return (org.jets3t.service.model.S3Bucket[]) jsBucketList
|
||||
|
|
|
@ -184,7 +184,7 @@ public class JCloudsS3ServiceTest extends S3IntegrationTest {
|
|||
S3Bucket[] jsBuckets = service.listAllBuckets();
|
||||
|
||||
List<org.jclouds.aws.s3.domain.S3Bucket.Metadata> jcBuckets = client
|
||||
.getOwnedBuckets().get(10, TimeUnit.SECONDS);
|
||||
.listOwnedBuckets().get(10, TimeUnit.SECONDS);
|
||||
|
||||
assert jsBuckets.length == jcBuckets.size();
|
||||
|
||||
|
@ -197,9 +197,9 @@ public class JCloudsS3ServiceTest extends S3IntegrationTest {
|
|||
.next();
|
||||
assert jsBucket.getName().equals(jcBucket.getName());
|
||||
assert jsBucket.getOwner().getId().equals(
|
||||
jcBucket.getCanonicalUser().getId());
|
||||
jcBucket.getOwner().getId());
|
||||
assert jsBucket.getOwner().getDisplayName().equals(
|
||||
jcBucket.getCanonicalUser().getDisplayName());
|
||||
jcBucket.getOwner().getDisplayName());
|
||||
}
|
||||
|
||||
client.deleteBucketIfEmpty(bucketName);
|
||||
|
|
|
@ -31,12 +31,13 @@ import java.util.Map;
|
|||
import java.util.TreeMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.jclouds.aws.s3.S3Constants;
|
||||
import org.jclouds.aws.s3.reference.S3Constants;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Optional;
|
||||
import org.testng.annotations.Parameters;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
||||
/**
|
||||
* Runs operations that amazon s3 sample code is capable of performing.
|
||||
*
|
||||
|
|
|
@ -56,7 +56,7 @@ public abstract class BaseJCloudsPerformance extends BasePerformance {
|
|||
String contentType) throws Exception {
|
||||
org.jclouds.aws.s3.domain.S3Object object = new org.jclouds.aws.s3.domain.S3Object(
|
||||
key);
|
||||
object.getMetaData().setContentType(contentType);
|
||||
object.getMetadata().setContentType(contentType);
|
||||
object.setData(data);
|
||||
return client.putObject(bucket, object).get(120, TimeUnit.SECONDS) != null;
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ public abstract class BaseJCloudsPerformance extends BasePerformance {
|
|||
String contentType) throws Exception {
|
||||
org.jclouds.aws.s3.domain.S3Object object = new org.jclouds.aws.s3.domain.S3Object(
|
||||
key);
|
||||
object.getMetaData().setContentType(contentType);
|
||||
object.getMetadata().setContentType(contentType);
|
||||
object.setData(data);
|
||||
return client.putObject(bucket, object).get(120, TimeUnit.SECONDS) != null;
|
||||
}
|
||||
|
@ -76,9 +76,9 @@ public abstract class BaseJCloudsPerformance extends BasePerformance {
|
|||
InputStream data, String contentType) throws Exception {
|
||||
org.jclouds.aws.s3.domain.S3Object object = new org.jclouds.aws.s3.domain.S3Object(
|
||||
key);
|
||||
object.getMetaData().setContentType(contentType);
|
||||
object.getMetadata().setContentType(contentType);
|
||||
object.setData(data);
|
||||
object.getMetaData().setSize(data.available());
|
||||
object.getMetadata().setSize(data.available());
|
||||
return client.putObject(bucket, object).get(120, TimeUnit.SECONDS) != null;
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ public abstract class BaseJCloudsPerformance extends BasePerformance {
|
|||
String contentType) throws Exception {
|
||||
org.jclouds.aws.s3.domain.S3Object object = new org.jclouds.aws.s3.domain.S3Object(
|
||||
key);
|
||||
object.getMetaData().setContentType(contentType);
|
||||
object.getMetadata().setContentType(contentType);
|
||||
object.setData(data);
|
||||
return client.putObject(bucket, object).get(120, TimeUnit.SECONDS) != null;
|
||||
}
|
||||
|
|
|
@ -36,14 +36,15 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.jclouds.aws.s3.S3Constants;
|
||||
import org.jclouds.aws.s3.S3IntegrationTest;
|
||||
import org.jclouds.aws.s3.reference.S3Constants;
|
||||
import org.testng.annotations.AfterTest;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Optional;
|
||||
import org.testng.annotations.Parameters;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
||||
import com.google.inject.Provider;
|
||||
|
||||
/**
|
||||
|
@ -256,7 +257,7 @@ public abstract class BasePerformance extends S3IntegrationTest {
|
|||
// }
|
||||
// for (Future<Boolean> isdeleted : deletes)
|
||||
// assert isdeleted.get(10,TimeUnit.SECONDS) :
|
||||
// String.format("failed to delete %1s",
|
||||
// String.format("failed to delete %1$ss",
|
||||
// isdeleted);
|
||||
// return
|
||||
// clientProvider.get(10,TimeUnit.SECONDS).deleteBucket(bucket).get(10,TimeUnit.SECONDS);
|
||||
|
|
|
@ -26,7 +26,7 @@ package com.amazon.s3;
|
|||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import org.jclouds.aws.PerformanceTest;
|
||||
import org.jclouds.aws.s3.DateService;
|
||||
import org.jclouds.aws.s3.util.DateService;
|
||||
import org.joda.time.DateTime;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ public class S3ParserTest extends org.jclouds.aws.s3.commands.S3ParserTest {
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
@Test(enabled = false)
|
||||
public void testAmazonCanParseListAllMyBuckets() throws IOException {
|
||||
ListAllMyBucketsResponse response = runAmazonParseListAllMyBuckets();
|
||||
List<Bucket> buckets = response.entries;
|
||||
|
|
|
@ -42,63 +42,79 @@ import org.jclouds.aws.s3.domain.S3Object;
|
|||
* during processing will be wrapped in an {@link ExecutionException} as
|
||||
* documented in {@link Future#get()}.
|
||||
*
|
||||
* @see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAPI.html
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public interface S3Connection {
|
||||
|
||||
/**
|
||||
* Retrieves the object and metadata associated with the key.
|
||||
* Retrieve a complete <code>S3Object</code>.
|
||||
*
|
||||
* @see GetObject
|
||||
* @param bucketName
|
||||
* namespace of the object you are retrieving
|
||||
*
|
||||
* @param key
|
||||
* unique key in the s3Bucket identifying the object
|
||||
* @return fully populated S3Object containing data stored in S3
|
||||
* @return Future reference to a fully populated S3Object including data
|
||||
* stored in S3 or {@link S3Object#NOT_FOUND} if not present.
|
||||
*/
|
||||
Future<S3Object> getObject(String bucketName, String key);
|
||||
|
||||
/**
|
||||
* Retrieves the object and metadata associated with the key.
|
||||
* Like {@link #getObject(String, String)} except you can use
|
||||
* {@link GetObjectOptions} to control delivery.
|
||||
*
|
||||
* @param bucketName
|
||||
* namespace of the object you are retrieving
|
||||
* @see #getObject(String, String)
|
||||
* @see GetObjectOptions
|
||||
* @return S3Object containing data relevant to the
|
||||
* <code>options</options> specified or {@link S3Object#NOT_FOUND} if not present.
|
||||
*
|
||||
* @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
|
||||
* @throws HttpResponseException
|
||||
* if the conditions requested set were not satisfied by the
|
||||
* object on the server.
|
||||
*/
|
||||
Future<S3Object> getObject(String bucketName, String key,
|
||||
GetObjectOptions options);
|
||||
|
||||
/**
|
||||
* Retrieves the metadata of the object associated with the key.
|
||||
* Retrieves the {@link S3Object.Metadata metadata} of the object associated
|
||||
* with the key.
|
||||
*
|
||||
* @see HeadObject
|
||||
* @param bucketName
|
||||
* namespace of the metadata you are retrieving
|
||||
*
|
||||
* @param key
|
||||
* unique key in the s3Bucket identifying the object
|
||||
* @return metadata associated with the key
|
||||
* @return metadata associated with the key or
|
||||
* {@link S3Object.Metadata#NOT_FOUND} if not present;
|
||||
*/
|
||||
Future<S3Object.Metadata> headObject(String bucketName, String key);
|
||||
|
||||
/**
|
||||
* Removes the object and metadata associated with the key.
|
||||
*
|
||||
* @see DeleteObject
|
||||
* @param bucketName
|
||||
* namespace of the object you are deleting
|
||||
* @param key
|
||||
* unique key in the s3Bucket identifying the object
|
||||
* @return true if deleted
|
||||
* @throws HttpResponseException
|
||||
* if the bucket is not available
|
||||
*/
|
||||
Future<Boolean> deleteObject(String bucketName, String key);
|
||||
|
||||
/**
|
||||
* Store data by creating or overwriting an object.
|
||||
* <p/>
|
||||
* This method will store the object with the default <code>private</code>
|
||||
* acl.
|
||||
*
|
||||
* @see CannedAccessPolicy#PRIVATE
|
||||
* @see PutObject
|
||||
* @param bucketName
|
||||
* namespace of the object you are storing
|
||||
* @param object
|
||||
|
@ -108,15 +124,19 @@ public interface S3Connection {
|
|||
Future<byte[]> putObject(String bucketName, S3Object object);
|
||||
|
||||
/**
|
||||
* Store data by creating or overwriting an object.
|
||||
* Like {@link #putObject(String, S3Object)} except you can use
|
||||
* {@link CopyObjectOptions} to specify an alternate
|
||||
* {@link CannedAccessPolicy acl}, override
|
||||
* {@link S3Object.Metadata#getUserMetadata() userMetadata}, or specify
|
||||
* conditions for copying the object.
|
||||
*
|
||||
* @param bucketName
|
||||
* namespace of the object you are storing
|
||||
* @param object
|
||||
* contains the data and metadata to create or overwrite
|
||||
* @see S3Connection#putObject(String, S3Object)
|
||||
* @see PutObjectOptions
|
||||
* @param options
|
||||
* options for creating the object
|
||||
* @return MD5 hash of the content uploaded
|
||||
* @throws HttpResponseException
|
||||
* if the conditions requested set are not satisfied by the
|
||||
* object on the server.
|
||||
*/
|
||||
Future<byte[]> putObject(String bucketName, S3Object object,
|
||||
PutObjectOptions options);
|
||||
|
@ -124,23 +144,25 @@ public interface S3Connection {
|
|||
/**
|
||||
* Create and name your own bucket in which to store your objects.
|
||||
*
|
||||
* @return true, if the bucket was created
|
||||
* @see PutBucket
|
||||
* @return true, if the bucket was created or already exists
|
||||
*/
|
||||
Future<Boolean> putBucketIfNotExists(String name);
|
||||
|
||||
/**
|
||||
* Create and name your own bucket in which to store your objects.
|
||||
* Like {@link #putBucketIfNotExists(String)} except that you can use
|
||||
* {@link PutBucketOptions} to create the bucket in EU. Create and name your
|
||||
*
|
||||
* @see PutBucketOptions
|
||||
* @param options
|
||||
* for creating your bucket
|
||||
* @return true, if the bucket was created
|
||||
* @see PutBucketOptions
|
||||
*/
|
||||
Future<Boolean> putBucketIfNotExists(String name, PutBucketOptions options);
|
||||
|
||||
/**
|
||||
* Deletes the bucket, if it is empty.
|
||||
*
|
||||
* @see DeleteBucket
|
||||
* @param s3Bucket
|
||||
* what to delete
|
||||
* @return false, if the bucket was not empty and therefore not deleted
|
||||
|
@ -148,34 +170,68 @@ public interface S3Connection {
|
|||
Future<Boolean> deleteBucketIfEmpty(String s3Bucket);
|
||||
|
||||
/**
|
||||
* Copies one object to another bucket
|
||||
* Copies one object to another bucket, retaining UserMetadata from the
|
||||
* source. The destination will have a private acl.
|
||||
*
|
||||
* @return metaData populated with lastModified and etag of the new object
|
||||
* @see CopyObject
|
||||
* @return metadata populated with lastModified and md5 of the new object
|
||||
*/
|
||||
Future<S3Object.Metadata> copyObject(String sourceBucket,
|
||||
String sourceObject, String destinationBucket,
|
||||
String destinationObject);
|
||||
|
||||
/**
|
||||
* Copies one object to another bucket using the specifid options
|
||||
* Like {@link #putObject(String, S3Object)} except you can use
|
||||
* {@link PutObjectOptions} to specify an alternate
|
||||
* {@link CannedAccessPolicy acl}.
|
||||
*
|
||||
* @return metaData populated with lastModified and etag of the new object
|
||||
* @see CopyObjectOptions
|
||||
* @see S3Connection#putObject(String, S3Object)
|
||||
* @see PutObjectOptions
|
||||
* @param options
|
||||
* options for creating the object
|
||||
* @throws HttpResponseException
|
||||
* if the conditions requested set are not satisfied by the
|
||||
* object on the server.
|
||||
*/
|
||||
Future<S3Object.Metadata> copyObject(String sourceBucket,
|
||||
String sourceObject, String destinationBucket,
|
||||
String destinationObject, CopyObjectOptions options);
|
||||
|
||||
/**
|
||||
* @see HeadBucket
|
||||
*/
|
||||
Future<Boolean> bucketExists(String name);
|
||||
|
||||
/**
|
||||
* Retrieve a complete <code>S3Bucket</code> listing.
|
||||
*
|
||||
* @param s3Bucket
|
||||
* @return
|
||||
* @see ListBucket
|
||||
* @param bucketName
|
||||
* namespace of the objects you wish to list
|
||||
*
|
||||
* @return Future reference to a fully populated S3Bucket including metadata
|
||||
* of the S3Objects it contains or {@link S3Bucket#NOT_FOUND} if not
|
||||
* present.
|
||||
*/
|
||||
Future<S3Bucket> listBucket(String name);
|
||||
Future<S3Bucket> listBucket(String bucketName);
|
||||
|
||||
/**
|
||||
* Like {@link #listBucket(String)} except you can use
|
||||
* {@link ListObjectOptions} to control the amount of S3Objects to return.
|
||||
*
|
||||
* @see #listBucket(String)
|
||||
* @see ListBucketOptions
|
||||
* @return S3Bucket containing a subset of {@link S3Object.Metadata}
|
||||
* depending on
|
||||
* <code>options</options> specified or {@link S3Bucket#NOT_FOUND} if not present.
|
||||
*
|
||||
*/
|
||||
Future<S3Bucket> listBucket(String name, ListBucketOptions options);
|
||||
|
||||
Future<List<S3Bucket.Metadata>> getOwnedBuckets();
|
||||
/**
|
||||
* @see ListOwnedBuckets
|
||||
* @return list of all of the buckets owned by the authenticated sender of
|
||||
* the request.
|
||||
*/
|
||||
Future<List<S3Bucket.Metadata>> listOwnedBuckets();
|
||||
}
|
||||
|
|
|
@ -23,10 +23,24 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3;
|
||||
|
||||
|
||||
/**
|
||||
* Represents an authenticated context to S3.
|
||||
*
|
||||
* <h2>Note</h2> Please issue {@link #close()} when you are finished with this
|
||||
* context in order to release resources.
|
||||
*
|
||||
*
|
||||
* @see S3Connection
|
||||
* @see S3InputStreamMap
|
||||
* @see S3ObjectMap
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public interface S3Context {
|
||||
|
||||
/**
|
||||
* low-level api to S3. Threadsafe implementations will return a singleton.
|
||||
*
|
||||
* @return a connection to S3
|
||||
*/
|
||||
S3Connection getConnection();
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
package org.jclouds.aws.s3;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.jclouds.aws.s3.S3Constants.PROPERTY_AWS_ACCESSKEYID;
|
||||
import static org.jclouds.aws.s3.S3Constants.PROPERTY_AWS_SECRETACCESSKEY;
|
||||
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_AWS_ACCESSKEYID;
|
||||
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_AWS_SECRETACCESSKEY;
|
||||
import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_IO_WORKER_THREADS;
|
||||
import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTIONS;
|
||||
import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTION_REUSE;
|
||||
|
@ -58,7 +58,17 @@ import com.google.inject.name.Names;
|
|||
/**
|
||||
* Creates {@link S3Context} or {@link Injector} instances based on the most
|
||||
* commonly requested arguments.
|
||||
* <p/>
|
||||
* Note that Threadsafe objects will be bound as singletons to the Injector or
|
||||
* Context provided.
|
||||
*
|
||||
* <p/>
|
||||
* If no <code>Module</code>s are specified, the default
|
||||
* {@link JDKLoggingModule logging} and
|
||||
* {@link JavaUrlHttpFutureCommandClientModule http transports} will be
|
||||
* installed.
|
||||
*
|
||||
* @see S3Context
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class S3ContextFactory {
|
||||
|
|
|
@ -27,7 +27,20 @@ import java.io.File;
|
|||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
public interface S3InputStreamMap extends Map<String, InputStream>, S3Map {
|
||||
/**
|
||||
* Map view of an {@link S3Bucket}. Provides additional methods for inserting
|
||||
* common object types.
|
||||
*
|
||||
* <h2>Note</h2> All <code>put</code> operations will invoke
|
||||
* {@link S3Object#generateMd5}. By extension, {@link #put(String, InputStream)}
|
||||
* will result in the InputStream being converted to a byte array. For this
|
||||
* reason, do not use {@link #put(String, InputStream)} to store files. Use
|
||||
* {@link #putFile(String, File)} or {@link S3ObjectMap} instead.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public interface S3InputStreamMap extends S3Map<String, InputStream> {
|
||||
InputStream putString(String key, String value);
|
||||
|
||||
InputStream putFile(String key, File value);
|
||||
|
|
|
@ -23,10 +23,23 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.aws.s3.domain.S3Bucket;
|
||||
|
||||
public interface S3Map {
|
||||
/**
|
||||
* All Map views of {@link S3Bucket}s provide means to access the underlying S3
|
||||
* object.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public interface S3Map<K, V> extends Map<K, V> {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return s3 bucket listing that this map represents
|
||||
*/
|
||||
S3Bucket getBucket();
|
||||
|
||||
}
|
|
@ -23,10 +23,19 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.aws.s3.domain.S3Bucket;
|
||||
import org.jclouds.aws.s3.domain.S3Object;
|
||||
|
||||
public interface S3ObjectMap extends Map<String, S3Object>, S3Map {
|
||||
/**
|
||||
* Map view of an {@link S3Bucket}.
|
||||
*
|
||||
* <p/>
|
||||
* This allows you to acces the underlying {@link S3Object} so that you can
|
||||
* manually set metadata such as length, content-type, or md5 hash.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public interface S3ObjectMap extends S3Map<String, S3Object> {
|
||||
|
||||
}
|
|
@ -26,31 +26,50 @@ package org.jclouds.aws.s3;
|
|||
import org.jclouds.aws.s3.domain.S3Error;
|
||||
import org.jclouds.http.HttpFutureCommand;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.http.HttpResponseException;
|
||||
|
||||
/**
|
||||
* Encapsulates an S3 Error from Amazon.
|
||||
*
|
||||
* @see http
|
||||
* ://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingRESTError.html
|
||||
* @see S3Error
|
||||
* @see ParseS3ErrorFromXmlContent
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public class S3ResponseException extends HttpResponseException {
|
||||
|
||||
public class S3ResponseException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final HttpFutureCommand<?> command;
|
||||
private final HttpResponse response;
|
||||
private S3Error error;
|
||||
private S3Error error = new S3Error();
|
||||
|
||||
public S3ResponseException(HttpFutureCommand<?> command,
|
||||
HttpResponse response, S3Error error) {
|
||||
super(String.format(
|
||||
"command: %1s failed with response: %2s; error from s3: %3s",
|
||||
command, response, error));
|
||||
this.command = command;
|
||||
this.response = response;
|
||||
super(error.toString(), command, response);
|
||||
this.setError(error);
|
||||
|
||||
}
|
||||
|
||||
public S3ResponseException(HttpFutureCommand<?> command,
|
||||
HttpResponse response) {
|
||||
super(String.format("command: %1s failed with response: %2s", command,
|
||||
response));
|
||||
this.command = command;
|
||||
this.response = response;
|
||||
HttpResponse response, S3Error error, Throwable cause) {
|
||||
super(error.toString(), command, response, cause);
|
||||
this.setError(error);
|
||||
|
||||
}
|
||||
|
||||
public S3ResponseException(String message, HttpFutureCommand<?> command,
|
||||
HttpResponse response, S3Error error) {
|
||||
super(message, command, response);
|
||||
this.setError(error);
|
||||
|
||||
}
|
||||
|
||||
public S3ResponseException(String message, HttpFutureCommand<?> command,
|
||||
HttpResponse response, S3Error error, Throwable cause) {
|
||||
super(message, command, response, cause);
|
||||
this.setError(error);
|
||||
|
||||
}
|
||||
|
||||
public void setError(S3Error error) {
|
||||
|
@ -61,12 +80,4 @@ public class S3ResponseException extends RuntimeException {
|
|||
return error;
|
||||
}
|
||||
|
||||
public HttpFutureCommand<?> getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public HttpResponse getResponse() {
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ import java.util.concurrent.ExecutionException;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.jclouds.aws.s3.S3ResponseException;
|
||||
import org.jclouds.http.HttpResponseException;
|
||||
import org.jclouds.http.commands.callables.ReturnTrueIf2xx;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
@ -37,6 +37,12 @@ import com.google.inject.Inject;
|
|||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.google.inject.name.Named;
|
||||
|
||||
/**
|
||||
* Issues a HEAD command to determine if the bucket exists or not.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public class BucketExists extends S3FutureCommand<Boolean> {
|
||||
|
||||
@Inject
|
||||
|
@ -57,8 +63,9 @@ public class BucketExists extends S3FutureCommand<Boolean> {
|
|||
|
||||
@VisibleForTesting
|
||||
Boolean attemptNotFound(ExecutionException e) throws ExecutionException {
|
||||
if (e.getCause() != null && e.getCause() instanceof S3ResponseException) {
|
||||
S3ResponseException responseException = (S3ResponseException) e
|
||||
if (e.getCause() != null
|
||||
&& e.getCause() instanceof HttpResponseException) {
|
||||
HttpResponseException responseException = (HttpResponseException) e
|
||||
.getCause();
|
||||
if (responseException.getResponse().getStatusCode() == 404) {
|
||||
return false;
|
||||
|
|
|
@ -34,6 +34,25 @@ import com.google.inject.Inject;
|
|||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.google.inject.name.Named;
|
||||
|
||||
/**
|
||||
* The copy operation creates a copy of an object that is already storedin
|
||||
* Amazon S3.
|
||||
* <p/>
|
||||
* When copying an object, you can preserve all metadata (default) or
|
||||
* {@link CopyObjectOptions#overrideMetadataWith(com.google.common.collect.Multimap)
|
||||
* specify new metadata}. However, the ACL is not preserved and is set to
|
||||
* private for the user making the request. To override the default ACL setting,
|
||||
* {@link CopyObjectOptions#overrideAcl(org.jclouds.aws.s3.domain.acl.CannedAccessPolicy)
|
||||
* specify a new ACL} when generating a copy request.
|
||||
*
|
||||
* @see http
|
||||
* ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectCOPY
|
||||
* .html
|
||||
* @see CopyObjectOptions
|
||||
* @see CannedAccessPolicy
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public class CopyObject extends S3FutureCommand<S3Object.Metadata> {
|
||||
|
||||
@Inject
|
||||
|
@ -51,9 +70,9 @@ public class CopyObject extends S3FutureCommand<S3Object.Metadata> {
|
|||
handler.setKey(destinationObject);
|
||||
getRequest().getHeaders().put(
|
||||
"x-amz-copy-source",
|
||||
String.format("/%1s/%2s", checkNotNull(sourceBucket,
|
||||
"sourceBucket"), checkNotNull(
|
||||
sourceObject, "sourceObject")));
|
||||
String.format("/%1$s/%2$s", checkNotNull(sourceBucket,
|
||||
"sourceBucket"), checkNotNull(sourceObject,
|
||||
"sourceObject")));
|
||||
getRequest().getHeaders().putAll(options.buildRequestHeaders());
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.jclouds.aws.s3.S3ResponseException;
|
||||
import org.jclouds.http.HttpResponseException;
|
||||
import org.jclouds.http.commands.callables.ReturnTrueIf2xx;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
@ -35,6 +36,17 @@ import com.google.inject.Inject;
|
|||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.google.inject.name.Named;
|
||||
|
||||
/**
|
||||
* The DELETE request operation deletes the bucket named in the URI. All objects
|
||||
* in the bucket must be deleted before the bucket itself can be deleted.
|
||||
* <p />
|
||||
* Only the owner of a bucket can delete it, regardless of the bucket's access
|
||||
* control policy.
|
||||
*
|
||||
* @see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?
|
||||
* RESTBucketDELETE.html
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class DeleteBucket extends S3FutureCommand<Boolean> {
|
||||
|
||||
@Inject
|
||||
|
@ -54,7 +66,8 @@ public class DeleteBucket extends S3FutureCommand<Boolean> {
|
|||
|
||||
@VisibleForTesting
|
||||
Boolean attemptNotFound(ExecutionException e) throws ExecutionException {
|
||||
if (e.getCause() != null && e.getCause() instanceof S3ResponseException) {
|
||||
if (e.getCause() != null
|
||||
&& e.getCause() instanceof HttpResponseException) {
|
||||
S3ResponseException responseException = (S3ResponseException) e
|
||||
.getCause();
|
||||
if (responseException.getResponse().getStatusCode() == 404) {
|
||||
|
|
|
@ -31,6 +31,14 @@ import com.google.inject.Inject;
|
|||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.google.inject.name.Named;
|
||||
|
||||
/**
|
||||
* The DELETE request operation removes the specified object from Amazon S3.
|
||||
* Once deleted, there is no method to restore or undelete an object.
|
||||
*
|
||||
* @see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?
|
||||
* RESTObjectDELETE.html
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class DeleteObject extends S3FutureCommand<Boolean> {
|
||||
|
||||
@Inject
|
||||
|
|
|
@ -43,8 +43,28 @@ import com.google.inject.name.Named;
|
|||
* Retrieves the S3Object associated with the Key or {@link S3Object#NOT_FOUND}
|
||||
* if not available;
|
||||
*
|
||||
* @author Adrian Cole
|
||||
* <p/>
|
||||
* To use GET, you must have READ access to the object. If READ access is
|
||||
* granted to the anonymous user, you can request the object without an
|
||||
* authorization header.
|
||||
* <p />
|
||||
* <p/>
|
||||
* This command allows you to specify {@link GetObjectOptions} to control
|
||||
* delivery of content.
|
||||
*
|
||||
* <h2>Note</h2> If you specify any of the below options, you will receive
|
||||
* partial content:
|
||||
* <ul>
|
||||
* <li>{@link GetObjectOptions#range}</li>
|
||||
* <li>{@link GetObjectOptions#startAt}</li>
|
||||
* <li>{@link GetObjectOptions#tail}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @see GetObjectOptions
|
||||
* @see http
|
||||
* ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectGET
|
||||
* .html
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class GetObject extends S3FutureCommand<S3Object> {
|
||||
|
||||
|
|
|
@ -29,9 +29,9 @@ import java.util.concurrent.ExecutionException;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.jclouds.aws.s3.S3ResponseException;
|
||||
import org.jclouds.aws.s3.commands.callables.ParseMetadataFromHeaders;
|
||||
import org.jclouds.aws.s3.domain.S3Object;
|
||||
import org.jclouds.http.HttpResponseException;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.inject.Inject;
|
||||
|
@ -40,15 +40,25 @@ 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.
|
||||
*
|
||||
* <p/>
|
||||
* The HEAD operation is used to retrieve information about a specific object or
|
||||
* object size, without actually fetching the object itself. This is useful if
|
||||
* you're only interested in the object metadata, and don't want to waste
|
||||
* bandwidth on the object data.
|
||||
*
|
||||
* @see GetObject
|
||||
* @see http
|
||||
* ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectHEAD
|
||||
* .html
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public class HeadMetaData extends S3FutureCommand<S3Object.Metadata> {
|
||||
public class HeadObject extends S3FutureCommand<S3Object.Metadata> {
|
||||
|
||||
@Inject
|
||||
public HeadMetaData(@Named("jclouds.http.address") String amazonHost,
|
||||
public HeadObject(@Named("jclouds.http.address") String amazonHost,
|
||||
ParseMetadataFromHeaders callable,
|
||||
@Assisted("bucketName") String bucket, @Assisted("key") String key) {
|
||||
super("HEAD", "/" + checkNotNull(key), callable, amazonHost, bucket);
|
||||
|
@ -68,8 +78,9 @@ public class HeadMetaData extends S3FutureCommand<S3Object.Metadata> {
|
|||
@VisibleForTesting
|
||||
S3Object.Metadata attemptNotFound(ExecutionException e)
|
||||
throws ExecutionException {
|
||||
if (e.getCause() != null && e.getCause() instanceof S3ResponseException) {
|
||||
S3ResponseException responseException = (S3ResponseException) e
|
||||
if (e.getCause() != null
|
||||
&& e.getCause() instanceof HttpResponseException) {
|
||||
HttpResponseException responseException = (HttpResponseException) e
|
||||
.getCause();
|
||||
if (responseException.getResponse().getStatusCode() == 404) {
|
||||
return S3Object.Metadata.NOT_FOUND;
|
|
@ -31,6 +31,7 @@ import org.jclouds.aws.s3.S3ResponseException;
|
|||
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.HttpResponseException;
|
||||
import org.jclouds.http.commands.callables.xml.ParseSax;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
@ -38,6 +39,21 @@ import com.google.inject.Inject;
|
|||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.google.inject.name.Named;
|
||||
|
||||
/**
|
||||
* A GET request operation using a bucket URI lists information about the
|
||||
* objects in the bucket.
|
||||
* <p />
|
||||
* To list the keys of a bucket, you must have READ access to the bucket.
|
||||
* <p/>
|
||||
* List output is controllable via {@link ListBucketOptions}
|
||||
*
|
||||
* @see ListBucketOptions
|
||||
* @see http
|
||||
* ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET
|
||||
* .html
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public class ListBucket extends S3FutureCommand<S3Bucket> {
|
||||
|
||||
@Inject
|
||||
|
@ -62,7 +78,8 @@ public class ListBucket extends S3FutureCommand<S3Bucket> {
|
|||
|
||||
@VisibleForTesting
|
||||
S3Bucket attemptNotFound(ExecutionException e) throws ExecutionException {
|
||||
if (e.getCause() != null && e.getCause() instanceof S3ResponseException) {
|
||||
if (e.getCause() != null
|
||||
&& e.getCause() instanceof HttpResponseException) {
|
||||
S3ResponseException responseException = (S3ResponseException) e
|
||||
.getCause();
|
||||
if ("NoSuchBucket".equals(responseException.getError().getCode())) {
|
||||
|
|
|
@ -35,13 +35,16 @@ import com.google.inject.name.Named;
|
|||
* Returns a list of all of the buckets owned by the authenticated sender of the
|
||||
* request.
|
||||
*
|
||||
* @see http
|
||||
* ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTServiceGET
|
||||
* .html
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public class GetMetaDataForOwnedBuckets extends S3FutureCommand<List<S3Bucket.Metadata>> {
|
||||
public class ListOwnedBuckets extends S3FutureCommand<List<S3Bucket.Metadata>> {
|
||||
|
||||
@Inject
|
||||
public GetMetaDataForOwnedBuckets(@Named("jclouds.http.address") String amazonHost,
|
||||
public ListOwnedBuckets(@Named("jclouds.http.address") String amazonHost,
|
||||
ParseSax<List<S3Bucket.Metadata>> callable) {
|
||||
super("GET", "/", callable, amazonHost);
|
||||
}
|
|
@ -23,8 +23,8 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.commands;
|
||||
|
||||
import org.jclouds.aws.s3.S3Utils;
|
||||
import org.jclouds.aws.s3.commands.options.PutBucketOptions;
|
||||
import org.jclouds.aws.s3.util.S3Utils;
|
||||
import org.jclouds.http.HttpHeaders;
|
||||
import org.jclouds.http.commands.callables.ReturnTrueIf2xx;
|
||||
|
||||
|
@ -34,7 +34,16 @@ import com.google.inject.name.Named;
|
|||
|
||||
/**
|
||||
* Create and name your own bucket in which to store your objects.
|
||||
* <p/>
|
||||
* The PUT request operation with a bucket URI creates a new bucket. Depending
|
||||
* on your latency and legal requirements, you can specify a location constraint
|
||||
* that will affect where your data physically resides. You can currently
|
||||
* specify a Europe (EU) location constraint via {@link PutBucketOptions}.
|
||||
*
|
||||
* @see PutBucketOptions
|
||||
* @see http
|
||||
* ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketPUT
|
||||
* .html
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -23,18 +23,36 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.commands;
|
||||
|
||||
import static com.google.common.base.Preconditions.*;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import org.jclouds.aws.s3.S3Utils;
|
||||
import org.jclouds.aws.s3.commands.callables.ParseMd5FromETagHeader;
|
||||
import org.jclouds.aws.s3.commands.options.PutObjectOptions;
|
||||
import org.jclouds.aws.s3.domain.S3Object;
|
||||
import org.jclouds.aws.s3.util.S3Utils;
|
||||
import org.jclouds.http.HttpHeaders;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.google.inject.name.Named;
|
||||
|
||||
/**
|
||||
* Store data by creating or overwriting an object.
|
||||
*
|
||||
* <p/>
|
||||
* This returns a byte[] of the md5 hash of what Amazon S3 received
|
||||
* <p />
|
||||
* <p/>
|
||||
* This command allows you to specify {@link PutObjectOptions} to control
|
||||
* delivery of content.
|
||||
*
|
||||
*
|
||||
* @see PutObjectOptions
|
||||
* @see http
|
||||
* ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectPUT
|
||||
* .html
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class PutObject extends S3FutureCommand<byte[]> {
|
||||
|
||||
@Inject
|
||||
|
@ -43,38 +61,38 @@ public class PutObject extends S3FutureCommand<byte[]> {
|
|||
@Assisted S3Object object, @Assisted PutObjectOptions options) {
|
||||
super("PUT", "/" + checkNotNull(object.getKey()), callable, amazonHost,
|
||||
s3Bucket);
|
||||
checkArgument(object.getMetaData().getSize() >=0,"size must be set");
|
||||
checkArgument(object.getMetadata().getSize() >= 0, "size must be set");
|
||||
|
||||
getRequest().setPayload(
|
||||
checkNotNull(object.getData(), "object.getContent()"));
|
||||
|
||||
getRequest().getHeaders().put(
|
||||
HttpHeaders.CONTENT_TYPE,
|
||||
checkNotNull(object.getMetaData().getContentType(),
|
||||
"object.metaData.contentType()"));
|
||||
checkNotNull(object.getMetadata().getContentType(),
|
||||
"object.metadata.contentType()"));
|
||||
|
||||
getRequest().getHeaders().put(HttpHeaders.CONTENT_LENGTH,
|
||||
object.getMetaData().getSize() + "");
|
||||
object.getMetadata().getSize() + "");
|
||||
|
||||
if (object.getMetaData().getCacheControl() != null) {
|
||||
if (object.getMetadata().getCacheControl() != null) {
|
||||
getRequest().getHeaders().put(HttpHeaders.CACHE_CONTROL,
|
||||
object.getMetaData().getCacheControl());
|
||||
object.getMetadata().getCacheControl());
|
||||
}
|
||||
if (object.getMetaData().getContentDisposition() != null) {
|
||||
if (object.getMetadata().getContentDisposition() != null) {
|
||||
getRequest().getHeaders().put(HttpHeaders.CONTENT_DISPOSITION,
|
||||
object.getMetaData().getContentDisposition());
|
||||
object.getMetadata().getContentDisposition());
|
||||
}
|
||||
if (object.getMetaData().getContentEncoding() != null) {
|
||||
if (object.getMetadata().getContentEncoding() != null) {
|
||||
getRequest().getHeaders().put(HttpHeaders.CONTENT_ENCODING,
|
||||
object.getMetaData().getContentEncoding());
|
||||
object.getMetadata().getContentEncoding());
|
||||
}
|
||||
|
||||
if (object.getMetaData().getMd5() != null)
|
||||
if (object.getMetadata().getMd5() != null)
|
||||
getRequest().getHeaders().put(HttpHeaders.CONTENT_MD5,
|
||||
S3Utils.toBase64String(object.getMetaData().getMd5()));
|
||||
S3Utils.toBase64String(object.getMetadata().getMd5()));
|
||||
|
||||
getRequest().getHeaders()
|
||||
.putAll(object.getMetaData().getUserMetadata());
|
||||
.putAll(object.getMetadata().getUserMetadata());
|
||||
getRequest().getHeaders().putAll(options.buildRequestHeaders());
|
||||
|
||||
}
|
||||
|
|
|
@ -116,23 +116,23 @@ public class S3CommandFactory {
|
|||
}
|
||||
|
||||
@Inject
|
||||
private HeadMetaDataFactory headMetaDataFactory;
|
||||
private HeadMetadataFactory headMetadataFactory;
|
||||
|
||||
public static interface HeadMetaDataFactory {
|
||||
HeadMetaData create(@Assisted("bucketName") String bucket,
|
||||
public static interface HeadMetadataFactory {
|
||||
HeadObject create(@Assisted("bucketName") String bucket,
|
||||
@Assisted("key") String key);
|
||||
}
|
||||
|
||||
public HeadMetaData createHeadMetaData(String bucket, String key) {
|
||||
return headMetaDataFactory.create(bucket, key);
|
||||
public HeadObject createHeadMetadata(String bucket, String key) {
|
||||
return headMetadataFactory.create(bucket, key);
|
||||
}
|
||||
|
||||
@Inject
|
||||
@Named("jclouds.http.address")
|
||||
String amazonHost;
|
||||
|
||||
public GetMetaDataForOwnedBuckets createGetMetaDataForOwnedBuckets() {
|
||||
return new GetMetaDataForOwnedBuckets(amazonHost, parserFactory
|
||||
public ListOwnedBuckets createGetMetadataForOwnedBuckets() {
|
||||
return new ListOwnedBuckets(amazonHost, parserFactory
|
||||
.createListBucketsParser());
|
||||
}
|
||||
|
||||
|
|
|
@ -24,11 +24,12 @@
|
|||
package org.jclouds.aws.s3.commands.callables;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jclouds.aws.s3.S3Headers;
|
||||
import org.jclouds.aws.s3.S3Utils;
|
||||
import org.jclouds.aws.s3.reference.S3Headers;
|
||||
import org.jclouds.aws.s3.util.S3Utils;
|
||||
import org.jclouds.http.HttpException;
|
||||
import org.jclouds.http.HttpFutureCommand;
|
||||
|
||||
|
||||
/**
|
||||
* Parses an MD5 checksum from the header {@link S3Headers#ETAG}.
|
||||
*
|
||||
|
|
|
@ -25,10 +25,11 @@ package org.jclouds.aws.s3.commands.callables;
|
|||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
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.aws.s3.domain.S3Object.Metadata;
|
||||
import org.jclouds.aws.s3.reference.S3Headers;
|
||||
import org.jclouds.aws.s3.util.DateService;
|
||||
import org.jclouds.aws.s3.util.S3Utils;
|
||||
import org.jclouds.http.HttpException;
|
||||
import org.jclouds.http.HttpFutureCommand;
|
||||
import org.jclouds.http.HttpHeaders;
|
||||
|
@ -52,30 +53,36 @@ public class ParseMetadataFromHeaders extends
|
|||
|
||||
/**
|
||||
* parses the http response headers to create a new
|
||||
* {@link S3Object.MetaData} object.
|
||||
* {@link S3Object.Metadata} object.
|
||||
*/
|
||||
public S3Object.Metadata call() throws HttpException {
|
||||
checkCode();
|
||||
|
||||
S3Object.Metadata metaData = new S3Object.Metadata(key);
|
||||
S3Object.Metadata metadata = new S3Object.Metadata(key);
|
||||
addAllHeadersTo(metadata);
|
||||
|
||||
extractUserMetadata(metaData);
|
||||
addMd5(metaData);
|
||||
addUserMetadataTo(metadata);
|
||||
addMd5To(metadata);
|
||||
|
||||
parseLastModifiedOrThrowException(metaData);
|
||||
setContentTypeOrThrowException(metaData);
|
||||
parseLastModifiedOrThrowException(metadata);
|
||||
setContentTypeOrThrowException(metadata);
|
||||
setContentLengthOrThrowException(metadata);
|
||||
|
||||
metaData.setCacheControl(getResponse().getFirstHeaderOrNull(
|
||||
metadata.setCacheControl(getResponse().getFirstHeaderOrNull(
|
||||
HttpHeaders.CACHE_CONTROL));
|
||||
metaData.setContentDisposition(getResponse().getFirstHeaderOrNull(
|
||||
metadata.setContentDisposition(getResponse().getFirstHeaderOrNull(
|
||||
HttpHeaders.CONTENT_DISPOSITION));
|
||||
metaData.setContentEncoding(getResponse().getFirstHeaderOrNull(
|
||||
metadata.setContentEncoding(getResponse().getFirstHeaderOrNull(
|
||||
HttpHeaders.CONTENT_ENCODING));
|
||||
return metaData;
|
||||
return metadata;
|
||||
|
||||
}
|
||||
|
||||
private void setContentTypeOrThrowException(S3Object.Metadata metaData)
|
||||
private void addAllHeadersTo(Metadata metadata) {
|
||||
metadata.getAllHeaders().putAll(getResponse().getHeaders());
|
||||
}
|
||||
|
||||
private void setContentTypeOrThrowException(S3Object.Metadata metadata)
|
||||
throws HttpException {
|
||||
String contentType = getResponse().getFirstHeaderOrNull(
|
||||
HttpHeaders.CONTENT_TYPE);
|
||||
|
@ -83,39 +90,50 @@ public class ParseMetadataFromHeaders extends
|
|||
throw new HttpException(HttpHeaders.CONTENT_TYPE
|
||||
+ " not found in headers");
|
||||
else
|
||||
metaData.setContentType(contentType);
|
||||
metadata.setContentType(contentType);
|
||||
}
|
||||
|
||||
private void parseLastModifiedOrThrowException(S3Object.Metadata metaData)
|
||||
private void setContentLengthOrThrowException(S3Object.Metadata metadata)
|
||||
throws HttpException {
|
||||
String contentLength = getResponse().getFirstHeaderOrNull(
|
||||
HttpHeaders.CONTENT_LENGTH);
|
||||
if (contentLength == null)
|
||||
throw new HttpException(HttpHeaders.CONTENT_LENGTH
|
||||
+ " not found in headers");
|
||||
else
|
||||
metadata.setSize(Long.parseLong(contentLength));
|
||||
}
|
||||
|
||||
private void parseLastModifiedOrThrowException(S3Object.Metadata metadata)
|
||||
throws HttpException {
|
||||
String lastModified = getResponse().getFirstHeaderOrNull(
|
||||
HttpHeaders.LAST_MODIFIED);
|
||||
metaData.setLastModified(dateParser
|
||||
metadata.setLastModified(dateParser
|
||||
.dateTimeFromHeaderFormat(lastModified));
|
||||
if (metaData.getLastModified() == null)
|
||||
if (metadata.getLastModified() == null)
|
||||
throw new HttpException("could not parse: "
|
||||
+ HttpHeaders.LAST_MODIFIED + ": " + lastModified);
|
||||
}
|
||||
|
||||
private void addMd5(S3Object.Metadata metaData) {
|
||||
private void addMd5To(S3Object.Metadata metadata) {
|
||||
String md5Header = getResponse()
|
||||
.getFirstHeaderOrNull(S3Headers.AMZ_MD5);
|
||||
if (md5Header != null) {
|
||||
metaData.setMd5(S3Utils.fromHexString(md5Header));
|
||||
metadata.setMd5(S3Utils.fromHexString(md5Header));
|
||||
}
|
||||
String eTag = getResponse().getFirstHeaderOrNull(S3Headers.ETAG);
|
||||
if (metaData.getMd5() == null && eTag != null) {
|
||||
metaData.setMd5(S3Utils.fromHexString(eTag.replaceAll("\"", "")));
|
||||
if (metadata.getMd5() == null && eTag != null) {
|
||||
metadata.setMd5(S3Utils.fromHexString(eTag.replaceAll("\"", "")));
|
||||
}
|
||||
}
|
||||
|
||||
private void extractUserMetadata(S3Object.Metadata metaData) {
|
||||
private void addUserMetadataTo(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(),
|
||||
metadata.getUserMetadata().put(header.getKey(),
|
||||
header.getValue());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
package org.jclouds.aws.s3.commands.callables;
|
||||
|
||||
import org.jclouds.aws.s3.domain.S3Object;
|
||||
import org.jclouds.aws.s3.domain.S3Object.Metadata;
|
||||
import org.jclouds.http.HttpException;
|
||||
import org.jclouds.http.HttpFutureCommand;
|
||||
import org.jclouds.http.HttpHeaders;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
|
@ -39,11 +39,12 @@ import com.google.inject.Inject;
|
|||
*/
|
||||
public class ParseObjectFromHeadersAndHttpContent extends
|
||||
HttpFutureCommand.ResponseCallable<S3Object> {
|
||||
private final ParseMetadataFromHeaders metaDataParser;
|
||||
private final ParseMetadataFromHeaders metadataParser;
|
||||
|
||||
@Inject
|
||||
public ParseObjectFromHeadersAndHttpContent(ParseMetadataFromHeaders metaDataParser) {
|
||||
this.metaDataParser = metaDataParser;
|
||||
public ParseObjectFromHeadersAndHttpContent(
|
||||
ParseMetadataFromHeaders metadataParser) {
|
||||
this.metadataParser = metadataParser;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -56,26 +57,38 @@ public class ParseObjectFromHeadersAndHttpContent extends
|
|||
*/
|
||||
public S3Object call() throws HttpException {
|
||||
checkCode();
|
||||
metaDataParser.setResponse(getResponse());
|
||||
S3Object.Metadata metaData = metaDataParser.call();
|
||||
|
||||
parseContentLengthOrThrowException(metaData);
|
||||
return new S3Object(metaData, getResponse().getContent());
|
||||
metadataParser.setResponse(getResponse());
|
||||
S3Object.Metadata metadata = metadataParser.call();
|
||||
S3Object object = new S3Object(metadata, getResponse().getContent());
|
||||
parseContentLengthOrThrowException(object);
|
||||
return object;
|
||||
}
|
||||
|
||||
private void parseContentLengthOrThrowException(Metadata metaData)
|
||||
@VisibleForTesting
|
||||
void parseContentLengthOrThrowException(S3Object object)
|
||||
throws HttpException {
|
||||
String contentLength = getResponse().getFirstHeaderOrNull(
|
||||
HttpHeaders.CONTENT_LENGTH);
|
||||
String contentRange = getResponse().getFirstHeaderOrNull(
|
||||
HttpHeaders.CONTENT_RANGE);
|
||||
if (contentLength == null)
|
||||
throw new HttpException(HttpHeaders.CONTENT_LENGTH
|
||||
+ " header not present in headers: "
|
||||
+ getResponse().getHeaders());
|
||||
metaData.setSize(Long.parseLong(contentLength));
|
||||
object.setContentLength(Long.parseLong(contentLength));
|
||||
|
||||
if (contentRange == null) {
|
||||
object.getMetadata().setSize(object.getContentLength());
|
||||
} else {
|
||||
object.setContentRange(contentRange);
|
||||
object.getMetadata().setSize(
|
||||
Long.parseLong(contentRange.substring(contentRange
|
||||
.lastIndexOf('/')+1)));
|
||||
}
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.metaDataParser.setKey(key);
|
||||
this.metadataParser.setKey(key);
|
||||
}
|
||||
|
||||
}
|
|
@ -27,7 +27,7 @@ import org.jclouds.aws.s3.commands.BucketExists;
|
|||
import org.jclouds.aws.s3.commands.DeleteBucket;
|
||||
import org.jclouds.aws.s3.commands.DeleteObject;
|
||||
import org.jclouds.aws.s3.commands.GetObject;
|
||||
import org.jclouds.aws.s3.commands.HeadMetaData;
|
||||
import org.jclouds.aws.s3.commands.HeadObject;
|
||||
import org.jclouds.aws.s3.commands.PutBucket;
|
||||
import org.jclouds.aws.s3.commands.PutObject;
|
||||
import org.jclouds.aws.s3.commands.S3CommandFactory;
|
||||
|
@ -76,10 +76,10 @@ public class S3CommandsModule extends AbstractModule {
|
|||
S3CommandFactory.GetObjectFactory.class,
|
||||
GetObject.class));
|
||||
|
||||
bind(S3CommandFactory.HeadMetaDataFactory.class).toProvider(
|
||||
bind(S3CommandFactory.HeadMetadataFactory.class).toProvider(
|
||||
FactoryProvider.newFactory(
|
||||
S3CommandFactory.HeadMetaDataFactory.class,
|
||||
HeadMetaData.class));
|
||||
S3CommandFactory.HeadMetadataFactory.class,
|
||||
HeadObject.class));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -29,8 +29,10 @@ import static com.google.common.base.Preconditions.checkState;
|
|||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import org.jclouds.aws.s3.DateService;
|
||||
import org.jclouds.aws.s3.S3Utils;
|
||||
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
|
||||
import org.jclouds.aws.s3.reference.S3Headers;
|
||||
import org.jclouds.aws.s3.util.DateService;
|
||||
import org.jclouds.aws.s3.util.S3Utils;
|
||||
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
|
@ -55,7 +57,7 @@ import com.google.common.collect.Multimap;
|
|||
*
|
||||
* // this will copy the object, provided it wasn't modified since yesterday.
|
||||
* // it will not use metadata from the source, and instead use what we pass in.
|
||||
* Future<S3Object.MetaData> object = connection.copyObject("sourceBucket", "objectName",
|
||||
* Future<S3Object.Metadata> object = connection.copyObject("sourceBucket", "objectName",
|
||||
* "destinationBucket", "destinationName",
|
||||
* overrideMetadataWith(meta).
|
||||
* ifSourceModifiedSince(new DateTime().minusDays(1))
|
||||
|
@ -75,6 +77,27 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
|
|||
|
||||
private Multimap<String, String> metadata;
|
||||
|
||||
private CannedAccessPolicy acl = CannedAccessPolicy.PRIVATE;
|
||||
|
||||
/**
|
||||
* Override the default ACL (private) with the specified one.
|
||||
*
|
||||
* @see CannedAccessPolicy
|
||||
*/
|
||||
public CopyObjectOptions overrideAcl(CannedAccessPolicy acl) {
|
||||
this.acl = checkNotNull(acl, "acl");
|
||||
if (!acl.equals(CannedAccessPolicy.PRIVATE))
|
||||
this.replaceHeader(S3Headers.CANNED_ACL, acl.toString());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see CopyObjectOptions#overrideAcl(CannedAccessPolicy)
|
||||
*/
|
||||
public CannedAccessPolicy getAcl() {
|
||||
return acl;
|
||||
}
|
||||
|
||||
/**
|
||||
* For use in the header x-amz-copy-source-if-unmodified-since
|
||||
* <p />
|
||||
|
@ -201,7 +224,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
|
|||
"ifMd5DoesntMatch() is not compatible with ifMd5Matches()");
|
||||
checkState(getIfModifiedSince() == null,
|
||||
"ifModifiedSince() is not compatible with ifMd5Matches()");
|
||||
replaceHeader("x-amz-copy-source-if-match", String.format("\"%1s\"",
|
||||
replaceHeader("x-amz-copy-source-if-match", String.format("\"%1$s\"",
|
||||
S3Utils.toHexString(checkNotNull(md5, "md5"))));
|
||||
return this;
|
||||
}
|
||||
|
@ -226,7 +249,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
|
|||
.checkState(getIfUnmodifiedSince() == null,
|
||||
"ifUnmodifiedSince() is not compatible with ifMd5DoesntMatch()");
|
||||
replaceHeader("x-amz-copy-source-if-none-match", String.format(
|
||||
"\"%1s\"", S3Utils.toHexString(checkNotNull(md5,
|
||||
"\"%1$s\"", S3Utils.toHexString(checkNotNull(md5,
|
||||
"ifMd5DoesntMatch"))));
|
||||
return this;
|
||||
}
|
||||
|
@ -257,6 +280,13 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
|
|||
}
|
||||
|
||||
public static class Builder {
|
||||
/**
|
||||
* @see CopyObjectOptions#overrideAcl(CannedAccessPolicy)
|
||||
*/
|
||||
public static CopyObjectOptions overrideAcl(CannedAccessPolicy acl) {
|
||||
CopyObjectOptions options = new CopyObjectOptions();
|
||||
return options.overrideAcl(acl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see CopyObjectOptions#getIfModifiedSince()
|
||||
|
|
|
@ -24,16 +24,20 @@
|
|||
package org.jclouds.aws.s3.commands.options;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.aws.s3.DateService;
|
||||
import org.jclouds.aws.s3.S3Headers;
|
||||
import org.jclouds.aws.s3.S3Utils;
|
||||
import org.jclouds.aws.s3.util.DateService;
|
||||
import org.jclouds.aws.s3.util.S3Utils;
|
||||
import org.jclouds.http.HttpHeaders;
|
||||
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
* Contains options supported in the REST API for the GET object operation. <h2>
|
||||
* Usage</h2> The recommended way to instantiate a GetObjectOptions object is to
|
||||
|
@ -58,16 +62,42 @@ import org.joda.time.DateTime;
|
|||
public class GetObjectOptions extends BaseHttpRequestOptions {
|
||||
private final static DateService dateService = new DateService();
|
||||
public static final GetObjectOptions NONE = new GetObjectOptions();
|
||||
private final List<String> ranges = new ArrayList<String>();
|
||||
|
||||
@Override
|
||||
public Multimap<String, String> buildRequestHeaders() {
|
||||
Multimap<String, String> headers = super.buildRequestHeaders();
|
||||
String range = getRange();
|
||||
if (range != null)
|
||||
headers.put(HttpHeaders.RANGE, this.getRange());
|
||||
return headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only download the specified range of the object.
|
||||
* download the specified range of the object.
|
||||
*/
|
||||
public GetObjectOptions range(long start, long end) {
|
||||
checkState(start >= 0, "start must be >= 0");
|
||||
checkState(end >= 0, "end must be >= 0");
|
||||
headers
|
||||
.put(S3Headers.RANGE, String
|
||||
.format("bytes=%1d-%2d", start, end));
|
||||
checkArgument(start >= 0, "start must be >= 0");
|
||||
checkArgument(end >= 0, "end must be >= 0");
|
||||
ranges.add(String.format("%d-%d", start, end));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* download the object offset at <code>start</code>
|
||||
*/
|
||||
public GetObjectOptions startAt(long start) {
|
||||
checkArgument(start >= 0, "start must be >= 0");
|
||||
ranges.add(String.format("%d-", start));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* download the last <code>count</code> bytes of the object
|
||||
*/
|
||||
public GetObjectOptions tail(long count) {
|
||||
checkArgument(count > 0, "count must be > 0");
|
||||
ranges.add(String.format("-%d", count));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -78,7 +108,8 @@ public class GetObjectOptions extends BaseHttpRequestOptions {
|
|||
* @see GetObjectOptions#range(long, long)
|
||||
*/
|
||||
public String getRange() {
|
||||
return this.getFirstHeaderOrNull(S3Headers.RANGE);
|
||||
return (ranges.size() > 0) ? String.format("bytes=%s", Joiner.on(",")
|
||||
.join(ranges)) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -88,11 +119,11 @@ public class GetObjectOptions extends BaseHttpRequestOptions {
|
|||
* {@link #ifUnmodifiedSince(DateTime)}
|
||||
*/
|
||||
public GetObjectOptions ifModifiedSince(DateTime ifModifiedSince) {
|
||||
checkState(getIfMatch() == null,
|
||||
checkArgument(getIfMatch() == null,
|
||||
"ifMd5Matches() is not compatible with ifModifiedSince()");
|
||||
checkState(getIfUnmodifiedSince() == null,
|
||||
checkArgument(getIfUnmodifiedSince() == null,
|
||||
"ifUnmodifiedSince() is not compatible with ifModifiedSince()");
|
||||
this.headers.put(S3Headers.OBJECT_IF_MODIFIED_SINCE,
|
||||
this.headers.put(HttpHeaders.IF_MODIFIED_SINCE,
|
||||
dateService.toHeaderString(checkNotNull(ifModifiedSince,
|
||||
"ifModifiedSince")));
|
||||
return this;
|
||||
|
@ -107,7 +138,7 @@ public class GetObjectOptions extends BaseHttpRequestOptions {
|
|||
* @see GetObjectOptions#ifModifiedSince(DateTime)
|
||||
*/
|
||||
public String getIfModifiedSince() {
|
||||
return this.getFirstHeaderOrNull(S3Headers.OBJECT_IF_MODIFIED_SINCE);
|
||||
return this.getFirstHeaderOrNull(HttpHeaders.IF_MODIFIED_SINCE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -117,11 +148,11 @@ public class GetObjectOptions extends BaseHttpRequestOptions {
|
|||
* {@link #ifModifiedSince(DateTime)}
|
||||
*/
|
||||
public GetObjectOptions ifUnmodifiedSince(DateTime ifUnmodifiedSince) {
|
||||
checkState(getIfNoneMatch() == null,
|
||||
checkArgument(getIfNoneMatch() == null,
|
||||
"ifMd5DoesntMatch() is not compatible with ifUnmodifiedSince()");
|
||||
checkState(getIfModifiedSince() == null,
|
||||
checkArgument(getIfModifiedSince() == null,
|
||||
"ifModifiedSince() is not compatible with ifUnmodifiedSince()");
|
||||
this.headers.put(S3Headers.OBJECT_IF_UNMODIFIED_SINCE, dateService
|
||||
this.headers.put(HttpHeaders.IF_UNMODIFIED_SINCE, dateService
|
||||
.toHeaderString(checkNotNull(ifUnmodifiedSince,
|
||||
"ifUnmodifiedSince")));
|
||||
return this;
|
||||
|
@ -136,7 +167,7 @@ public class GetObjectOptions extends BaseHttpRequestOptions {
|
|||
* @see GetObjectOptions#ifUnmodifiedSince(DateTime)
|
||||
*/
|
||||
public String getIfUnmodifiedSince() {
|
||||
return this.getFirstHeaderOrNull(S3Headers.OBJECT_IF_UNMODIFIED_SINCE);
|
||||
return this.getFirstHeaderOrNull(HttpHeaders.IF_UNMODIFIED_SINCE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -153,11 +184,11 @@ public class GetObjectOptions extends BaseHttpRequestOptions {
|
|||
*/
|
||||
public GetObjectOptions ifMd5Matches(byte[] md5)
|
||||
throws UnsupportedEncodingException {
|
||||
checkState(getIfNoneMatch() == null,
|
||||
checkArgument(getIfNoneMatch() == null,
|
||||
"ifMd5DoesntMatch() is not compatible with ifMd5Matches()");
|
||||
checkState(getIfModifiedSince() == null,
|
||||
checkArgument(getIfModifiedSince() == null,
|
||||
"ifModifiedSince() is not compatible with ifMd5Matches()");
|
||||
this.headers.put(S3Headers.OBJECT_IF_MATCH, String.format("\"%1s\"",
|
||||
this.headers.put(HttpHeaders.IF_MATCH, String.format("\"%1$s\"",
|
||||
S3Utils.toHexString(checkNotNull(md5, "md5"))));
|
||||
return this;
|
||||
}
|
||||
|
@ -171,7 +202,7 @@ public class GetObjectOptions extends BaseHttpRequestOptions {
|
|||
* @see GetObjectOptions#ifMd5Matches(String)
|
||||
*/
|
||||
public String getIfMatch() {
|
||||
return this.getFirstHeaderOrNull(S3Headers.OBJECT_IF_MATCH);
|
||||
return this.getFirstHeaderOrNull(HttpHeaders.IF_MATCH);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -188,13 +219,12 @@ public class GetObjectOptions extends BaseHttpRequestOptions {
|
|||
*/
|
||||
public GetObjectOptions ifMd5DoesntMatch(byte[] md5)
|
||||
throws UnsupportedEncodingException {
|
||||
checkState(getIfMatch() == null,
|
||||
checkArgument(getIfMatch() == null,
|
||||
"ifMd5Matches() is not compatible with ifMd5DoesntMatch()");
|
||||
checkState(getIfUnmodifiedSince() == null,
|
||||
checkArgument(getIfUnmodifiedSince() == null,
|
||||
"ifUnmodifiedSince() is not compatible with ifMd5DoesntMatch()");
|
||||
this.headers.put(S3Headers.OBJECT_IF_NONE_MATCH, String.format(
|
||||
"\"%1s\"", S3Utils.toHexString(checkNotNull(md5,
|
||||
"ifMd5DoesntMatch"))));
|
||||
this.headers.put(HttpHeaders.IF_NONE_MATCH, String.format("\"%1$s\"",
|
||||
S3Utils.toHexString(checkNotNull(md5, "ifMd5DoesntMatch"))));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -207,7 +237,8 @@ public class GetObjectOptions extends BaseHttpRequestOptions {
|
|||
* @see GetObjectOptions#ifMd5DoesntMatch(String)
|
||||
*/
|
||||
public String getIfNoneMatch() {
|
||||
return this.getFirstHeaderOrNull(S3Headers.OBJECT_IF_NONE_MATCH);
|
||||
return this
|
||||
.getFirstHeaderOrNull(org.jclouds.http.HttpHeaders.IF_NONE_MATCH);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
@ -220,6 +251,22 @@ public class GetObjectOptions extends BaseHttpRequestOptions {
|
|||
return options.range(start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see GetObjectOptions#startAt(long)
|
||||
*/
|
||||
public static GetObjectOptions startAt(long start) {
|
||||
GetObjectOptions options = new GetObjectOptions();
|
||||
return options.startAt(start);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see GetObjectOptions#tail(long)
|
||||
*/
|
||||
public static GetObjectOptions tail(long count) {
|
||||
GetObjectOptions options = new GetObjectOptions();
|
||||
return options.tail(count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see GetObjectOptions#getIfModifiedSince()
|
||||
*/
|
||||
|
|
|
@ -23,11 +23,12 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.commands.options;
|
||||
|
||||
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.aws.s3.reference.S3Headers;
|
||||
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.*;
|
||||
|
||||
/**
|
||||
|
@ -38,7 +39,7 @@ import static com.google.common.base.Preconditions.*;
|
|||
* <p/>
|
||||
* <code>
|
||||
* import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.*
|
||||
* import static org.jclouds.aws.s3.domain.S3Bucket.MetaData.LocationConstraint.*;
|
||||
* import static org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint.*;
|
||||
* import org.jclouds.aws.s3.S3Connection;
|
||||
*
|
||||
* S3Connection connection = // get connection
|
||||
|
@ -64,7 +65,7 @@ public class PutBucketOptions extends BaseHttpRequestOptions {
|
|||
this.constraint = checkNotNull(constraint, "constraint");
|
||||
this.payload = String
|
||||
.format(
|
||||
"<CreateBucketConfiguration><LocationConstraint>%1s</LocationConstraint></CreateBucketConfiguration>",
|
||||
"<CreateBucketConfiguration><LocationConstraint>%1$s</LocationConstraint></CreateBucketConfiguration>",
|
||||
constraint.toString());
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -23,10 +23,11 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.commands.options;
|
||||
|
||||
import org.jclouds.aws.s3.S3Headers;
|
||||
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
|
||||
import org.jclouds.aws.s3.reference.S3Headers;
|
||||
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.*;
|
||||
|
||||
/**
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.jclouds.aws.s3.internal.GuiceS3Context;
|
|||
import org.jclouds.aws.s3.internal.LiveS3Connection;
|
||||
import org.jclouds.aws.s3.internal.LiveS3InputStreamMap;
|
||||
import org.jclouds.aws.s3.internal.LiveS3ObjectMap;
|
||||
import org.jclouds.http.CloseContentAndSetExceptionHandler;
|
||||
import org.jclouds.http.HttpConstants;
|
||||
import org.jclouds.http.HttpRequestFilter;
|
||||
import org.jclouds.http.HttpResponseHandler;
|
||||
|
@ -88,13 +89,14 @@ public class S3ContextModule extends AbstractModule {
|
|||
LiveS3InputStreamMap.class));
|
||||
bind(S3Context.class).to(GuiceS3Context.class);
|
||||
bind(HttpResponseHandler.class).annotatedWith(RedirectHandler.class)
|
||||
.to(ParseS3ErrorFromXmlContent.class).in(Scopes.SINGLETON);
|
||||
.to(CloseContentAndSetExceptionHandler.class).in(
|
||||
Scopes.SINGLETON);
|
||||
bind(HttpResponseHandler.class).annotatedWith(ClientErrorHandler.class)
|
||||
.to(ParseS3ErrorFromXmlContent.class).in(Scopes.SINGLETON);
|
||||
bind(HttpResponseHandler.class).annotatedWith(ServerErrorHandler.class)
|
||||
.to(ParseS3ErrorFromXmlContent.class).in(Scopes.SINGLETON);
|
||||
requestInjection(this);
|
||||
logger.info("S3 Context = %1s://%2s:%3s",
|
||||
logger.info("S3 Context = %1$s://%2$s:%3$s",
|
||||
(isSecure ? "https" : "http"), address, port);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,22 +24,38 @@
|
|||
package org.jclouds.aws.s3.domain;
|
||||
|
||||
/**
|
||||
* // TODO: Adrian: Document this!
|
||||
* Every bucket and object in Amazon S3 has an owner, the user that created the
|
||||
* bucket or object. The owner of a bucket or object cannot be changed. However,
|
||||
* if the object is overwritten by another user (deleted and rewritten), the new
|
||||
* object will have a new owner.
|
||||
* <p/>
|
||||
*
|
||||
* @see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?
|
||||
* RESTAccessPolicy.html
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class S3Owner {
|
||||
private String id;
|
||||
public class CanonicalUser {
|
||||
private final String id;
|
||||
private String displayName;
|
||||
|
||||
public CanonicalUser(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("S3Owner");
|
||||
sb.append("{id='").append(id).append('\'');
|
||||
sb.append(", displayName='").append(displayName).append('\'');
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
@ -50,13 +66,18 @@ public class S3Owner {
|
|||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof S3Owner)) return false;
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof CanonicalUser))
|
||||
return false;
|
||||
|
||||
S3Owner s3Owner = (S3Owner) o;
|
||||
CanonicalUser s3Owner = (CanonicalUser) o;
|
||||
|
||||
if (displayName != null ? !displayName.equals(s3Owner.displayName) : s3Owner.displayName != null) return false;
|
||||
if (!id.equals(s3Owner.id)) return false;
|
||||
if (displayName != null ? !displayName.equals(s3Owner.displayName)
|
||||
: s3Owner.displayName != null)
|
||||
return false;
|
||||
if (!id.equals(s3Owner.id))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -64,7 +85,8 @@ public class S3Owner {
|
|||
@Override
|
||||
public int hashCode() {
|
||||
int result = id.hashCode();
|
||||
result = 31 * result + (displayName != null ? displayName.hashCode() : 0);
|
||||
result = 31 * result
|
||||
+ (displayName != null ? displayName.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -42,7 +42,7 @@ public class S3Bucket {
|
|||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("S3Bucket");
|
||||
sb.append("{metaData=").append(metaData);
|
||||
sb.append("{metadata=").append(metadata);
|
||||
sb.append(", isComplete=").append(isComplete);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
|
@ -59,7 +59,7 @@ public class S3Bucket {
|
|||
|
||||
if (isComplete != s3Bucket.isComplete)
|
||||
return false;
|
||||
if (!metaData.equals(s3Bucket.metaData))
|
||||
if (!metadata.equals(s3Bucket.metadata))
|
||||
return false;
|
||||
if (objects != null ? !objects.equals(s3Bucket.objects)
|
||||
: s3Bucket.objects != null)
|
||||
|
@ -71,7 +71,7 @@ public class S3Bucket {
|
|||
@Override
|
||||
public int hashCode() {
|
||||
int result = objects != null ? objects.hashCode() : 0;
|
||||
result = 31 * result + metaData.hashCode();
|
||||
result = 31 * result + metadata.hashCode();
|
||||
result = 31 * result + (isComplete ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ public class S3Bucket {
|
|||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("MetaData");
|
||||
sb.append("Metadata");
|
||||
sb.append("{name='").append(name).append('\'');
|
||||
sb.append(", creationDate=").append(creationDate);
|
||||
sb.append(", canonicalUser=").append(canonicalUser);
|
||||
|
@ -95,17 +95,12 @@ public class S3Bucket {
|
|||
if (!(o instanceof Metadata))
|
||||
return false;
|
||||
|
||||
Metadata metaData = (Metadata) o;
|
||||
|
||||
Metadata metadata = (Metadata) o;
|
||||
if (canonicalUser != null ? !canonicalUser
|
||||
.equals(metaData.canonicalUser)
|
||||
: metaData.canonicalUser != null)
|
||||
.equals(metadata.canonicalUser)
|
||||
: metadata.canonicalUser != null)
|
||||
return false;
|
||||
if (creationDate != null ? !creationDate
|
||||
.equals(metaData.creationDate)
|
||||
: metaData.creationDate != null)
|
||||
return false;
|
||||
if (!name.equals(metaData.name))
|
||||
if (!name.equals(metadata.name))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -114,8 +109,6 @@ public class S3Bucket {
|
|||
@Override
|
||||
public int hashCode() {
|
||||
int result = name.hashCode();
|
||||
result = 31 * result
|
||||
+ (creationDate != null ? creationDate.hashCode() : 0);
|
||||
result = 31 * result
|
||||
+ (canonicalUser != null ? canonicalUser.hashCode() : 0);
|
||||
return result;
|
||||
|
@ -127,7 +120,7 @@ public class S3Bucket {
|
|||
|
||||
private final String name;
|
||||
private DateTime creationDate;
|
||||
private S3Owner canonicalUser;
|
||||
private CanonicalUser canonicalUser;
|
||||
|
||||
public Metadata(String name) {
|
||||
this.name = checkNotNull(name, "name");
|
||||
|
@ -145,11 +138,17 @@ public class S3Bucket {
|
|||
this.creationDate = creationDate;
|
||||
}
|
||||
|
||||
public S3Owner getCanonicalUser() {
|
||||
/**
|
||||
* Every bucket and object in Amazon S3 has an owner, the user that
|
||||
* created the bucket or object. The owner of a bucket or object cannot
|
||||
* be changed. However, if the object is overwritten by another user
|
||||
* (deleted and rewritten), the new object will have a new owner.
|
||||
*/
|
||||
public CanonicalUser getOwner() {
|
||||
return canonicalUser;
|
||||
}
|
||||
|
||||
public void setCanonicalUser(S3Owner canonicalUser) {
|
||||
public void setOwner(CanonicalUser canonicalUser) {
|
||||
this.canonicalUser = canonicalUser;
|
||||
}
|
||||
|
||||
|
@ -163,20 +162,20 @@ public class S3Bucket {
|
|||
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();
|
||||
return this.metadata.getName();
|
||||
}
|
||||
|
||||
public S3Bucket(Metadata metaData) {
|
||||
this.metaData = checkNotNull(metaData, "metaData");
|
||||
public S3Bucket(Metadata metadata) {
|
||||
this.metadata = checkNotNull(metadata, "metadata");
|
||||
}
|
||||
|
||||
public Set<S3Object.Metadata> getContents() {
|
||||
|
@ -195,8 +194,8 @@ public class S3Bucket {
|
|||
isComplete = complete;
|
||||
}
|
||||
|
||||
public Metadata getMetaData() {
|
||||
return metaData;
|
||||
public Metadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public void setCommonPrefixes(Set<String> commonPrefixes) {
|
||||
|
|
|
@ -23,17 +23,25 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.domain;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* When an Amazon S3 request is in error, the client receives an error response.
|
||||
*
|
||||
* @see http
|
||||
* ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?ErrorResponse
|
||||
* .html
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public class S3Error {
|
||||
private String code;
|
||||
private String message;
|
||||
private String resource;
|
||||
private String requestId;
|
||||
private String hostId;
|
||||
private String header;
|
||||
private String signatureProvided;
|
||||
private String stringToSign;
|
||||
private String requestToken;
|
||||
private Map<String, String> details = new HashMap<String, String>();
|
||||
private String stringSigned;
|
||||
private String stringToSignBytes;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
@ -41,17 +49,12 @@ public class S3Error {
|
|||
sb.append("S3Error");
|
||||
sb.append("{code='").append(code).append('\'');
|
||||
sb.append(", message='").append(message).append('\'');
|
||||
sb.append(", resource='").append(resource).append('\'');
|
||||
sb.append(", requestId='").append(requestId).append('\'');
|
||||
sb.append(", hostId='").append(hostId).append('\'');
|
||||
sb.append(", header='").append(header).append('\'');
|
||||
sb.append(", signatureProvided='").append(signatureProvided).append(
|
||||
'\'');
|
||||
sb.append(", stringToSign='").append(stringToSign).append('\'');
|
||||
sb.append(", stringSigned='").append(getStringSigned()).append('\'');
|
||||
sb.append(", stringToSignBytes='").append(stringToSignBytes).append(
|
||||
'\'');
|
||||
sb.append('}');
|
||||
sb.append(", requestToken='").append(requestToken).append('\'');
|
||||
if (stringSigned != null)
|
||||
sb.append(", stringSigned='").append(stringSigned).append('\'');
|
||||
sb.append(", context='").append(details.toString()).append('\'')
|
||||
.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
@ -59,6 +62,13 @@ public class S3Error {
|
|||
this.code = code;
|
||||
}
|
||||
|
||||
/**
|
||||
* The error code is a string that uniquely identifies an error condition.
|
||||
* It is meant to be read and understood by programs that detect and handle
|
||||
* errors by type
|
||||
*
|
||||
* @see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/ErrorCode.html
|
||||
*/
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
@ -67,71 +77,58 @@ public class S3Error {
|
|||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* The error message contains a generic description of the error condition
|
||||
* in English.
|
||||
*
|
||||
* @see http
|
||||
* ://docs.amazonwebservices.com/AmazonS3/2006-03-01/ErrorMessage.html
|
||||
*/
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setResource(String resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
public String getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
public void setRequestId(String requestId) {
|
||||
this.requestId = requestId;
|
||||
}
|
||||
|
||||
/**
|
||||
* * A unique ID assigned to each request by the system. In the unlikely
|
||||
* event that you have problems with Amazon S3, Amazon can use this to help
|
||||
* troubleshoot the problem.
|
||||
*
|
||||
*/
|
||||
public String getRequestId() {
|
||||
return requestId;
|
||||
}
|
||||
|
||||
public void setHostId(String hostId) {
|
||||
this.hostId = hostId;
|
||||
}
|
||||
|
||||
public String getHostId() {
|
||||
return hostId;
|
||||
}
|
||||
|
||||
public void setSignatureProvided(String signatureProvided) {
|
||||
this.signatureProvided = signatureProvided;
|
||||
}
|
||||
|
||||
public String getSignatureProvided() {
|
||||
return signatureProvided;
|
||||
}
|
||||
|
||||
public void setStringToSign(String stringToSign) {
|
||||
this.stringToSign = stringToSign;
|
||||
}
|
||||
|
||||
public String getStringToSign() {
|
||||
return stringToSign;
|
||||
}
|
||||
|
||||
public void setStringToSignBytes(String stringToSignBytes) {
|
||||
this.stringToSignBytes = stringToSignBytes;
|
||||
}
|
||||
|
||||
public String getStringToSignBytes() {
|
||||
return stringToSignBytes;
|
||||
}
|
||||
|
||||
public void setHeader(String header) {
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
public String getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public void setStringSigned(String stringSigned) {
|
||||
this.stringSigned = stringSigned;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return what jclouds signed before sending the request.
|
||||
*/
|
||||
public String getStringSigned() {
|
||||
return stringSigned;
|
||||
}
|
||||
|
||||
public void setDetails(Map<String, String> context) {
|
||||
this.details = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return additional details surrounding the error.
|
||||
*/
|
||||
public Map<String, String> getDetails() {
|
||||
return details;
|
||||
}
|
||||
|
||||
public void setRequestToken(String requestToken) {
|
||||
this.requestToken = requestToken;
|
||||
}
|
||||
|
||||
public String getRequestToken() {
|
||||
return requestToken;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,8 +31,8 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.jclouds.aws.s3.S3Utils;
|
||||
import org.jclouds.aws.s3.S3Utils.Md5InputStreamResult;
|
||||
import org.jclouds.aws.s3.util.S3Utils;
|
||||
import org.jclouds.aws.s3.util.S3Utils.Md5InputStreamResult;
|
||||
import org.jclouds.http.ContentTypes;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
|
@ -48,18 +48,20 @@ public class S3Object {
|
|||
public static final S3Object NOT_FOUND = new S3Object(Metadata.NOT_FOUND);
|
||||
|
||||
private Object data;
|
||||
private Metadata metaData;
|
||||
private Metadata metadata;
|
||||
private long contentLength = -1;
|
||||
private String contentRange;
|
||||
|
||||
public S3Object(String key) {
|
||||
this(new Metadata(key));
|
||||
}
|
||||
|
||||
public S3Object(Metadata metaData) {
|
||||
this.metaData = metaData;
|
||||
public S3Object(Metadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public S3Object(Metadata metaData, Object data) {
|
||||
this(metaData);
|
||||
public S3Object(Metadata metadata, Object data) {
|
||||
this(metadata);
|
||||
setData(data);
|
||||
}
|
||||
|
||||
|
@ -77,6 +79,7 @@ public class S3Object {
|
|||
private volatile long size = -1;
|
||||
|
||||
// only parsed during head or get
|
||||
private Multimap<String, String> allHeaders = HashMultimap.create();
|
||||
private Multimap<String, String> userMetadata = HashMultimap.create();
|
||||
private DateTime lastModified;
|
||||
private String dataType = ContentTypes.UNKNOWN_MIME_TYPE;
|
||||
|
@ -85,7 +88,7 @@ public class S3Object {
|
|||
private String dataEncoding;
|
||||
|
||||
// only parsed on list
|
||||
private S3Owner owner = null;
|
||||
private CanonicalUser owner = null;
|
||||
private String storageClass = null;
|
||||
|
||||
public Metadata(String key) {
|
||||
|
@ -97,7 +100,7 @@ public class S3Object {
|
|||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("MetaData");
|
||||
sb.append("Metadata");
|
||||
sb.append("{key='").append(key).append('\'');
|
||||
sb.append(", lastModified=").append(lastModified);
|
||||
sb.append(", md5=").append(
|
||||
|
@ -116,20 +119,20 @@ public class S3Object {
|
|||
if (!(o instanceof Metadata))
|
||||
return false;
|
||||
|
||||
Metadata metaData = (Metadata) o;
|
||||
Metadata metadata = (Metadata) o;
|
||||
|
||||
if (size != metaData.size)
|
||||
if (size != metadata.size)
|
||||
return false;
|
||||
if (dataType != null ? !dataType.equals(metaData.dataType)
|
||||
: metaData.dataType != null)
|
||||
if (dataType != null ? !dataType.equals(metadata.dataType)
|
||||
: metadata.dataType != null)
|
||||
return false;
|
||||
if (!key.equals(metaData.key))
|
||||
if (!key.equals(metadata.key))
|
||||
return false;
|
||||
if (lastModified != null ? !lastModified
|
||||
.equals(metaData.lastModified)
|
||||
: metaData.lastModified != null)
|
||||
.equals(metadata.lastModified)
|
||||
: metadata.lastModified != null)
|
||||
return false;
|
||||
if (!Arrays.equals(getMd5(), metaData.getMd5()))
|
||||
if (!Arrays.equals(getMd5(), metadata.getMd5()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -190,11 +193,17 @@ public class S3Object {
|
|||
return userMetadata;
|
||||
}
|
||||
|
||||
public void setOwner(S3Owner owner) {
|
||||
public void setOwner(CanonicalUser owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public S3Owner getOwner() {
|
||||
/**
|
||||
* Every bucket and object in Amazon S3 has an owner, the user that
|
||||
* created the bucket or object. The owner of a bucket or object cannot
|
||||
* be changed. However, if the object is overwritten by another user
|
||||
* (deleted and rewritten), the new object will have a new owner.
|
||||
*/
|
||||
public CanonicalUser getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
|
@ -229,16 +238,24 @@ public class S3Object {
|
|||
public String getContentEncoding() {
|
||||
return dataEncoding;
|
||||
}
|
||||
|
||||
public void setAllHeaders(Multimap<String, String> allHeaders) {
|
||||
this.allHeaders = allHeaders;
|
||||
}
|
||||
|
||||
public Multimap<String, String> getAllHeaders() {
|
||||
return allHeaders;
|
||||
}
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return metaData.getKey();
|
||||
return metadata.getKey();
|
||||
}
|
||||
|
||||
public void setData(Object data) {
|
||||
this.data = checkNotNull(data, "data");
|
||||
if (getMetaData().getSize() == -1)
|
||||
this.getMetaData().setSize(S3Utils.calculateSize(data));
|
||||
if (getMetadata().getSize() == -1)
|
||||
this.getMetadata().setSize(S3Utils.calculateSize(data));
|
||||
}
|
||||
|
||||
public void generateMd5() throws IOException {
|
||||
|
@ -246,11 +263,11 @@ public class S3Object {
|
|||
if (data instanceof InputStream) {
|
||||
Md5InputStreamResult result = S3Utils
|
||||
.generateMd5Result((InputStream) data);
|
||||
getMetaData().setSize(result.length);
|
||||
getMetaData().setMd5(result.md5);
|
||||
getMetadata().setSize(result.length);
|
||||
getMetadata().setMd5(result.md5);
|
||||
setData(result.data);
|
||||
} else {
|
||||
getMetaData().setMd5(S3Utils.md5(data));
|
||||
getMetadata().setMd5(S3Utils.md5(data));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,19 +275,19 @@ public class S3Object {
|
|||
return data;
|
||||
}
|
||||
|
||||
public void setMetaData(Metadata metaData) {
|
||||
this.metaData = metaData;
|
||||
public void setMetadata(Metadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public Metadata getMetaData() {
|
||||
return metaData;
|
||||
public Metadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("S3Object");
|
||||
sb.append("{metaData=").append(metaData);
|
||||
sb.append("{metadata=").append(metadata);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
|
@ -286,7 +303,7 @@ public class S3Object {
|
|||
|
||||
if (data != null ? !data.equals(s3Object.data) : s3Object.data != null)
|
||||
return false;
|
||||
if (!metaData.equals(s3Object.metaData))
|
||||
if (!metadata.equals(s3Object.metadata))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -295,8 +312,24 @@ public class S3Object {
|
|||
@Override
|
||||
public int hashCode() {
|
||||
int result = data != null ? data.hashCode() : 0;
|
||||
result = 31 * result + metaData.hashCode();
|
||||
result = 31 * result + metadata.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setContentLength(long contentLength) {
|
||||
this.contentLength = contentLength;
|
||||
}
|
||||
|
||||
public long getContentLength() {
|
||||
return contentLength;
|
||||
}
|
||||
|
||||
public void setContentRange(String contentRange) {
|
||||
this.contentRange = contentRange;
|
||||
}
|
||||
|
||||
public String getContentRange() {
|
||||
return contentRange;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,13 +30,14 @@ import javax.annotation.Resource;
|
|||
import org.apache.commons.io.IOUtils;
|
||||
import org.jclouds.aws.s3.S3ResponseException;
|
||||
import org.jclouds.aws.s3.domain.S3Error;
|
||||
import org.jclouds.aws.s3.reference.S3Headers;
|
||||
import org.jclouds.aws.s3.xml.S3ParserFactory;
|
||||
import org.jclouds.http.HttpException;
|
||||
import org.jclouds.http.HttpFutureCommand;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.http.HttpResponseHandler;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
|
@ -57,30 +58,27 @@ public class ParseS3ErrorFromXmlContent implements HttpResponseHandler {
|
|||
}
|
||||
|
||||
public void handle(HttpFutureCommand<?> command, HttpResponse response) {
|
||||
int code = response.getStatusCode();
|
||||
if (code >= 300) {
|
||||
S3Error error = new S3Error();
|
||||
error.setRequestId(response.getFirstHeaderOrNull(S3Headers.REQUEST_ID));
|
||||
error.setRequestToken(response
|
||||
.getFirstHeaderOrNull(S3Headers.REQUEST_TOKEN));
|
||||
InputStream errorStream = response.getContent();
|
||||
if (errorStream != null) {
|
||||
try {
|
||||
S3Error error = parserFactory.createErrorParser().parse(
|
||||
errorStream);
|
||||
if (errorStream != null) {
|
||||
error = parserFactory.createErrorParser().parse(errorStream);
|
||||
if ("SignatureDoesNotMatch".equals(error.getCode()))
|
||||
error.setStringSigned(RequestAuthorizeSignature
|
||||
.createStringToSign(command.getRequest()));
|
||||
logger.trace("received the following error from s3: %1s",
|
||||
error);
|
||||
command.setException(new S3ResponseException(command,
|
||||
response, error));
|
||||
} catch (HttpException he) {
|
||||
logger.error(he, "error parsing response %1s", response);
|
||||
error.setRequestToken(response
|
||||
.getFirstHeaderOrNull(S3Headers.REQUEST_TOKEN));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.warn(e, "error parsing XML reponse: %1$s", response);
|
||||
} finally {
|
||||
command.setException(new S3ResponseException(command, response,
|
||||
error));
|
||||
IOUtils.closeQuietly(errorStream);
|
||||
}
|
||||
} else {
|
||||
command
|
||||
.setException(new S3ResponseException(command, response));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -29,14 +29,15 @@ import java.util.TreeSet;
|
|||
import java.util.concurrent.atomic.AtomicLong;
|
||||
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.aws.s3.reference.S3Constants;
|
||||
import org.jclouds.aws.s3.util.DateService;
|
||||
import org.jclouds.aws.s3.util.S3Utils;
|
||||
import org.jclouds.http.HttpException;
|
||||
import org.jclouds.http.HttpHeaders;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpRequestFilter;
|
||||
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.name.Named;
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
@ -40,16 +39,16 @@ import java.util.concurrent.TimeoutException;
|
|||
|
||||
import org.jclouds.Utils;
|
||||
import org.jclouds.aws.s3.S3Connection;
|
||||
import org.jclouds.aws.s3.S3Constants;
|
||||
import org.jclouds.aws.s3.S3Map;
|
||||
import org.jclouds.aws.s3.domain.S3Bucket;
|
||||
import org.jclouds.aws.s3.domain.S3Object;
|
||||
import org.jclouds.aws.s3.reference.S3Constants;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.google.inject.name.Named;
|
||||
|
||||
public abstract class BaseS3Map<T> implements Map<String, T>, S3Map {
|
||||
public abstract class BaseS3Map<V> implements S3Map<String, V> {
|
||||
|
||||
protected final S3Connection connection;
|
||||
protected final String bucket;
|
||||
|
@ -88,8 +87,8 @@ 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()) {
|
||||
if (Arrays.equals(md5, metaData.getMd5()))
|
||||
for (S3Object.Metadata metadata : refreshBucket().getContents()) {
|
||||
if (Arrays.equals(md5, metadata.getMd5()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -104,9 +103,9 @@ public abstract class BaseS3Map<T> implements Map<String, T>, S3Map {
|
|||
} else {
|
||||
object = new S3Object("dummy", value);
|
||||
}
|
||||
if (object.getMetaData().getMd5() == null)
|
||||
if (object.getMetadata().getMd5() == null)
|
||||
object.generateMd5();
|
||||
return object.getMetaData().getMd5();
|
||||
return object.getMetadata().getMd5();
|
||||
}
|
||||
|
||||
protected Set<S3Object> getAllObjects() {
|
||||
|
@ -123,7 +122,7 @@ public abstract class BaseS3Map<T> implements Map<String, T>, S3Map {
|
|||
} catch (Exception e) {
|
||||
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
|
||||
throw new S3RuntimeException(String.format(
|
||||
"Error getting value from bucket %1s:%2s", bucket,
|
||||
"Error getting value from bucket %1$s:%2$s", bucket,
|
||||
object != null ? object.getKey() : "unknown"), e);
|
||||
}
|
||||
if (object != S3Object.NOT_FOUND)
|
||||
|
@ -146,7 +145,7 @@ public abstract class BaseS3Map<T> implements Map<String, T>, S3Map {
|
|||
} catch (Exception e) {
|
||||
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
|
||||
throw new S3RuntimeException(String.format(
|
||||
"Error searching for ETAG of value: [%2s] in bucket:%1s",
|
||||
"Error searching for ETAG of value: [%2$s] in bucket:%1$s",
|
||||
bucket, value), e);
|
||||
}
|
||||
}
|
||||
|
@ -210,7 +209,7 @@ public abstract class BaseS3Map<T> implements Map<String, T>, S3Map {
|
|||
} catch (Exception e) {
|
||||
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
|
||||
throw new S3RuntimeException(String.format(
|
||||
"Error searching for %1s:%2s", bucket, key), e);
|
||||
"Error searching for %1$s:%2$s", bucket, key), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,9 +31,9 @@ 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.GetMetaDataForOwnedBuckets;
|
||||
import org.jclouds.aws.s3.commands.ListOwnedBuckets;
|
||||
import org.jclouds.aws.s3.commands.GetObject;
|
||||
import org.jclouds.aws.s3.commands.HeadMetaData;
|
||||
import org.jclouds.aws.s3.commands.HeadObject;
|
||||
import org.jclouds.aws.s3.commands.ListBucket;
|
||||
import org.jclouds.aws.s3.commands.PutBucket;
|
||||
import org.jclouds.aws.s3.commands.PutObject;
|
||||
|
@ -96,12 +96,12 @@ public class LiveS3Connection implements S3Connection {
|
|||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see HeadMetaData
|
||||
* @see HeadObject
|
||||
*/
|
||||
public Future<S3Object.Metadata> headObject(String s3Bucket, String key) {
|
||||
HeadMetaData headMetaData = factory.createHeadMetaData(s3Bucket, key);
|
||||
client.submit(headMetaData);
|
||||
return headMetaData;
|
||||
HeadObject headMetadata = factory.createHeadMetadata(s3Bucket, key);
|
||||
client.submit(headMetadata);
|
||||
return headMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -230,11 +230,11 @@ public class LiveS3Connection implements S3Connection {
|
|||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see GetMetaDataForOwnedBuckets
|
||||
* @see ListOwnedBuckets
|
||||
*/
|
||||
public Future<List<Metadata>> getOwnedBuckets() {
|
||||
GetMetaDataForOwnedBuckets listRequest = factory
|
||||
.createGetMetaDataForOwnedBuckets();
|
||||
public Future<List<Metadata>> listOwnedBuckets() {
|
||||
ListOwnedBuckets listRequest = factory
|
||||
.createGetMetadataForOwnedBuckets();
|
||||
client.submit(listRequest);
|
||||
return listRequest;
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
|
|||
} catch (Exception e) {
|
||||
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
|
||||
throw new S3RuntimeException(String.format(
|
||||
"Error geting object %1s:%2s", bucket, o), e);
|
||||
"Error geting object %1$s:%2$s", bucket, o), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
|
|||
} catch (Exception e) {
|
||||
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
|
||||
throw new S3RuntimeException(String.format(
|
||||
"Error removing object %1s:%2s", bucket, o), e);
|
||||
"Error removing object %1$s:%2$s", bucket, o), e);
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
|
|||
} catch (Exception e) {
|
||||
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
|
||||
throw new S3RuntimeException(String.format(
|
||||
"Error adding object %1s:%2s", bucket, object), e);
|
||||
"Error adding object %1$s:%2$s", bucket, object), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ public class LiveS3ObjectMap extends BaseS3Map<S3Object> implements S3ObjectMap
|
|||
} catch (Exception e) {
|
||||
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
|
||||
throw new S3RuntimeException(String.format(
|
||||
"Error geting object %1s:%2s", bucket, key), e);
|
||||
"Error geting object %1$s:%2$s", bucket, key), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ public class LiveS3ObjectMap extends BaseS3Map<S3Object> implements S3ObjectMap
|
|||
} catch (Exception e) {
|
||||
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
|
||||
throw new S3RuntimeException(String.format(
|
||||
"Error putting object %1s:%2s%n%1s", bucket, key, value), e);
|
||||
"Error putting object %1$s:%2$s%n%1$s", bucket, key, value), e);
|
||||
}
|
||||
return returnVal;
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ public class LiveS3ObjectMap extends BaseS3Map<S3Object> implements S3ObjectMap
|
|||
} catch (Exception e) {
|
||||
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
|
||||
throw new S3RuntimeException(String.format(
|
||||
"Error removing object %1s:%2s", bucket, key), e);
|
||||
"Error removing object %1$s:%2$s", bucket, key), e);
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* This package contains an Amazon S3 client implemented by {@link HttpFutureCommand} commands.
|
||||
*
|
||||
* @see http://aws.amazon.com/s3/
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
package org.jclouds.aws.s3;
|
|
@ -21,7 +21,7 @@
|
|||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.aws.s3;
|
||||
package org.jclouds.aws.s3.reference;
|
||||
|
||||
import org.jclouds.command.pool.PoolConstants;
|
||||
import org.jclouds.http.HttpConstants;
|
|
@ -21,9 +21,11 @@
|
|||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.aws.s3;
|
||||
package org.jclouds.aws.s3.reference;
|
||||
|
||||
public interface S3Headers {
|
||||
import org.jclouds.http.HttpHeaders;
|
||||
|
||||
public interface S3Headers extends HttpHeaders{
|
||||
|
||||
/**
|
||||
* The canned ACL to apply to the object. Options include private,
|
||||
|
@ -38,12 +40,8 @@ public interface S3Headers {
|
|||
* 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";
|
||||
public static final String REQUEST_ID = "x-amz-request-id";
|
||||
public static final String REQUEST_TOKEN = "x-amz-id-2";
|
||||
|
||||
}
|
|
@ -21,7 +21,7 @@
|
|||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.aws.s3;
|
||||
package org.jclouds.aws.s3.util;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
|
@ -21,7 +21,7 @@
|
|||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.aws.s3;
|
||||
package org.jclouds.aws.s3.util;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
@ -231,7 +231,7 @@ public class S3Utils extends Utils {
|
|||
|
||||
if (o instanceof InputStream) {
|
||||
String returnVal = toStringAndClose((InputStream) o);
|
||||
if (object.getMetaData().getContentType().indexOf("xml") >= 0) {
|
||||
if (object.getMetadata().getContentType().indexOf("xml") >= 0) {
|
||||
|
||||
}
|
||||
return returnVal;
|
|
@ -23,9 +23,9 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.xml;
|
||||
|
||||
import org.jclouds.aws.s3.DateService;
|
||||
import org.jclouds.aws.s3.S3Utils;
|
||||
import org.jclouds.aws.s3.domain.S3Object;
|
||||
import org.jclouds.aws.s3.util.DateService;
|
||||
import org.jclouds.aws.s3.util.S3Utils;
|
||||
import org.jclouds.http.commands.callables.xml.ParseSax;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
@ -38,25 +38,25 @@ import com.google.inject.Inject;
|
|||
public class CopyObjectHandler extends
|
||||
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() {
|
||||
return metaData;
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public void endElement(String uri, String name, String qName) {
|
||||
if (qName.equals("ETag")) {
|
||||
metaData.setMd5(S3Utils.fromHexString(currentText.toString()
|
||||
metadata.setMd5(S3Utils.fromHexString(currentText.toString()
|
||||
.replaceAll("\"", "")));
|
||||
} else if (qName.equals("LastModified")) {
|
||||
metaData.setLastModified(dateParser
|
||||
metadata.setLastModified(dateParser
|
||||
.dateTimeFromXMLFormat(currentText.toString()));
|
||||
}
|
||||
currentText = new StringBuilder();
|
||||
|
|
|
@ -29,6 +29,9 @@ import org.jclouds.http.commands.callables.xml.ParseSax;
|
|||
/**
|
||||
* Parses the error from the Amazon S3 REST API.
|
||||
*
|
||||
* @see http
|
||||
* ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingRESTError
|
||||
* .html
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ErrorHandler extends ParseSax.HandlerWithResult<S3Error> {
|
||||
|
@ -46,20 +49,10 @@ public class ErrorHandler extends ParseSax.HandlerWithResult<S3Error> {
|
|||
error.setCode(currentText.toString());
|
||||
} else if (qName.equals("Message")) {
|
||||
error.setMessage(currentText.toString());
|
||||
} else if (qName.equals("Resource")) {
|
||||
error.setResource(currentText.toString());
|
||||
} else if (qName.equals("RequestId")) {
|
||||
error.setRequestId(currentText.toString());
|
||||
} else if (qName.equals("HostId")) {
|
||||
error.setHostId(currentText.toString());
|
||||
} else if (qName.equals("Header")) {
|
||||
error.setHeader(currentText.toString());
|
||||
} else if (qName.equals("SignatureProvided")) {
|
||||
error.setSignatureProvided(currentText.toString());
|
||||
} else if (qName.equals("StringToSign")) {
|
||||
error.setStringToSign(currentText.toString());
|
||||
} else if (qName.equals("StringToSignBytes")) {
|
||||
error.setStringToSignBytes(currentText.toString());
|
||||
} else if (!qName.equals("Error")) {
|
||||
error.getDetails().put(qName, currentText.toString());
|
||||
}
|
||||
currentText = new StringBuilder();
|
||||
}
|
||||
|
|
|
@ -26,17 +26,21 @@ package org.jclouds.aws.s3.xml;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.aws.s3.DateService;
|
||||
import org.jclouds.aws.s3.domain.CanonicalUser;
|
||||
import org.jclouds.aws.s3.domain.S3Bucket;
|
||||
import org.jclouds.aws.s3.domain.S3Owner;
|
||||
import org.jclouds.aws.s3.util.DateService;
|
||||
import org.jclouds.http.commands.callables.xml.ParseSax;
|
||||
import org.xml.sax.Attributes;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* Parses the response from Amazon S3 GET Service command.
|
||||
* Parses the following XML document:
|
||||
* <p/>
|
||||
* ListAllMyBucketsResult xmlns="http://doc.s3.amazonaws.com/2006-03-01"
|
||||
*
|
||||
* @see http
|
||||
* ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTServiceGET
|
||||
* .html
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ListAllMyBucketsHandler extends
|
||||
|
@ -44,7 +48,7 @@ public class ListAllMyBucketsHandler extends
|
|||
|
||||
private List<S3Bucket.Metadata> buckets = new ArrayList<S3Bucket.Metadata>();
|
||||
private S3Bucket.Metadata currentS3Bucket;
|
||||
private S3Owner currentOwner;
|
||||
private CanonicalUser currentOwner;
|
||||
private StringBuilder currentText = new StringBuilder();
|
||||
|
||||
private final DateService dateParser;
|
||||
|
@ -58,21 +62,13 @@ public class ListAllMyBucketsHandler extends
|
|||
return buckets;
|
||||
}
|
||||
|
||||
public void startElement(String uri, String name, String qName,
|
||||
Attributes attrs) {
|
||||
if (qName.equals("Bucket")) {
|
||||
} else if (qName.equals("Owner")) {
|
||||
currentOwner = new S3Owner();
|
||||
}
|
||||
}
|
||||
|
||||
public void endElement(String uri, String name, String qName) {
|
||||
if (qName.equals("ID")) { // owner stuff
|
||||
currentOwner.setId(currentText.toString());
|
||||
currentOwner = new CanonicalUser(currentText.toString());
|
||||
} else if (qName.equals("DisplayName")) {
|
||||
currentOwner.setDisplayName(currentText.toString());
|
||||
} else if (qName.equals("Bucket")) {
|
||||
currentS3Bucket.setCanonicalUser(currentOwner);
|
||||
currentS3Bucket.setOwner(currentOwner);
|
||||
buckets.add(currentS3Bucket);
|
||||
} else if (qName.equals("Name")) {
|
||||
currentS3Bucket = new S3Bucket.Metadata(currentText.toString());
|
||||
|
|
|
@ -25,82 +25,79 @@ package org.jclouds.aws.s3.xml;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import org.jclouds.aws.s3.DateService;
|
||||
import org.jclouds.aws.s3.S3Utils;
|
||||
import org.jclouds.aws.s3.domain.CanonicalUser;
|
||||
import org.jclouds.aws.s3.domain.S3Bucket;
|
||||
import org.jclouds.aws.s3.domain.S3Object;
|
||||
import org.jclouds.aws.s3.domain.S3Owner;
|
||||
import org.jclouds.aws.s3.util.DateService;
|
||||
import org.jclouds.aws.s3.util.S3Utils;
|
||||
import org.jclouds.http.commands.callables.xml.ParseSax;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* // TODO: Adrian: Document this!
|
||||
* Parses the following XML document:
|
||||
* <p/>
|
||||
* ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01"
|
||||
*
|
||||
* @see http
|
||||
* ://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET
|
||||
* .html
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ListBucketHandler extends ParseSax.HandlerWithResult<S3Bucket> {
|
||||
private S3Bucket s3Bucket;
|
||||
private S3Object.Metadata currentObjectMetadata;
|
||||
private CanonicalUser currentOwner;
|
||||
private StringBuilder currentText = new StringBuilder();
|
||||
|
||||
private final DateService dateParser;
|
||||
|
||||
@Inject
|
||||
public ListBucketHandler(DateService dateParser) {
|
||||
this.dateParser = dateParser;
|
||||
}
|
||||
|
||||
public S3Bucket getResult() {
|
||||
return s3Bucket;
|
||||
}
|
||||
|
||||
public void setBucketName(String bucketName) {
|
||||
this.s3Bucket = new S3Bucket(bucketName);
|
||||
this.s3Bucket = new S3Bucket(checkNotNull(bucketName, "bucketName"));
|
||||
}
|
||||
|
||||
private S3Bucket s3Bucket;
|
||||
private S3Object.Metadata currentObjectMetaData;
|
||||
private S3Owner currentOwner;
|
||||
private StringBuilder currentText = new StringBuilder();
|
||||
@Inject
|
||||
private DateService dateParser;
|
||||
private boolean inCommonPrefixes;
|
||||
|
||||
@Override
|
||||
public void startDocument() throws SAXException {
|
||||
checkNotNull(s3Bucket, "s3Bucket");
|
||||
s3Bucket.getContents().clear();
|
||||
s3Bucket.getCommonPrefixes().clear();
|
||||
super.startDocument();
|
||||
}
|
||||
|
||||
public void startElement(String uri, String name, String qName,
|
||||
Attributes attrs) {
|
||||
if (qName.equals("Contents")) {
|
||||
} else if (qName.equals("Owner")) {
|
||||
currentOwner = new S3Owner();
|
||||
} else if (qName.equals("CommonPrefixes")) {
|
||||
if (qName.equals("CommonPrefixes")) {
|
||||
inCommonPrefixes = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void endElement(String uri, String name, String qName) {
|
||||
|
||||
if (qName.equals("ID")) { // owner stuff
|
||||
currentOwner.setId(currentText.toString());
|
||||
if (qName.equals("ID")) {
|
||||
currentOwner = new CanonicalUser(currentText.toString());
|
||||
} 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
|
||||
currentObjectMetadata.setLastModified(dateParser
|
||||
.dateTimeFromXMLFormat(currentText.toString()));
|
||||
} else if (qName.equals("ETag")) {
|
||||
currentObjectMetaData.setMd5(S3Utils.fromHexString(currentText
|
||||
currentObjectMetadata.setMd5(S3Utils.fromHexString(currentText
|
||||
.toString().replaceAll("\"", "")));
|
||||
} else if (qName.equals("Size")) {
|
||||
currentObjectMetaData.setSize(Long
|
||||
currentObjectMetadata.setSize(Long
|
||||
.parseLong(currentText.toString()));
|
||||
} else if (qName.equals("Owner")) {
|
||||
currentObjectMetaData.setOwner(currentOwner);
|
||||
currentObjectMetadata.setOwner(currentOwner);
|
||||
} else if (qName.equals("StorageClass")) {
|
||||
currentObjectMetaData.setStorageClass(currentText.toString());
|
||||
currentObjectMetadata.setStorageClass(currentText.toString());
|
||||
} else if (qName.equals("Contents")) {
|
||||
s3Bucket.getContents().add(currentObjectMetaData);
|
||||
s3Bucket.getContents().add(currentObjectMetadata);
|
||||
} else if (qName.equals("Name")) {// bucket stuff last, as least likely
|
||||
} else if (qName.equals("Prefix")) {
|
||||
String prefix = currentText.toString().trim();
|
||||
|
|
|
@ -35,7 +35,9 @@ import com.google.inject.Inject;
|
|||
import com.google.inject.Provider;
|
||||
|
||||
/**
|
||||
* Creates Parsers needed to interpret S3 Server responses
|
||||
* Creates Parsers needed to interpret S3 Server messages. This class uses guice
|
||||
* assisted inject, which mandates the creation of many single-method
|
||||
* interfaces. These interfaces are not intended for public api.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
|
@ -44,6 +46,7 @@ public class S3ParserFactory {
|
|||
@Inject
|
||||
private GenericParseFactory<List<S3Bucket.Metadata>> parseListAllMyBucketsFactory;
|
||||
|
||||
@VisibleForTesting
|
||||
public static interface GenericParseFactory<T> {
|
||||
ParseSax<T> create(ParseSax.HandlerWithResult<T> handler);
|
||||
}
|
||||
|
@ -51,7 +54,9 @@ public class S3ParserFactory {
|
|||
@Inject
|
||||
Provider<ListAllMyBucketsHandler> ListAllMyBucketsHandlerprovider;
|
||||
|
||||
@VisibleForTesting
|
||||
/**
|
||||
* @return a parser used to handle {@link ListOwnedBuckets} responses
|
||||
*/
|
||||
public ParseSax<List<S3Bucket.Metadata>> createListBucketsParser() {
|
||||
return parseListAllMyBucketsFactory
|
||||
.create(ListAllMyBucketsHandlerprovider.get());
|
||||
|
@ -63,7 +68,9 @@ public class S3ParserFactory {
|
|||
@Inject
|
||||
Provider<ListBucketHandler> ListBucketHandlerprovider;
|
||||
|
||||
@VisibleForTesting
|
||||
/**
|
||||
* @return a parser used to handle {@link ListBucket} responses
|
||||
*/
|
||||
public ParseSax<S3Bucket> createListBucketParser() {
|
||||
return parseListBucketFactory.create(ListBucketHandlerprovider.get());
|
||||
}
|
||||
|
@ -74,7 +81,9 @@ public class S3ParserFactory {
|
|||
@Inject
|
||||
Provider<CopyObjectHandler> copyObjectHandlerProvider;
|
||||
|
||||
@VisibleForTesting
|
||||
/**
|
||||
* @return a parser used to handle {@link CopyObject} responses
|
||||
*/
|
||||
public ParseSax<S3Object.Metadata> createCopyObjectParser() {
|
||||
return parseCopyObjectFactory.create(copyObjectHandlerProvider.get());
|
||||
}
|
||||
|
@ -85,6 +94,9 @@ public class S3ParserFactory {
|
|||
@Inject
|
||||
Provider<ErrorHandler> errorHandlerProvider;
|
||||
|
||||
/**
|
||||
* @return a parser used to handle error conditions.
|
||||
*/
|
||||
public ParseSax<S3Error> createErrorParser() {
|
||||
return parseErrorFactory.create(errorHandlerProvider.get());
|
||||
}
|
||||
|
|
|
@ -46,37 +46,23 @@ import com.google.inject.assistedinject.FactoryProvider;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
public class S3ParserModule extends AbstractModule {
|
||||
private final TypeLiteral<S3ParserFactory.GenericParseFactory<List<S3Bucket.Metadata>>> listBucketsTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<List<S3Bucket.Metadata>>>() {
|
||||
};
|
||||
private final TypeLiteral<S3ParserFactory.GenericParseFactory<S3Bucket>> bucketTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<S3Bucket>>() {
|
||||
};
|
||||
private final TypeLiteral<S3ParserFactory.GenericParseFactory<S3Object.Metadata>> objectMetadataTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<S3Object.Metadata>>() {
|
||||
};
|
||||
private final TypeLiteral<S3ParserFactory.GenericParseFactory<S3Error>> errorTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<S3Error>>() {
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(new SaxModule());
|
||||
bindCallablesThatReturnParseResults();
|
||||
bindParserImplementationsToReturnTypes();
|
||||
}
|
||||
|
||||
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<S3Error>> errorTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<S3Error>>() {
|
||||
};
|
||||
|
||||
bind(listBucketsTypeLiteral).toProvider(
|
||||
FactoryProvider.newFactory(listBucketsTypeLiteral,
|
||||
new TypeLiteral<ParseSax<List<S3Bucket.Metadata>>>() {
|
||||
}));
|
||||
bind(bucketTypeLiteral).toProvider(
|
||||
FactoryProvider.newFactory(bucketTypeLiteral,
|
||||
new TypeLiteral<ParseSax<S3Bucket>>() {
|
||||
}));
|
||||
bind(objectMetaDataTypeLiteral).toProvider(
|
||||
FactoryProvider.newFactory(objectMetaDataTypeLiteral,
|
||||
new TypeLiteral<ParseSax<S3Object.Metadata>>() {
|
||||
}));
|
||||
bind(errorTypeLiteral).toProvider(
|
||||
FactoryProvider.newFactory(errorTypeLiteral,
|
||||
new TypeLiteral<ParseSax<S3Error>>() {
|
||||
}));
|
||||
|
||||
// Bind the implementations of handlers to the interfaces they implement
|
||||
private void bindParserImplementationsToReturnTypes() {
|
||||
bind(
|
||||
new TypeLiteral<ParseSax.HandlerWithResult<List<S3Bucket.Metadata>>>() {
|
||||
}).to(ListAllMyBucketsHandler.class);
|
||||
|
@ -88,4 +74,23 @@ public class S3ParserModule extends AbstractModule {
|
|||
}).to(ErrorHandler.class);
|
||||
}
|
||||
|
||||
private void bindCallablesThatReturnParseResults() {
|
||||
bind(listBucketsTypeLiteral).toProvider(
|
||||
FactoryProvider.newFactory(listBucketsTypeLiteral,
|
||||
new TypeLiteral<ParseSax<List<S3Bucket.Metadata>>>() {
|
||||
}));
|
||||
bind(bucketTypeLiteral).toProvider(
|
||||
FactoryProvider.newFactory(bucketTypeLiteral,
|
||||
new TypeLiteral<ParseSax<S3Bucket>>() {
|
||||
}));
|
||||
bind(objectMetadataTypeLiteral).toProvider(
|
||||
FactoryProvider.newFactory(objectMetadataTypeLiteral,
|
||||
new TypeLiteral<ParseSax<S3Object.Metadata>>() {
|
||||
}));
|
||||
bind(errorTypeLiteral).toProvider(
|
||||
FactoryProvider.newFactory(errorTypeLiteral,
|
||||
new TypeLiteral<ParseSax<S3Error>>() {
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
|
@ -40,7 +40,7 @@ public class S3ConnectionTest extends S3IntegrationTest {
|
|||
|
||||
@Test
|
||||
void testListBuckets() throws Exception {
|
||||
List<S3Bucket.Metadata> myBuckets = client.getOwnedBuckets().get(10,
|
||||
List<S3Bucket.Metadata> myBuckets = client.listOwnedBuckets().get(10,
|
||||
TimeUnit.SECONDS);
|
||||
for (S3Bucket.Metadata bucket : myBuckets) {
|
||||
context.createInputStreamMap(bucket.getName()).size();
|
||||
|
|
|
@ -46,6 +46,8 @@ import java.util.logging.Logger;
|
|||
|
||||
import org.jclouds.aws.s3.domain.S3Bucket;
|
||||
import org.jclouds.aws.s3.domain.S3Object;
|
||||
import org.jclouds.aws.s3.reference.S3Constants;
|
||||
import org.jclouds.aws.s3.util.S3Utils;
|
||||
import org.jclouds.http.HttpConstants;
|
||||
import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule;
|
||||
import org.testng.annotations.AfterTest;
|
||||
|
@ -54,10 +56,15 @@ import org.testng.annotations.Optional;
|
|||
import org.testng.annotations.Parameters;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
||||
import com.google.inject.Module;
|
||||
|
||||
@Test
|
||||
public class S3IntegrationTest {
|
||||
protected static final String TEST_STRING = "<apples><apple name=\"fuji\" /></apples>";
|
||||
|
||||
protected byte[] goodMd5;
|
||||
protected byte[] badMd5;
|
||||
|
||||
protected void createBucketAndEnsureEmpty(String sourceBucket)
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
|
@ -66,13 +73,11 @@ public class S3IntegrationTest {
|
|||
.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.getMetadata().setContentType("text/xml");
|
||||
sourceObject.setData(TEST_STRING);
|
||||
addObjectToBucket(sourceBucket, sourceObject);
|
||||
}
|
||||
|
@ -146,6 +151,8 @@ public class S3IntegrationTest {
|
|||
: sysAWSSecretAccessKey);
|
||||
client = context.getConnection();
|
||||
deleteEverything();
|
||||
goodMd5 = S3Utils.md5(TEST_STRING);
|
||||
badMd5 = S3Utils.md5("alf");
|
||||
}
|
||||
|
||||
protected boolean debugEnabled() {
|
||||
|
@ -168,7 +175,6 @@ public class S3IntegrationTest {
|
|||
checkNotNull(AWSSecretAccessKey, "AWSSecretAccessKey"));
|
||||
properties.setProperty(HttpConstants.PROPERTY_HTTP_SECURE, "false");
|
||||
properties.setProperty(HttpConstants.PROPERTY_HTTP_PORT, "80");
|
||||
// properties.setProperty("jclouds.http.sax.debug", "true");
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
@ -178,10 +184,10 @@ public class S3IntegrationTest {
|
|||
|
||||
protected void deleteEverything() throws Exception {
|
||||
try {
|
||||
List<S3Bucket.Metadata> metaData = client.getOwnedBuckets().get(10,
|
||||
List<S3Bucket.Metadata> metadata = client.listOwnedBuckets().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.listBucket(metaDatum.getName())
|
||||
.get(10, TimeUnit.SECONDS);
|
||||
|
|
|
@ -37,6 +37,7 @@ import java.util.Map.Entry;
|
|||
import org.apache.commons.io.IOUtils;
|
||||
import org.jclouds.aws.s3.domain.S3Object;
|
||||
import org.jclouds.aws.s3.internal.BaseS3Map;
|
||||
import org.jclouds.aws.s3.util.S3Utils;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
|
@ -141,7 +142,7 @@ public class S3ObjectMapTest extends BaseS3MapTest<S3Object> {
|
|||
for (String key : fiveInputs.keySet()) {
|
||||
S3Object object = new S3Object(key);
|
||||
object.setData(fiveInputs.get(key));
|
||||
object.getMetaData().setSize(fiveBytes.get(key).length);
|
||||
object.getMetadata().setSize(fiveBytes.get(key).length);
|
||||
newMap.put(key, object);
|
||||
}
|
||||
map.putAll(newMap);
|
||||
|
|
|
@ -25,6 +25,7 @@ package org.jclouds.aws.s3;
|
|||
|
||||
import org.bouncycastle.util.encoders.Base64;
|
||||
import org.jclouds.aws.PerformanceTest;
|
||||
import org.jclouds.aws.s3.util.S3Utils;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
|
|
@ -79,8 +79,8 @@ public class StubS3Connection implements S3Connection {
|
|||
.get(s3Bucket);
|
||||
if (!realContents.containsKey(key))
|
||||
return S3Object.Metadata.NOT_FOUND;
|
||||
S3Object.Metadata metaData = new S3Object.Metadata(key);
|
||||
return metaData;
|
||||
S3Object.Metadata metadata = new S3Object.Metadata(key);
|
||||
return metadata;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -173,8 +173,8 @@ public class StubS3Connection implements S3Connection {
|
|||
.get(s3Bucket);
|
||||
if (realContents != null) {
|
||||
for (String key : realContents.keySet()) {
|
||||
S3Object.Metadata metaData = new S3Object.Metadata(key);
|
||||
contents.add(metaData);
|
||||
S3Object.Metadata metadata = new S3Object.Metadata(key);
|
||||
contents.add(metadata);
|
||||
}
|
||||
}
|
||||
S3Bucket returnVal = new S3Bucket(s3Bucket);
|
||||
|
@ -205,7 +205,7 @@ public class StubS3Connection implements S3Connection {
|
|||
}
|
||||
}
|
||||
|
||||
public Future<List<Metadata>> getOwnedBuckets() {
|
||||
public Future<List<Metadata>> listOwnedBuckets() {
|
||||
return new FutureBase<List<S3Bucket.Metadata>>() {
|
||||
public List<S3Bucket.Metadata> get() throws InterruptedException,
|
||||
ExecutionException {
|
||||
|
|
|
@ -27,22 +27,26 @@ import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSo
|
|||
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceMd5Matches;
|
||||
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceModifiedSince;
|
||||
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceUnmodifiedSince;
|
||||
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.overrideAcl;
|
||||
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.overrideMetadataWith;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.jclouds.aws.s3.S3Headers;
|
||||
import org.jclouds.aws.s3.S3IntegrationTest;
|
||||
import org.jclouds.aws.s3.S3ResponseException;
|
||||
import org.jclouds.aws.s3.S3Utils;
|
||||
import org.jclouds.aws.s3.domain.S3Object;
|
||||
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
|
||||
import org.jclouds.aws.s3.reference.S3Headers;
|
||||
import org.jclouds.aws.s3.util.S3Utils;
|
||||
import org.jclouds.http.HttpResponseException;
|
||||
import org.joda.time.DateTime;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
|
@ -60,6 +64,25 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest {
|
|||
String sourceKey = "apples";
|
||||
String destinationKey = "pears";
|
||||
|
||||
|
||||
@Test()
|
||||
void testCannedAccessPolicyPublic() throws Exception {
|
||||
String sourceBucket = bucketPrefix + "tcapp";
|
||||
String destinationBucket = sourceBucket + "dest";
|
||||
|
||||
setupSourceBucket(sourceBucket, sourceKey);
|
||||
|
||||
createBucketAndEnsureEmpty(destinationBucket);
|
||||
client.copyObject(sourceBucket, sourceKey, destinationBucket,
|
||||
destinationKey,overrideAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, TimeUnit.SECONDS);
|
||||
|
||||
validateContent(destinationBucket, destinationKey);
|
||||
|
||||
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com/%2$s",
|
||||
destinationBucket, destinationKey));
|
||||
S3Utils.toStringAndClose(url.openStream());
|
||||
|
||||
}
|
||||
@Test()
|
||||
void testCopyObject() throws Exception {
|
||||
String sourceBucket = bucketPrefix + "testcopyobject";
|
||||
|
@ -110,7 +133,7 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest {
|
|||
destinationKey, ifSourceModifiedSince(after)).get(10,
|
||||
TimeUnit.SECONDS);
|
||||
} catch (ExecutionException e) {
|
||||
S3ResponseException ex = (S3ResponseException) e.getCause();
|
||||
HttpResponseException ex = (HttpResponseException) e.getCause();
|
||||
assertEquals(ex.getResponse().getStatusCode(), 412);
|
||||
}
|
||||
}
|
||||
|
@ -136,7 +159,7 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest {
|
|||
destinationKey, ifSourceModifiedSince(before)).get(10,
|
||||
TimeUnit.SECONDS);
|
||||
} catch (ExecutionException e) {
|
||||
S3ResponseException ex = (S3ResponseException) e.getCause();
|
||||
HttpResponseException ex = (HttpResponseException) e.getCause();
|
||||
assertEquals(ex.getResponse().getStatusCode(), 412);
|
||||
}
|
||||
}
|
||||
|
@ -145,8 +168,6 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest {
|
|||
void testCopyIfMatch() throws InterruptedException, ExecutionException,
|
||||
TimeoutException, IOException {
|
||||
String sourceBucket = bucketPrefix + "tcim";
|
||||
byte[] realMd5 = S3Utils.md5(TEST_STRING);
|
||||
byte[] badMd5 = S3Utils.md5("alf");
|
||||
|
||||
String destinationBucket = sourceBucket + "dest";
|
||||
|
||||
|
@ -154,7 +175,7 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest {
|
|||
|
||||
createBucketAndEnsureEmpty(destinationBucket);
|
||||
client.copyObject(sourceBucket, sourceKey, destinationBucket,
|
||||
destinationKey, ifSourceMd5Matches(realMd5)).get(10,
|
||||
destinationKey, ifSourceMd5Matches(goodMd5)).get(10,
|
||||
TimeUnit.SECONDS);
|
||||
validateContent(destinationBucket, destinationKey);
|
||||
|
||||
|
@ -163,7 +184,7 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest {
|
|||
destinationKey, ifSourceMd5Matches(badMd5)).get(10,
|
||||
TimeUnit.SECONDS);
|
||||
} catch (ExecutionException e) {
|
||||
S3ResponseException ex = (S3ResponseException) e.getCause();
|
||||
HttpResponseException ex = (HttpResponseException) e.getCause();
|
||||
assertEquals(ex.getResponse().getStatusCode(), 412);
|
||||
}
|
||||
}
|
||||
|
@ -172,8 +193,6 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest {
|
|||
void testCopyIfNoneMatch() throws IOException, InterruptedException,
|
||||
ExecutionException, TimeoutException {
|
||||
String sourceBucket = bucketPrefix + "tcinm";
|
||||
byte[] realMd5 = S3Utils.md5(TEST_STRING);
|
||||
byte[] badMd5 = S3Utils.md5("alf");
|
||||
|
||||
String destinationBucket = sourceBucket + "dest";
|
||||
|
||||
|
@ -187,10 +206,10 @@ public class CopyObjectIntegrationTest extends S3IntegrationTest {
|
|||
|
||||
try {
|
||||
client.copyObject(sourceBucket, sourceKey, destinationBucket,
|
||||
destinationKey, ifSourceMd5DoesntMatch(realMd5)).get(10,
|
||||
destinationKey, ifSourceMd5DoesntMatch(goodMd5)).get(10,
|
||||
TimeUnit.SECONDS);
|
||||
} catch (ExecutionException e) {
|
||||
S3ResponseException ex = (S3ResponseException) e.getCause();
|
||||
HttpResponseException ex = (HttpResponseException) e.getCause();
|
||||
assertEquals(ex.getResponse().getStatusCode(), 412);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.aws.s3.S3IntegrationTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Tests integrated functionality of all deleteBucket 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.DeleteBucketIntegrationTest")
|
||||
public class DeleteBucketIntegrationTest extends S3IntegrationTest {
|
||||
|
||||
@Test()
|
||||
void deleteBucketIfEmptyNotFound() throws Exception {
|
||||
String bucketName = bucketPrefix + "dbienf";
|
||||
assert client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Test()
|
||||
void deleteBucketIfEmptyButHasContents() throws Exception {
|
||||
String bucketName = bucketPrefix + "dbiebhc";
|
||||
createBucketAndEnsureEmpty(bucketName);
|
||||
addObjectToBucket(bucketName,"test");
|
||||
assert !client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Test()
|
||||
void deleteBucketIfEmpty() throws Exception {
|
||||
String bucketName = bucketPrefix + "dbie";
|
||||
createBucketAndEnsureEmpty(bucketName);
|
||||
assert client.deleteBucketIfEmpty(bucketName).get(10, TimeUnit.SECONDS);
|
||||
assert !client.bucketExists(bucketName).get(10, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
*
|
||||
* 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.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.aws.s3.S3IntegrationTest;
|
||||
import org.jclouds.aws.s3.S3ResponseException;
|
||||
import org.jclouds.aws.s3.domain.S3Object;
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Tests integrated functionality of all deleteObject 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.DeleteObjectIntegrationTest")
|
||||
public class DeleteObjectIntegrationTest extends S3IntegrationTest {
|
||||
|
||||
@Test()
|
||||
void deleteObjectNotFound() throws Exception {
|
||||
String bucketName = bucketPrefix + "donf";
|
||||
createBucketAndEnsureEmpty(bucketName);
|
||||
addObjectToBucket(bucketName, "test");
|
||||
assert client.deleteObject(bucketName, "test")
|
||||
.get(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteObjectNoBucket() throws Exception {
|
||||
String bucketName = bucketPrefix + "donb";
|
||||
try {
|
||||
client.deleteObject(bucketName, "test").get(10, TimeUnit.SECONDS);
|
||||
} catch (ExecutionException e) {
|
||||
assert e.getCause() instanceof S3ResponseException;
|
||||
assertEquals(((S3ResponseException) e.getCause()).getResponse()
|
||||
.getStatusCode(), 404);
|
||||
}
|
||||
}
|
||||
|
||||
@Test()
|
||||
void deleteObject() throws Exception {
|
||||
String bucketName = bucketPrefix + "do";
|
||||
createBucketAndEnsureEmpty(bucketName);
|
||||
addObjectToBucket(bucketName, "test");
|
||||
assert client.deleteObject(bucketName, "test")
|
||||
.get(10, TimeUnit.SECONDS);
|
||||
assert client.headObject(bucketName, "test").get(10, TimeUnit.SECONDS) == S3Object.Metadata.NOT_FOUND;
|
||||
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
|
||||
* Getright (C) 2009 Adrian Cole <adrian@jclouds.org>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
|
@ -23,11 +23,17 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.commands;
|
||||
|
||||
import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.*;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
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.jclouds.aws.s3.domain.S3Object;
|
||||
import org.jclouds.aws.s3.util.S3Utils;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
|
@ -41,14 +47,181 @@ import org.testng.annotations.Test;
|
|||
*/
|
||||
@Test(groups = "integration", testName = "s3.GetObjectIntegrationTest")
|
||||
public class GetObjectIntegrationTest extends S3IntegrationTest {
|
||||
//
|
||||
// @Test
|
||||
// void testGetIfModifiedSince() throws InterruptedException,
|
||||
// ExecutionException, TimeoutException, IOException {
|
||||
// String bucket = bucketPrefix + "testGetIfModifiedSince".toLowerCase();
|
||||
// String key = "apples";
|
||||
//
|
||||
// DateTime before = new DateTime();
|
||||
// setUpBucket(bucket, key);
|
||||
// DateTime after = new DateTime().plusSeconds(1);
|
||||
//
|
||||
// client.getObject(bucket, key, ifModifiedSince(before)).get(10,
|
||||
// TimeUnit.SECONDS);
|
||||
// validateContent(bucket, key);
|
||||
//
|
||||
// try {
|
||||
// client.getObject(bucket, key, ifModifiedSince(after)).get(10,
|
||||
// TimeUnit.SECONDS);
|
||||
// validateContent(bucket, key);
|
||||
// } catch (ExecutionException e) {
|
||||
// if (e.getCause() instanceof HttpResponseException) {
|
||||
// HttpResponseException ex = (HttpResponseException) e.getCause();
|
||||
// assertEquals(ex.getResponse().getStatusCode(), 304);
|
||||
// } else {
|
||||
// throw e;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
|
||||
//
|
||||
// @Test
|
||||
// void testGetIfUnmodifiedSince() throws InterruptedException,
|
||||
// ExecutionException, TimeoutException, IOException {
|
||||
// String bucket = bucketPrefix + "testGetIfUnmodifiedSince".toLowerCase();
|
||||
// String key = "apples";
|
||||
//
|
||||
// DateTime before = new DateTime();
|
||||
// setUpBucket(bucket, key);
|
||||
// DateTime after = new DateTime().plusSeconds(1);
|
||||
//
|
||||
// client.getObject(bucket, key, ifUnmodifiedSince(after)).get(10,
|
||||
// TimeUnit.SECONDS);
|
||||
// validateContent(bucket, key);
|
||||
//
|
||||
// try {
|
||||
// client.getObject(bucket, key, ifUnmodifiedSince(before)).get(10,
|
||||
// TimeUnit.SECONDS);
|
||||
// validateContent(bucket, key);
|
||||
// } catch (ExecutionException e) {
|
||||
// if (e.getCause() instanceof S3ResponseException) {
|
||||
// S3ResponseException ex = (S3ResponseException) e.getCause();
|
||||
// assertEquals(ex.getResponse().getStatusCode(), 412);
|
||||
// } else {
|
||||
// throw e;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testGetIfMatch() throws InterruptedException, ExecutionException,
|
||||
// TimeoutException, IOException {
|
||||
// String bucket = bucketPrefix + "testGetIfMatch".toLowerCase();
|
||||
// String key = "apples";
|
||||
//
|
||||
// setUpBucket(bucket, key);
|
||||
//
|
||||
// client.getObject(bucket, key, ifMd5Matches(goodMd5)).get(10,
|
||||
// TimeUnit.SECONDS);
|
||||
// validateContent(bucket, key);
|
||||
//
|
||||
// try {
|
||||
// client.getObject(bucket, key, ifMd5Matches(badMd5)).get(10,
|
||||
// TimeUnit.SECONDS);
|
||||
// validateContent(bucket, key);
|
||||
// } catch (ExecutionException e) {
|
||||
// if (e.getCause() instanceof S3ResponseException) {
|
||||
// S3ResponseException ex = (S3ResponseException) e.getCause();
|
||||
// assertEquals(ex.getResponse().getStatusCode(), 412);
|
||||
// } else {
|
||||
// throw e;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// void testGetIfNoneMatch() throws InterruptedException,
|
||||
// ExecutionException,
|
||||
// TimeoutException, IOException {
|
||||
// String bucket = bucketPrefix + "testGetIfNoneMatch".toLowerCase();
|
||||
// String key = "apples";
|
||||
//
|
||||
// setUpBucket(bucket, key);
|
||||
//
|
||||
// client.getObject(bucket, key, ifMd5DoesntMatch(badMd5)).get(10,
|
||||
// TimeUnit.SECONDS);
|
||||
// validateContent(bucket, key);
|
||||
//
|
||||
// try {
|
||||
// client.getObject(bucket, key, ifMd5DoesntMatch(goodMd5)).get(10,
|
||||
// TimeUnit.SECONDS);
|
||||
// validateContent(bucket, key);
|
||||
// } catch (ExecutionException e) {
|
||||
// if (e.getCause() instanceof HttpResponseException) {
|
||||
// HttpResponseException ex = (HttpResponseException) e.getCause();
|
||||
// assertEquals(ex.getResponse().getStatusCode(), 304);
|
||||
// } else {
|
||||
// throw e;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
@Test
|
||||
void testGetIfModifiedSince() throws InterruptedException, ExecutionException, TimeoutException, IOException {
|
||||
String bucket = bucketPrefix + "testGetIfModifiedSince".toLowerCase();
|
||||
void testGetRange() throws InterruptedException, ExecutionException,
|
||||
TimeoutException, IOException {
|
||||
String bucket = bucketPrefix + "testGetRange".toLowerCase();
|
||||
String key = "apples";
|
||||
|
||||
setUpBucket(bucket, key);
|
||||
S3Object object1 = client.getObject(bucket, key, range(0, 5)).get(10,
|
||||
TimeUnit.SECONDS);
|
||||
assertEquals(S3Utils.getContentAsStringAndClose(object1), TEST_STRING
|
||||
.substring(0, 6));
|
||||
|
||||
S3Object object2 = client.getObject(bucket, key,
|
||||
range(5, TEST_STRING.length())).get(10, TimeUnit.SECONDS);
|
||||
assertEquals(S3Utils.getContentAsStringAndClose(object2), TEST_STRING
|
||||
.substring(5, TEST_STRING.length()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetTwoRanges() throws InterruptedException, ExecutionException,
|
||||
TimeoutException, IOException {
|
||||
String bucket = bucketPrefix + "testGetTwoRanges".toLowerCase();
|
||||
String key = "apples";
|
||||
|
||||
setUpBucket(bucket, key);
|
||||
S3Object object = client.getObject(bucket, key,
|
||||
range(0, 5).range(5, TEST_STRING.length())).get(10,
|
||||
TimeUnit.SECONDS);
|
||||
|
||||
assertEquals(S3Utils.getContentAsStringAndClose(object), TEST_STRING);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetTail() throws InterruptedException, ExecutionException,
|
||||
TimeoutException, IOException {
|
||||
String bucket = bucketPrefix + "testGetTail".toLowerCase();
|
||||
String key = "apples";
|
||||
|
||||
setUpBucket(bucket, key);
|
||||
S3Object object = client.getObject(bucket, key, tail(5)).get(10,
|
||||
TimeUnit.SECONDS);
|
||||
assertEquals(S3Utils.getContentAsStringAndClose(object), TEST_STRING
|
||||
.substring(TEST_STRING.length() - 5));
|
||||
assertEquals(object.getContentLength(), 5);
|
||||
assertEquals(object.getMetadata().getSize(), TEST_STRING.length());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetStartAt() throws InterruptedException, ExecutionException,
|
||||
TimeoutException, IOException {
|
||||
String bucket = bucketPrefix + "testGetStartAt".toLowerCase();
|
||||
String key = "apples";
|
||||
|
||||
setUpBucket(bucket, key);
|
||||
S3Object object = client.getObject(bucket, key, startAt(5)).get(10,
|
||||
TimeUnit.SECONDS);
|
||||
assertEquals(S3Utils.getContentAsStringAndClose(object), TEST_STRING
|
||||
.substring(5, TEST_STRING.length()));
|
||||
assertEquals(object.getContentLength(), TEST_STRING.length() - 5);
|
||||
assertEquals(object.getMetadata().getSize(), TEST_STRING.length());
|
||||
}
|
||||
|
||||
private void setUpBucket(String sourceBucket, String sourceKey)
|
||||
|
@ -58,29 +231,4 @@ public class GetObjectIntegrationTest extends S3IntegrationTest {
|
|||
addObjectToBucket(sourceBucket, sourceKey);
|
||||
validateContent(sourceBucket, sourceKey);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetIfUnmodifiedSince() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetIfMatch() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetIfNoneMatch() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetWithMetadata() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetRange() {
|
||||
// TODO
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
*
|
||||
* 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.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.aws.s3.S3IntegrationTest;
|
||||
import org.jclouds.aws.s3.domain.S3Bucket;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Tests integrated functionality of all listOwnedBucket 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.ListOwnedBucketsIntegrationTest")
|
||||
public class ListOwnedBucketsIntegrationTest extends S3IntegrationTest {
|
||||
|
||||
@Test()
|
||||
void bucketDoesntExist() throws Exception {
|
||||
String bucketName = bucketPrefix + "shouldntexist";
|
||||
List<S3Bucket.Metadata> list = client.listOwnedBuckets().get(10,
|
||||
TimeUnit.SECONDS);
|
||||
assert !list.contains(new S3Bucket(bucketName));
|
||||
}
|
||||
|
||||
@Test()
|
||||
void bucketExists() throws Exception {
|
||||
String bucketName = bucketPrefix + "needstoexist";
|
||||
assert client.putBucketIfNotExists(bucketName)
|
||||
.get(10, TimeUnit.SECONDS);
|
||||
List<S3Bucket.Metadata> list = client.listOwnedBuckets().get(10,
|
||||
TimeUnit.SECONDS);
|
||||
S3Bucket.Metadata firstBucket = list.get(0);
|
||||
S3Bucket.Metadata toMatch = new S3Bucket.Metadata(bucketName);
|
||||
toMatch.setOwner(firstBucket.getOwner());
|
||||
|
||||
assert list.contains(toMatch);
|
||||
}
|
||||
}
|
|
@ -31,9 +31,9 @@ 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.jclouds.aws.s3.util.S3Utils;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
|
@ -55,7 +55,7 @@ public class PutBucketIntegrationTest extends S3IntegrationTest {
|
|||
client.putBucketIfNotExists(bucketName,
|
||||
withBucketAcl(CannedAccessPolicy.PUBLIC_READ)).get(10,
|
||||
TimeUnit.SECONDS);
|
||||
URL url = new URL(String.format("http://%1s.s3.amazonaws.com",
|
||||
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com",
|
||||
bucketName));
|
||||
S3Utils.toStringAndClose(url.openStream());
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ public class PutBucketIntegrationTest extends S3IntegrationTest {
|
|||
String bucketName = bucketPrefix + "private";
|
||||
|
||||
client.putBucketIfNotExists(bucketName).get(10, TimeUnit.SECONDS);
|
||||
URL url = new URL(String.format("http://%1s.s3.amazonaws.com",
|
||||
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com",
|
||||
bucketName));
|
||||
S3Utils.toStringAndClose(url.openStream());
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ public class PutBucketIntegrationTest extends S3IntegrationTest {
|
|||
CannedAccessPolicy.PUBLIC_READ)).get(10,
|
||||
TimeUnit.SECONDS);
|
||||
|
||||
URL url = new URL(String.format("http://%1s.s3.amazonaws.com",
|
||||
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com",
|
||||
bucketName));
|
||||
S3Utils.toStringAndClose(url.openStream());
|
||||
}
|
||||
|
|
|
@ -35,15 +35,16 @@ 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.jclouds.aws.s3.reference.S3Headers;
|
||||
import org.jclouds.aws.s3.util.S3Utils;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
||||
/**
|
||||
* Tests integrated functionality of all PutObject commands.
|
||||
* <p/>
|
||||
|
@ -70,13 +71,13 @@ public class PutObjectIntegrationTest extends S3IntegrationTest {
|
|||
@Test(dataProvider = "putTests")
|
||||
void testPutObject(String key, String type, Object content,
|
||||
Object realObject) throws Exception {
|
||||
String bucketName = bucketPrefix + "filetestsforadrian";
|
||||
String bucketName = bucketPrefix + "tpo";
|
||||
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.getMetadata().setContentType(type);
|
||||
object.setData(content);
|
||||
if (content instanceof InputStream) {
|
||||
object.generateMd5();
|
||||
|
@ -92,42 +93,42 @@ public class PutObjectIntegrationTest extends S3IntegrationTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testMetaData() throws Exception {
|
||||
String bucketName = bucketPrefix + "header";
|
||||
void testMetadata() throws Exception {
|
||||
String bucketName = bucketPrefix + "tmd";
|
||||
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(
|
||||
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(
|
||||
object.getMetadata().getUserMetadata().put(
|
||||
S3Headers.USER_METADATA_PREFIX + "adrian", "powderpuff");
|
||||
object.getMetaData().setMd5(S3Utils.md5(TEST_STRING.getBytes()));
|
||||
object.getMetadata().setMd5(S3Utils.md5(TEST_STRING.getBytes()));
|
||||
|
||||
addObjectToBucket(bucketName, object);
|
||||
S3Object newObject = validateContent(bucketName, key);
|
||||
|
||||
// TODO.. why does this come back as binary/octetstring
|
||||
assertEquals(newObject.getMetaData().getContentType(),
|
||||
assertEquals(newObject.getMetadata().getContentType(),
|
||||
"binary/octet-stream");
|
||||
assertEquals(newObject.getMetaData().getContentEncoding(), "x-compress");
|
||||
assertEquals(newObject.getMetaData().getContentDisposition(),
|
||||
assertEquals(newObject.getMetadata().getContentEncoding(), "x-compress");
|
||||
assertEquals(newObject.getMetadata().getContentDisposition(),
|
||||
"attachment; filename=hello.txt");
|
||||
assertEquals(newObject.getMetaData().getCacheControl(), "no-cache");
|
||||
assertEquals(newObject.getMetaData().getSize(), TEST_STRING.length());
|
||||
assertEquals(newObject.getMetaData().getUserMetadata().values()
|
||||
assertEquals(newObject.getMetadata().getCacheControl(), "no-cache");
|
||||
assertEquals(newObject.getMetadata().getSize(), TEST_STRING.length());
|
||||
assertEquals(newObject.getMetadata().getUserMetadata().values()
|
||||
.iterator().next(), "powderpuff");
|
||||
assertEquals(newObject.getMetaData().getMd5(), S3Utils.md5(TEST_STRING
|
||||
assertEquals(newObject.getMetadata().getMd5(), S3Utils.md5(TEST_STRING
|
||||
.getBytes()));
|
||||
}
|
||||
|
||||
@Test()
|
||||
void testCannedAccessPolicyPublic() throws Exception {
|
||||
String bucketName = bucketPrefix + "aclpublic";
|
||||
String bucketName = bucketPrefix + "tcapp";
|
||||
createBucketAndEnsureEmpty(bucketName);
|
||||
String key = "hello";
|
||||
|
||||
|
@ -138,7 +139,7 @@ public class PutObjectIntegrationTest extends S3IntegrationTest {
|
|||
|
||||
withAcl(CannedAccessPolicy.PUBLIC_READ)).get(10, TimeUnit.SECONDS);
|
||||
|
||||
URL url = new URL(String.format("http://%1s.s3.amazonaws.com/%1s",
|
||||
URL url = new URL(String.format("http://%1$s.s3.amazonaws.com/%2$s",
|
||||
bucketName, key));
|
||||
S3Utils.toStringAndClose(url.openStream());
|
||||
|
||||
|
|
|
@ -116,22 +116,22 @@ public class S3CommandFactoryTest {
|
|||
|
||||
@Test
|
||||
void testCreatePutObject() {
|
||||
S3Object.Metadata metaData = createMock(S3Object.Metadata.class);
|
||||
S3Object object = new S3Object(metaData);
|
||||
expect(metaData.getSize()).andReturn(4L).atLeastOnce();
|
||||
expect(metaData.getKey()).andReturn("rawr");
|
||||
expect(metaData.getContentType()).andReturn("text/xml").atLeastOnce();
|
||||
expect(metaData.getCacheControl()).andReturn("no-cache").atLeastOnce();
|
||||
expect(metaData.getContentDisposition()).andReturn("disposition")
|
||||
S3Object.Metadata metadata = createMock(S3Object.Metadata.class);
|
||||
S3Object object = new S3Object(metadata);
|
||||
expect(metadata.getSize()).andReturn(4L).atLeastOnce();
|
||||
expect(metadata.getKey()).andReturn("rawr");
|
||||
expect(metadata.getContentType()).andReturn("text/xml").atLeastOnce();
|
||||
expect(metadata.getCacheControl()).andReturn("no-cache").atLeastOnce();
|
||||
expect(metadata.getContentDisposition()).andReturn("disposition")
|
||||
.atLeastOnce();
|
||||
expect(metaData.getContentEncoding()).andReturn("encoding")
|
||||
expect(metadata.getContentEncoding()).andReturn("encoding")
|
||||
.atLeastOnce();
|
||||
expect(metaData.getMd5()).andReturn("encoding".getBytes())
|
||||
expect(metadata.getMd5()).andReturn("encoding".getBytes())
|
||||
.atLeastOnce();
|
||||
Multimap<String, String> userMdata = HashMultimap.create();
|
||||
expect(metaData.getUserMetadata()).andReturn(userMdata).atLeastOnce();
|
||||
expect(metadata.getUserMetadata()).andReturn(userMdata).atLeastOnce();
|
||||
|
||||
replay(metaData);
|
||||
replay(metadata);
|
||||
object.setData("<a></a>");
|
||||
|
||||
assert commandFactory.createPutObject("test", object,
|
||||
|
@ -145,13 +145,13 @@ public class S3CommandFactoryTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testCreateHeadMetaData() {
|
||||
assert commandFactory.createHeadMetaData("test", "blah") != null;
|
||||
void testCreateHeadMetadata() {
|
||||
assert commandFactory.createHeadMetadata("test", "blah") != null;
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateListAllMyBuckets() {
|
||||
assert commandFactory.createGetMetaDataForOwnedBuckets() != null;
|
||||
assert commandFactory.createGetMetadataForOwnedBuckets() != null;
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -35,10 +35,10 @@ import java.util.concurrent.ExecutorCompletionService;
|
|||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jclouds.aws.PerformanceTest;
|
||||
import org.jclouds.aws.s3.S3Utils;
|
||||
import org.jclouds.aws.s3.domain.CanonicalUser;
|
||||
import org.jclouds.aws.s3.domain.S3Bucket;
|
||||
import org.jclouds.aws.s3.domain.S3Object;
|
||||
import org.jclouds.aws.s3.domain.S3Owner;
|
||||
import org.jclouds.aws.s3.util.S3Utils;
|
||||
import org.jclouds.aws.s3.xml.CopyObjectHandler;
|
||||
import org.jclouds.aws.s3.xml.ListBucketHandler;
|
||||
import org.jclouds.aws.s3.xml.S3ParserFactory;
|
||||
|
@ -122,11 +122,10 @@ public class S3ParserTest extends PerformanceTest {
|
|||
DateTime date2 = bucket2.getCreationDate();
|
||||
assert date2.equals(expectedDate2);
|
||||
assert s3Buckets.size() == 2;
|
||||
S3Owner owner = new S3Owner();
|
||||
owner
|
||||
.setId("e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0");
|
||||
assert bucket1.getCanonicalUser().equals(owner);
|
||||
assert bucket2.getCanonicalUser().equals(owner);
|
||||
CanonicalUser owner = new CanonicalUser(
|
||||
"e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0");
|
||||
assert bucket1.getOwner().equals(owner);
|
||||
assert bucket2.getOwner().equals(owner);
|
||||
}
|
||||
|
||||
public static final String listBucketResult = "<ListBucketHandler xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Name>adrianjbosstest</Name><Prefix></Prefix><Marker></Marker><MaxKeys>1000</MaxKeys><IsTruncated>false</IsTruncated><Contents><Key>3366</Key><LastModified>2009-03-12T02:00:13.000Z</LastModified><ETag>"9d7bb64e8e18ee34eec06dd2cf37b766"</ETag><Size>136</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents></ListBucketHandler>";
|
||||
|
@ -140,15 +139,14 @@ public class S3ParserTest extends PerformanceTest {
|
|||
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
|
||||
.format("expected %1s, but got %1s", expected, object
|
||||
assert object.getLastModified().equals(expected) : String.format(
|
||||
"expected %1$s, but got %1$s", expected, object
|
||||
.getLastModified());
|
||||
assertEquals(S3Utils.toHexString(object.getMd5()),
|
||||
"9d7bb64e8e18ee34eec06dd2cf37b766");
|
||||
assert object.getSize() == 136;
|
||||
S3Owner owner = new S3Owner();
|
||||
owner
|
||||
.setId("e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0");
|
||||
CanonicalUser owner = new CanonicalUser(
|
||||
"e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0");
|
||||
owner.setDisplayName("ferncam");
|
||||
assert object.getOwner().equals(owner);
|
||||
assert object.getStorageClass().equals("STANDARD");
|
||||
|
|
|
@ -1,92 +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.commands.callables;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Test
|
||||
public class DeleteBucketCallableTest {
|
||||
|
||||
// private HttpFutureCommand.ResponseCallable<Boolean> callable = null;
|
||||
//
|
||||
// @BeforeMethod
|
||||
// void setUp() {
|
||||
// callable = new DeleteBucketCallable();
|
||||
// }
|
||||
//
|
||||
// @AfterMethod
|
||||
// void tearDown() {
|
||||
// callable = null;
|
||||
// }
|
||||
//
|
||||
// @Test(expectedExceptions = HttpException.class)
|
||||
// public void testExceptionWhenNoContentOn409() throws Exception {
|
||||
// HttpResponse response = createMock(HttpResponse.class);
|
||||
// expect(response.getStatusCode()).andReturn(409).atLeastOnce();
|
||||
// expect(response.getContent()).andReturn(null);
|
||||
// replay(response);
|
||||
// callable.setResponse(response);
|
||||
// callable.call();
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testExceptionWhenIOExceptionOn409() throws
|
||||
// ExecutionException,
|
||||
// InterruptedException, TimeoutException, IOException {
|
||||
// HttpResponse response = createMock(HttpResponse.class);
|
||||
// expect(response.getStatusCode()).andReturn(409).atLeastOnce();
|
||||
// RuntimeException exception = new RuntimeException("bad");
|
||||
// expect(response.getContent()).andThrow(exception);
|
||||
// replay(response);
|
||||
// callable.setResponse(response);
|
||||
// try {
|
||||
// callable.call();
|
||||
// } catch (Exception e) {
|
||||
// assert e.equals(exception);
|
||||
// }
|
||||
// verify(response);
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testFalseWhenBucketNotEmptyOn409() throws Exception {
|
||||
// HttpResponse response = createMock(HttpResponse.class);
|
||||
// expect(response.getStatusCode()).andReturn(409).atLeastOnce();
|
||||
// expect(response.getContent()).andReturn(
|
||||
// IOUtils.toInputStream("BucketNotEmpty")).atLeastOnce();
|
||||
// replay(response);
|
||||
// callable.setResponse(response);
|
||||
// assert !callable.call().booleanValue();
|
||||
// verify(response);
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testResponseOk() throws Exception {
|
||||
// HttpResponse response = createMock(HttpResponse.class);
|
||||
// expect(response.getStatusCode()).andReturn(204).atLeastOnce();
|
||||
// replay(response);
|
||||
// callable.setResponse(response);
|
||||
// assertEquals(callable.call(), new Boolean(true));
|
||||
// verify(response);
|
||||
// }
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package org.jclouds.aws.s3.commands.callables;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
import static org.easymock.classextension.EasyMock.*;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jclouds.aws.s3.domain.S3Object;
|
||||
import org.jclouds.aws.s3.domain.S3Object.Metadata;
|
||||
import org.jclouds.http.HttpException;
|
||||
import org.jclouds.http.HttpHeaders;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.testng.annotations.AfterMethod;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public class ParseObjectFromHeadersAndHttpContentTest {
|
||||
ParseObjectFromHeadersAndHttpContent callable;
|
||||
ParseMetadataFromHeaders metadataParser;
|
||||
|
||||
@BeforeMethod
|
||||
void setUp() {
|
||||
metadataParser = createMock(ParseMetadataFromHeaders.class);
|
||||
callable = new ParseObjectFromHeadersAndHttpContent(metadataParser);
|
||||
}
|
||||
|
||||
@AfterMethod
|
||||
void tearDown() {
|
||||
callable = null;
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalStateException.class)
|
||||
public void testCall() throws HttpException {
|
||||
HttpResponse response = createMock(HttpResponse.class);
|
||||
expect(response.getStatusCode()).andReturn(409).atLeastOnce();
|
||||
expect(response.getContent()).andReturn(null);
|
||||
replay(response);
|
||||
callable.setResponse(response);
|
||||
callable.call();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseContentLengthWhenContentRangeSet()
|
||||
throws HttpException {
|
||||
HttpResponse response = createMock(HttpResponse.class);
|
||||
metadataParser.setResponse(response);
|
||||
Metadata meta = createMock(Metadata.class);
|
||||
expect(metadataParser.call()).andReturn(meta);
|
||||
expect(meta.getSize()).andReturn(-1l);
|
||||
meta.setSize(-1l);
|
||||
expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH))
|
||||
.andReturn("10485760").atLeastOnce();
|
||||
expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_RANGE))
|
||||
.andReturn("0-10485759/20232760").atLeastOnce();
|
||||
meta.setSize(20232760l);
|
||||
expect(meta.getSize()).andReturn(20232760l);
|
||||
|
||||
expect(response.getStatusCode()).andReturn(200).atLeastOnce();
|
||||
expect(response.getContent()).andReturn(IOUtils.toInputStream("test"));
|
||||
replay(response);
|
||||
replay(metadataParser);
|
||||
replay(meta);
|
||||
|
||||
callable.setResponse(response);
|
||||
S3Object object = callable.call();
|
||||
assertEquals(object.getContentLength(), 10485760);
|
||||
assertEquals(object.getMetadata().getSize(), 20232760);
|
||||
assertEquals(object.getContentRange(), "0-10485759/20232760");
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -27,6 +27,7 @@ import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSo
|
|||
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceMd5Matches;
|
||||
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceModifiedSince;
|
||||
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.ifSourceUnmodifiedSince;
|
||||
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.overrideAcl;
|
||||
import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.overrideMetadataWith;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNull;
|
||||
|
@ -34,8 +35,10 @@ import static org.testng.Assert.assertTrue;
|
|||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import org.jclouds.aws.s3.DateService;
|
||||
import org.jclouds.aws.s3.S3Utils;
|
||||
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
|
||||
import org.jclouds.aws.s3.reference.S3Headers;
|
||||
import org.jclouds.aws.s3.util.DateService;
|
||||
import org.jclouds.aws.s3.util.S3Utils;
|
||||
import org.joda.time.DateTime;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
@ -311,4 +314,26 @@ public class CopyObjectOptionsTest {
|
|||
assertTrue(headers.containsValue(value));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAclDefault() {
|
||||
CopyObjectOptions options = new CopyObjectOptions();
|
||||
assertEquals(options.getAcl(), CannedAccessPolicy.PRIVATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAclStatic() {
|
||||
CopyObjectOptions options = overrideAcl(CannedAccessPolicy.AUTHENTICATED_READ);
|
||||
assertEquals(options.getAcl(), CannedAccessPolicy.AUTHENTICATED_READ);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuildRequestHeadersACL() throws UnsupportedEncodingException {
|
||||
|
||||
Multimap<String, String> headers = overrideAcl(
|
||||
CannedAccessPolicy.AUTHENTICATED_READ).buildRequestHeaders();
|
||||
assertEquals(headers.get(S3Headers.CANNED_ACL).iterator().next(),
|
||||
CannedAccessPolicy.AUTHENTICATED_READ.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.commands.options;
|
||||
|
||||
import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.startAt;
|
||||
import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.tail;
|
||||
import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.ifMd5DoesntMatch;
|
||||
import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.ifMd5Matches;
|
||||
import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.ifModifiedSince;
|
||||
|
@ -33,8 +35,8 @@ import static org.testng.Assert.assertNull;
|
|||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import org.jclouds.aws.s3.DateService;
|
||||
import org.jclouds.aws.s3.S3Utils;
|
||||
import org.jclouds.aws.s3.util.DateService;
|
||||
import org.jclouds.aws.s3.util.S3Utils;
|
||||
import org.joda.time.DateTime;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
@ -128,6 +130,58 @@ public class GetObjectOptionsTest {
|
|||
assertEquals(options.getRange(), "bytes=0-1024");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRangeZeroToFive() {
|
||||
GetObjectOptions options = new GetObjectOptions();
|
||||
options.range(0, 5);
|
||||
assertEquals(options.getRange(), "bytes=0-5");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTail() {
|
||||
GetObjectOptions options = new GetObjectOptions();
|
||||
options.tail(100);
|
||||
assertEquals(options.getRange(), "bytes=-100");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTailStatic() {
|
||||
GetObjectOptions options = tail(100);
|
||||
assertEquals(options.getRange(), "bytes=-100");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testTailFail() {
|
||||
GetObjectOptions options = new GetObjectOptions();
|
||||
options.tail(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartAt() {
|
||||
GetObjectOptions options = new GetObjectOptions();
|
||||
options.startAt(100);
|
||||
assertEquals(options.getRange(), "bytes=100-");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartAtStatic() {
|
||||
GetObjectOptions options = startAt(100);
|
||||
assertEquals(options.getRange(), "bytes=100-");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testStartAtFail() {
|
||||
GetObjectOptions options = new GetObjectOptions();
|
||||
options.startAt(-1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRangeZeroToFiveAnd10through100() {
|
||||
GetObjectOptions options = new GetObjectOptions();
|
||||
options.range(0, 5).range(10, 100);
|
||||
assertEquals(options.getRange(), "bytes=0-5,10-100");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullRange() {
|
||||
GetObjectOptions options = new GetObjectOptions();
|
||||
|
@ -140,17 +194,17 @@ public class GetObjectOptionsTest {
|
|||
bytes1to1024(options);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalStateException.class)
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testRangeNegative1() {
|
||||
range(-1, 0);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalStateException.class)
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testRangeNegative2() {
|
||||
range(0, -1);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalStateException.class)
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testRangeNegative() {
|
||||
range(-1, -1);
|
||||
}
|
||||
|
@ -209,7 +263,7 @@ public class GetObjectOptionsTest {
|
|||
assertEquals(match, expected);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalStateException.class)
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testIfUnmodifiedAfterModified() {
|
||||
ifModifiedSince(now).ifUnmodifiedSince(now);
|
||||
|
||||
|
@ -221,19 +275,19 @@ public class GetObjectOptionsTest {
|
|||
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalStateException.class)
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testIfUnmodifiedAfterMd5DoesntMatch()
|
||||
throws UnsupportedEncodingException {
|
||||
ifMd5DoesntMatch(testBytes).ifUnmodifiedSince(now);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalStateException.class)
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testIfModifiedAfterUnmodified() {
|
||||
ifUnmodifiedSince(now).ifModifiedSince(now);
|
||||
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalStateException.class)
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testIfModifiedAfterMd5Matches()
|
||||
throws UnsupportedEncodingException {
|
||||
ifMd5Matches(testBytes).ifModifiedSince(now);
|
||||
|
@ -245,7 +299,7 @@ public class GetObjectOptionsTest {
|
|||
ifMd5DoesntMatch(testBytes).ifModifiedSince(now);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalStateException.class)
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testMd5MatchesAfterIfModified()
|
||||
throws UnsupportedEncodingException {
|
||||
ifModifiedSince(now).ifMd5Matches(testBytes);
|
||||
|
@ -258,7 +312,7 @@ public class GetObjectOptionsTest {
|
|||
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalStateException.class)
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testMd5MatchesAfterMd5DoesntMatch()
|
||||
throws UnsupportedEncodingException {
|
||||
ifMd5DoesntMatch(testBytes).ifMd5Matches(testBytes);
|
||||
|
@ -270,14 +324,14 @@ public class GetObjectOptionsTest {
|
|||
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalStateException.class)
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testMd5DoesntMatchAfterIfUnmodified()
|
||||
throws UnsupportedEncodingException {
|
||||
ifUnmodifiedSince(now).ifMd5DoesntMatch(testBytes);
|
||||
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalStateException.class)
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testMd5DoesntMatchAfterMd5Matches()
|
||||
throws UnsupportedEncodingException {
|
||||
ifMd5Matches(testBytes).ifMd5DoesntMatch(testBytes);
|
||||
|
|
|
@ -30,11 +30,12 @@ import static org.testng.Assert.assertNull;
|
|||
|
||||
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.jclouds.aws.s3.reference.S3Headers;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,10 +28,11 @@ 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.jclouds.aws.s3.reference.S3Headers;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,8 +25,9 @@ package org.jclouds.aws.s3.config;
|
|||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.jclouds.aws.s3.S3Constants;
|
||||
import org.jclouds.aws.s3.filters.ParseS3ErrorFromXmlContent;
|
||||
import org.jclouds.aws.s3.reference.S3Constants;
|
||||
import org.jclouds.http.CloseContentAndSetExceptionHandler;
|
||||
import org.jclouds.http.HttpResponseHandler;
|
||||
import org.jclouds.http.annotation.ClientErrorHandler;
|
||||
import org.jclouds.http.annotation.RedirectHandler;
|
||||
|
@ -36,6 +37,7 @@ import org.testng.annotations.AfterMethod;
|
|||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
|
@ -118,7 +120,7 @@ public class S3ContextModuleTest {
|
|||
RedirectHandlerTest error = injector
|
||||
.getInstance(RedirectHandlerTest.class);
|
||||
assertEquals(error.errorHandler.getClass(),
|
||||
ParseS3ErrorFromXmlContent.class);
|
||||
CloseContentAndSetExceptionHandler.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -39,7 +39,7 @@ public class S3ObjectTest {
|
|||
S3Object object = new S3Object("test");
|
||||
File file = new File("hello.txt");
|
||||
object.setData(file);
|
||||
assertEquals(object.getMetaData().getContentType(),
|
||||
assertEquals(object.getMetadata().getContentType(),
|
||||
ContentTypes.UNKNOWN_MIME_TYPE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,11 +26,13 @@ package org.jclouds.aws.s3.filters;
|
|||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.name.Names;
|
||||
import org.jclouds.aws.s3.DateService;
|
||||
import org.jclouds.aws.s3.S3Constants;
|
||||
|
||||
import org.jclouds.aws.s3.reference.S3Constants;
|
||||
import org.jclouds.aws.s3.util.DateService;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
||||
|
||||
@Test(groups = "unit", sequential = true, testName = "s3.RequestAuthorizeSignatureTest")
|
||||
public class RequestAuthorizeSignatureTest {
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.xml;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jclouds.aws.s3.domain.S3Error;
|
||||
|
@ -31,7 +31,6 @@ import org.jclouds.http.HttpException;
|
|||
import org.jclouds.http.commands.callables.xml.ParseSax;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
||||
@Test
|
||||
public class ErrorHandlerTest extends BaseHandlerTest {
|
||||
public static final String errorFromAmazonIfYouDontRemoveTransferEncodingHeader = "<Error><Code>NotImplemented</Code><Message>A header you provided implies functionality that is not implemented</Message><Header>Transfer-Encoding</Header><RequestId>7C59925D75D15561</RequestId><HostId>fbskVU51OZJg2yZS/wNIxoE2PmCf0ZqFd0iH6Vrzw0uKG3KmokswBytL/Bfp/GWb</HostId></Error>";
|
||||
|
@ -46,9 +45,9 @@ public class ErrorHandlerTest extends BaseHandlerTest {
|
|||
assertEquals(error.getCode(), "NotImplemented");
|
||||
assertEquals(error.getMessage(),
|
||||
"A header you provided implies functionality that is not implemented");
|
||||
assertEquals(error.getHeader(), "Transfer-Encoding");
|
||||
assertEquals(error.getDetails().get("Header"), "Transfer-Encoding");
|
||||
assertEquals(error.getRequestId(), "7C59925D75D15561");
|
||||
assertEquals(error.getHostId(),
|
||||
assertEquals(error.getDetails().get("HostId"),
|
||||
"fbskVU51OZJg2yZS/wNIxoE2PmCf0ZqFd0iH6Vrzw0uKG3KmokswBytL/Bfp/GWb");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,54 +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.
|
||||
====================================================================
|
||||
====
|
||||
This samples uses the Google App Engine for Java SDK located at http://googleappengine.googlecode.com/files/appengine-java-sdk-1.2.0.zip
|
||||
|
||||
Please unzip the above file and modify your maven settings.xml like below before attempting to run 'mvn install'
|
||||
|
||||
<profile>
|
||||
<id>appengine</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<properties>
|
||||
<appengine.home>/path/to/appengine-java-sdk-1.2.0</appengine.home>
|
||||
</properties>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>aws</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<properties>
|
||||
<jclouds.aws.accesskeyid>YOUR_ACCESS_KEY_ID</jclouds.aws.accesskeyid>
|
||||
<jclouds.aws.secretaccesskey>YOUR_SECRET_KEY</jclouds.aws.secretaccesskey>
|
||||
</properties>
|
||||
</profile>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jclouds</id>
|
||||
<url>http://jclouds.googlecode.com/svn/trunk/repo</url>
|
||||
</repository>
|
||||
</repositories>
|
|
@ -1,194 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
$HeadURL$
|
||||
$Revision$
|
||||
$Date$
|
||||
|
||||
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.html
|
||||
|
||||
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.
|
||||
====================================================================
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>jclouds-project</artifactId>
|
||||
<groupId>org.jclouds</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<relativePath>../../project/pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jclouds-gae-s3-example</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<name>JClouds Sample for Google App Engine</name>
|
||||
<description>JClouds Sample for Google App Engine</description>
|
||||
|
||||
<properties>
|
||||
<!-- note you must set the property ${appengine.home} to a valid extraction of appengine-java-sdk -->
|
||||
<appengine.home>/Users/adriancole/Desktop/appengine-java-sdk-1.2.0</appengine.home>
|
||||
<devappserver.address>localhost</devappserver.address>
|
||||
<devappserver.port>8088</devappserver.port>
|
||||
<jclouds.aws.accesskeyid></jclouds.aws.accesskeyid>
|
||||
<jclouds.aws.secretaccesskey></jclouds.aws.secretaccesskey>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>guice-snapshot</id>
|
||||
<url>http://guice-maven.googlecode.com/svn/trunk</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>Main Maven Repo</id>
|
||||
<url>http://repo1.maven.org/maven2/</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-gae</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-s3</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-s3</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
<type>test-jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.guice</groupId>
|
||||
<artifactId>guice-servlet</artifactId>
|
||||
<version>2.0-r943</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>standard</artifactId>
|
||||
<groupId>taglibs</groupId>
|
||||
<version>1.1.2</version>
|
||||
<type>jar</type>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>jstl</artifactId>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<version>1.1.2</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.geronimo.specs</groupId>
|
||||
<artifactId>geronimo-el_1.0_spec</artifactId>
|
||||
<version>1.0.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.geronimo.specs</groupId>
|
||||
<artifactId>geronimo-jsp_2.1_spec</artifactId>
|
||||
<version>1.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.geronimo.specs</groupId>
|
||||
<artifactId>geronimo-servlet_2.5_spec</artifactId>
|
||||
<version>1.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.appengine</groupId>
|
||||
<artifactId>appengine-tools-api</artifactId>
|
||||
<version>1.2.0</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${appengine.home}/lib/appengine-tools-api.jar</systemPath>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<testSourceDirectory>src/it/java</testSourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.4.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>integration</id>
|
||||
<phase>integration-test</phase>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<testClassesDirectory>target/test-classes</testClassesDirectory>
|
||||
<systemProperties>
|
||||
<property>
|
||||
<name>jclouds.aws.accesskeyid</name>
|
||||
<value>${jclouds.aws.accesskeyid}</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>jclouds.aws.secretaccesskey</name>
|
||||
<value>${jclouds.aws.secretaccesskey}</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>appengine.home</name>
|
||||
<value>${appengine.home}</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>devappserver.address</name>
|
||||
<value>${devappserver.address}</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>devappserver.port</name>
|
||||
<value>${devappserver.port}</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>warfile</name>
|
||||
<value>${project.build.directory}/${project.artifactId}</value>
|
||||
</property>
|
||||
</systemProperties>
|
||||
<additionalClasspathElements>
|
||||
<additionalClasspathElement>${appengine.home}/lib/appengine-tools-api.jar
|
||||
</additionalClasspathElement>
|
||||
</additionalClasspathElements>
|
||||
<environmentVariables>
|
||||
<DEBUG>true</DEBUG>
|
||||
<SDK_BIN>${appengine.home}/bin</SDK_BIN>
|
||||
<SDK_LIB>${appengine.home}/lib</SDK_LIB>
|
||||
<SDK_CONFIG>${appengine.home}/config/sdk</SDK_CONFIG>
|
||||
</environmentVariables>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<!-- fool default surefire execution in 'test' to not find any test classes -->
|
||||
<testClassesDirectory>target/classes</testClassesDirectory>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
</project>
|
|
@ -1,75 +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.samples.googleappengine.functest;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.testng.annotations.AfterTest;
|
||||
|
||||
import com.google.appengine.tools.KickStart;
|
||||
|
||||
/**
|
||||
* Basic functionality to start a local google app engine instance.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public abstract class BaseGoogleAppEngineTest {
|
||||
|
||||
Thread server;
|
||||
URL url;
|
||||
|
||||
protected void writePropertiesAndStartServer(final String address,
|
||||
final String port, final String warfile, Properties props)
|
||||
throws IOException, FileNotFoundException, InterruptedException {
|
||||
url = new URL(String.format("http://%1s:%2s", address, port));
|
||||
|
||||
props.store(new FileOutputStream(String.format(
|
||||
"%1s/WEB-INF/jclouds.properties", warfile)), "test");
|
||||
this.server = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
KickStart
|
||||
.main(new String[] {
|
||||
"com.google.appengine.tools.development.DevAppServerMain",
|
||||
"--disable_update_check", "-a", address, "-p",
|
||||
port, warfile });
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
server.start();
|
||||
Thread.sleep(7 * 1000);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@AfterTest
|
||||
public void stopDevAppServer() throws Exception {
|
||||
server.stop();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,100 +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.samples.googleappengine.functest;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jclouds.aws.s3.S3Constants;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Optional;
|
||||
import org.testng.annotations.Parameters;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Starts up the Google App Engine for Java Development environment and deploys
|
||||
* an application which tests S3.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
@Test(groups = "integration", enabled = true, sequential = true, testName = "functionalTests")
|
||||
public class GoogleAppEngineTest extends BaseGoogleAppEngineTest {
|
||||
|
||||
private static final String sysAWSAccessKeyId = System
|
||||
.getProperty(S3Constants.PROPERTY_AWS_ACCESSKEYID);
|
||||
private static final String sysAWSSecretAccessKey = System
|
||||
.getProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY);
|
||||
|
||||
@BeforeTest
|
||||
@Parameters( { "warfile", "devappserver.address", "devappserver.port",
|
||||
S3Constants.PROPERTY_AWS_ACCESSKEYID,
|
||||
S3Constants.PROPERTY_AWS_SECRETACCESSKEY })
|
||||
public void startDevAppServer(final String warfile, final String address,
|
||||
final String port, @Optional String AWSAccessKeyId,
|
||||
@Optional String AWSSecretAccessKey) throws Exception {
|
||||
AWSAccessKeyId = AWSAccessKeyId != null ? AWSAccessKeyId
|
||||
: sysAWSAccessKeyId;
|
||||
AWSSecretAccessKey = AWSSecretAccessKey != null ? AWSSecretAccessKey
|
||||
: sysAWSSecretAccessKey;
|
||||
|
||||
checkNotNull(AWSAccessKeyId, "AWSAccessKeyId");
|
||||
checkNotNull(AWSSecretAccessKey, "AWSSecretAccessKey");
|
||||
|
||||
Properties props = new Properties();
|
||||
props.put(S3Constants.PROPERTY_AWS_ACCESSKEYID, AWSAccessKeyId);
|
||||
props.put(S3Constants.PROPERTY_AWS_SECRETACCESSKEY, AWSSecretAccessKey);
|
||||
writePropertiesAndStartServer(address, port, warfile, props);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPass() throws InterruptedException, IOException {
|
||||
InputStream i = url.openStream();
|
||||
String string = IOUtils.toString(i);
|
||||
assert string.indexOf("Hello World!") >= 0 : string;
|
||||
}
|
||||
|
||||
@Test(invocationCount = 5, enabled = true)
|
||||
public void testGuiceJCloudsSerial() throws InterruptedException,
|
||||
IOException {
|
||||
URL gurl = new URL(url, "/guice/listbuckets.s3");
|
||||
InputStream i = gurl.openStream();
|
||||
String string = IOUtils.toString(i);
|
||||
assert string.indexOf("List") >= 0 : string;
|
||||
}
|
||||
|
||||
@Test(invocationCount = 50, enabled = false, threadPoolSize = 10)
|
||||
public void testGuiceJCloudsParallel() throws InterruptedException,
|
||||
IOException {
|
||||
URL gurl = new URL(url, "/guice/listbuckets.s3");
|
||||
InputStream i = gurl.openStream();
|
||||
String string = IOUtils.toString(i);
|
||||
assert string.indexOf("List") >= 0 : string;
|
||||
}
|
||||
}
|
|
@ -1,75 +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.samples.googleappengine;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.jclouds.aws.s3.S3Context;
|
||||
import org.jclouds.aws.s3.domain.S3Bucket;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
/**
|
||||
* Shows an example of how to use @{link S3Connection} injected with Guice.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class JCloudsServlet extends HttpServlet {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Inject
|
||||
S3Context context;
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest httpServletRequest,
|
||||
HttpServletResponse httpServletResponse) throws ServletException,
|
||||
IOException {
|
||||
httpServletResponse.setContentType("text/plain");
|
||||
Writer writer = httpServletResponse.getWriter();
|
||||
try {
|
||||
List<S3Bucket.Metadata> myBuckets = context.getConnection()
|
||||
.getOwnedBuckets().get(10, TimeUnit.SECONDS);
|
||||
writer.write("List:\n");
|
||||
for (S3Bucket.Metadata bucket : myBuckets) {
|
||||
writer.write(String.format(" %1s: %2s entries%n", bucket
|
||||
.getName(), context.createInputStreamMap(
|
||||
bucket.getName()).size()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ServletException(e);
|
||||
}
|
||||
writer.flush();
|
||||
writer.close();
|
||||
}
|
||||
}
|
|
@ -1,99 +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.samples.googleappengine.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.servlet.ServletContextEvent;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jclouds.aws.s3.S3Constants;
|
||||
import org.jclouds.aws.s3.S3Context;
|
||||
import org.jclouds.aws.s3.S3ContextFactory;
|
||||
import org.jclouds.gae.config.URLFetchServiceClientModule;
|
||||
import org.jclouds.samples.googleappengine.JCloudsServlet;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.servlet.GuiceServletContextListener;
|
||||
import com.google.inject.servlet.ServletModule;
|
||||
|
||||
/**
|
||||
* Setup Logging and create Injector for use in testing S3.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public class GuiceServletConfig extends GuiceServletContextListener {
|
||||
@Inject
|
||||
S3Context context;
|
||||
String accessKeyId;
|
||||
String secretAccessKey;
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent servletContextEvent) {
|
||||
Properties props = loadJCloudsProperties(servletContextEvent);
|
||||
this.accessKeyId = props
|
||||
.getProperty(S3Constants.PROPERTY_AWS_ACCESSKEYID);
|
||||
this.secretAccessKey = props
|
||||
.getProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY);
|
||||
super.contextInitialized(servletContextEvent);
|
||||
}
|
||||
|
||||
private Properties loadJCloudsProperties(
|
||||
ServletContextEvent servletContextEvent) {
|
||||
InputStream input = servletContextEvent.getServletContext()
|
||||
.getResourceAsStream("/WEB-INF/jclouds.properties");
|
||||
Properties props = new Properties();
|
||||
try {
|
||||
props.load(input);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(input);
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Injector getInjector() {
|
||||
return S3ContextFactory.createInjector(accessKeyId, secretAccessKey,
|
||||
false, new URLFetchServiceClientModule(),
|
||||
new ServletModule() {
|
||||
@Override
|
||||
protected void configureServlets() {
|
||||
serve("*.s3").with(JCloudsServlet.class);
|
||||
requestInjection(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent servletContextEvent) {
|
||||
context.close();
|
||||
super.contextDestroyed(servletContextEvent);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue