public Map<String, Object> createModel(ScriptContext scriptContext) { Map<String, Object> model = new HashMap<>(); Bindings bindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE); for (Object entryObj : bindings.entrySet()) { Map.Entry<?, ?> entry = (Map.Entry<?, ?>) entryObj; model.put((String) entry.getKey(), entry.getValue()); } model.put("properties", new ScriptContextAdapter(scriptContext).getResource().getValueMap()); return model; }
private ScriptEngines createScriptEngines() { // plugins already on the path - ones static to the classpath final List<GremlinPlugin> globalPlugins = new ArrayList<>(); ServiceLoader.load(GremlinPlugin.class).forEach(globalPlugins::add); return new ScriptEngines( se -> { // this first part initializes the scriptengines Map for (Map.Entry<String, EngineSettings> config : settings.entrySet()) { final String language = config.getKey(); se.reload( language, new HashSet<>(config.getValue().getImports()), new HashSet<>(config.getValue().getStaticImports()), config.getValue().getConfig()); } // use grabs dependencies and returns plugins to load final List<GremlinPlugin> pluginsToLoad = new ArrayList<>(globalPlugins); use.forEach( u -> { if (u.size() != 3) logger.warn( "Could not resolve dependencies for [{}]. Each entry for the 'use' configuration must include [groupId, artifactId, version]", u); else { logger.info("Getting dependencies for [{}]", u); pluginsToLoad.addAll(se.use(u.get(0), u.get(1), u.get(2))); } }); // now that all dependencies are in place, the imports can't get messed up if a plugin // tries to execute // a script (as the script engine appends the import list to the top of all scripts passed // to the engine). // only enable those plugins that are configured to be enabled. se.loadPlugins( pluginsToLoad .stream() .filter(plugin -> enabledPlugins.contains(plugin.getName())) .collect(Collectors.toList())); // initialization script eval can now be performed now that dependencies are present with // "use" for (Map.Entry<String, EngineSettings> config : settings.entrySet()) { final String language = config.getKey(); // script engine initialization files that fail will only log warnings - not fail server // initialization final AtomicBoolean hasErrors = new AtomicBoolean(false); config .getValue() .getScripts() .stream() .map(File::new) .filter( f -> { if (!f.exists()) { logger.warn( "Could not initialize {} ScriptEngine with {} as file does not exist", language, f); hasErrors.set(true); } return f.exists(); }) .map( f -> { try { return Pair.with(f, Optional.of(new FileReader(f))); } catch (IOException ioe) { logger.warn( "Could not initialize {} ScriptEngine with {} as file could not be read - {}", language, f, ioe.getMessage()); hasErrors.set(true); return Pair.with(f, Optional.<FileReader>empty()); } }) .filter(p -> p.getValue1().isPresent()) .map(p -> Pair.with(p.getValue0(), p.getValue1().get())) .forEachOrdered( p -> { try { final Bindings bindings = new SimpleBindings(); bindings.putAll(this.globalBindings); // evaluate init scripts with hard reference so as to ensure it doesn't get // garbage collected bindings.put( GremlinGroovyScriptEngine.KEY_REFERENCE_TYPE, GremlinGroovyScriptEngine.REFERENCE_TYPE_HARD); se.eval(p.getValue1(), bindings, language); // re-assign graph bindings back to global bindings and grab TraversalSource // creations. // prevent assignment of non-graph implementations just in case someone // tries to overwrite // them in the init bindings .entrySet() .stream() .filter(promoteBinding) .forEach(kv -> this.globalBindings.put(kv.getKey(), kv.getValue())); logger.info("Initialized {} ScriptEngine with {}", language, p.getValue0()); } catch (ScriptException sx) { hasErrors.set(true); logger.warn( "Could not initialize {} ScriptEngine with {} as script could not be evaluated - {}", language, p.getValue0(), sx.getMessage()); } }); } }); }