Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 084268afac45
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: e4ea2a3ce315
Choose a head ref
  • 6 commits
  • 16 files changed
  • 2 contributors

Commits on Aug 10, 2015

  1. allow to add classloader to instance config

    when the runtime gets created the classloader root gets added to the LOAD_PATH
    and to the Gem::Specification.dirs in case these uri-like paths are directories
    mkristian committed Aug 10, 2015
    2
    Copy the full SHA
    2adae43 View commit details
  2. revert recent addition of adding classloader to LOAD_PATH or GEM_PATH

    in favour of adding classloader to instance_config
    mkristian committed Aug 10, 2015
    Copy the full SHA
    5ab8133 View commit details
  3. Copy the full SHA
    9fcd48c View commit details
  4. Copy the full SHA
    ae5567f View commit details
  5. Copy the full SHA
    081c71b View commit details
  6. added more info on how to generate .jrubydir files

    those .jrubydir are needed when adding classloader to JRuby instance config to
    work consistently. some classloaders produce some directory info via 'getResource'
    and other classloader do not. sometimes JRuby is able to inspect the classloader
    and parse all the attached jars. adding a classloader to the instance config only
    works consistently with those .jrubydir files.
    mkristian committed Aug 10, 2015
    Copy the full SHA
    e4ea2a3 View commit details
53 changes: 52 additions & 1 deletion core/src/main/java/org/jruby/RubyInstanceConfig.java
Original file line number Diff line number Diff line change
@@ -36,14 +36,17 @@
import org.jruby.runtime.backtrace.TraceType;
import org.jruby.runtime.load.LoadService;
import org.jruby.runtime.profile.builtin.ProfileOutput;
import org.jruby.util.ClassLoaderGetResourses;
import org.jruby.util.ClasspathLauncher;
import org.jruby.util.FileResource;
import org.jruby.util.GetResources;
import org.jruby.util.InputStreamMarkCursor;
import org.jruby.util.JRubyFile;
import org.jruby.util.KCode;
import org.jruby.util.NormalizedFile;
import org.jruby.util.SafePropertyAccessor;
import org.jruby.util.URLResource;
import org.jruby.util.UriLikePathHelper;
import org.jruby.util.cli.ArgumentProcessor;
import org.jruby.util.cli.Options;
import org.jruby.util.cli.OutputStrings;
@@ -65,6 +68,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -77,6 +81,7 @@
* embedding.
*/
public class RubyInstanceConfig {

public RubyInstanceConfig() {
currentDirectory = Ruby.isSecurityRestricted() ? "/" : JRubyFile.getFileProperty("user.dir");

@@ -670,7 +675,7 @@ private void setupEnvironment(String jrubyHome) {
if (RubyFile.PROTOCOL_PATTERN.matcher(jrubyHome).matches() && !environment.containsKey("RUBY")) {
// the assumption that if JRubyHome is not a regular file that jruby
// got launched in an embedded fashion
environment.put("RUBY", ClasspathLauncher.jrubyCommand(defaultClassLoader()) );
environment.put("RUBY", ClasspathLauncher.jrubyCommand(defaultClassLoader()));
}
}

@@ -686,6 +691,52 @@ public void setLoader(ClassLoader loader) {
this.loader = loader;
}

private final List<String> extraLoadPaths = new LinkedList<>();
public List<String> getExtraLoadPaths() {
return extraLoadPaths;
}

private final List<String> extraGemPaths = new LinkedList<>();
public List<String> getExtraGemPaths() {
return extraGemPaths;
}

/**
* adds a given ClassLoader to jruby. i.e. adds the root of
* the classloader to the LOAD_PATH so embedded ruby scripts
* can be found. dito for embedded gems.
*
* since classloaders do not provide directory information (some
* do and some do not) the source of the classloader needs to have
* a '.jrubydir' in each with the list of files and directories of the
* same directory. (see jruby-stdlib.jar or jruby-complete.jar inside
* META-INF/jruby.home for examples).
*
* these files can be generated by <code>jruby -S generate_dir_info {path/to/ruby/files}</code>
*
* @param loader
*/
public void addLoader(ClassLoader loader) {
addLoader(new ClassLoaderGetResourses(loader));
}

/**
* adds a given "bundle" to jruby. an OSGi bundle and a classloader
* both have common set of method but do not share a common interface.
* for adding a bundle or classloader to jruby is done via the base URL of
* the classloader/bundle. all we need is the 'getResource'/'getResources'
* method to do so.
* @param bundle
*/
public void addLoader(GetResources bundle) {
// loader can be a ClassLoader or an Bundle from OSGi
UriLikePathHelper helper = new UriLikePathHelper(bundle);
String uri = helper.getUriLikePath();
if (uri != null) extraLoadPaths.add(uri);
uri = helper.getUriLikeGemPath();
if (uri != null) extraGemPaths.add(uri);
}

public String[] getArgv() {
return argv;
}
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@
import java.util.List;
import java.util.LinkedList;

import org.jruby.util.ClassLoaderGetResourses;
import org.jruby.util.UriLikePathHelper;

/**
@@ -57,7 +58,7 @@ public IsolatedScriptingContainer( LocalContextScope scope,
setLoadPaths(loadPaths);

// set the right jruby home
UriLikePathHelper uriPath = new UriLikePathHelper(getClassLoader());
UriLikePathHelper uriPath = new UriLikePathHelper(new ClassLoaderGetResourses(getClassLoader()));
URL url = uriPath.getResource("/.jrubydir");
if (url != null){
setCurrentDirectory( URI_CLASSLOADER );
11 changes: 11 additions & 0 deletions core/src/main/java/org/jruby/embed/ScriptingContainer.java
Original file line number Diff line number Diff line change
@@ -1904,14 +1904,24 @@ public boolean getClassloaderDelegate() {
return getProvider().getRubyInstanceConfig().isClassloaderDelegate();
}

/**
* add the given classloader to the LOAD_PATH and GEM_PATH
* @param classloader
*/
public void addClassLoader(ClassLoader classLoader) {
getProvider().getRubyInstanceConfig().addLoader(classLoader);
}

/**
* add the given classloader to the LOAD_PATH
* @param classloader
*/
@Deprecated
public void addLoadPath(ClassLoader classloader) {
addLoadPath(createUri(classloader, "/.jrubydir"));
}

@Deprecated
protected void addLoadPath(String uri) {
runScriptlet( "$LOAD_PATH << '" + uri + "' unless $LOAD_PATH.member?( '" + uri + "' )" );
}
@@ -1920,6 +1930,7 @@ protected void addLoadPath(String uri) {
* add the given classloader to the GEM_PATH
* @param classloader
*/
@Deprecated
public void addGemPath(ClassLoader classloader) {
addGemPath(createUri(classloader, "/specifications/.jrubydir"));
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package org.jruby.embed.osgi;

import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;

import org.jruby.embed.IsolatedScriptingContainer;
import org.jruby.embed.LocalContextScope;
import org.jruby.embed.LocalVariableBehavior;

import org.jruby.util.GetResources;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
@@ -62,8 +65,9 @@ private Bundle toBundle(String symbolicName) {
return bundle;
}

@Deprecated
private String createUri(Bundle cl, String ref) {
URL url = cl.getResource( ref );
URL url = cl.getResource(ref);
if ( url == null && ref.startsWith( "/" ) ) {
url = cl.getResource( ref.substring( 1 ) );
}
@@ -76,6 +80,7 @@ private String createUri(Bundle cl, String ref) {
* add the classloader from the given bundle to the LOAD_PATH
* @param bundle
*/
@Deprecated
public void addBundleToLoadPath(Bundle bundle) {
addLoadPath(createUri(bundle, "/.jrubydir"));
}
@@ -86,25 +91,64 @@ public void addBundleToLoadPath(Bundle bundle) {
*
* @param symbolicName
*/
@Deprecated
public void addBundleToLoadPath(String symbolicName) {
addBundleToLoadPath(toBundle(symbolicName));
}

/**
* add the classloader from the given bundle to the LOAD_PATH and the GEM_PATH
* using the bundle symbolic name
* @param symbolicName
*/
public void addBundle(String symbolicName) {
addBundle(toBundle(symbolicName));
}

/**
* add the classloader from the given bundle to the LOAD_PATH and the GEM_PATH
* @param bundle
*/
public void addBundle(Bundle bundle) {
getProvider().getRubyInstanceConfig().addLoader(new BundleGetResources(bundle));
}

/**
* add the classloader from the given bundle to the GEM_PATH
* @param bundle
*/
@Deprecated
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
*/
@Deprecated
public void addBundleToGemPath(String symbolicName) {
addBundleToGemPath(toBundle(symbolicName));
}

static class BundleGetResources implements GetResources {

private final Bundle bundle;

BundleGetResources(Bundle bundle) {
this.bundle = bundle;
}

@Override
public URL getResource(String path) {
return bundle.getResource(path);
}

@Override
public Enumeration<URL> getResources(String path) throws IOException {
return bundle.getResources(path);
}
}
}
9 changes: 0 additions & 9 deletions core/src/main/java/org/jruby/javasupport/JavaEmbedUtils.java
Original file line number Diff line number Diff line change
@@ -203,15 +203,6 @@ public IRubyObject run() {
}
}

public static void addLoadPath(Ruby runtime, ClassLoader cl) {
runtime.getLoadService().addPaths(new UriLikePathHelper(cl).getUriLikePath());
}

public static void addGemPath(Ruby runtime, ClassLoader cl) {
String uri = new UriLikePathHelper(cl).getUriLikePath();
runtime.evalScriptlet("Gem::Specification.add_dir '" + uri + "' unless Gem::Specification.dirs.member?( '" + uri + "' )" );
}

/**
* Dispose of the runtime you initialized.
*
1 change: 1 addition & 0 deletions core/src/main/java/org/jruby/runtime/load/LoadService.java
Original file line number Diff line number Diff line change
@@ -251,6 +251,7 @@ public void init(List prependDirectories) {
}

} catch(SecurityException ignore) {}
addPaths(runtime.getInstanceConfig().getExtraLoadPaths());
}

/**
24 changes: 24 additions & 0 deletions core/src/main/java/org/jruby/util/ClassLoaderGetResourses.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.jruby.util;

import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;

public class ClassLoaderGetResourses implements GetResources {

private final ClassLoader loader;

public ClassLoaderGetResourses(ClassLoader loader) {
this.loader = loader;
}

@Override
public URL getResource(String path) {
return loader.getResource(path);
}

@Override
public Enumeration<URL> getResources(String path) throws IOException {
return loader.getResources(path);
}
}
15 changes: 15 additions & 0 deletions core/src/main/java/org/jruby/util/GetResources.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.jruby.util;

import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;

/**
* Created by cmeier on 7/30/15.
*/
public interface GetResources {

URL getResource(String path);// throws IOException;

Enumeration<URL> getResources(String path) throws IOException;
}
28 changes: 16 additions & 12 deletions core/src/main/java/org/jruby/util/UriLikePathHelper.java
Original file line number Diff line number Diff line change
@@ -30,32 +30,36 @@

public class UriLikePathHelper {

private final ClassLoader classLoader;
private final GetResources loader;

public UriLikePathHelper(ClassLoader classLoader) {
this.classLoader = classLoader;
public UriLikePathHelper(GetResources loader) {
this.loader = loader;
}

public URL getResource(String ref) {
URL url = classLoader.getResource( ref );
URL url = get( ref );
if ( url == null && ref.startsWith( "/" ) ) {
url = classLoader.getResource( ref.substring( 1 ) );
url = get( ref.substring( 1 ) );
}
return url;
}


private URL get(String ref) {
return loader.getResource(ref);
}

public String getUriLikePath() {
return createUri("/.jrubydir");
}

public String getUriLikePath(String ref) {
return createUri(ref);
public String getUriLikeGemPath() {
return createUri("/specifications/.jrubydir");
}
String createUri(String ref) {

private String createUri(String ref) {
URL url = getResource( ref );
if ( url == null ) {
throw new RuntimeException( "reference " + ref + " not found on classloader " + classLoader );
return null;
}
return "uri:" + url.toString().replaceFirst( ref + "$", "" );
}
2 changes: 1 addition & 1 deletion core/src/main/ruby/jruby/commands.rb
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ class << self
end
end

def generate_dir_info( dir, is_root = true )
def generate_dir_info( dir = ARGV[0], is_root = true )
return if dir != nil && !File.directory?( dir )
File.open( dir + '/.jrubydir', 'w' ) do |f|
f.puts ".." unless is_root
10 changes: 6 additions & 4 deletions core/src/test/java/org/jruby/javasupport/JavaEmbedUtilsTest.java
Original file line number Diff line number Diff line change
@@ -46,9 +46,11 @@ public static void restClassLoader() {
@Test
public void testAddClassloaderToLoadPathOnTCCL() throws Exception {
Thread.currentThread().setContextClassLoader( cl );
Ruby runtime = JavaEmbedUtils.initialize(EMPTY);
RubyInstanceConfig config = new RubyInstanceConfig();
config.setLoader(RubyInstanceConfig.class.getClassLoader());
URL url = new File("src/test/resources/java_embed_utils").toURI().toURL();
JavaEmbedUtils.addLoadPath(runtime, new URLClassLoader(new URL[] { url }));
config.addLoader(new URLClassLoader(new URL[]{url}));
Ruby runtime = JavaEmbedUtils.initialize(EMPTY, config);
String result = runtime.evalScriptlet("require 'test_me'; $result").toString();
assertEquals(result, "uri:" + url);
}
@@ -57,9 +59,9 @@ public void testAddClassloaderToLoadPathOnTCCL() throws Exception {
public void testAddClassloaderToLoadPathOnNoneTCCL() throws Exception {
RubyInstanceConfig config = new RubyInstanceConfig();
config.setLoader(RubyInstanceConfig.class.getClassLoader());
Ruby runtime = JavaEmbedUtils.initialize(EMPTY, config);
URL url = new File("src/test/resources/java_embed_utils").toURI().toURL();
JavaEmbedUtils.addLoadPath(runtime, new URLClassLoader(new URL[] { url }));
config.addLoader(new URLClassLoader(new URL[]{url}));
Ruby runtime = JavaEmbedUtils.initialize(EMPTY, config);
String result = runtime.evalScriptlet("require 'test_me';$result").toString();
assertEquals(result, "uri:" + url);
}
Loading