diff --git a/README.md b/README.md index e21e8c3..a003034 100644 --- a/README.md +++ b/README.md @@ -80,8 +80,10 @@ s3proxy.keystore-path=keystore.jks s3proxy.keystore-password=password ``` -Users can also set a variety of Java and -[jclouds properties](https://github.com/jclouds/jclouds/blob/master/core/src/main/java/org/jclouds/Constants.java). +Users can also set other Java, +[jclouds](https://github.com/jclouds/jclouds/blob/master/core/src/main/java/org/jclouds/Constants.java), +and [S3Proxy](https://github.com/andrewgaul/s3proxy/blob/master/src/main/java/org/gaul/s3proxy/S3ProxyConstants.java) +properties. Limitations ----------- diff --git a/src/main/java/org/gaul/s3proxy/S3Proxy.java b/src/main/java/org/gaul/s3proxy/S3Proxy.java index bbd5ffe..af9c983 100644 --- a/src/main/java/org/gaul/s3proxy/S3Proxy.java +++ b/src/main/java/org/gaul/s3proxy/S3Proxy.java @@ -49,8 +49,9 @@ public final class S3Proxy { System.setProperty("org.eclipse.jetty.http.HttpParser.STRICT", "true"); } - public S3Proxy(BlobStore blobStore, URI endpoint, String identity, - String credential, String keyStorePath, String keyStorePassword) { + S3Proxy(BlobStore blobStore, URI endpoint, String identity, + String credential, String keyStorePath, String keyStorePassword, + boolean forceMultiPartUpload) { Preconditions.checkNotNull(blobStore); Preconditions.checkNotNull(endpoint); // TODO: allow service paths? @@ -73,7 +74,8 @@ public final class S3Proxy { connector.setHost(endpoint.getHost()); connector.setPort(endpoint.getPort()); server.addConnector(connector); - server.setHandler(new S3ProxyHandler(blobStore, identity, credential)); + server.setHandler(new S3ProxyHandler(blobStore, identity, credential, + forceMultiPartUpload)); } public void start() throws Exception { @@ -150,6 +152,9 @@ public final class S3Proxy { } } + String forceMultiPartUpload = properties.getProperty( + S3ProxyConstants.PROPERTY_FORCE_MULTI_PART_UPLOAD); + ContextBuilder builder = ContextBuilder .newBuilder(provider) .credentials(identity, credential) @@ -161,7 +166,8 @@ public final class S3Proxy { URI s3ProxyEndpoint = new URI(s3ProxyEndpointString); S3Proxy s3Proxy = new S3Proxy(context.getBlobStore(), s3ProxyEndpoint, localIdentity, localCredential, keyStorePath, - keyStorePassword); + keyStorePassword, + "true".equalsIgnoreCase(forceMultiPartUpload)); s3Proxy.start(); } } diff --git a/src/main/java/org/gaul/s3proxy/S3ProxyConstants.java b/src/main/java/org/gaul/s3proxy/S3ProxyConstants.java index 49d1851..9945129 100644 --- a/src/main/java/org/gaul/s3proxy/S3ProxyConstants.java +++ b/src/main/java/org/gaul/s3proxy/S3ProxyConstants.java @@ -29,6 +29,9 @@ public final class S3ProxyConstants { "s3proxy.keystore-path"; public static final String PROPERTY_KEYSTORE_PASSWORD = "s3proxy.keystore-password"; + /** Force all proxy-server put objects to use multi-part upload. */ + public static final String PROPERTY_FORCE_MULTI_PART_UPLOAD = + "s3proxy.force-multi-part-upload"; private S3ProxyConstants() { throw new AssertionError("Cannot instantiate utility constructor"); diff --git a/src/main/java/org/gaul/s3proxy/S3ProxyHandler.java b/src/main/java/org/gaul/s3proxy/S3ProxyHandler.java index 6fa53c5..698eaa6 100644 --- a/src/main/java/org/gaul/s3proxy/S3ProxyHandler.java +++ b/src/main/java/org/gaul/s3proxy/S3ProxyHandler.java @@ -64,6 +64,7 @@ import org.jclouds.blobstore.domain.StorageType; import org.jclouds.blobstore.options.CreateContainerOptions; import org.jclouds.blobstore.options.GetOptions; import org.jclouds.blobstore.options.ListContainerOptions; +import org.jclouds.blobstore.options.PutOptions; import org.jclouds.domain.Location; import org.jclouds.http.HttpResponseException; import org.jclouds.io.ContentMetadata; @@ -93,11 +94,14 @@ final class S3ProxyHandler extends AbstractHandler { private final BlobStore blobStore; private final String identity; private final String credential; + private final boolean forceMultiPartUpload; - S3ProxyHandler(BlobStore blobStore, String identity, String credential) { + S3ProxyHandler(BlobStore blobStore, String identity, String credential, + boolean forceMultiPartUpload) { this.blobStore = Preconditions.checkNotNull(blobStore); this.identity = identity; this.credential = credential; + this.forceMultiPartUpload = forceMultiPartUpload; } @Override @@ -723,8 +727,11 @@ final class S3ProxyHandler extends AbstractHandler { if (contentMD5 != null) { builder = builder.contentMD5(contentMD5); } + PutOptions options = new PutOptions() + .multipart(forceMultiPartUpload); try { - String eTag = blobStore.putBlob(containerName, builder.build()); + String eTag = blobStore.putBlob(containerName, builder.build(), + options); response.addHeader(HttpHeaders.ETAG, "\"" + eTag + "\""); } catch (ContainerNotFoundException cnfe) { sendSimpleErrorResponse(response, diff --git a/src/test/java/org/gaul/s3proxy/S3ProxyTest.java b/src/test/java/org/gaul/s3proxy/S3ProxyTest.java index c668606..4bc757e 100644 --- a/src/test/java/org/gaul/s3proxy/S3ProxyTest.java +++ b/src/test/java/org/gaul/s3proxy/S3ProxyTest.java @@ -80,6 +80,8 @@ public final class S3ProxyTest { S3ProxyConstants.PROPERTY_KEYSTORE_PATH); String keyStorePassword = s3ProxyProperties.getProperty( S3ProxyConstants.PROPERTY_KEYSTORE_PASSWORD); + String forceMultiPartUpload = s3ProxyProperties.getProperty( + S3ProxyConstants.PROPERTY_FORCE_MULTI_PART_UPLOAD); Properties properties = new Properties(); properties.setProperty(Constants.PROPERTY_ENDPOINT, @@ -108,7 +110,8 @@ public final class S3ProxyTest { s3Proxy = new S3Proxy(blobStore, s3Endpoint, s3Identity, s3Credential, Resources.getResource(keyStorePath).toString(), - keyStorePassword); + keyStorePassword, + "true".equalsIgnoreCase(forceMultiPartUpload)); s3Proxy.start(); }