You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ha...@apache.org on 2011/06/08 05:04:37 UTC

svn commit: r1133232 - in /camel/trunk: camel-core/src/main/java/org/apache/camel/builder/ camel-core/src/main/java/org/apache/camel/component/bean/ camel-core/src/main/java/org/apache/camel/impl/osgi/ camel-core/src/main/java/org/apache/camel/spi/ cam...

Author: hadrian
Date: Wed Jun  8 03:04:36 2011
New Revision: 1133232

URL: http://svn.apache.org/viewvc?rev=1133232&view=rev
Log:
CAMEL-4047. Remove dependency on jsr-223 scripting engines in camel-core. Thsnks dkulp for patch.

Removed:
    camel/trunk/camel-core/src/main/java/org/apache/camel/spi/ScriptEngineResolver.java
Modified:
    camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/impl/osgi/Activator.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/util/LRUSoftCache.java
    camel/trunk/camel-core/src/test/java/org/apache/camel/impl/DefaultExchangeHolderTest.java
    camel/trunk/camel-core/src/test/java/org/apache/camel/issues/ExceptionThrownFromOnExceptionTest.java
    camel/trunk/components/camel-script/src/main/java/org/apache/camel/script/osgi/Activator.java

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java?rev=1133232&r1=1133231&r2=1133232&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java Wed Jun  8 03:04:36 2011
@@ -93,7 +93,7 @@ public final class AdviceWithTasks {
      */
     private static final class MatchByType implements MatchBy {
 
-        private final Class type;
+        private final Class<?> type;
 
         private MatchByType(Class<?> type) {
             this.type = type;

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java?rev=1133232&r1=1133231&r2=1133232&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java Wed Jun  8 03:04:36 2011
@@ -339,6 +339,7 @@ public class BeanInfo {
     }
 
     protected List<Annotation>[] collectParameterAnnotations(Class<?> c, Method m) {
+        @SuppressWarnings("unchecked")
         List<Annotation>[] annotations = new List[m.getParameterTypes().length];
         for (int i = 0; i < annotations.length; i++) {
             annotations[i] = new ArrayList<Annotation>();

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/osgi/Activator.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/osgi/Activator.java?rev=1133232&r1=1133231&r2=1133232&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/osgi/Activator.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/osgi/Activator.java Wed Jun  8 03:04:36 2011
@@ -35,8 +35,6 @@ import java.util.Set;
 import java.util.StringTokenizer;
 import java.util.concurrent.ConcurrentHashMap;
 
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineFactory;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Component;
 import org.apache.camel.Converter;
@@ -54,7 +52,6 @@ import org.apache.camel.spi.Injector;
 import org.apache.camel.spi.Language;
 import org.apache.camel.spi.LanguageResolver;
 import org.apache.camel.spi.PackageScanFilter;
-import org.apache.camel.spi.ScriptEngineResolver;
 import org.apache.camel.spi.TypeConverterLoader;
 import org.apache.camel.spi.TypeConverterRegistry;
 import org.apache.camel.util.IOHelper;
@@ -76,8 +73,6 @@ public class Activator implements Bundle
     public static final String META_INF_DATAFORMAT = "META-INF/services/org/apache/camel/dataformat/";
     public static final String META_INF_TYPE_CONVERTER = "META-INF/services/org/apache/camel/TypeConverter";
     public static final String META_INF_FALLBACK_TYPE_CONVERTER = "META-INF/services/org/apache/camel/FallbackTypeConverter";
-    public static final String META_INF_SERVICES_DIR = "META-INF/services";
-    public static final String SCRIPT_ENGINE_SERVICE_FILE = "javax.script.ScriptEngineFactory";
 
     private static final transient Logger LOG = LoggerFactory.getLogger(Activator.class);
 
@@ -101,7 +96,6 @@ public class Activator implements Bundle
         LOG.debug("Bundle started: {}", bundle.getSymbolicName());
         List<BaseService> r = new ArrayList<BaseService>();
         registerComponents(bundle, r);
-        registerScriptEngines(bundle, r);
         registerLanguages(bundle, r);
         registerDataFormats(bundle, r);
         registerTypeConverterLoader(bundle, r);
@@ -140,17 +134,6 @@ public class Activator implements Bundle
         }
     }
 
-    protected void registerScriptEngines(Bundle bundle, List<BaseService> resolvers) {
-        URL configURL = null;
-        for (Enumeration e = bundle.findEntries(META_INF_SERVICES_DIR, SCRIPT_ENGINE_SERVICE_FILE, false); e != null && e.hasMoreElements();) {
-            configURL = (URL) e.nextElement();
-        }
-        if (configURL != null) {
-            LOG.info("Found ScriptEngineFactory in " + bundle.getSymbolicName());
-            resolvers.add(new BundleScriptEngineResolver(bundle, configURL));
-        }
-    }
-
     protected void registerLanguages(Bundle bundle, List<BaseService> resolvers) {
         if (checkCompat(bundle, Language.class)) {
             Map<String, String> languages = new HashMap<String, String>();
@@ -276,59 +259,6 @@ public class Activator implements Bundle
         }
     }
 
-    protected static class BundleScriptEngineResolver extends BaseResolver<ScriptEngineFactory> implements ScriptEngineResolver {
-        private final URL configFile;
-
-        public BundleScriptEngineResolver(Bundle bundle, URL configFile) {
-            super(bundle, ScriptEngineFactory.class);
-            this.configFile = configFile;
-        }
-
-        public ScriptEngine resolveScriptEngine(String name) {
-            try {
-                BufferedReader in = new BufferedReader(new InputStreamReader(configFile.openStream()));
-                String className = in.readLine();
-                in.close();
-                Class cls = bundle.loadClass(className);
-                if (!ScriptEngineFactory.class.isAssignableFrom(cls)) {
-                    throw new IllegalStateException("Invalid ScriptEngineFactory: " + cls.getName());
-                }
-                ScriptEngineFactory factory = (ScriptEngineFactory) cls.newInstance();
-                List<String> names = factory.getNames();
-                for (String test : names) {
-                    if (test.equals(name)) {
-                        ClassLoader old = Thread.currentThread().getContextClassLoader();
-                        ScriptEngine engine;
-                        try {
-                            // JRuby seems to require the correct TCCL to call getScriptEngine
-                            Thread.currentThread().setContextClassLoader(factory.getClass().getClassLoader());
-                            engine = factory.getScriptEngine();
-                        } finally {
-                            Thread.currentThread().setContextClassLoader(old);
-                        }
-                        LOG.trace("Resolved ScriptEngineFactory: {} for expected name: {}", engine, name);
-                        return engine;
-                    }
-                }
-                LOG.debug("ScriptEngineFactory: {} does not match expected name: {}", factory.getEngineName(), name);
-                return null;
-            } catch (Exception e) {
-                LOG.warn("Cannot create ScriptEngineFactory: " + e.getClass().getName(), e);
-                return null;
-            }
-        }
-
-        @Override
-        public void register() {
-            doRegister(ScriptEngineResolver.class);
-        }
-
-        @Override
-        public String toString() {
-            return "OSGi script engine resolver for " + bundle.getSymbolicName();
-        }
-    }
-
     protected static class BundleTypeConverterLoader extends BaseResolver<TypeConverter> implements TypeConverterLoader {
 
         private final AnnotationTypeConverterLoader loader = new Loader();

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/util/LRUSoftCache.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/util/LRUSoftCache.java?rev=1133232&r1=1133231&r2=1133232&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/util/LRUSoftCache.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/util/LRUSoftCache.java Wed Jun  8 03:04:36 2011
@@ -75,7 +75,6 @@ public class LRUSoftCache<K, V> extends 
     }
 
     @Override
-    @SuppressWarnings("unchecked")
     public void putAll(Map<? extends K, ? extends V> map) {
         // do not use entrySet but copy one by one
         for (K key : map.keySet()) {

Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/DefaultExchangeHolderTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/impl/DefaultExchangeHolderTest.java?rev=1133232&r1=1133231&r2=1133232&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/impl/DefaultExchangeHolderTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/impl/DefaultExchangeHolderTest.java Wed Jun  8 03:04:36 2011
@@ -146,6 +146,7 @@ public class DefaultExchangeHolderTest e
             this.foo = foo;
         }
 
+        @SuppressWarnings("unused")
         public String getFoo() {
             return foo;
         }

Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/issues/ExceptionThrownFromOnExceptionTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/issues/ExceptionThrownFromOnExceptionTest.java?rev=1133232&r1=1133231&r2=1133232&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/issues/ExceptionThrownFromOnExceptionTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/issues/ExceptionThrownFromOnExceptionTest.java Wed Jun  8 03:04:36 2011
@@ -25,13 +25,13 @@ import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
 import org.apache.camel.builder.RouteBuilder;
 
-/**
+/*
  * @version 
  */
 public class ExceptionThrownFromOnExceptionTest extends ContextTestSupport {
 
-    private static AtomicInteger retry = new AtomicInteger();
-    private static AtomicInteger onExceptionRetry = new AtomicInteger();
+    private static final AtomicInteger RETRY = new AtomicInteger();
+    private static final AtomicInteger ON_EXCEPTION_RETRY = new AtomicInteger();
 
     @Override
     public boolean isUseRouteBuilder() {
@@ -39,8 +39,8 @@ public class ExceptionThrownFromOnExcept
     }
 
     public void testExceptionThrownFromOnException() throws Exception {
-        retry.set(0);
-        onExceptionRetry.set(0);
+        RETRY.set(0);
+        ON_EXCEPTION_RETRY.set(0);
 
         context.addRoutes(new RouteBuilder() {
             @Override
@@ -52,7 +52,7 @@ public class ExceptionThrownFromOnExcept
                     .process(new Processor() {
                         @Override
                         public void process(Exchange exchange) throws Exception {
-                            onExceptionRetry.incrementAndGet();
+                            ON_EXCEPTION_RETRY.incrementAndGet();
                             throw new IOException("Some other IOException");
                         }
                     })
@@ -67,7 +67,7 @@ public class ExceptionThrownFromOnExcept
                     .process(new Processor() {
                         @Override
                         public void process(Exchange exchange) throws Exception {
-                            retry.incrementAndGet();
+                            RETRY.incrementAndGet();
                             throw new IOException("IO error");
                         }
                     })
@@ -92,13 +92,13 @@ public class ExceptionThrownFromOnExcept
 
         assertMockEndpointsSatisfied();
 
-        assertEquals("Should try 4 times (1 first, 3 retry)", 4, retry.get());
-        assertEquals("Should only invoke onException once", 1, onExceptionRetry.get());
+        assertEquals("Should try 4 times (1 first, 3 retry)", 4, RETRY.get());
+        assertEquals("Should only invoke onException once", 1, ON_EXCEPTION_RETRY.get());
     }
 
     public void testExceptionThrownFromOnExceptionAndHandled() throws Exception {
-        retry.set(0);
-        onExceptionRetry.set(0);
+        RETRY.set(0);
+        ON_EXCEPTION_RETRY.set(0);
 
         context.addRoutes(new RouteBuilder() {
             @Override
@@ -112,7 +112,7 @@ public class ExceptionThrownFromOnExcept
                     .process(new Processor() {
                         @Override
                         public void process(Exchange exchange) throws Exception {
-                            onExceptionRetry.incrementAndGet();
+                            ON_EXCEPTION_RETRY.incrementAndGet();
                             throw new IOException("Some other IOException");
                         }
                     })
@@ -127,7 +127,7 @@ public class ExceptionThrownFromOnExcept
                     .process(new Processor() {
                         @Override
                         public void process(Exchange exchange) throws Exception {
-                            retry.incrementAndGet();
+                            RETRY.incrementAndGet();
                             throw new IOException("IO error");
                         }
                     })
@@ -152,13 +152,13 @@ public class ExceptionThrownFromOnExcept
 
         assertMockEndpointsSatisfied();
 
-        assertEquals("Should try 4 times (1 first, 3 retry)", 4, retry.get());
-        assertEquals("Should only invoke onException once", 1, onExceptionRetry.get());
+        assertEquals("Should try 4 times (1 first, 3 retry)", 4, RETRY.get());
+        assertEquals("Should only invoke onException once", 1, ON_EXCEPTION_RETRY.get());
     }
 
     public void testExceptionThrownFromOnExceptionWithDeadLetterChannel() throws Exception {
-        retry.set(0);
-        onExceptionRetry.set(0);
+        RETRY.set(0);
+        ON_EXCEPTION_RETRY.set(0);
 
         context.addRoutes(new RouteBuilder() {
             @Override
@@ -173,7 +173,7 @@ public class ExceptionThrownFromOnExcept
                     .process(new Processor() {
                         @Override
                         public void process(Exchange exchange) throws Exception {
-                            onExceptionRetry.incrementAndGet();
+                            ON_EXCEPTION_RETRY.incrementAndGet();
                             throw new IOException("Some other IOException");
                         }
                     })
@@ -188,7 +188,7 @@ public class ExceptionThrownFromOnExcept
                     .process(new Processor() {
                         @Override
                         public void process(Exchange exchange) throws Exception {
-                            retry.incrementAndGet();
+                            RETRY.incrementAndGet();
                             throw new IOException("IO error");
                         }
                     })
@@ -216,13 +216,13 @@ public class ExceptionThrownFromOnExcept
 
         assertMockEndpointsSatisfied();
 
-        assertEquals("Should try 4 times (1 first, 3 retry)", 4, retry.get());
-        assertEquals("Should only invoke onException once", 1, onExceptionRetry.get());
+        assertEquals("Should try 4 times (1 first, 3 retry)", 4, RETRY.get());
+        assertEquals("Should only invoke onException once", 1, ON_EXCEPTION_RETRY.get());
     }
 
     public void testExceptionThrownFromOnExceptionAndHandledWithDeadLetterChannel() throws Exception {
-        retry.set(0);
-        onExceptionRetry.set(0);
+        RETRY.set(0);
+        ON_EXCEPTION_RETRY.set(0);
 
         context.addRoutes(new RouteBuilder() {
             @Override
@@ -239,7 +239,7 @@ public class ExceptionThrownFromOnExcept
                     .process(new Processor() {
                         @Override
                         public void process(Exchange exchange) throws Exception {
-                            onExceptionRetry.incrementAndGet();
+                            ON_EXCEPTION_RETRY.incrementAndGet();
                             throw new IOException("Some other IOException");
                         }
                     })
@@ -254,7 +254,7 @@ public class ExceptionThrownFromOnExcept
                     .process(new Processor() {
                         @Override
                         public void process(Exchange exchange) throws Exception {
-                            retry.incrementAndGet();
+                            RETRY.incrementAndGet();
                             throw new IOException("IO error");
                         }
                     })
@@ -282,13 +282,13 @@ public class ExceptionThrownFromOnExcept
 
         assertMockEndpointsSatisfied();
 
-        assertEquals("Should try 4 times (1 first, 3 retry)", 4, retry.get());
-        assertEquals("Should only invoke onException once", 1, onExceptionRetry.get());
+        assertEquals("Should try 4 times (1 first, 3 retry)", 4, RETRY.get());
+        assertEquals("Should only invoke onException once", 1, ON_EXCEPTION_RETRY.get());
     }
 
     public void testNoExceptionThrownFromOnExceptionWithDeadLetterChannel() throws Exception {
-        retry.set(0);
-        onExceptionRetry.set(0);
+        RETRY.set(0);
+        ON_EXCEPTION_RETRY.set(0);
 
         context.addRoutes(new RouteBuilder() {
             @Override
@@ -303,7 +303,7 @@ public class ExceptionThrownFromOnExcept
                     .process(new Processor() {
                         @Override
                         public void process(Exchange exchange) throws Exception {
-                            onExceptionRetry.incrementAndGet();
+                            ON_EXCEPTION_RETRY.incrementAndGet();
                             // no exception is thrown this time
                         }
                     })
@@ -318,7 +318,7 @@ public class ExceptionThrownFromOnExcept
                     .process(new Processor() {
                         @Override
                         public void process(Exchange exchange) throws Exception {
-                            retry.incrementAndGet();
+                            RETRY.incrementAndGet();
                             throw new IOException("IO error");
                         }
                     })
@@ -348,13 +348,13 @@ public class ExceptionThrownFromOnExcept
 
         assertMockEndpointsSatisfied();
 
-        assertEquals("Should try 4 times (1 first, 3 retry)", 4, retry.get());
-        assertEquals("Should only invoke onException once", 1, onExceptionRetry.get());
+        assertEquals("Should try 4 times (1 first, 3 retry)", 4, RETRY.get());
+        assertEquals("Should only invoke onException once", 1, ON_EXCEPTION_RETRY.get());
     }
 
     public void testNoExceptionThrownFromOnExceptionAndHandledWithDeadLetterChannel() throws Exception {
-        retry.set(0);
-        onExceptionRetry.set(0);
+        RETRY.set(0);
+        ON_EXCEPTION_RETRY.set(0);
 
         context.addRoutes(new RouteBuilder() {
             @Override
@@ -371,7 +371,7 @@ public class ExceptionThrownFromOnExcept
                     .process(new Processor() {
                         @Override
                         public void process(Exchange exchange) throws Exception {
-                            onExceptionRetry.incrementAndGet();
+                            ON_EXCEPTION_RETRY.incrementAndGet();
                             // no exception is thrown this time
                         }
                     })
@@ -386,7 +386,7 @@ public class ExceptionThrownFromOnExcept
                     .process(new Processor() {
                         @Override
                         public void process(Exchange exchange) throws Exception {
-                            retry.incrementAndGet();
+                            RETRY.incrementAndGet();
                             throw new IOException("IO error");
                         }
                     })
@@ -409,8 +409,8 @@ public class ExceptionThrownFromOnExcept
 
         assertMockEndpointsSatisfied();
 
-        assertEquals("Should try 4 times (1 first, 3 retry)", 4, retry.get());
-        assertEquals("Should only invoke onException once", 1, onExceptionRetry.get());
+        assertEquals("Should try 4 times (1 first, 3 retry)", 4, RETRY.get());
+        assertEquals("Should only invoke onException once", 1, ON_EXCEPTION_RETRY.get());
     }
 
 }

Modified: camel/trunk/components/camel-script/src/main/java/org/apache/camel/script/osgi/Activator.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-script/src/main/java/org/apache/camel/script/osgi/Activator.java?rev=1133232&r1=1133231&r2=1133232&view=diff
==============================================================================
--- camel/trunk/components/camel-script/src/main/java/org/apache/camel/script/osgi/Activator.java (original)
+++ camel/trunk/components/camel-script/src/main/java/org/apache/camel/script/osgi/Activator.java Wed Jun  8 03:04:36 2011
@@ -16,33 +16,84 @@
  */
 package org.apache.camel.script.osgi;
 
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
 import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
 
-import org.apache.camel.spi.ScriptEngineResolver;
+import org.apache.camel.impl.osgi.tracker.BundleTracker;
+import org.apache.camel.impl.osgi.tracker.BundleTrackerCustomizer;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class Activator implements BundleActivator {
+public class Activator implements BundleActivator, BundleTrackerCustomizer {
+    public static final String META_INF_SERVICES_DIR = "META-INF/services";
+    public static final String SCRIPT_ENGINE_SERVICE_FILE = "javax.script.ScriptEngineFactory";
+
     private static final transient Logger LOG = LoggerFactory.getLogger(Activator.class);
     private static BundleContext context;
-    private static Bundle bundle;
+    private BundleTracker tracker;
     
+    private Map<Long, List<BundleScriptEngineResolver>> resolvers 
+        = new ConcurrentHashMap<Long, List<BundleScriptEngineResolver>>();
 
-    public static Bundle getBundle() {
-        return bundle;
-    }
-    
     public static BundleContext getBundleContext() {
         return context;
     }
     
+    public void start(BundleContext context) throws Exception {
+        Activator.context = context;
+        LOG.info("Camel-Script activator starting");
+        tracker = new BundleTracker(context, Bundle.ACTIVE, this);
+        tracker.open();
+        LOG.info("Camel-Script activator started");
+    }
+
+    public void stop(BundleContext context) throws Exception {
+        LOG.info("Camel-Script activator stopping");
+        tracker.close();
+        LOG.info("Camel-Script activator stopped");
+        Activator.context = null;
+    }
+
+    public Object addingBundle(Bundle bundle, BundleEvent event) {
+        List<BundleScriptEngineResolver> r = new ArrayList<BundleScriptEngineResolver>();
+        registerScriptEngines(bundle, r);
+        for (BundleScriptEngineResolver service : r) {
+            service.register();
+        }
+        resolvers.put(bundle.getBundleId(), r);
+        return bundle;
+    }
+
+    public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
+    }
+
+    public void removedBundle(Bundle bundle, BundleEvent event, Object object) {
+        LOG.debug("Bundle stopped: {}", bundle.getSymbolicName());
+        List<BundleScriptEngineResolver> r = resolvers.remove(bundle.getBundleId());
+        if (r != null) {
+            for (BundleScriptEngineResolver service : r) {
+                service.unregister();
+            }
+        }
+    }
+
     public static ScriptEngine resolveScriptEngine(String scriptEngineName) throws InvalidSyntaxException {
         ServiceReference[] refs = context.getServiceReferences(ScriptEngineResolver.class.getName(), null);
         if (refs == null) {
@@ -64,13 +115,75 @@ public class Activator implements Bundle
         return null;
     }
 
-    public void start(BundleContext context) throws Exception {
-        Activator.context = context;
-        Activator.bundle = context.getBundle();
+
+    protected void registerScriptEngines(Bundle bundle, List<BundleScriptEngineResolver> resolvers) {
+        URL configURL = null;
+        for (Enumeration e = bundle.findEntries(META_INF_SERVICES_DIR, SCRIPT_ENGINE_SERVICE_FILE, false); e != null && e.hasMoreElements();) {
+            configURL = (URL) e.nextElement();
+        }
+        if (configURL != null) {
+            LOG.info("Found ScriptEngineFactory in " + bundle.getSymbolicName());
+            resolvers.add(new BundleScriptEngineResolver(bundle, configURL));
+        }
+    } 
+    public static interface ScriptEngineResolver {
+        ScriptEngine resolveScriptEngine(String name);
     }
+    protected static class BundleScriptEngineResolver implements ScriptEngineResolver {
+        protected final Bundle bundle;
+        private ServiceRegistration reg;
+        private final URL configFile;
+
+        public BundleScriptEngineResolver(Bundle bundle, URL configFile) {
+            this.bundle = bundle;
+            this.configFile = configFile;
+        }
+        public void register() {
+            reg = bundle.getBundleContext().registerService(ScriptEngineResolver.class.getName(), 
+                                                            this, null);
+        }
+        public void unregister() {
+            reg.unregister();
+        }
+        public ScriptEngine resolveScriptEngine(String name) {
+            try {
+                BufferedReader in = new BufferedReader(new InputStreamReader(configFile.openStream()));
+                String className = in.readLine();
+                in.close();
+                Class cls = bundle.loadClass(className);
+                if (!ScriptEngineFactory.class.isAssignableFrom(cls)) {
+                    throw new IllegalStateException("Invalid ScriptEngineFactory: " + cls.getName());
+                }
+                ScriptEngineFactory factory = (ScriptEngineFactory) cls.newInstance();
+                List<String> names = factory.getNames();
+                for (String test : names) {
+                    if (test.equals(name)) {
+                        ClassLoader old = Thread.currentThread().getContextClassLoader();
+                        ScriptEngine engine;
+                        try {
+                            // JRuby seems to require the correct TCCL to call getScriptEngine
+                            Thread.currentThread().setContextClassLoader(factory.getClass().getClassLoader());
+                            engine = factory.getScriptEngine();
+                        } finally {
+                            Thread.currentThread().setContextClassLoader(old);
+                        }
+                        LOG.trace("Resolved ScriptEngineFactory: {} for expected name: {}", engine, name);
+                        return engine;
+                    }
+                }
+                LOG.debug("ScriptEngineFactory: {} does not match expected name: {}", factory.getEngineName(), name);
+                return null;
+            } catch (Exception e) {
+                LOG.warn("Cannot create ScriptEngineFactory: " + e.getClass().getName(), e);
+                return null;
+            }
+        }
 
-    public void stop(BundleContext context) throws Exception {
-        Activator.context = null;
-        Activator.bundle = null;
+        @Override
+        public String toString() {
+            return "OSGi script engine resolver for " + bundle.getSymbolicName();
+        }
     }
+
+
 }