/*
 * Copyright 2015-2019 the original author or authors.
 *
 * All rights reserved. This program and the accompanying materials are
 * made available under the terms of the Eclipse Public License v2.0 which
 * accompanies this distribution and is available at
 *
 * http://www.eclipse.org/legal/epl-v20.html
 */

package org.junit.jupiter.engine.script;

import static org.apiguardian.api.API.Status.INTERNAL;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.apiguardian.api.API;
import org.junit.platform.commons.util.Preconditions;

Entry point for script execution support.
Since:5.1
/** * Entry point for script execution support. * * @since 5.1 */
@API(status = INTERNAL, since = "5.1") public class ScriptExecutionManager { private final ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); private final ConcurrentMap<String, ScriptEngine> scriptEngines = new ConcurrentHashMap<>(); private final ConcurrentMap<Script, CompiledScript> compiledScripts = new ConcurrentHashMap<>(); private final ScriptAccessor systemPropertyAccessor = new ScriptAccessor.SystemPropertyAccessor(); private final ScriptAccessor environmentVariableAccessor = new ScriptAccessor.EnvironmentVariableAccessor(); // package-private for testing purposes -- make it configurable? boolean forceScriptEvaluation = false;
Evaluate the script using the given bindings.
Params:
  • script – the script to evaluate
  • bindings – the context-aware bindings
Throws:
Returns:the result object
/** * Evaluate the script using the given bindings. * * @param script the script to evaluate * @param bindings the context-aware bindings * @return the result object * @throws ScriptException if an error occurs in script. */
public Object evaluate(Script script, Bindings bindings) throws ScriptException { // Always look for a compiled script in our cache. CompiledScript compiledScript = compiledScripts.get(script); // No compiled script found? if (compiledScript == null) { String source = script.getSource(); ScriptEngine scriptEngine = scriptEngines.computeIfAbsent(script.getEngine(), this::createScriptEngine); if (!(scriptEngine instanceof Compilable) || forceScriptEvaluation) { return scriptEngine.eval(source, bindings); } // Compile and store it in our cache. Fall-through for execution compiledScript = ((Compilable) scriptEngine).compile(source); compiledScripts.putIfAbsent(script, compiledScript); } // Let the cached compiled script do its work. return compiledScript.eval(bindings); } ScriptEngine createScriptEngine(String engine) { ScriptEngine scriptEngine = scriptEngineManager.getEngineByName(engine); if (scriptEngine == null) { scriptEngine = scriptEngineManager.getEngineByExtension(engine); } if (scriptEngine == null) { scriptEngine = scriptEngineManager.getEngineByMimeType(engine); } Preconditions.notNull(scriptEngine, () -> "Script engine not found: " + engine); Bindings bindings = scriptEngine.getBindings(ScriptContext.GLOBAL_SCOPE); bindings.put(Script.BIND_SYSTEM_PROPERTY, systemPropertyAccessor); bindings.put(Script.BIND_SYSTEM_ENVIRONMENT, environmentVariableAccessor); return scriptEngine; } boolean isCompiledScriptsEmpty() { return compiledScripts.isEmpty(); } }