Package org.pirkaengine.core.script

Source Code of org.pirkaengine.core.script.MultiThreadScriptInvoker

package org.pirkaengine.core.script;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.pirkaengine.core.expression.Function;


/**
* ScriptInvoker.
* <p>
* スクリプトの実行クラスを提供する。<br />
* ScriptInvokerでは、コンストラクタで指定されたClassLoaderを用いてスクリプトを実行する。
* ScriptInvokerでは実行用スレッドを作成し、そのスレッド内で使用されるClassLoaderを保証する。
* </p>
* <p>
* このクラスはスレッドセーフを保証する。
* </p>
* @author shuji.w6e
* @since 0.1.0
*/
public class MultiThreadScriptInvoker extends ScriptInvoker {

    private final ExecutorService service;
    private final ScriptEngine engine;

    @Override
    ScriptEngine getEngine() {
        return engine;
    }

    /**
     * スクリプト言語とClassLoaderを指定してインスタンスを生成する。
     * <p>
     * 実行用のスレッドはExecutorServiceとして初期化される。
     * それらのスレッドのClassLoaderは引数で指定されたClassLoaderが設定される。
     * </p>
     * <p>
     * また、実行するScriptEngineは指定されたClassLoaderから取得される。
     * </p>
     * @param language スクリプト言語
     * @param classLoader ClassLoader
     * @throws ScriptEngineException
     */
    public MultiThreadScriptInvoker(final String language, final ClassLoader classLoader) throws ScriptEngineException {
        if (language == null) throw new IllegalArgumentException("language == null");
        if (classLoader == null) throw new IllegalArgumentException("classLoader == null");
        this.service = Executors.newCachedThreadPool(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r);
                thread.setContextClassLoader(classLoader);
                return thread;
            }
        });
        Future<ScriptEngine> future = this.service.submit(new Callable<ScriptEngine>() {
            @Override
            public ScriptEngine call() {
                ScriptEngineManager mng = new ScriptEngineManager();
                return mng.getEngineByName(language);
            }
        });
        try {
            engine = future.get();
        } catch (InterruptedException e) {
            throw new ScriptEngineException("init error.", e);
        } catch (ExecutionException e) {
            throw new ScriptEngineException("init error.", e);
        }
        if (engine == null) throw new ScriptEngineException("Cant find ScriptEngineManager: language=" + language);
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * org.pirkaengine.core.script.Invoker#invoke(org.pirkaengine.core.expression
     * .Function, java.lang.Object[])
     */
    @Override
    public Object invoke(final Function function, final Object[] params) throws ScriptEngineException {
        Future<Object> future = service.submit(new Callable<Object>() {
            @Override
            public Object call() throws ScriptException, NoSuchMethodException {
                return getInvocable(function).invokeFunction(function.name, params);
            }
        });
        try {
            return future.get();
        } catch (InterruptedException e) {
            throw new ScriptEngineException("function invoke error.", e);
        } catch (ExecutionException e) {
            throw new ScriptEngineException("function invoke error.", e);
        }
    }

}
TOP

Related Classes of org.pirkaengine.core.script.MultiThreadScriptInvoker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.