Package dovetaildb.dbrepository

Source Code of dovetaildb.dbrepository.ScriptEnv

/**
*
*/
package dovetaildb.dbrepository;

import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.script.Bindings;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;


import dovetaildb.api.ApiException;
import dovetaildb.dbrepository.StandardDbRepository.ScriptFile;

public class ScriptEnv {
  protected ScriptEngineManager manager = new ScriptEngineManager();
  protected ConcurrentHashMap<String, ScriptEngine> engines = new ConcurrentHashMap<String, ScriptEngine>();
  protected ConcurrentHashMap<String,Object> globals;
 
  public ScriptEnv(ConcurrentHashMap<String,Object> globals) {
    this.globals = globals;
  }
 
  public ScriptEngine getScriptEngine(String name) {
    ScriptEngine engine = engines.get(name);
    if (engine == null) {
      for(ScriptEngineFactory factory : manager.getEngineFactories()) {
        String curName = StandardDbRepository.getScriptEngineFactoryName(factory);
        if (curName.equals(name)) {
          engine = factory.getScriptEngine();
          for(Map.Entry<String,Object> entry : globals.entrySet()) {
            engine.put(entry.getKey(), entry.getValue());
          }
          if (factory.getParameter("THREADING") != null) {
            engines.put(name, engine);
          }
          break;
        }
      }
      if (engine == null) {
        ArrayList<String> availableNames = new ArrayList<String>();
        for(ScriptEngineFactory factory : manager.getEngineFactories()) {
          availableNames.add(StandardDbRepository.getScriptEngineFactoryName(factory));
        }
        throw new ApiException("UnknownScriptEngine", "\""+name+"\" is not a known script engine; available engines are: "+availableNames);
      }
    }
    return engine;
  }
  Object ingestScript(String filename, String code, Map<String,Object> env) {
    ScriptFile file = new ScriptFile(code);
    ScriptEngine engine = getScriptEngine(file.language);
    try {
      if (env != null) {
        Bindings bindings = engine.createBindings();
        for(Map.Entry<String,Object> entry : globals.entrySet()) {
          bindings.put(entry.getKey(), entry.getValue());
        }
        for(Map.Entry<String, Object> entry : env.entrySet()) {
          bindings.put(entry.getKey(), entry.getValue());
        }
        return engine.eval(code, bindings);
      } else {
        return engine.eval(code);
      }
    } catch (ScriptException e) {
      String desc = e.getMessage();
      desc = desc.substring(0, desc.lastIndexOf(" in "));
      desc += " in \""+filename+"\"";
      if (e.getLineNumber() != -1) {
        desc += ", line "+e.getLineNumber();
      }
      if (e.getColumnNumber() != -1) {
        desc += ", column "+e.getColumnNumber();
      }
      Throwable cause = e.getCause();
      if (cause != null && cause instanceof Exception) {
        throw new ApiException("ScriptException", desc, (Exception)cause);
      } else {
        throw new ApiException("ScriptException", desc, e);
      }
    }
  }
  <T>T getInterface(Class<T> iface, Object... args) {
    T impl = null;
    for(ScriptEngine engine : engines.values()) {
      if (engine instanceof Invocable) {
        T curImpl = ((Invocable)engine).getInterface(iface);
        if (impl != null) throw new RuntimeException("The "+iface.getSimpleName()+" interface is implemented multiple times in different scripting languages.");
        impl = curImpl;
      }
    }
    return impl;
  }
  public Object invokeFunction(String functionName, Object[] args) {
    int dotIdx = functionName.indexOf('.');
    boolean isMethod = dotIdx > -1;
    String objectName= null;
    if (isMethod) {
      objectName = functionName.substring(0, dotIdx);
      functionName = functionName.substring(dotIdx+1);
    }
    for(ScriptEngine engine : engines.values()) {
      if (engine instanceof Invocable) {
        Invocable invocable = (Invocable)engine;
        try {
          if (isMethod) {
            Object target = engine.get(objectName);
            if (target != null) {
              try {
                return invocable.invokeMethod(target, functionName, args);
              } catch (NoSuchMethodException e) {
                throw new ApiException("UnknownFunction", "Method \""+functionName+"\" not defined on object \""+objectName+"\"");
              }
            }
          } else {
            try {
              return ((Invocable)engine).invokeFunction(functionName, args);
            } catch (NoSuchMethodException e) {}
          }
        } catch (ScriptException e) {
          throw new ApiException("ScriptException", e);
        }
      }
    }
    throw new ApiException("UnknownFunction", "Function not defined: \""+functionName+"\"");
  }
  public void putInAll(String name, Object value) {
    for(ScriptEngine engine : engines.values()) {
      engine.put(name, value);
    }
  }
}
TOP

Related Classes of dovetaildb.dbrepository.ScriptEnv

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.