Add read-only BlobStore middleware

Implement as a proof-of-concept JavaScript middleware.  Requires JDK
8.
pull/218/head
Andrew Gaul 2017-05-04 23:29:25 -07:00
rodzic 35d7c48475
commit 8041761c8c
6 zmienionych plików z 123 dodań i 9 usunięć

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -55,7 +55,7 @@
<property name="classes" value="java.lang.Boolean,java.lang.Short,java.lang.Integer,java.lang.Long"/>
</module>
<module name="ImportOrder">
<property name="groups" value="java,javax,com,org"/>
<property name="groups" value="java,javax,jdk,com,org"/>
<property name="separated" value="true"/>
<property name="option" value="top"/>
</module>

Wyświetl plik

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

Wyświetl plik

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