Skip to content

Commit

Permalink
Showing 4 changed files with 138 additions and 37 deletions.
55 changes: 23 additions & 32 deletions core/src/main/java/org/jruby/embed/IsolatedScriptingContainer.java
Original file line number Diff line number Diff line change
@@ -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:
* <li>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<String,String> env = environment == null ? new HashMap<String,String>() : new HashMap<String,String>(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 + "' )" );
}
}
Original file line number Diff line number Diff line change
@@ -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.
*
* <code>new URL( uri ).openStream()</code>, i.e. <code>new URL(classloader.getResource().toString()).openStream()</code> 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));
}
}
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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" );

0 comments on commit 0fb4442

Please sign in to comment.