Added ConfigurationCustomizerCompiler This CustomizerCompiler implementation makes it possible to set low-level configurations in the GremlinGroovyScriptEngine on the Groovy CompilerConfiguration which ultimately controls script compilation settings used by the classloader.
Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/e32347c1 Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/e32347c1 Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/e32347c1 Branch: refs/heads/tp31 Commit: e32347c13e6c4917ebc691aa70e8531cb6b36e1a Parents: ddddc5f Author: Stephen Mallette <sp...@genoprime.com> Authored: Thu Jun 2 16:39:51 2016 -0400 Committer: Stephen Mallette <sp...@genoprime.com> Committed: Thu Jun 2 16:39:51 2016 -0400 ---------------------------------------------------------------------- CHANGELOG.asciidoc | 1 + .../src/reference/gremlin-applications.asciidoc | 5 +- .../gremlin/groovy/engine/ScriptEngines.java | 28 ++++++- .../jsr223/GremlinGroovyScriptEngine.java | 8 +- .../ConfigurationCustomizerProvider.java | 83 ++++++++++++++++++++ .../groovy/jsr223/BaseScriptForTesting.java | 30 +++++++ .../GremlinGroovyScriptEngineConfigTest.java | 40 ++++++++++ .../ConfigurationCustomizerProviderTest.java | 78 ++++++++++++++++++ .../gremlin/server/BaseScriptForTesting.java | 30 +++++++ .../server/GremlinServerIntegrateTest.java | 50 +++++++++--- 10 files changed, 338 insertions(+), 15 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/e32347c1/CHANGELOG.asciidoc ---------------------------------------------------------------------- diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 9590a90..6b53bb2 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -34,6 +34,7 @@ TinkerPop 3.2.1 (NOT OFFICIALLY RELEASED YET) * Added `EmptyMemory` for ease of use when no memory exists. * Updated `VertexComputing.generateProgram()` API to include `Memory`. (*breaking*) * `ImmutablePath.TailPath` is now serializable like `ImmutablePath`. +* Added `ConfigurationCompilerProvider` which allows fine-grained control of some of the internal `GremlinGroovyScriptEngine` settings at the Groovy compilation level. * Intoduced the `application/vnd.gremlin-v1.0+gryo-lite` serialization type to Gremlin Server which users "reference" elements rather than "detached". * `GryoMapper` allows overrides of existing serializers on calls to `addCustom` on the builder. * Added a traversal style guide to the recipes cookbook. http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/e32347c1/docs/src/reference/gremlin-applications.asciidoc ---------------------------------------------------------------------- diff --git a/docs/src/reference/gremlin-applications.asciidoc b/docs/src/reference/gremlin-applications.asciidoc index a8070ba..8c987fe 100644 --- a/docs/src/reference/gremlin-applications.asciidoc +++ b/docs/src/reference/gremlin-applications.asciidoc @@ -979,8 +979,8 @@ run Gremlin Server with Ganglia monitoring, download the `org.acplt:oncrpc` jar link:http://repo1.maven.org/maven2/org/acplt/oncrpc/1.0.7/[here] and copy it to the Gremlin Server `/lib` directory before starting the server. -Security -^^^^^^^^ +Security and Execution +^^^^^^^^^^^^^^^^^^^^^^ image:gremlin-server-secure.png[width=175,float=right] Gremlin Server provides for several features that aid in the security of the graphs that it exposes. It has built in SSL support and a pluggable authentication framework using @@ -1151,6 +1151,7 @@ There are a number of pre-packaged `CustomizerProvider` implementations: |========================================================= |Customizer |Description |`CompileStaticCustomizerProvider` |Applies `CompileStatic` annotations to incoming scripts thus removing dynamic dispatch. More information about static compilation can be found in the link:http://docs.groovy-lang.org/latest/html/documentation/#_static_compilation[Groovy Documentation]. It is possible to configure this `CustomizerProvider` by specifying a comma separated list of link:http://docs.groovy-lang.org/latest/html/documentation/#Typecheckingextensions-Workingwithextensions[type checking extensions] that can have the effect of securing calls to various methods. +|`ConfigurationCustomizerProvider` |Allows configuration of the the Groovy `CompilerConfiguration` object by taking a `Map` of key/value pairs where the "key" is a property to set on the `CompilerConfiguration`. |`ThreadInterruptCustomizerProvider` |Injects checks for thread interruption, thus allowing the thread to potentially respect calls to `Thread.interrupt()` |`TimedInterruptCustomizerProvider` |Injects checks into loops to interrupt them if they exceed the configured timeout in milliseconds. |`TypeCheckedCustomizerProvider` |Similar to the above mentioned, `CompileStaticCustomizerProvider`, the `TypeCheckedCustomizerProvider` injects `TypeChecked` annotations to incoming scripts. More information on the nature of this annotation can be found in the link:http://docs.groovy-lang.org/latest/html/documentation/#_the_code_typechecked_code_annotation[Groovy Documentation]. It too takes a comma separated list of link:http://docs.groovy-lang.org/latest/html/documentation/#Typecheckingextensions-Workingwithextensions[type checking extensions]. http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/e32347c1/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEngines.java ---------------------------------------------------------------------- diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEngines.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEngines.java index 1113eb5..3d54bea 100644 --- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEngines.java +++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEngines.java @@ -23,6 +23,7 @@ import org.apache.tinkerpop.gremlin.groovy.DefaultImportCustomizerProvider; import org.apache.tinkerpop.gremlin.groovy.jsr223.DependencyManager; import org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine; import org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngineFactory; +import org.apache.tinkerpop.gremlin.groovy.jsr223.customizer.ConfigurationCustomizerProvider; import org.apache.tinkerpop.gremlin.groovy.plugin.GremlinPlugin; import org.apache.tinkerpop.gremlin.groovy.plugin.IllegalEnvironmentException; import org.slf4j.Logger; @@ -382,8 +383,17 @@ public class ScriptEngines implements AutoCloseable { final Class<?>[] argClasses = new Class<?>[args.length]; Stream.of(args).map(a -> a.getClass()).collect(Collectors.toList()).toArray(argClasses); - final Constructor constructor = providerClass.getConstructor(argClasses); - providers.add((CompilerCustomizerProvider) constructor.newInstance(args)); + + final Optional<Constructor> constructor = Stream.of(providerClass.getConstructors()) + .filter(c -> c.getParameterCount() == argClasses.length && + allMatch(c.getParameterTypes(), argClasses)) + .findFirst(); + + if (constructor.isPresent()) providers.add((CompilerCustomizerProvider) + constructor.get().newInstance(args)); + else + throw new IllegalStateException(String.format("Could not configure %s with the supplied options %s", + ConfigurationCustomizerProvider.class.getName(), Arrays.asList(args))); } else { providers.add((CompilerCustomizerProvider) providerClass.newInstance()); } @@ -400,6 +410,20 @@ public class ScriptEngines implements AutoCloseable { } /** + * Determine if the constructor argument types match the arg types that are going to be passed in to that + * constructor. + */ + private static boolean allMatch(final Class<?>[] constructorArgTypes, final Class<?>[] argTypes) { + for (int ix = 0; ix < constructorArgTypes.length; ix++) { + if (!constructorArgTypes[ix].isAssignableFrom(argTypes[ix])) { + return false; + } + } + + return true; + } + + /** * Takes the bindings from a request for eval and merges them with the {@code ENGINE_SCOPE} bindings. */ private static Bindings mergeBindings(final Bindings bindings, final ScriptEngine engine) { http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/e32347c1/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java ---------------------------------------------------------------------- diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java index 23240cb..0069103 100644 --- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java +++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java @@ -23,6 +23,7 @@ import org.apache.tinkerpop.gremlin.groovy.DefaultImportCustomizerProvider; import org.apache.tinkerpop.gremlin.groovy.EmptyImportCustomizerProvider; import org.apache.tinkerpop.gremlin.groovy.ImportCustomizerProvider; import org.apache.tinkerpop.gremlin.groovy.NoImportCustomizerProvider; +import org.apache.tinkerpop.gremlin.groovy.jsr223.customizer.ConfigurationCustomizerProvider; import org.apache.tinkerpop.gremlin.groovy.jsr223.customizer.InterpreterModeCustomizerProvider; import org.apache.tinkerpop.gremlin.groovy.loaders.GremlinLoader; import org.apache.tinkerpop.gremlin.groovy.plugin.Artifact; @@ -610,7 +611,12 @@ public class GremlinGroovyScriptEngine extends GroovyScriptEngineImpl implements final CompilerConfiguration conf = new CompilerConfiguration(); conf.addCompilationCustomizers(this.importCustomizerProvider.create()); - customizerProviders.forEach(p -> conf.addCompilationCustomizers(p.create())); + // ConfigurationCustomizerProvider is treated separately + customizerProviders.stream().filter(cp -> !(cp instanceof ConfigurationCustomizerProvider)) + .forEach(p -> conf.addCompilationCustomizers(p.create())); + + customizerProviders.stream().filter(cp -> cp instanceof ConfigurationCustomizerProvider).findFirst() + .ifPresent(cp -> ((ConfigurationCustomizerProvider) cp).applyCustomization(conf)); this.loader = new GremlinGroovyClassLoader(getParentLoader(), conf); } http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/e32347c1/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/customizer/ConfigurationCustomizerProvider.java ---------------------------------------------------------------------- diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/customizer/ConfigurationCustomizerProvider.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/customizer/ConfigurationCustomizerProvider.java new file mode 100644 index 0000000..ba9855c --- /dev/null +++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/customizer/ConfigurationCustomizerProvider.java @@ -0,0 +1,83 @@ +/* + * 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.apache.tinkerpop.gremlin.groovy.jsr223.customizer; + +import org.apache.tinkerpop.gremlin.groovy.CompilerCustomizerProvider; +import org.apache.tinkerpop.gremlin.structure.util.ElementHelper; +import org.codehaus.groovy.control.CompilerConfiguration; +import org.codehaus.groovy.control.customizers.CompilationCustomizer; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * Allows configurations to be directly supplied to a groovy {@code CompilerConfiguration} when a + * {@link org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine} is initialized, providing fine-grained + * control over its internals. + * + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +public class ConfigurationCustomizerProvider implements CompilerCustomizerProvider { + + private final Map<String,Object> properties; + + /** + * Creates a new instance using configuration values specified + */ + public ConfigurationCustomizerProvider(final Object... keyValues) { + if (null == keyValues || keyValues.length == 0) + throw new IllegalArgumentException("ConfigurationCustomizerProvider must have key/values specified"); + + if (keyValues.length % 2 != 0) + throw new IllegalArgumentException("The keyValues must have an even number of values"); + + properties = ElementHelper.asMap(keyValues); + } + + /** + * Creates a new instance using configuration values specified + */ + public ConfigurationCustomizerProvider(final Map<String,Object> keyValues) { + properties = keyValues; + } + + public CompilerConfiguration applyCustomization(final CompilerConfiguration compilerConfiguration) { + final Class<CompilerConfiguration> clazz = CompilerConfiguration.class; + final List<Method> methods = Arrays.asList(clazz.getMethods()); + for (Map.Entry<String,Object> entry : properties.entrySet()) { + final Method method = methods.stream().filter(m -> m.getName().equals("set" + entry.getKey())).findFirst() + .orElseThrow(() -> new IllegalStateException("Invalid setting [" + entry.getKey() + "] for CompilerConfiguration")); + + try { + method.invoke(compilerConfiguration, entry.getValue()); + } catch (Exception ex) { + throw new IllegalStateException(ex); + } + } + + return compilerConfiguration; + } + + @Override + public CompilationCustomizer create() { + throw new UnsupportedOperationException("This is a marker implementation that does not create a CompilationCustomizer instance"); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/e32347c1/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/BaseScriptForTesting.java ---------------------------------------------------------------------- diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/BaseScriptForTesting.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/BaseScriptForTesting.java new file mode 100644 index 0000000..98c8e8c --- /dev/null +++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/BaseScriptForTesting.java @@ -0,0 +1,30 @@ +/* + * 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.apache.tinkerpop.gremlin.groovy.jsr223; + +import groovy.lang.Script; + +/** + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +public abstract class BaseScriptForTesting extends Script { + public String hello(final String name) { + return "hello, " + name; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/e32347c1/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineConfigTest.java ---------------------------------------------------------------------- diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineConfigTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineConfigTest.java new file mode 100644 index 0000000..d354ffa --- /dev/null +++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineConfigTest.java @@ -0,0 +1,40 @@ +/* + * 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.apache.tinkerpop.gremlin.groovy.jsr223; + +import org.apache.tinkerpop.gremlin.groovy.DefaultImportCustomizerProvider; +import org.apache.tinkerpop.gremlin.groovy.jsr223.customizer.ConfigurationCustomizerProvider; +import org.junit.Test; + +import javax.script.ScriptEngine; + +import static org.junit.Assert.assertEquals; + +/** + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +public class GremlinGroovyScriptEngineConfigTest { + @Test + public void shouldAddBaseScriptClass() throws Exception { + final ScriptEngine engine = new GremlinGroovyScriptEngine( + new ConfigurationCustomizerProvider("ScriptBaseClass", BaseScriptForTesting.class.getName()), new DefaultImportCustomizerProvider()); + + assertEquals("hello, stephen", engine.eval("hello('stephen')")); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/e32347c1/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/customizer/ConfigurationCustomizerProviderTest.java ---------------------------------------------------------------------- diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/customizer/ConfigurationCustomizerProviderTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/customizer/ConfigurationCustomizerProviderTest.java new file mode 100644 index 0000000..54b55b1 --- /dev/null +++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/customizer/ConfigurationCustomizerProviderTest.java @@ -0,0 +1,78 @@ +/* + * 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.apache.tinkerpop.gremlin.groovy.jsr223.customizer; + +import org.apache.commons.lang.exception.ExceptionUtils; +import org.codehaus.groovy.control.CompilerConfiguration; +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsInstanceOf.instanceOf; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +public class ConfigurationCustomizerProviderTest { + @Test(expected = IllegalArgumentException.class) + public void shouldThrowExceptionForNoSettings() { + new ConfigurationCustomizerProvider(); + } + + @Test(expected = IllegalArgumentException.class) + public void shouldThrowExceptionForInvalidSettings() { + new ConfigurationCustomizerProvider("only-one-arg"); + } + + @Test + public void shouldThrowExceptionForNotFoundSetting() { + final CompilerConfiguration configuration = new CompilerConfiguration(); + try { + final ConfigurationCustomizerProvider provider = new ConfigurationCustomizerProvider( + "Tolerance", 3, + "NotRealSettingThatWouldEverOccur2", new java.util.Date()); + + provider.applyCustomization(configuration); + } catch (Exception ex) { + assertThat(ex, instanceOf(IllegalStateException.class)); + assertEquals("Invalid setting [NotRealSettingThatWouldEverOccur2] for CompilerConfiguration", ex.getMessage()); + } + } + + @Test + public void shouldApplyConfigurationChanges() { + final CompilerConfiguration configuration = new CompilerConfiguration(); + + assertEquals(10, configuration.getTolerance()); + assertNull(configuration.getScriptBaseClass()); + assertEquals(false, configuration.getDebug()); + + final ConfigurationCustomizerProvider provider = new ConfigurationCustomizerProvider( + "Tolerance", 3, + "ScriptBaseClass", "Something", + "Debug", true); + + provider.applyCustomization(configuration); + + assertEquals(3, configuration.getTolerance()); + assertEquals("Something", configuration.getScriptBaseClass()); + assertEquals(true, configuration.getDebug()); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/e32347c1/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/BaseScriptForTesting.java ---------------------------------------------------------------------- diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/BaseScriptForTesting.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/BaseScriptForTesting.java new file mode 100644 index 0000000..ae4c713 --- /dev/null +++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/BaseScriptForTesting.java @@ -0,0 +1,30 @@ +/* + * 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.apache.tinkerpop.gremlin.server; + +import groovy.lang.Script; + +/** + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +public abstract class BaseScriptForTesting extends Script { + public String hello(final String name) { + return "hello, " + name; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/e32347c1/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java ---------------------------------------------------------------------- diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java index 16cbdee..a2b415d 100644 --- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java +++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java @@ -41,6 +41,7 @@ import org.apache.tinkerpop.gremlin.driver.simple.SimpleClient; import org.apache.tinkerpop.gremlin.driver.simple.WebSocketClient; import org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine; import org.apache.tinkerpop.gremlin.groovy.jsr223.customizer.CompileStaticCustomizerProvider; +import org.apache.tinkerpop.gremlin.groovy.jsr223.customizer.ConfigurationCustomizerProvider; import org.apache.tinkerpop.gremlin.groovy.jsr223.customizer.InterpreterModeCustomizerProvider; import org.apache.tinkerpop.gremlin.groovy.jsr223.customizer.SimpleSandboxExtension; import org.apache.tinkerpop.gremlin.groovy.jsr223.customizer.TimedInterruptCustomizerProvider; @@ -55,7 +56,6 @@ import org.junit.Before; import org.junit.Test; import java.nio.channels.ClosedChannelException; -import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -72,12 +72,15 @@ import java.util.stream.IntStream; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.StringEndsWith.endsWith; import static org.hamcrest.core.StringStartsWith.startsWith; -import static org.junit.Assert.*; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; import static org.junit.Assume.assumeThat; +import static org.junit.Assert.assertEquals; /** * Integration tests for server-side settings and processing. @@ -161,6 +164,9 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration case "shouldReceiveFailureTimeOutOnScriptEvalOfOutOfControlLoop": settings.scriptEngines.get("gremlin-groovy").config = getScriptEngineConfForTimedInterrupt(); break; + case "shouldUseBaseScript": + settings.scriptEngines.get("gremlin-groovy").config = getScriptEngineConfForBaseScript(); + break; } return settings; @@ -206,6 +212,30 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration return scriptEngineConf; } + private static Map<String, Object> getScriptEngineConfForBaseScript() { + final Map<String,Object> scriptEngineConf = new HashMap<>(); + final Map<String,Object> compilerCustomizerProviderConf = new HashMap<>(); + final List<Object> keyValues = new ArrayList<>(); + + final Map<String,Object> properties = new HashMap<>(); + properties.put("ScriptBaseClass", BaseScriptForTesting.class.getName()); + keyValues.add(properties); + + compilerCustomizerProviderConf.put(ConfigurationCustomizerProvider.class.getName(), keyValues); + scriptEngineConf.put("compilerCustomizerProviders", compilerCustomizerProviderConf); + return scriptEngineConf; + } + + @Test + public void shouldUseBaseScript() throws Exception { + final Cluster cluster = Cluster.open(); + final Client client = cluster.connect(name.getMethodName()); + + assertEquals("hello, stephen", client.submit("hello('stephen')").all().get().get(0).getString()); + + cluster.close(); + } + @Test public void shouldUseInterpreterMode() throws Exception { final Cluster cluster = Cluster.open(); @@ -368,12 +398,12 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration }); }); - assertTrue(latch.await(30000, TimeUnit.MILLISECONDS)); + assertThat(latch.await(30000, TimeUnit.MILLISECONDS), is(true)); assertEquals(0, latch.getCount()); - assertFalse(faulty.get()); - assertTrue(expected.get()); + assertThat(faulty.get(), is(false)); + assertThat(expected.get(), is(true)); - assertTrue(recordingAppender.getMessages().stream().anyMatch(m -> m.contains("Pausing response writing as writeBufferHighWaterMark exceeded on"))); + assertThat(recordingAppender.getMessages().stream().anyMatch(m -> m.contains("Pausing response writing as writeBufferHighWaterMark exceeded on")), is(true)); } catch (Exception ex) { fail("Shouldn't have tossed an exception"); } finally { @@ -410,7 +440,7 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration if (!latch.await(3000, TimeUnit.MILLISECONDS)) fail("Request should have returned error, but instead timed out"); - assertTrue(pass.get()); + assertThat(pass.get(), is(true)); } } @@ -433,7 +463,7 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration if (!latch.await(3000, TimeUnit.MILLISECONDS)) fail("Request should have returned error, but instead timed out"); - assertTrue(pass.get()); + assertThat(pass.get(), is(true)); } } @@ -456,7 +486,7 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration if (!latch.await(3000, TimeUnit.MILLISECONDS)) fail("Request should have returned error, but instead timed out"); - assertTrue(pass.get()); + assertThat(pass.get(), is(true)); } } @@ -691,7 +721,7 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration client.submit("1+1").all().join(); fail(); } catch (RuntimeException re) { - assertTrue(re.getCause().getCause() instanceof ClosedChannelException); + assertThat(re.getCause().getCause() instanceof ClosedChannelException, is(true)); // // should recover when the server comes back