All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.hutool.script.ScriptUtil Maven / Gradle / Ivy

There is a newer version: 5.8.33
Show newest version
package cn.hutool.script;

import cn.hutool.core.map.WeakConcurrentMap;
import cn.hutool.core.util.StrUtil;

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

/**
 * 脚本工具类
 *
 * @author Looly
 */
public class ScriptUtil {

	private static final ScriptEngineManager MANAGER = new ScriptEngineManager();
	private static final WeakConcurrentMap CACHE = new WeakConcurrentMap<>();

	/**
	 * 获得单例的{@link ScriptEngine} 实例
	 *
	 * @param nameOrExtOrMime 脚本名称
	 * @return {@link ScriptEngine} 实例
	 */
	public static ScriptEngine getScript(String nameOrExtOrMime) {
		return CACHE.computeIfAbsent(nameOrExtOrMime, () -> createScript(nameOrExtOrMime));
	}

	/**
	 * 创建 {@link ScriptEngine} 实例
	 *
	 * @param nameOrExtOrMime 脚本名称
	 * @return {@link ScriptEngine} 实例
	 * @since 5.2.6
	 */
	public static ScriptEngine createScript(String nameOrExtOrMime) {
		ScriptEngine engine = MANAGER.getEngineByName(nameOrExtOrMime);
		if (null == engine) {
			engine = MANAGER.getEngineByExtension(nameOrExtOrMime);
		}
		if (null == engine) {
			engine = MANAGER.getEngineByMimeType(nameOrExtOrMime);
		}
		if (null == engine) {
			throw new NullPointerException(StrUtil.format("Script for [{}] not support !", nameOrExtOrMime));
		}
		return engine;
	}

	/**
	 * 获得非单例的 Javascript引擎 {@link JavaScriptEngine}
	 *
	 * @return {@link JavaScriptEngine}
	 */
	public static JavaScriptEngine getJavaScriptEngine() {
		return new JavaScriptEngine();
	}

	/**
	 * 获得单例的JavaScript引擎
	 *
	 * @return Javascript引擎
	 * @since 5.2.5
	 */
	public static ScriptEngine getJsEngine() {
		return getScript("js");
	}

	/**
	 * 创建新的JavaScript引擎
	 *
	 * @return Javascript引擎
	 * @since 5.2.6
	 */
	public static ScriptEngine createJsEngine() {
		return createScript("js");
	}

	/**
	 * 获得单例的Python引擎
* 需要引入org.python:jython * * @return Python引擎 * @since 5.2.5 */ public static ScriptEngine getPythonEngine() { System.setProperty("python.import.site", "false"); return getScript("python"); } /** * 创建Python引擎
* 需要引入org.python:jython * * @return Python引擎 * @since 5.2.6 */ public static ScriptEngine createPythonEngine() { System.setProperty("python.import.site", "false"); return createScript("python"); } /** * 获得单例的Lua引擎
* 需要引入org.luaj:luaj-jse * * @return Lua引擎 * @since 5.2.5 */ public static ScriptEngine getLuaEngine() { return getScript("lua"); } /** * 创建Lua引擎
* 需要引入org.luaj:luaj-jse * * @return Lua引擎 * @since 5.2.6 */ public static ScriptEngine createLuaEngine() { return createScript("lua"); } /** * 获得单例的Groovy引擎
* 需要引入org.codehaus.groovy:groovy-all * * @return Groovy引擎 * @since 5.2.5 */ public static ScriptEngine getGroovyEngine() { return getScript("groovy"); } /** * 创建Groovy引擎
* 需要引入org.codehaus.groovy:groovy-all * * @return Groovy引擎 * @since 5.2.6 */ public static ScriptEngine createGroovyEngine() { return createScript("groovy"); } /** * 执行Javascript脚本,返回Invocable,此方法分为两种情况: * *
    *
  1. 执行的脚本返回值是可执行的脚本方法
  2. *
  3. 脚本为函数库,则ScriptEngine本身为可执行方法
  4. *
* * @param script 脚本内容 * @return 执行结果 * @throws ScriptRuntimeException 脚本异常 * @since 5.3.6 */ public static Invocable evalInvocable(String script) throws ScriptRuntimeException { final ScriptEngine jsEngine = getJsEngine(); final Object eval; try { eval = jsEngine.eval(script); } catch (ScriptException e) { throw new ScriptRuntimeException(e); } if(eval instanceof Invocable){ return (Invocable)eval; } else if(jsEngine instanceof Invocable){ return (Invocable)jsEngine; } throw new ScriptRuntimeException("Script is not invocable !"); } /** * 执行有返回值的Javascript脚本 * * @param script 脚本内容 * @return 执行结果 * @throws ScriptRuntimeException 脚本异常 * @since 3.2.0 */ public static Object eval(String script) throws ScriptRuntimeException { try { return getJsEngine().eval(script); } catch (ScriptException e) { throw new ScriptRuntimeException(e); } } /** * 执行有返回值的脚本 * * @param script 脚本内容 * @param context 脚本上下文 * @return 执行结果 * @throws ScriptRuntimeException 脚本异常 * @since 3.2.0 */ public static Object eval(String script, ScriptContext context) throws ScriptRuntimeException { try { return getJsEngine().eval(script, context); } catch (ScriptException e) { throw new ScriptRuntimeException(e); } } /** * 执行有返回值的脚本 * * @param script 脚本内容 * @param bindings 绑定的参数 * @return 执行结果 * @throws ScriptRuntimeException 脚本异常 * @since 3.2.0 */ public static Object eval(String script, Bindings bindings) throws ScriptRuntimeException { try { return getJsEngine().eval(script, bindings); } catch (ScriptException e) { throw new ScriptRuntimeException(e); } } /** * 执行JS脚本中的指定方法 * * @param script js脚本 * @param func 方法名 * @param args 方法参数 * @return 结果 * @since 5.3.6 */ public static Object invoke(String script, String func, Object... args) { final Invocable eval = evalInvocable(script); try { return eval.invokeFunction(func, args); } catch (ScriptException | NoSuchMethodException e) { throw new ScriptRuntimeException(e); } } /** * 编译Javascript脚本 * * @param script 脚本内容 * @return {@link CompiledScript} * @throws ScriptRuntimeException 脚本异常 * @since 3.2.0 */ public static CompiledScript compile(String script) throws ScriptRuntimeException { try { return compile(getJsEngine(), script); } catch (ScriptException e) { throw new ScriptRuntimeException(e); } } /** * 编译Javascript脚本 * * @param engine 引擎 * @param script 脚本内容 * @return {@link CompiledScript} * @throws ScriptException 脚本异常 */ public static CompiledScript compile(ScriptEngine engine, String script) throws ScriptException { if (engine instanceof Compilable) { final Compilable compEngine = (Compilable) engine; return compEngine.compile(script); } return null; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy