/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */ package javax.script; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.logging.Logger; /** * A manager for script engines. */ public class ScriptEngineManager { private static final Logger log = Logger.getLogger(ScriptEngineManager.class.getName()); private ArrayList _engineFactories = new ArrayList(); protected HashSet engineSpis = new HashSet(); protected HashMap extensionAssociations = new HashMap(); protected Bindings globalScope = new SimpleBindings(); protected HashMap mimeTypeAssociations = new HashMap(); protected HashMap nameAssociations = new HashMap(); /** * The constructor checks for implementations of the factory. */ public ScriptEngineManager() { this(Thread.currentThread().getContextClassLoader()); } /** * The constructor checks for implementations of the factory. */ public ScriptEngineManager(ClassLoader loader) { initEngines(loader); } /** * Sets the global scope bindings. */ public void setBindings(Bindings globalScope) { this.globalScope = globalScope; } /** * Gets the global scope bindings. */ public Bindings getBindings() { return this.globalScope; } /** * Puts a value in the global scope. */ public void put(String key, Object value) { getBindings().put(key, value); } /** * Gets a value in the global scope. */ public Object get(String key) { return getBindings().get(key); } /** * Returns the engine for the script factory by name. */ public ScriptEngine getEngineByName(String shortName) { Class fClass = (Class) this.nameAssociations.get(shortName); if (fClass != null) return getEngineByClass(fClass); else return null; } /** * Returns the engine for the script factory by extension. */ public ScriptEngine getEngineByExtension(String ext) { Class fClass = (Class) this.extensionAssociations.get(ext); if (fClass != null) return getEngineByClass(fClass); else return null; } /** * Returns the engine for the script factory by mime-type. */ public ScriptEngine getEngineByMimeType(String mimeType) { Class fClass = (Class) this.mimeTypeAssociations.get(mimeType); if (fClass != null) return getEngineByClass(fClass); else return null; } /** * Returns the known factories. */ public List<ScriptEngineFactory> getEngineFactories() { return new ArrayList<ScriptEngineFactory>(_engineFactories); } /** * Registers an engine name. */ public void registerEngineName(String name, Class factory) { this.nameAssociations.put(name, factory); } /** * Registers an engine mime-type. */ public void registerEngineMimeType(String mimeType, Class factory) { this.mimeTypeAssociations.put(mimeType, factory); } /** * Registers an engine extension */ public void registerEngineExtension(String ext, Class factory) { this.extensionAssociations.put(ext, factory); } /** * Initialize the script engine. */ private void initEngines(ClassLoader loader) { try { Enumeration resources = loader.getResources("META-INF/services/javax.script.ScriptEngineFactory"); while (resources.hasMoreElements()) { URL url = (URL) resources.nextElement(); InputStream is = url.openStream(); try { readFactoryFile(is); } finally { is.close(); } } } catch (IOException e) { throw new RuntimeException(e); } } /** * Initialize the script engine. */ private void readFactoryFile(InputStream is) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); String line; while ((line = reader.readLine()) != null) { int p = line.indexOf('#'); if (p >= 0) line = line.substring(0, p); line = line.trim(); if (line.length() > 0) { addFactoryClass(line); } } } /** * Handles the factory class */ private void addFactoryClass(String className) { try { Thread thread = Thread.currentThread(); ClassLoader loader = thread.getContextClassLoader(); Class cl = Class.forName(className, false, loader); ScriptEngineFactory factory = (ScriptEngineFactory) cl.newInstance(); if (this.engineSpis.contains(cl)) return; _engineFactories.add(factory); this.engineSpis.add(cl); for (String name : factory.getNames()) { registerEngineName(name, cl); } for (String mimeType : factory.getMimeTypes()) { registerEngineMimeType(mimeType, cl); } for (String ext : factory.getExtensions()) { registerEngineExtension(ext, cl); } } catch (Exception e) { throw new RuntimeException(e); } } /** * Returns an instance of the factory with the given class. */ private ScriptEngine getEngineByClass(Class cl) { ScriptEngineFactory factory = getFactoryByClass(cl); if (factory != null) { ScriptEngine engine = factory.getScriptEngine(); ScriptContext cxt = engine.getContext(); cxt.setBindings(this.globalScope, ScriptContext.GLOBAL_SCOPE); return engine; } else return null; } /** * Returns the factory with the given class. */ private ScriptEngineFactory getFactoryByClass(Class cl) { for (int i = 0; i < _engineFactories.size(); i++) { ScriptEngineFactory factory; factory = (ScriptEngineFactory) _engineFactories.get(i); if (factory.getClass().equals(cl)) return factory; } return null; } }