diff --git a/core/src/main/java/org/jruby/embed/IsolatedScriptingContainer.java b/core/src/main/java/org/jruby/embed/IsolatedScriptingContainer.java index 85ce646a21f..c11ad250264 100644 --- a/core/src/main/java/org/jruby/embed/IsolatedScriptingContainer.java +++ b/core/src/main/java/org/jruby/embed/IsolatedScriptingContainer.java @@ -2,8 +2,8 @@ import java.net.URL; import java.util.Arrays; - -import org.osgi.framework.Bundle; +import java.util.HashMap; +import java.util.Map; /** * the IsolatedScriptingContainer detects the whether it is used with @@ -16,7 +16,7 @@ * * the root of the "main" classloader is add to LOAD_PATH and GEM_PATH. * - * in the OSGi case there are helper methods to add ClassLoaders to the LOAD_PATH or GEM_PATH + * in the OSGi case see the OSGiIsolatedScriptingContainer * * a typical setup for the ContextClassLoader case and OSGi case looks likes this: *
  • LOAD_PATH == [ "uri:classloader:/META-INF/jruby.home/lib/ruby/1.9/site_ruby", @@ -79,6 +79,24 @@ public IsolatedScriptingContainer( LocalContextScope scope, + "Gem::Specification.reset;" + "Gem::Specification.add_dir 'uri:classloader:" + JRUBY_HOME + "/lib/ruby/gems/shared';" + "Gem::Specification.add_dir 'uri:classloader:';"); + + // setup the isolated GEM_PATH, i.e. without $HOME/.gem/** + setEnvironment(null); + } + + @Override + public void setEnvironment(Map environment) { + if (environment == null || !environment.containsKey("GEM_PATH") + || !environment.containsKey("GEM_HOME")|| !environment.containsKey("JARS_HOME")) { + Map env = environment == null ? new HashMap() : new HashMap(environment); + if (!env.containsKey("GEM_PATH")) env.put("GEM_PATH", "uri:classloader://"); + if (!env.containsKey("GEM_HOME")) env.put("GEM_HOME", "uri:classloader://"); + if (!env.containsKey("JARS_HOME")) env.put("JARS_HOME", "uri:classloader://jars"); + super.setEnvironment(env); + } + else { + super.setEnvironment(environment); + } } public void addLoadPath( ClassLoader cl ) { @@ -89,37 +107,10 @@ public void addLoadPath( ClassLoader cl, String ref ) { addLoadPath(createUri(cl, ref)); } - public void addBundleToLoadPath( Bundle cl ) { - addBundleToLoadPath( cl, JRUBYDIR ); - } - - public void addBundleToLoadPath( Bundle cl, String ref ) { - addLoadPath(createUriFromBundle(cl, ref)); - } - - private String createUriFromBundle( Bundle cl, String ref) { - URL url = cl.getResource( ref ); - if ( url == null && ref.startsWith( "/" ) ) { - url = cl.getResource( ref.substring( 1 ) ); - } - if ( url == null ) { - throw new RuntimeException( "reference " + ref + " not found on bundle " + cl ); - } - return "uri:" + url.toString().replaceFirst( ref + "$", "" ); - } - - private void addLoadPath(String uri) { + protected void addLoadPath(String uri) { runScriptlet( "$LOAD_PATH << '" + uri + "' unless $LOAD_PATH.member?( '" + uri + "' )" ); } - public void addBundleToGemPath( Bundle cl ) { - addBundleToGemPath( cl, "/specifications" + JRUBYDIR ); - } - - public void addBundleToGemPath( Bundle cl, String ref ) { - addGemPath(createUriFromBundle(cl, ref)); - } - public void addGemPath( ClassLoader cl ) { addGemPath( cl, "/specifications" + JRUBYDIR ); } @@ -139,7 +130,7 @@ private String createUri(ClassLoader cl, String ref) { return "uri:" + url.toString().replaceFirst( ref + "$", "" ); } - private void addGemPath(String uri) { + protected void addGemPath(String uri) { runScriptlet( "Gem::Specification.add_dir '" + uri + "' unless Gem::Specification.dirs.member?( '" + uri + "' )" ); } } diff --git a/core/src/main/java/org/jruby/embed/osgi/OSGiIsolatedScriptingContainer.java b/core/src/main/java/org/jruby/embed/osgi/OSGiIsolatedScriptingContainer.java new file mode 100644 index 00000000000..fc59e049fe0 --- /dev/null +++ b/core/src/main/java/org/jruby/embed/osgi/OSGiIsolatedScriptingContainer.java @@ -0,0 +1,110 @@ +package org.jruby.embed.osgi; + +import java.net.URL; + +import org.jruby.embed.IsolatedScriptingContainer; +import org.jruby.embed.LocalContextScope; +import org.jruby.embed.LocalVariableBehavior; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; + +/** + * adds some helper methods to add Bundle to the LOAD_PATH or GEM_PATH using the + * IsolatedScriptingContainer as base. + * + * new URL( uri ).openStream(), i.e. new URL(classloader.getResource().toString()).openStream() has to work for + * those classloaders. felix, knoplerfish and equinox OSGi framework do work. + */ +public class OSGiIsolatedScriptingContainer extends IsolatedScriptingContainer { + + public OSGiIsolatedScriptingContainer() + { + this(LocalContextScope.SINGLETON); + } + + public OSGiIsolatedScriptingContainer( LocalContextScope scope, + LocalVariableBehavior behavior ) + { + this(scope, behavior, true); + } + + public OSGiIsolatedScriptingContainer( LocalContextScope scope ) + { + this(scope, LocalVariableBehavior.TRANSIENT); + } + + public OSGiIsolatedScriptingContainer( LocalVariableBehavior behavior ) + { + this(LocalContextScope.SINGLETON, behavior); + } + + public OSGiIsolatedScriptingContainer( LocalContextScope scope, + LocalVariableBehavior behavior, + boolean lazy ) + { + super(scope, behavior, lazy); + } + + private Bundle toBundle(String symbolicName) { + BundleContext context = FrameworkUtil.getBundle(getClass()).getBundleContext(); + Bundle bundle = null; + for (Bundle b : context.getBundles()) { + if (b.getSymbolicName().equals(symbolicName)) { + bundle = b; + break; + } + } + if (bundle == null ) { + throw new RuntimeException("unknown bundle: " + symbolicName); + } + return bundle; + } + + private String createUri(Bundle cl, String ref) { + URL url = cl.getResource( ref ); + if ( url == null && ref.startsWith( "/" ) ) { + url = cl.getResource( ref.substring( 1 ) ); + } + if ( url == null ) { + throw new RuntimeException( "reference " + ref + " not found on classloader " + cl ); + } + return "uri:" + url.toString().replaceFirst( ref + "$", "" ); + } + /** + * add the classloader from the given bundle to the LOAD_PATH + * @param bundle + */ + public void addBundleToLoadPath(Bundle bundle) { + addLoadPath(createUri(bundle, "/.jrubydir")); + } + + /** + * add the classloader from the given bundle to the LOAD_PATH + * using the bundle symbolic name + * + * @param symbolicName + */ + public void addBundleToLoadPath(String symbolicName) { + addBundleToLoadPath(toBundle(symbolicName)); + } + + /** + * add the classloader from the given bundle to the GEM_PATH + * @param bundle + */ + public void addBundleToGemPath(Bundle bundle) { + addGemPath(createUri(bundle, "/specifications/.jrubydir")); + } + + /** + * add the classloader from the given bundle to the GEM_PATH + * using the bundle symbolic name + * + * @param symbolicName + */ + public void addBundleToGemPath(String symbolicName) { + addBundleToGemPath(toBundle(symbolicName)); + } +} diff --git a/maven/jruby-complete/src/templates/osgi_many_bundles_with_embedded_gems/test/src/test/java/org/jruby/embed/osgi/test/JRubyOsgiEmbedTest.java b/maven/jruby-complete/src/templates/osgi_many_bundles_with_embedded_gems/test/src/test/java/org/jruby/embed/osgi/test/JRubyOsgiEmbedTest.java index 933b6e3ae47..71710421dd8 100644 --- a/maven/jruby-complete/src/templates/osgi_many_bundles_with_embedded_gems/test/src/test/java/org/jruby/embed/osgi/test/JRubyOsgiEmbedTest.java +++ b/maven/jruby-complete/src/templates/osgi_many_bundles_with_embedded_gems/test/src/test/java/org/jruby/embed/osgi/test/JRubyOsgiEmbedTest.java @@ -42,7 +42,7 @@ import org.jruby.embed.LocalContextScope; import org.jruby.embed.LocalVariableBehavior; import org.jruby.embed.ScriptingContainer; -import org.jruby.embed.IsolatedScriptingContainer; +import org.jruby.embed.osgi.OSGiIsolatedScriptingContainer; import org.junit.Test; import org.junit.Ignore; import org.junit.runner.RunWith; @@ -80,8 +80,8 @@ public void testJRubyCreate() throws Exception { // System.setProperty( "jruby.debug.loadService", "true" ); //System.setProperty( "jruby.native.enabled", "true" ); - IsolatedScriptingContainer jruby = new IsolatedScriptingContainer(); - jruby.addLoadPath( Scripts.class.getClassLoader() ); + OSGiIsolatedScriptingContainer jruby = new OSGiIsolatedScriptingContainer(); + jruby.addBundleToLoadPath( "org.jruby.osgi.scripts-bundle" ); jruby.addBundleToGemPath( FrameworkUtil.getBundle( Gems.class ) ); // run a script from LOAD_PATH diff --git a/maven/jruby/src/templates/osgi_all_inclusive/src/test/java/org/jruby/embed/osgi/test/JRubyOsgiEmbedTest.java b/maven/jruby/src/templates/osgi_all_inclusive/src/test/java/org/jruby/embed/osgi/test/JRubyOsgiEmbedTest.java index a091fb6959a..0f5510790bc 100644 --- a/maven/jruby/src/templates/osgi_all_inclusive/src/test/java/org/jruby/embed/osgi/test/JRubyOsgiEmbedTest.java +++ b/maven/jruby/src/templates/osgi_all_inclusive/src/test/java/org/jruby/embed/osgi/test/JRubyOsgiEmbedTest.java @@ -38,7 +38,7 @@ import org.jruby.embed.LocalContextScope; import org.jruby.embed.LocalVariableBehavior; import org.jruby.embed.ScriptingContainer; -import org.jruby.embed.IsolatedScriptingContainer; +import org.jruby.embed.osgi.OSGiIsolatedScriptingContainer; import org.junit.Test; import org.junit.Ignore; import org.junit.runner.RunWith; @@ -67,7 +67,7 @@ public void testJRubyCreate() throws InterruptedException { System.err.println(); // System.setProperty( "jruby.debug.loadService", "true" ); - IsolatedScriptingContainer jruby = new IsolatedScriptingContainer(); + OSGiIsolatedScriptingContainer jruby = new OSGiIsolatedScriptingContainer(); // run a script from LOAD_PATH String hello = (String) jruby.runScriptlet( "require 'hello'; Hello.say" );