Repository: jclouds-karaf
Updated Branches:
  refs/heads/fix-script-engine 5e0fcbef1 -> 6c0c7e6e8


Move OSGi script engine helpers to their own package

Also change log level of exception handlers for script engine creation
to ERROR


Project: http://git-wip-us.apache.org/repos/asf/jclouds-karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-karaf/commit/4014f4cb
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-karaf/tree/4014f4cb
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-karaf/diff/4014f4cb

Branch: refs/heads/fix-script-engine
Commit: 4014f4cbc9003d69b3ebcfd170a66cc2a49a2c8e
Parents: 5e0fcbe
Author: Andrew Phillips <[email protected]>
Authored: Mon Sep 12 00:50:24 2016 +0100
Committer: Andrew Phillips <[email protected]>
Committed: Mon Sep 12 00:50:28 2016 +0100

----------------------------------------------------------------------
 .../table/internal/OSGiScriptEngine.java        |  95 ------
 .../table/internal/OSGiScriptEngineFactory.java |  98 ------
 .../table/internal/OSGiScriptEngineManager.java | 296 -------------------
 .../table/internal/osgi/OSGiScriptEngine.java   |  95 ++++++
 .../internal/osgi/OSGiScriptEngineFactory.java  |  98 ++++++
 .../internal/osgi/OSGiScriptEngineManager.java  | 296 +++++++++++++++++++
 6 files changed, 489 insertions(+), 489 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-karaf/blob/4014f4cb/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
deleted file mode 100644
index d3415c3..0000000
--- 
a/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngine.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed under the Apache License, Version 2.0 (the "License");
- *   you may not use this file except in compliance with the License.
- *   You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- *   Unless required by applicable law or agreed to in writing, software
- *   distributed under the License is distributed on an "AS IS" BASIS,
- *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *   See the License for the specific language governing permissions and
- *   limitations under the License.
- *
- */
-
-package org.jclouds.karaf.commands.table.internal;
-
-import java.io.Reader;
-
-import javax.script.Bindings;
-import javax.script.ScriptContext;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineFactory;
-import javax.script.ScriptException;
-
-// 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/4014f4cb/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
deleted file mode 100644
index 1a8d318..0000000
--- 
a/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngineFactory.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed under the Apache License, Version 2.0 (the "License");
- *   you may not use this file except in compliance with the License.
- *   You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- *   Unless required by applicable law or agreed to in writing, software
- *   distributed under the License is distributed on an "AS IS" BASIS,
- *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *   See the License for the specific language governing permissions and
- *   limitations under the License.
- *
- */
-package org.jclouds.karaf.commands.table.internal;
-
-import java.util.List;
-
-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)
- */
-
-// 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/4014f4cb/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
deleted file mode 100644
index 95668ae..0000000
--- 
a/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngineManager.java
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed under the Apache License, Version 2.0 (the "License");
- *   you may not use this file except in compliance with the License.
- *   You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- *   Unless required by applicable law or agreed to in writing, software
- *   distributed under the License is distributed on an "AS IS" BASIS,
- *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *   See the License for the specific language governing permissions and
- *   limitations under the License.
- *
- */
-
-package org.jclouds.karaf.commands.table.internal;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.script.Bindings;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineFactory;
-import javax.script.ScriptEngineManager;
-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.
- *
- * Caveats:
- * <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>
- */
-
-// 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);
-
-   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);
-   }
-
-   public Bindings getBindings() {
-      return bindings;
-   }
-
-   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 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 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 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);
-      }
-   }
-
-   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;
-   }
-
-   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;
-      }
-   }
-
-   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) {
-            }
-         }
-      }
-      return factoryCandidates;
-   }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-karaf/blob/4014f4cb/commands/src/main/java/org/jclouds/karaf/commands/table/internal/osgi/OSGiScriptEngine.java
----------------------------------------------------------------------
diff --git 
a/commands/src/main/java/org/jclouds/karaf/commands/table/internal/osgi/OSGiScriptEngine.java
 
b/commands/src/main/java/org/jclouds/karaf/commands/table/internal/osgi/OSGiScriptEngine.java
new file mode 100644
index 0000000..8f7f7a2
--- /dev/null
+++ 
b/commands/src/main/java/org/jclouds/karaf/commands/table/internal/osgi/OSGiScriptEngine.java
@@ -0,0 +1,95 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+
+package org.jclouds.karaf.commands.table.internal.osgi;
+
+import java.io.Reader;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptException;
+
+// 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/4014f4cb/commands/src/main/java/org/jclouds/karaf/commands/table/internal/osgi/OSGiScriptEngineFactory.java
----------------------------------------------------------------------
diff --git 
a/commands/src/main/java/org/jclouds/karaf/commands/table/internal/osgi/OSGiScriptEngineFactory.java
 
b/commands/src/main/java/org/jclouds/karaf/commands/table/internal/osgi/OSGiScriptEngineFactory.java
new file mode 100644
index 0000000..08d80c4
--- /dev/null
+++ 
b/commands/src/main/java/org/jclouds/karaf/commands/table/internal/osgi/OSGiScriptEngineFactory.java
@@ -0,0 +1,98 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.jclouds.karaf.commands.table.internal.osgi;
+
+import java.util.List;
+
+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)
+ */
+
+// 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/4014f4cb/commands/src/main/java/org/jclouds/karaf/commands/table/internal/osgi/OSGiScriptEngineManager.java
----------------------------------------------------------------------
diff --git 
a/commands/src/main/java/org/jclouds/karaf/commands/table/internal/osgi/OSGiScriptEngineManager.java
 
b/commands/src/main/java/org/jclouds/karaf/commands/table/internal/osgi/OSGiScriptEngineManager.java
new file mode 100644
index 0000000..0190ecd
--- /dev/null
+++ 
b/commands/src/main/java/org/jclouds/karaf/commands/table/internal/osgi/OSGiScriptEngineManager.java
@@ -0,0 +1,296 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+
+package org.jclouds.karaf.commands.table.internal.osgi;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.script.Bindings;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptEngineManager;
+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.
+ *
+ * Caveats:
+ * <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>
+ */
+
+// 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);
+
+   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);
+   }
+
+   public Bindings getBindings() {
+      return bindings;
+   }
+
+   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 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 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 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);
+      }
+   }
+
+   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;
+   }
+
+   private static ClassLoader tryGetClassLoader(String className) {
+      try {
+         return Class.forName(className).getClassLoader();
+      } catch (ClassNotFoundException exception) {
+         LOGGER.error("Tried to load class {} but failed due to: {}",
+               className, exception.getMessage());
+         return null;
+      }
+   }
+
+   private static ScriptEngineManager tryCreateScriptEngineManager(
+         String factoryName, ClassLoader factoryLoader) {
+      try {
+         return new ScriptEngineManager(factoryLoader);
+      } catch (Exception exception) {
+         LOGGER.error("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) {
+            }
+         }
+      }
+      return factoryCandidates;
+   }
+}
\ No newline at end of file

Reply via email to