TINKERPOP-1562 Bring back GremlinModule and deprecate it. GremlinModule was introduced in 3.2.3. Wasn't sure if GremlinModule was equal to a GremlinPlugin so I had named it differently. It was never promoted as a replacement for GremlinPlugin and it was never used in core infrastructure like Gremlin Console or Gremlin Server, but I figured it better to avoid breaking change and simply deprecate it for removal later.
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/d09cf9ce Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/d09cf9ce Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/d09cf9ce Branch: refs/heads/TINKERPOP-1562 Commit: d09cf9ce4ed42bc4da5d52438e896777ea5a667f Parents: 052f19f Author: Stephen Mallette <sp...@genoprime.com> Authored: Mon Nov 21 13:34:27 2016 -0500 Committer: Stephen Mallette <sp...@genoprime.com> Committed: Thu Dec 1 06:41:42 2016 -0500 ---------------------------------------------------------------------- .../gremlin/jsr223/CoreGremlinModule.java | 64 +++++++++++++++++ .../DefaultGremlinScriptEngineManager.java | 39 +++++++++-- .../tinkerpop/gremlin/jsr223/GremlinModule.java | 72 ++++++++++++++++++++ .../jsr223/GremlinScriptEngineManager.java | 10 ++- .../gremlin/groovy/engine/GremlinExecutor.java | 4 +- .../jsr223/GremlinEnabledScriptEngineTest.java | 28 +++++++- 6 files changed, 207 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d09cf9ce/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreGremlinModule.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreGremlinModule.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreGremlinModule.java new file mode 100644 index 0000000..6869064 --- /dev/null +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreGremlinModule.java @@ -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. + */ +package org.apache.tinkerpop.gremlin.jsr223; + +import org.apache.tinkerpop.gremlin.util.CoreImports; + +import java.util.Optional; + +/** + * This module is required for a {@code ScriptEngine} to be Gremlin-enabled. + * + * @author Stephen Mallette (http://stephen.genoprime.com) + * @deprecated As of release 3.2.4, replaced by {@link CoreGremlinPlugin}. + */ +@Deprecated +public final class CoreGremlinModule implements GremlinModule { + + private static final String MODULE_NAME = "tinkerpop.core"; + + private static final ImportCustomizer gremlinCore = ImportCustomizer.build() + .addClassImports(CoreImports.getClassImports()) + .addEnumImports(CoreImports.getEnumImports()) + .addMethodImports(CoreImports.getMethodImports()).create(); + + private static final Customizer[] customizers = new Customizer[] {gremlinCore}; + + /** + * @deprecated As of 3.2.4, replaced by {@link #instance()} as this field will later become private. + */ + @Deprecated + public static final CoreGremlinModule INSTANCE = new CoreGremlinModule(); + + private CoreGremlinModule() {} + + public static CoreGremlinModule instance() { + return INSTANCE; + } + + @Override + public Optional<Customizer[]> getCustomizers(final String scriptEngineName) { + return Optional.of(customizers); + } + + @Override + public String getName() { + return MODULE_NAME; + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d09cf9ce/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/DefaultGremlinScriptEngineManager.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/DefaultGremlinScriptEngineManager.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/DefaultGremlinScriptEngineManager.java index 10bdfa3..1484f90 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/DefaultGremlinScriptEngineManager.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/DefaultGremlinScriptEngineManager.java @@ -95,7 +95,15 @@ public class DefaultGremlinScriptEngineManager implements GremlinScriptEngineMan * List of extensions for the {@link GremlinScriptEngineManager} which will be used to supply * {@link Customizer} instances to {@link GremlinScriptEngineFactory} that are instantiated. */ - private List<GremlinPlugin> modules = new ArrayList<>(); + private List<GremlinPlugin> plugins = new ArrayList<>(); + + /** + * List of extensions for the {@link GremlinScriptEngineManager} which will be used to supply + * {@link Customizer} instances to {@link GremlinScriptEngineFactory} that are instantiated. + * + * @deprecated As of release 3.2.4, replaced by {@link #plugins}. + */ + private List<GremlinModule> modules = new ArrayList<>(); /** * The effect of calling this constructor is the same as calling @@ -118,18 +126,37 @@ public class DefaultGremlinScriptEngineManager implements GremlinScriptEngineMan @Override public List<Customizer> getCustomizers(final String scriptEngineName) { - return modules.stream().flatMap(module -> { - final Optional<Customizer[]> moduleCustomizers = module.getCustomizers(scriptEngineName); - return Stream.of(moduleCustomizers.orElse(new Customizer[0])); + final List<Customizer> pluginCustomizers = plugins.stream().flatMap(plugin -> { + final Optional<Customizer[]> customizers = plugin.getCustomizers(scriptEngineName); + return Stream.of(customizers.orElse(new Customizer[0])); }).collect(Collectors.toList()); + + // modules are deprecated in favor of GremlinPlugin - this line will eventually be removed + pluginCustomizers.addAll(modules.stream().flatMap(plugin -> { + final Optional<Customizer[]> customizers = plugin.getCustomizers(scriptEngineName); + return Stream.of(customizers.orElse(new Customizer[0])); + }).collect(Collectors.toList())); + + + return pluginCustomizers; } + /** + * @deprecated As of release 3.2.4, replaced by {@link #addPlugin(GremlinPlugin)}. + */ @Override - public void addModule(final GremlinPlugin module) { + @Deprecated + public void addModule(final GremlinModule module) { // TODO: should modules be a set based on "name" to ensure uniqueness? not sure what bad stuff can happen with dupes if (module != null) modules.add(module); } + @Override + public void addPlugin(final GremlinPlugin plugin) { + // TODO: should modules be a set based on "name" to ensure uniqueness? not sure what bad stuff can happen with dupes + if (plugin != null) plugins.add(plugin); + } + /** * Stores the specified {@code Bindings} as a global for all {@link GremlinScriptEngine} objects created by it. * If the bindings are to be updated by multiple threads it is recommended that a {@link ConcurrentBindings} @@ -378,7 +405,7 @@ public class DefaultGremlinScriptEngineManager implements GremlinScriptEngineMan private void initEngines(final ClassLoader loader) { // always need this module for a scriptengine to be "Gremlin-enabled" - modules.add(CoreGremlinPlugin.INSTANCE); + plugins.add(CoreGremlinPlugin.instance()); Iterator<GremlinScriptEngineFactory> itty; try { http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d09cf9ce/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinModule.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinModule.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinModule.java new file mode 100644 index 0000000..1345841 --- /dev/null +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinModule.java @@ -0,0 +1,72 @@ +/* + * 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.jsr223; + +import java.util.Optional; + +/** + * @author Stephen Mallette (http://stephen.genoprime.com) + * @deprecated As of release 3.2.4, replaced by {@link GremlinPlugin}. + */ +@Deprecated +public interface GremlinModule { + /** + * The name of the module. This name should be unique (use a namespaced approach) as naming clashes will + * prevent proper module operations. Modules developed by TinkerPop will be prefixed with "tinkerpop." + * For example, TinkerPop's implementation of Giraph would be named "tinkerpop.giraph". If Facebook were + * to do their own implementation the implementation might be called "facebook.giraph". + */ + public String getName(); + + /** + * Some modules may require a restart of the plugin host for the classloader to pick up the features. This is + * typically true of modules that rely on {@code Class.forName()} to dynamically instantiate classes from the + * root classloader (e.g. JDBC drivers that instantiate via @{code DriverManager}). + */ + public default boolean requireRestart() { + return false; + } + + /** + * Gets the list of all {@link Customizer} implementations to assign to a new {@link GremlinScriptEngine}. This is + * the same as doing {@code getCustomizers(null)}. + */ + public default Optional<Customizer[]> getCustomizers(){ + return getCustomizers(null); + } + + /** + * Gets the list of {@link Customizer} implementations to assign to a new {@link GremlinScriptEngine}. The + * implementation should filter the returned {@code Customizers} according to the supplied name of the + * Gremlin-enabled {@code ScriptEngine}. By providing a filter, {@code GremlinModule} developers can have the + * ability to target specific {@code ScriptEngines}. + * + * @param scriptEngineName The name of the {@code ScriptEngine} or null to get all the available {@code Customizers} + */ + public Optional<Customizer[]> getCustomizers(final String scriptEngineName); + + /** + * Allows a plugin to utilize features of the {@code :remote} and {@code :submit} commands of the Gremlin Console. + * This method does not need to be implemented if the plugin is not meant for the Console for some reason or + * if it does not intend to take advantage of those commands. + */ + public default Optional<RemoteAcceptor> remoteAcceptor() { + return Optional.empty(); + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d09cf9ce/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinScriptEngineManager.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinScriptEngineManager.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinScriptEngineManager.java index b2966c5..a48d761 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinScriptEngineManager.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinScriptEngineManager.java @@ -118,9 +118,17 @@ public interface GremlinScriptEngineManager { public List<GremlinScriptEngineFactory> getEngineFactories(); /** + * Add {@link GremlinModule} instances to customize newly created {@link GremlinScriptEngine} instances. + * + * @deprecated As of release 3.2.4, replaced by {@link #addPlugin(GremlinPlugin)}. + */ + @Deprecated + public void addModule(final GremlinModule module); + + /** * Add {@link GremlinPlugin} instances to customize newly created {@link GremlinScriptEngine} instances. */ - public void addModule(final GremlinPlugin module); + public void addPlugin(final GremlinPlugin plugin); /** * Registers a {@link GremlinScriptEngineFactory} to handle a language name. Overrides any such association found http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d09cf9ce/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutor.java ---------------------------------------------------------------------- diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutor.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutor.java index 8659e24..4449e1b 100644 --- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutor.java +++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutor.java @@ -438,7 +438,7 @@ public class GremlinExecutor implements AutoCloseable { // first try instance() and if that fails try to use build() try { final Method instanceMethod = clazz.getMethod("instance"); - gremlinScriptEngineManager.addModule((GremlinPlugin) instanceMethod.invoke(null)); + gremlinScriptEngineManager.addPlugin((GremlinPlugin) instanceMethod.invoke(null)); } catch (Exception ex) { final Method builderMethod = clazz.getMethod("build"); Object moduleBuilder = builderMethod.invoke(null); @@ -463,7 +463,7 @@ public class GremlinExecutor implements AutoCloseable { } final Method create = builderClazz.getMethod("create"); - gremlinScriptEngineManager.addModule((GremlinPlugin) create.invoke(moduleBuilder)); + gremlinScriptEngineManager.addPlugin((GremlinPlugin) create.invoke(moduleBuilder)); } } catch (Exception ex) { throw new IllegalStateException(ex); http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d09cf9ce/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinEnabledScriptEngineTest.java ---------------------------------------------------------------------- diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinEnabledScriptEngineTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinEnabledScriptEngineTest.java index 76e8f55..34a37ae 100644 --- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinEnabledScriptEngineTest.java +++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinEnabledScriptEngineTest.java @@ -25,7 +25,9 @@ import org.apache.tinkerpop.gremlin.structure.VertexProperty; import org.junit.Test; import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.Optional; import static org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineSuite.ENGINE_TO_TEST; import static org.junit.Assert.assertEquals; @@ -47,11 +49,35 @@ public class GremlinEnabledScriptEngineTest { @Test public void shouldHaveCoreImportsInPlace() throws Exception { - // TODO: delete this test - other tests will give us confidence on such things as we get further along final GremlinScriptEngine scriptEngine = manager.getEngineByName(ENGINE_TO_TEST); final List<Class> classesToCheck = Arrays.asList(Vertex.class, Edge.class, Graph.class, VertexProperty.class); for (Class clazz : classesToCheck) { assertEquals(clazz, scriptEngine.eval(clazz.getSimpleName())); } } + + @Test + public void shouldSupportDeprecatedGremlinModules() throws Exception { + final GremlinScriptEngineManager mgr = new DefaultGremlinScriptEngineManager(); + mgr.addModule(new GremlinModule() { + @Override + public String getName() { + return "test.junk"; + } + + @Override + public Optional<Customizer[]> getCustomizers(final String scriptEngineName) { + return Optional.of(new Customizer[] {ImportCustomizer.build() + .addClassImports(java.awt.Color.class) + .addClassImports(java.sql.CallableStatement.class) + .create() }); + } + }); + + final GremlinScriptEngine scriptEngine = mgr.getEngineByName(ENGINE_TO_TEST); + final List<Class> classesToCheck = Arrays.asList(java.awt.Color.class, java.sql.CallableStatement.class); + for (Class clazz : classesToCheck) { + assertEquals(clazz, scriptEngine.eval(clazz.getSimpleName())); + } + } }