diff --git a/.travis.yml b/.travis.yml
index d546b9f..9844f6b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,7 +2,7 @@ dist: trusty
sudo: required
language: java
jdk:
- - openjdk7
+ - openjdk8
env:
global:
- secure: "aY2WMlIMs7qiKJ6ZH4CgC4JpkXHUgZm9VyrBUPNa7E5vDVRK8+fQpZx2xSlUOIl/DG6OhtPyFGydXiYNjSdBldjEN6mqCo85bzZfRnl0E/fp2lBYarMvAcNrN8+8CSme077Hs/wV7XSdsEhBpm/LAWd7Enql9x3Vwuj4NxAN04c=" # DOCKER_EMAIL
diff --git a/src/main/java/org/gaul/s3proxy/Main.java b/src/main/java/org/gaul/s3proxy/Main.java
index d4629d5..66413db 100644
--- a/src/main/java/org/gaul/s3proxy/Main.java
+++ b/src/main/java/org/gaul/s3proxy/Main.java
@@ -19,6 +19,7 @@ package org.gaul.s3proxy;
import java.io.Console;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
@@ -29,9 +30,14 @@ import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
+import javax.script.Invocable;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.io.Files;
+import com.google.common.io.Resources;
import com.google.inject.Module;
import org.jclouds.Constants;
@@ -61,6 +67,9 @@ public final class Main {
@Option(name = "--version", usage = "display version")
private boolean version;
+
+ @Option(name = "--middleware", usage = "JavaScript file")
+ private String middleware;
}
public static void main(String[] args) throws Exception {
@@ -196,6 +205,22 @@ public final class Main {
blobStore = ReadOnlyBlobStore.newReadOnlyBlobStore(blobStore);
}
+ if (options.middleware != null) {
+ ScriptEngineManager factory = new ScriptEngineManager();
+ ScriptEngine engine = factory.getEngineByName("nashorn");
+ String script;
+ try {
+ script = Files.toString(new File(options.middleware),
+ StandardCharsets.UTF_8);
+ } catch (FileNotFoundException fnfe) {
+ script = Resources.toString(Resources.getResource(
+ options.middleware), StandardCharsets.UTF_8);
+ }
+ engine.eval(script);
+ blobStore = (BlobStore) ((Invocable) engine).invokeFunction(
+ "newBlobStore", blobStore, properties);
+ }
+
S3Proxy s3Proxy;
try {
S3Proxy.Builder s3ProxyBuilder = S3Proxy.builder()
diff --git a/src/main/java/org/gaul/s3proxy/S3ProxyHandlerJetty.java b/src/main/java/org/gaul/s3proxy/S3ProxyHandlerJetty.java
index 0e51e29..050113f 100644
--- a/src/main/java/org/gaul/s3proxy/S3ProxyHandlerJetty.java
+++ b/src/main/java/org/gaul/s3proxy/S3ProxyHandlerJetty.java
@@ -23,6 +23,8 @@ import java.util.concurrent.TimeoutException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import jdk.nashorn.api.scripting.NashornException;
+
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
@@ -67,7 +69,11 @@ final class S3ProxyHandlerJetty extends AbstractHandler {
baseRequest.setAttribute(S3ProxyConstants.ATTRIBUTE_QUERY_ENCODING,
baseRequest.getQueryEncoding());
- handler.doHandle(baseRequest, request, response, is);
+ try {
+ handler.doHandle(baseRequest, request, response, is);
+ } catch (NashornException ne) {
+ throw ne.getCause();
+ }
baseRequest.setHandled(true);
} catch (ContainerNotFoundException cnfe) {
S3ErrorCode code = S3ErrorCode.NO_SUCH_BUCKET;
@@ -96,6 +102,8 @@ final class S3ProxyHandlerJetty extends AbstractHandler {
}
baseRequest.setHandled(true);
return;
+ } catch (IOException ioe) {
+ throw ioe;
} catch (IllegalArgumentException iae) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
baseRequest.setHandled(true);
@@ -130,7 +138,7 @@ final class S3ProxyHandlerJetty extends AbstractHandler {
baseRequest.setHandled(true);
return;
} else {
- throw throwable;
+ throw new RuntimeException(throwable);
}
}
}
diff --git a/src/main/resources/checkstyle.xml b/src/main/resources/checkstyle.xml
index 8ffd88f..7d49d22 100644
--- a/src/main/resources/checkstyle.xml
+++ b/src/main/resources/checkstyle.xml
@@ -55,7 +55,7 @@
-
+
diff --git a/src/test/java/org/gaul/s3proxy/ReadOnlyBlobStoreTest.java b/src/test/java/org/gaul/s3proxy/ReadOnlyBlobStoreTest.java
index 22a2ffa..09d9ce0 100644
--- a/src/test/java/org/gaul/s3proxy/ReadOnlyBlobStoreTest.java
+++ b/src/test/java/org/gaul/s3proxy/ReadOnlyBlobStoreTest.java
@@ -18,9 +18,18 @@ package org.gaul.s3proxy;
import static org.assertj.core.api.Assertions.assertThat;
+import java.nio.charset.StandardCharsets;
+import java.util.Properties;
import java.util.Random;
+import javax.script.Invocable;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+
+import jdk.nashorn.api.scripting.NashornException;
+
import com.google.common.collect.ImmutableList;
+import com.google.common.io.Resources;
import com.google.inject.Module;
import org.assertj.core.api.Fail;
@@ -50,7 +59,13 @@ public final class ReadOnlyBlobStoreTest {
.build(BlobStoreContext.class);
blobStore = context.getBlobStore();
blobStore.createContainerInLocation(null, containerName);
- readOnlyBlobStore = ReadOnlyBlobStore.newReadOnlyBlobStore(blobStore);
+
+ ScriptEngineManager factory = new ScriptEngineManager();
+ ScriptEngine engine = factory.getEngineByName("nashorn");
+ engine.eval(Resources.toString(Resources.getResource(
+ "readonly_blobstore.js"), StandardCharsets.UTF_8));
+ readOnlyBlobStore = (BlobStore) ((Invocable) engine).invokeFunction(
+ "newBlobStore", blobStore, new Properties());
}
@After
@@ -73,9 +88,10 @@ public final class ReadOnlyBlobStoreTest {
try {
readOnlyBlobStore.putBlob(containerName, null);
Fail.failBecauseExceptionWasNotThrown(
+ NashornException.class);
+ } catch (NashornException ne) {
+ assertThat(ne.getCause().getClass()).isEqualTo(
UnsupportedOperationException.class);
- } catch (UnsupportedOperationException ne) {
- // expected
}
}
@@ -84,9 +100,10 @@ public final class ReadOnlyBlobStoreTest {
try {
readOnlyBlobStore.putBlob(containerName, null, new PutOptions());
Fail.failBecauseExceptionWasNotThrown(
+ NashornException.class);
+ } catch (NashornException ne) {
+ assertThat(ne.getCause().getClass()).isEqualTo(
UnsupportedOperationException.class);
- } catch (UnsupportedOperationException ne) {
- // expected
}
}
diff --git a/src/test/resources/readonly_blobstore.js b/src/test/resources/readonly_blobstore.js
new file mode 100644
index 0000000..64a8faa
--- /dev/null
+++ b/src/test/resources/readonly_blobstore.js
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+var newBlobStore = function(blobStore) {
+ var readOnlyBlobStore = Java.extend(Java.type("org.jclouds.blobstore.util.ForwardingBlobStore"));
+ return new readOnlyBlobStore(blobStore) {
+ // container operations
+ createContainerInLocation: function(location, container) {
+ throw new java.lang.UnsupportedOperationException();
+ },
+ deleteContainer: function(container) {
+ throw new java.lang.UnsupportedOperationException();
+ },
+ deleteContainerIfEmpty: function(container) {
+ throw new java.lang.UnsupportedOperationException();
+ },
+ clearContainer: function(container) {
+ throw new java.lang.UnsupportedOperationException();
+ },
+ setContainerAccess: function(container, access) {
+ throw new java.lang.UnsupportedOperationException();
+ },
+
+ // object operations
+ putBlob: function(containerName, blob) {
+ throw new java.lang.UnsupportedOperationException();
+ },
+ removeBlob: function(containerName, blobName) {
+ throw new java.lang.UnsupportedOperationException();
+ },
+ removeBlobs: function(containerName, iterable) {
+ throw new java.lang.UnsupportedOperationException();
+ },
+ initiateMultipartUpload: function(containerName, blobMetadata, options) {
+ throw new java.lang.UnsupportedOperationException();
+ },
+ abortMultipartUpload: function(mpu) {
+ throw new java.lang.UnsupportedOperationException();
+ },
+ completeMultipartUpload: function(mpu, parts) {
+ throw new java.lang.UnsupportedOperationException();
+ },
+ uploadMultipartPart: function(mpu, partNumber, payload) {
+ throw new java.lang.UnsupportedOperationException();
+ },
+ setBlobAccess: function(container, blob, access) {
+ throw new java.lang.UnsupportedOperationException();
+ },
+ }
+}