package com.voxeo.tropo.app; import java.io.File; import java.util.HashMap; import java.util.Map; import java.util.Queue; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.TimeUnit; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import org.apache.log4j.Logger; import com.voxeo.tropo.ServletContextConstants; public class ScriptEnginePool { private static final Logger LOG = Logger.getLogger(ScriptEnginePool.class); protected ScriptEngineManager _engMgr; protected Map<String, Integer> _sizes; Map<String, Queue<ScriptEngine>> _pool = new HashMap<String, Queue<ScriptEngine>>(); public ScriptEnginePool(ScriptEngineManager engMgr, Map<String, Integer> initSize) { _engMgr = engMgr; _sizes = initSize; String tropoRuby = (System.getProperty(ServletContextConstants.ROOT_PATH) + "WEB-INF/classes/com/voxeo/tropo/jruby").replace("/", File.separator); for (String type : _sizes.keySet()) { int size = _sizes.get(type); LOG.info("Initializing " + size + " script engine for " + type + " ..."); ArrayBlockingQueue<ScriptEngine> queue = new ArrayBlockingQueue<ScriptEngine>(size); _pool.put(type, queue); for (int i = 0; i < size; i++) { ScriptEngine eng = _engMgr.getEngineByName(type); if (eng == null) { LOG.error("Unsupported script type :" + type); } else { if (type.equalsIgnoreCase("jruby")) { try { //remove . from load path and add tropo.rb to the load path eng.eval("$LOAD_PATH.pop if $LOAD_PATH.last == '.'; $LOAD_PATH.unshift '" + tropoRuby + "'"); if (LOG.isDebugEnabled()) { //eng.eval("puts $LOAD_PATH"); LOG.debug("Added [" + tropoRuby + "] to JRUBY load path."); } } catch (ScriptException e) { LOG.error(e); } } queue.offer(eng); } } } LOG.info("Done with the initialization of script engine pool."); } /** * null if still empty after waitMiliseconds * * @param type * @return */ public ScriptEngine get(String type) { return get(type, 10000); } public void put(String type, ScriptEngine eng) { Queue<ScriptEngine> queue = _pool.get(type); queue.offer(eng); } /** * null if still empty after waitMiliseconds * * @param type * @return */ public ScriptEngine get(String type, int waitMiliseconds) { ArrayBlockingQueue<ScriptEngine> queue = (ArrayBlockingQueue<ScriptEngine>) _pool.get(type); try { return queue.poll(waitMiliseconds, TimeUnit.MILLISECONDS); } catch (InterruptedException e1) { return queue.poll(); } } public Map<String, Queue<ScriptEngine>> getPoolMap() { return _pool; } }