Repository: jclouds-karaf
Updated Branches:
  refs/heads/fix-script-engine [created] 0b99dad1a


Try to use an OSGi-compliant way of loading JSR 223 script engines


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

Branch: refs/heads/fix-script-engine
Commit: 0b99dad1aa7786eaf11028bf91fc1d272c189f0b
Parents: 960a9c7
Author: Andrew Phillips <[email protected]>
Authored: Tue Sep 6 23:28:19 2016 -0400
Committer: Andrew Phillips <[email protected]>
Committed: Tue Sep 6 23:28:19 2016 -0400

----------------------------------------------------------------------
 .../commands/table/BasicShellTableFactory.java  |   9 +-
 .../table/internal/OSGiScriptEngine.java        |  79 ++++++
 .../table/internal/OSGiScriptEngineFactory.java |  83 ++++++
 .../table/internal/OSGiScriptEngineManager.java | 272 +++++++++++++++++++
 .../table/internal/ScriptEngineShellTable.java  |  12 +-
 .../OSGI-INF/blueprint/jclouds-commands.xml     |   8 +-
 feature/src/main/resources/feature.xml          |   1 -
 7 files changed, 452 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-karaf/blob/0b99dad1/commands/src/main/java/org/jclouds/karaf/commands/table/BasicShellTableFactory.java
----------------------------------------------------------------------
diff --git 
a/commands/src/main/java/org/jclouds/karaf/commands/table/BasicShellTableFactory.java
 
b/commands/src/main/java/org/jclouds/karaf/commands/table/BasicShellTableFactory.java
index 1769c7f..afb368a 100644
--- 
a/commands/src/main/java/org/jclouds/karaf/commands/table/BasicShellTableFactory.java
+++ 
b/commands/src/main/java/org/jclouds/karaf/commands/table/BasicShellTableFactory.java
@@ -24,10 +24,13 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.script.ScriptEngineManager;
+
 /**
  * A basic {@link org.jclouds.karaf.commands.table.ShellTableFactory} 
implementation which is backed by a {@link Map}.
  */
 public class BasicShellTableFactory implements ShellTableFactory {
+   private ScriptEngineManager scriptEngineManager;
 
    private final Map properties = new HashMap();
   /**
@@ -49,7 +52,7 @@ public class BasicShellTableFactory implements 
ShellTableFactory {
       List<String> headers =  Arrays.asList(headersValue.split(delimiter));
       List<String> expressions =  
Arrays.asList(expressionsValue.split(delimiter));
       List<String> alignments =  Arrays.asList(alignValue.split(delimiter));
-      ShellTable shellTable = new ScriptEngineShellTable(engine);
+      ShellTable shellTable = new ScriptEngineShellTable(scriptEngineManager, 
engine);
 
       shellTable.setType(type);
       shellTable.setHeaders(headers);
@@ -63,4 +66,8 @@ public class BasicShellTableFactory implements 
ShellTableFactory {
   public Map getProperties() {
     return properties;
   }
+
+  public void setScriptEngineManager(ScriptEngineManager scriptEngineManager) {
+    this.scriptEngineManager = scriptEngineManager;
+  }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-karaf/blob/0b99dad1/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
new file mode 100644
index 0000000..119cb15
--- /dev/null
+++ 
b/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngine.java
@@ -0,0 +1,79 @@
+/*
+ *   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.
+ *
+ */
+
+// 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;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+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);
+       }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-karaf/blob/0b99dad1/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
new file mode 100644
index 0000000..0281b82
--- /dev/null
+++ 
b/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngineFactory.java
@@ -0,0 +1,83 @@
+/*
+ *   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)
+ */
+
+// 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;
+       }
+       
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-karaf/blob/0b99dad1/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
new file mode 100644
index 0000000..7448b49
--- /dev/null
+++ 
b/commands/src/main/java/org/jclouds/karaf/commands/table/internal/OSGiScriptEngineManager.java
@@ -0,0 +1,272 @@
+/*
+ *   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;
+
+/**
+ * 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>
+ * 
+ */
+
+// 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);
+       }
+
+       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) {
+      // 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;
+    }
+       }
+
+       /**
+        * 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 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/0b99dad1/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 9bce9e6..88ad5b8 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
@@ -26,18 +26,14 @@ import javax.script.ScriptEngineManager;
  * A shell table implementation that works with groovy expressions.
  */
 public class ScriptEngineShellTable<D extends Object> extends 
BasicShellTable<D> {
-
-  private final String engine;
-  private final ScriptEngineManager scriptEngineFactory = new 
ScriptEngineManager();
   private final ScriptEngine scriptEngine;
 
   /**
    * Constructor
    * @param engine
    */
-  public ScriptEngineShellTable(String engine) {
-    this.engine = engine;
-    this.scriptEngine = scriptEngineFactory.getEngineByName(engine);
+  public ScriptEngineShellTable(ScriptEngineManager scriptEngineManager, 
String engine) {
+    this.scriptEngine = scriptEngineManager.getEngineByName(engine);
   }
 
   /**
@@ -51,9 +47,7 @@ public class ScriptEngineShellTable<D extends Object> extends 
BasicShellTable<D>
     try {
       scriptEngine.put(getType(), obj);
       result = String.valueOf(scriptEngine.eval(expression));
-    } catch (Exception ex) {
-      //Ignore
-    }
+    } catch (Exception ignored) {}
     return result;
   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-karaf/blob/0b99dad1/commands/src/main/resources/OSGI-INF/blueprint/jclouds-commands.xml
----------------------------------------------------------------------
diff --git 
a/commands/src/main/resources/OSGI-INF/blueprint/jclouds-commands.xml 
b/commands/src/main/resources/OSGI-INF/blueprint/jclouds-commands.xml
index 30e3dd0..092740e 100644
--- a/commands/src/main/resources/OSGI-INF/blueprint/jclouds-commands.xml
+++ b/commands/src/main/resources/OSGI-INF/blueprint/jclouds-commands.xml
@@ -566,7 +566,13 @@ limitations under the License.
 
     <bean id="osFamilyCompleter" 
class="org.jclouds.karaf.commands.compute.completer.OsFamilyCompleter"/>
 
-  <bean id="shellTableFactory" 
class="org.jclouds.karaf.commands.table.internal.ManagedShellTableFactory"/>
+  <bean id="osgiScriptEngineManager" 
class="org.jclouds.karaf.commands.table.internal.OSGiScriptEngineManager">
+      <argument ref="blueprintBundleContext"/>
+  </bean>
+
+  <bean id="shellTableFactory" 
class="org.jclouds.karaf.commands.table.internal.ManagedShellTableFactory">
+      <property name="scriptEngineManager" ref="osgiScriptEngineManager"/>
+  </bean>
 
   <service ref="shellTableFactory">
       <interfaces>

http://git-wip-us.apache.org/repos/asf/jclouds-karaf/blob/0b99dad1/feature/src/main/resources/feature.xml
----------------------------------------------------------------------
diff --git a/feature/src/main/resources/feature.xml 
b/feature/src/main/resources/feature.xml
index 44c536d..b53cda8 100644
--- a/feature/src/main/resources/feature.xml
+++ b/feature/src/main/resources/feature.xml
@@ -418,7 +418,6 @@ limitations under the License.
     <feature name="jclouds-commands" description="Karaf Commands for jclouds" 
version="${project.version}" resolver="(obr)">
         <configfile 
finalname="/etc/org.apache.jclouds.shell.cfg">mvn:org.apache.jclouds.karaf/jclouds-karaf/${project.version}/cfg/shell</configfile>
         <feature version='${project.version}'>jclouds-services</feature>
-        
<bundle>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.scripting-api-1.0/${scripting.api.bundle.version}</bundle>
         <bundle 
dependency="true">mvn:org.codehaus.groovy/groovy/${groovy.version}</bundle>
         <bundle 
dependency="true">mvn:org.codehaus.groovy/groovy-jsr223/${groovy.version}</bundle>
         <bundle>mvn:org.apache.jclouds.karaf/core/${project.version}</bundle>

Reply via email to