Repository: jclouds-karaf Updated Branches: refs/heads/fix-script-engine 6c68f0d23 -> 5e0fcbef1
Clean up formatting and throw an IllegalStateException if no script engine can be loadad Project: http://git-wip-us.apache.org/repos/asf/jclouds-karaf/repo Commit: http://git-wip-us.apache.org/repos/asf/jclouds-karaf/commit/5e0fcbef Tree: http://git-wip-us.apache.org/repos/asf/jclouds-karaf/tree/5e0fcbef Diff: http://git-wip-us.apache.org/repos/asf/jclouds-karaf/diff/5e0fcbef Branch: refs/heads/fix-script-engine Commit: 5e0fcbef105bdb8bed0461519fb7b0d2671beed3 Parents: 6c68f0d Author: Andrew Phillips <[email protected]> Authored: Sun Sep 11 15:58:56 2016 +0100 Committer: Andrew Phillips <[email protected]> Committed: Sun Sep 11 15:58:56 2016 +0100 ---------------------------------------------------------------------- .../table/internal/OSGiScriptEngine.java | 116 ++--- .../table/internal/OSGiScriptEngineFactory.java | 125 +++--- .../table/internal/OSGiScriptEngineManager.java | 442 ++++++++++--------- .../table/internal/ScriptEngineShellTable.java | 10 +- 4 files changed, 378 insertions(+), 315 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jclouds-karaf/blob/5e0fcbef/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngine.java ---------------------------------------------------------------------- diff --git a/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngine.java b/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngine.java index 119cb15..d3415c3 100644 --- a/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngine.java +++ b/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngine.java @@ -15,7 +15,6 @@ * */ -// implementation copied from http://svn.apache.org/repos/asf/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngine.java package org.jclouds.karaf.commands.table.internal; import java.io.Reader; @@ -26,54 +25,71 @@ import javax.script.ScriptEngine; import javax.script.ScriptEngineFactory; import javax.script.ScriptException; -public class OSGiScriptEngine implements ScriptEngine{ - private ScriptEngine engine; - private OSGiScriptEngineFactory factory; - public OSGiScriptEngine(ScriptEngine engine, OSGiScriptEngineFactory factory){ - this.engine=engine; - this.factory=factory; - } - public Bindings createBindings() { - return engine.createBindings(); - } - public Object eval(Reader reader, Bindings n) throws ScriptException { - return engine.eval(reader, n); - } - public Object eval(Reader reader, ScriptContext context) throws ScriptException { - return engine.eval(reader, context); - } - public Object eval(Reader reader) throws ScriptException { - return engine.eval(reader); - } - public Object eval(String script, Bindings n) throws ScriptException { - return engine.eval(script, n); - } - public Object eval(String script, ScriptContext context) throws ScriptException { - return engine.eval(script, context); - } - public Object eval(String script) throws ScriptException { - return engine.eval(script); - } - public Object get(String key) { - return engine.get(key); - } - public Bindings getBindings(int scope) { - return engine.getBindings(scope); - } - public ScriptContext getContext() { - return engine.getContext(); - } - public ScriptEngineFactory getFactory() { - return factory; - } - public void put(String key, Object value) { - engine.put(key, value); - } - public void setBindings(Bindings bindings, int scope) { - engine.setBindings(bindings, scope); - } - public void setContext(ScriptContext context) { - engine.setContext(context); - } +// modified version of http://svn.apache.org/repos/asf/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngine.java +public class OSGiScriptEngine implements ScriptEngine { + private ScriptEngine engine; + private OSGiScriptEngineFactory factory; + public OSGiScriptEngine(ScriptEngine engine, OSGiScriptEngineFactory factory) { + this.engine = engine; + this.factory = factory; + } + + public Bindings createBindings() { + return engine.createBindings(); + } + + public Object eval(Reader reader, Bindings n) throws ScriptException { + return engine.eval(reader, n); + } + + public Object eval(Reader reader, ScriptContext context) + throws ScriptException { + return engine.eval(reader, context); + } + + public Object eval(Reader reader) throws ScriptException { + return engine.eval(reader); + } + + public Object eval(String script, Bindings n) throws ScriptException { + return engine.eval(script, n); + } + + public Object eval(String script, ScriptContext context) + throws ScriptException { + return engine.eval(script, context); + } + + public Object eval(String script) throws ScriptException { + return engine.eval(script); + } + + public Object get(String key) { + return engine.get(key); + } + + public Bindings getBindings(int scope) { + return engine.getBindings(scope); + } + + public ScriptContext getContext() { + return engine.getContext(); + } + + public ScriptEngineFactory getFactory() { + return factory; + } + + public void put(String key, Object value) { + engine.put(key, value); + } + + public void setBindings(Bindings bindings, int scope) { + engine.setBindings(bindings, scope); + } + + public void setContext(ScriptContext context) { + engine.setContext(context); + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/jclouds-karaf/blob/5e0fcbef/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngineFactory.java ---------------------------------------------------------------------- diff --git a/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngineFactory.java b/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngineFactory.java index 0281b82..1a8d318 100644 --- a/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngineFactory.java +++ b/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngineFactory.java @@ -22,62 +22,77 @@ import javax.script.ScriptEngine; import javax.script.ScriptEngineFactory; /** - * This is a wrapper class for the ScriptEngineFactory class that deals with context class loader issues - * It is necessary because engines (at least ruby) use the context classloader to find their resources (i.e., their "native" classes) + * This is a wrapper class for the ScriptEngineFactory class that deals with + * context class loader issues It is necessary because engines (at least ruby) + * use the context classloader to find their resources (i.e., their "native" + * classes) */ -// implementation copied from http://svn.apache.org/repos/asf/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngineFactory.java -public class OSGiScriptEngineFactory implements ScriptEngineFactory{ - private ScriptEngineFactory factory; - private ClassLoader contextClassLoader; - public OSGiScriptEngineFactory (ScriptEngineFactory factory, ClassLoader contextClassLoader){ - this.factory=factory; - this.contextClassLoader=contextClassLoader; - } - public String getEngineName() { - return factory.getEngineName(); - } - public String getEngineVersion() { - return factory.getEngineVersion(); - } - public List<String> getExtensions() { - return factory.getExtensions(); - } - public String getLanguageName() { - return factory.getLanguageName(); - } - public String getLanguageVersion() { - return factory.getLanguageVersion(); - } - public String getMethodCallSyntax(String obj, String m, String... args) { - return factory.getMethodCallSyntax(obj, m, args); - } - public List<String> getMimeTypes() { - return factory.getMimeTypes(); - } - public List<String> getNames() { - return factory.getNames(); - } - public String getOutputStatement(String toDisplay) { - return factory.getOutputStatement(toDisplay); - } - public Object getParameter(String key) { - return factory.getParameter(key); - } - public String getProgram(String... statements) { - return factory.getProgram(statements); - } - public ScriptEngine getScriptEngine() { - ScriptEngine engine=null; - if(contextClassLoader!=null){ - ClassLoader old=Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(contextClassLoader); - engine=factory.getScriptEngine(); - Thread.currentThread().setContextClassLoader(old); - } - else engine=factory.getScriptEngine(); - return engine; - } - +// modified version of http://svn.apache.org/repos/asf/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngineFactory.java +public class OSGiScriptEngineFactory implements ScriptEngineFactory { + private ScriptEngineFactory factory; + private ClassLoader contextClassLoader; + + public OSGiScriptEngineFactory(ScriptEngineFactory factory, + ClassLoader contextClassLoader) { + this.factory = factory; + this.contextClassLoader = contextClassLoader; + } + + public String getEngineName() { + return factory.getEngineName(); + } + + public String getEngineVersion() { + return factory.getEngineVersion(); + } + + public List<String> getExtensions() { + return factory.getExtensions(); + } + + public String getLanguageName() { + return factory.getLanguageName(); + } + + public String getLanguageVersion() { + return factory.getLanguageVersion(); + } + + public String getMethodCallSyntax(String obj, String m, String... args) { + return factory.getMethodCallSyntax(obj, m, args); + } + + public List<String> getMimeTypes() { + return factory.getMimeTypes(); + } + + public List<String> getNames() { + return factory.getNames(); + } + + public String getOutputStatement(String toDisplay) { + return factory.getOutputStatement(toDisplay); + } + + public Object getParameter(String key) { + return factory.getParameter(key); + } + + public String getProgram(String... statements) { + return factory.getProgram(statements); + } + + public ScriptEngine getScriptEngine() { + ScriptEngine engine = null; + if (contextClassLoader != null) { + ClassLoader old = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(contextClassLoader); + engine = factory.getScriptEngine(); + Thread.currentThread().setContextClassLoader(old); + } else + engine = factory.getScriptEngine(); + return engine; + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/jclouds-karaf/blob/5e0fcbef/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngineManager.java ---------------------------------------------------------------------- diff --git a/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngineManager.java b/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngineManager.java index 7448b49..95668ae 100644 --- a/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngineManager.java +++ b/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngineManager.java @@ -14,6 +14,7 @@ * limitations under the License. * */ + package org.jclouds.karaf.commands.table.internal; import java.io.BufferedReader; @@ -34,239 +35,262 @@ import javax.script.SimpleBindings; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * This class acts as a delegate for all the available ScriptEngineManagers. Unluckily, the standard did not - * define it as an interface, so we need to extend it to allow polymorphism. However, no calls to super are used. - * It wraps all available ScriptEngineManagers in the OSGi ServicePlatform into a merged ScriptEngineManager. - * - * Internally, what this class does is creating ScriptEngineManagers for each bundle - * that contains a ScriptEngineFactory and includes a META-INF/services/javax.script.ScriptEngineFactory file. - * It assumes that the file contains a list of @link ScriptEngineFactory classes. For each bundle, it creates a - * ScriptEngineManager, then merges them. @link ScriptEngineFactory objects are wrapped - * into @link OSGiScriptEngineFactory objects to deal with problems of context class loader: - * Those scripting engines that rely on the ContextClassloader for finding resources need to use this wrapper - * and the @link OSGiScriptFactory. Mainly, jruby does. - * - * Note that even if no context classloader issues arose, it would still be needed to search manually for the - * factories and either use them directly (losing the mimeType/extension/shortName mechanisms for finding engines - * or manually registering them) or still use this class, which would be smarter. In the latter case, - * it would only be needed to remove the hack that temporarily sets the context classloader to the appropriate, - * bundle-related, class loader. - * + * This class acts as a delegate for all the available ScriptEngineManagers. + * Unluckily, the standard did not define it as an interface, so we need to + * extend it to allow polymorphism. However, no calls to super are used. It + * wraps all available ScriptEngineManagers in the OSGi ServicePlatform into a + * merged ScriptEngineManager. + * + * Internally, what this class does is creating ScriptEngineManagers for each + * bundle that contains a ScriptEngineFactory and includes a + * META-INF/services/javax.script.ScriptEngineFactory file. It assumes that the + * file contains a list of @link ScriptEngineFactory classes. For each bundle, + * it creates a ScriptEngineManager, then merges them. @link ScriptEngineFactory + * objects are wrapped into @link OSGiScriptEngineFactory objects to deal with + * problems of context class loader: Those scripting engines that rely on the + * ContextClassloader for finding resources need to use this wrapper and the @link + * OSGiScriptFactory. Mainly, jruby does. + * + * Note that even if no context classloader issues arose, it would still be + * needed to search manually for the factories and either use them directly + * (losing the mimeType/extension/shortName mechanisms for finding engines or + * manually registering them) or still use this class, which would be smarter. + * In the latter case, it would only be needed to remove the hack that + * temporarily sets the context classloader to the appropriate, bundle-related, + * class loader. + * * Caveats: - * <ul><li> - * All factories are wrapped with an {@link OSGiScriptEngineFactory}. As Engines are not wrapped, - * calls like - * <code> + * <ul> + * <li> + * All factories are wrapped with an {@link OSGiScriptEngineFactory}. As Engines + * are not wrapped, calls like <code> * ScriptEngineManager osgiManager=new OSGiScriptEngineManager(context);<br> * ScriptEngine engine=osgiManager.getEngineByName("ruby"); * ScriptEngineFactory factory=engine.getFactory() //this does not return the OSGiFactory wrapper * factory.getScriptEngine(); //this might fail, as it does not use OSGiScriptEngineFactory wrapper * </code> - * might result in unexpected errors. Future versions may wrap the ScriptEngine with a OSGiScriptEngine to solve this - * issue, but for the moment it is not needed. - * </li> - * + * might result in unexpected errors. Future versions may wrap the ScriptEngine + * with a OSGiScriptEngine to solve this issue, but for the moment it is not + * needed.</li> */ -// implementation copied from http://svn.apache.org/repos/asf/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngineManager.java -public class OSGiScriptEngineManager extends ScriptEngineManager{ - private Bindings bindings; - private Map <ScriptEngineManager, ClassLoader> classLoaders; - private BundleContext context; - - public OSGiScriptEngineManager(BundleContext context){ - this.context=context; - bindings=new SimpleBindings(); - this.classLoaders=findManagers(context); - } - /** - * This method is the only one that is visible and not part of the ScriptEngineManager class. - * Its purpose is to find new managers that weren't available before, but keeping the globalScope bindings - * set. - * If you want to clean the bindings you can either get a fresh instance of OSGiScriptManager or - * setting up a new bindings object. - * This can be done with: - * <code> - * ScriptEngineManager manager=new OSGiScriptEngineManager(context); - * (...)//do stuff - * osgiManager=(OSGiScriptEngineManager)manager;//cast to ease reading - * osgiManager.reloadManagers(); - * - * manager.setBindings(new OSGiBindings());//or you can use your own bindings implementation - * - * </code> - * - */ - public void reloadManagers(){ - this.classLoaders=findManagers(context); - } - - public Object get(String key) { - return bindings.get(key); - } +// modified version of http://svn.apache.org/repos/asf/felix/trunk/mishell/src/main/java/org/apache/felix/mishell/OSGiScriptEngineManager.java +public class OSGiScriptEngineManager extends ScriptEngineManager { + private static final Logger LOGGER = LoggerFactory.getLogger(OSGiScriptEngineManager.class); - public Bindings getBindings() { - return bindings; - } + private Bindings bindings; + private Map<ScriptEngineManager, ClassLoader> classLoaders; + private BundleContext context; - public ScriptEngine getEngineByExtension(String extension) { - //TODO this is a hack to deal with context class loader issues - ScriptEngine engine=null; - for(ScriptEngineManager manager: classLoaders.keySet()){ - ClassLoader old=Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(classLoaders.get(manager)); - engine=manager.getEngineByExtension(extension); - Thread.currentThread().setContextClassLoader(old); - if (engine!=null) break; - } - return engine; - } + public OSGiScriptEngineManager(BundleContext context) { + this.context = context; + bindings = new SimpleBindings(); + this.classLoaders = findManagers(context); + } - public ScriptEngine getEngineByMimeType(String mimeType) { - //TODO this is a hack to deal with context class loader issues - ScriptEngine engine=null; - for(ScriptEngineManager manager: classLoaders.keySet()){ - ClassLoader old=Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(classLoaders.get(manager)); - engine=manager.getEngineByMimeType(mimeType); - Thread.currentThread().setContextClassLoader(old); - if (engine!=null) break; - } - return engine; - } + /** + * This method is the only one that is visible and not part of the + * ScriptEngineManager class. Its purpose is to find new managers that + * weren't available before, but keeping the globalScope bindings set. If you + * want to clean the bindings you can either get a fresh instance of + * OSGiScriptManager or setting up a new bindings object. This can be done + * with: <code> + * ScriptEngineManager manager=new OSGiScriptEngineManager(context); + * (...) //do stuff + * osgiManager=(OSGiScriptEngineManager)manager; //cast to ease reading + * osgiManager.reloadManagers(); + * + * manager.setBindings(new OSGiBindings()); //or you can use your own bindings implementation + * </code> + */ + public void reloadManagers() { + this.classLoaders = findManagers(context); + } - public ScriptEngine getEngineByName(String shortName) { - //TODO this is a hack to deal with context class loader issues - for(ScriptEngineManager manager: classLoaders.keySet()){ - ClassLoader old=Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(classLoaders.get(manager)); - ScriptEngine engine=manager.getEngineByName(shortName); - Thread.currentThread().setContextClassLoader(old); - if (engine!=null){ - return new OSGiScriptEngine(engine, new OSGiScriptEngineFactory(engine.getFactory(), classLoaders.get(manager))); - } - } - return null; - } - public List<ScriptEngineFactory> getEngineFactories() { - List<ScriptEngineFactory> osgiFactories=new ArrayList<ScriptEngineFactory>(); - for(ScriptEngineManager engineManager: classLoaders.keySet()){ - for (ScriptEngineFactory factory : engineManager.getEngineFactories()){ - osgiFactories.add(new OSGiScriptEngineFactory(factory, classLoaders.get(engineManager))); - } - } - return osgiFactories; - } + public Object get(String key) { + return bindings.get(key); + } - public void put(String key, Object value) { - bindings.put(key, value); - } + public Bindings getBindings() { + return bindings; + } - public void registerEngineExtension(String extension, ScriptEngineFactory factory) { - for(ScriptEngineManager engineManager: classLoaders.keySet()) - engineManager.registerEngineExtension(extension, factory); - } + public ScriptEngine getEngineByExtension(String extension) { + // TODO this is a hack to deal with context class loader issues + ScriptEngine engine = null; + for (ScriptEngineManager manager : classLoaders.keySet()) { + ClassLoader old = Thread.currentThread().getContextClassLoader(); + Thread.currentThread() + .setContextClassLoader(classLoaders.get(manager)); + engine = manager.getEngineByExtension(extension); + Thread.currentThread().setContextClassLoader(old); + if (engine != null) + break; + } + return engine; + } - public void registerEngineMimeType(String type, ScriptEngineFactory factory) { - for(ScriptEngineManager engineManager: classLoaders.keySet()) - engineManager.registerEngineMimeType(type, factory); - } + public ScriptEngine getEngineByMimeType(String mimeType) { + // TODO this is a hack to deal with context class loader issues + ScriptEngine engine = null; + for (ScriptEngineManager manager : classLoaders.keySet()) { + ClassLoader old = Thread.currentThread().getContextClassLoader(); + Thread.currentThread() + .setContextClassLoader(classLoaders.get(manager)); + engine = manager.getEngineByMimeType(mimeType); + Thread.currentThread().setContextClassLoader(old); + if (engine != null) + break; + } + return engine; + } - public void registerEngineName(String name, ScriptEngineFactory factory) { - for(ScriptEngineManager engineManager: classLoaders.keySet()) - engineManager.registerEngineName(name, factory); - } - /** - * Follows the same behavior of @link javax.script.ScriptEngineManager#setBindings(Bindings) - * This means that the same bindings are applied to all the underlying managers. - * @param bindings - */ - public void setBindings(Bindings bindings) { - this.bindings=bindings; - for(ScriptEngineManager manager: classLoaders.keySet()){ - manager.setBindings(bindings); - } - } + public ScriptEngine getEngineByName(String shortName) { + // TODO this is a hack to deal with context class loader issues + for (ScriptEngineManager manager : classLoaders.keySet()) { + ClassLoader old = Thread.currentThread().getContextClassLoader(); + Thread.currentThread() + .setContextClassLoader(classLoaders.get(manager)); + ScriptEngine engine = manager.getEngineByName(shortName); + Thread.currentThread().setContextClassLoader(old); + if (engine != null) { + return new OSGiScriptEngine(engine, new OSGiScriptEngineFactory( + engine.getFactory(), classLoaders.get(manager))); + } + } + return null; + } - private Map<ScriptEngineManager, ClassLoader> findManagers(BundleContext context) { - Map<ScriptEngineManager, ClassLoader> managers=new HashMap<ScriptEngineManager, ClassLoader>(); - for (String factoryName : findFactoryCandidates(context)) { - // we do not really need the class, but we need the classloader - ClassLoader factoryLoader = tryGetClassLoader(factoryName); - if (factoryLoader == null) { - continue; + public List<ScriptEngineFactory> getEngineFactories() { + List<ScriptEngineFactory> osgiFactories = new ArrayList<ScriptEngineFactory>(); + for (ScriptEngineManager engineManager : classLoaders.keySet()) { + for (ScriptEngineFactory factory : engineManager.getEngineFactories()) { + osgiFactories.add(new OSGiScriptEngineFactory(factory, classLoaders + .get(engineManager))); + } } - ScriptEngineManager manager = tryCreateScriptEngineManager(factoryName, factoryLoader); - if (manager != null) { - manager.setBindings(bindings); - managers.put(manager, factoryLoader); + return osgiFactories; + } + + public void put(String key, Object value) { + bindings.put(key, value); + } + + public void registerEngineExtension(String extension, + ScriptEngineFactory factory) { + for (ScriptEngineManager engineManager : classLoaders.keySet()) + engineManager.registerEngineExtension(extension, factory); + } + + public void registerEngineMimeType(String type, ScriptEngineFactory factory) { + for (ScriptEngineManager engineManager : classLoaders.keySet()) + engineManager.registerEngineMimeType(type, factory); + } + + public void registerEngineName(String name, ScriptEngineFactory factory) { + for (ScriptEngineManager engineManager : classLoaders.keySet()) + engineManager.registerEngineName(name, factory); + } + + /** + * Follows the same behavior of @link + * javax.script.ScriptEngineManager#setBindings(Bindings) This means that the + * same bindings are applied to all the underlying managers. + * + * @param bindings + */ + public void setBindings(Bindings bindings) { + this.bindings = bindings; + for (ScriptEngineManager manager : classLoaders.keySet()) { + manager.setBindings(bindings); } - } - return managers; - } - - private static ClassLoader tryGetClassLoader(String className) { - try { - return Class.forName(className).getClassLoader(); - } catch (ClassNotFoundException exception) { - // TODO: use a logger - System.err.println("WARN: Tried to load class " + - className + " but failed due to: " + exception.getMessage()); - return null; - } - } + } - private static ScriptEngineManager tryCreateScriptEngineManager(String factoryName, ClassLoader factoryLoader) { - try { - return new ScriptEngineManager(factoryLoader); - } catch (Exception exception) { - // TODO: use a logger - System.err.println("WARN: Found ScriptEngineFactory candidate " + - factoryName + " but failed to create a factory due to: " + exception.getMessage()); - return null; - } - } + private Map<ScriptEngineManager, ClassLoader> findManagers( + BundleContext context) { + Map<ScriptEngineManager, ClassLoader> managers = new HashMap<ScriptEngineManager, ClassLoader>(); + for (String factoryName : findFactoryCandidates(context)) { + // we do not really need the class, but we need the classloader + ClassLoader factoryLoader = tryGetClassLoader(factoryName); + if (factoryLoader == null) { + continue; + } + ScriptEngineManager manager = tryCreateScriptEngineManager( + factoryName, factoryLoader); + if (manager != null) { + manager.setBindings(bindings); + managers.put(manager, factoryLoader); + } + } + return managers; + } - /** - * Iterates through all bundles to get the available @link ScriptEngineFactory classes - * @return the names of the available ScriptEngineFactory classes - * @throws IOException - */ - private List<String> findFactoryCandidates(BundleContext context) { - Bundle[] bundles = context.getBundles(); - List<String> factoryCandidates = new ArrayList<String>(); - for (Bundle bundle : bundles) { - if (bundle == null) { - continue; + private static ClassLoader tryGetClassLoader(String className) { + try { + return Class.forName(className).getClassLoader(); + } catch (ClassNotFoundException exception) { + LOGGER.warn("Tried to load class {} but failed due to: {}", + className, exception.getMessage()); + return null; } + } - if (bundle.getSymbolicName().equals("system.bundle")) { - continue; - } - Enumeration urls = bundle.findEntries("META-INF/services", - "javax.script.ScriptEngineFactory", false); - if (urls == null) { - continue; - } - - while (urls.hasMoreElements()) { - URL u = (URL) urls.nextElement(); - try { - BufferedReader reader = new BufferedReader( - new InputStreamReader(u.openStream())); - String line; - while ((line = reader.readLine()) != null) { - line = line.trim(); - // ignore comments and empty lines - if (!line.isEmpty() && !line.startsWith("#")) { - factoryCandidates.add(line); + private static ScriptEngineManager tryCreateScriptEngineManager( + String factoryName, ClassLoader factoryLoader) { + try { + return new ScriptEngineManager(factoryLoader); + } catch (Exception exception) { + LOGGER.warn("Found ScriptEngineFactory candidate {} but failed to create a factory due to: {}", + factoryName, exception.getMessage()); + return null; + } + } + + /** + * Iterates through all bundles to get the available @link + * ScriptEngineFactory classes + * + * @return the names of the available ScriptEngineFactory classes + * @throws IOException + */ + private List<String> findFactoryCandidates(BundleContext context) { + Bundle[] bundles = context.getBundles(); + List<String> factoryCandidates = new ArrayList<String>(); + for (Bundle bundle : bundles) { + if (bundle == null) { + continue; + } + + if (bundle.getSymbolicName().equals("system.bundle")) { + continue; + } + Enumeration<URL> urls = bundle.findEntries("META-INF/services", + "javax.script.ScriptEngineFactory", false); + if (urls == null) { + continue; + } + + while (urls.hasMoreElements()) { + URL u = (URL) urls.nextElement(); + try { + BufferedReader reader = new BufferedReader( + new InputStreamReader(u.openStream())); + String line; + while ((line = reader.readLine()) != null) { + line = line.trim(); + // ignore comments and empty lines + if (!line.isEmpty() && !line.startsWith("#")) { + factoryCandidates.add(line); + } + } + } catch (IOException ignored) { } - } - } catch (IOException ignored) {} - } - } - return factoryCandidates; - } + } + } + return factoryCandidates; + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/jclouds-karaf/blob/5e0fcbef/commands/src/main/java/org/jclouds/karaf/commands/table/internal/ScriptEngineShellTable.java ---------------------------------------------------------------------- diff --git a/commands/src/main/java/org/jclouds/karaf/commands/table/internal/ScriptEngineShellTable.java b/commands/src/main/java/org/jclouds/karaf/commands/table/internal/ScriptEngineShellTable.java index 88ad5b8..5f2733f 100644 --- a/commands/src/main/java/org/jclouds/karaf/commands/table/internal/ScriptEngineShellTable.java +++ b/commands/src/main/java/org/jclouds/karaf/commands/table/internal/ScriptEngineShellTable.java @@ -17,6 +17,8 @@ package org.jclouds.karaf.commands.table.internal; +import static java.lang.String.format; + import org.jclouds.karaf.commands.table.BasicShellTable; import javax.script.ScriptEngine; @@ -34,6 +36,9 @@ public class ScriptEngineShellTable<D extends Object> extends BasicShellTable<D> */ public ScriptEngineShellTable(ScriptEngineManager scriptEngineManager, String engine) { this.scriptEngine = scriptEngineManager.getEngineByName(engine); + if (scriptEngine == null) { + throw new IllegalStateException("Unable to load script engine " + engine); + } } /** @@ -47,7 +52,10 @@ public class ScriptEngineShellTable<D extends Object> extends BasicShellTable<D> try { scriptEngine.put(getType(), obj); result = String.valueOf(scriptEngine.eval(expression)); - } catch (Exception ignored) {} + } catch (Exception exception) { + result = format("Unable to evaluate expression %s due to: %s. Please check your shell confugration", + expression, exception.getMessage()); + } return result; } }
