package org.jruby.embed;

import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.LinkedList;

import org.jruby.util.ClassesLoader;
import org.jruby.util.UriLikePathHelper;

The IsolatedScriptingContainer does set GEM_HOME and GEM_PATH and JARS_HOME in such a way that it uses only resources which can be reached with classloader. GEM_HOME is uri:classloader://META-INF/jruby.home/lib/ruby/gems/shared GEM_PATH is uri:classloader:// JARS_HOME is uri:classloader://jars But whenever you want to set them via setEnvironment(Map) this will be honored. It also allows to add a classloaders to LOAD_PATH or GEM_PATH. This container also sets option classloader.delegate to false, i.e. the JRubyClassloader for each runtime will lookup classes first on itself before looking into the parent classloader. WARNING: this can give problems when joda-time is used inside the JRubyClassloader or with current version of nokogiri (1.6.7.2) as it uses (sun-)jdk classes which conflicts with classes nokogiri loaded into the JRubyClassloader. With any classloader related problem the first thing is to try container.getProvider().getRubyInstanceConfig().setClassloaderDelegate(true); to solve it.
/** * The IsolatedScriptingContainer does set GEM_HOME and GEM_PATH and JARS_HOME * in such a way that it uses only resources which can be reached with classloader. * * GEM_HOME is uri:classloader://META-INF/jruby.home/lib/ruby/gems/shared * GEM_PATH is uri:classloader:// * JARS_HOME is uri:classloader://jars * * But whenever you want to set them via {@link #setEnvironment(Map)} this will be honored. * * It also allows to add a classloaders to LOAD_PATH or GEM_PATH. * * This container also sets option classloader.delegate to false, i.e. the JRubyClassloader * for each runtime will lookup classes first on itself before looking into the parent * classloader. * * WARNING: this can give problems when joda-time is used inside the * JRubyClassloader or with current version of nokogiri (1.6.7.2) as it uses * (sun-)jdk classes which conflicts with classes nokogiri loaded into the * JRubyClassloader. * * With any classloader related problem the first thing is to try * <code>container.getProvider().getRubyInstanceConfig().setClassloaderDelegate(true);</code> to solve it. */
public class IsolatedScriptingContainer extends ScriptingContainer { private static final String URI_CLASSLOADER = "uri:classloader:/"; public IsolatedScriptingContainer() { this(LocalContextScope.SINGLETON); } public IsolatedScriptingContainer( LocalContextScope scope, LocalVariableBehavior behavior ) { this(scope, behavior, true); } public IsolatedScriptingContainer( LocalContextScope scope ) { this(scope, LocalVariableBehavior.TRANSIENT); } public IsolatedScriptingContainer( LocalVariableBehavior behavior ) { this(LocalContextScope.SINGLETON, behavior); } public IsolatedScriptingContainer( LocalContextScope scope, LocalVariableBehavior behavior, boolean lazy ) { super(scope, behavior, lazy); List<String> loadPaths = new LinkedList<String>(); loadPaths.add(URI_CLASSLOADER); setLoadPaths(loadPaths); // set the right jruby home UriLikePathHelper uriPath = new UriLikePathHelper(new ClassesLoader(getClassLoader())); URL url = uriPath.getResource("/.jrubydir"); if (url != null){ setCurrentDirectory( URI_CLASSLOADER ); } // setup the isolated GEM_PATH, i.e. without $HOME/.gem/** setEnvironment(null); // give preference to jrubyClassloader over parent-classloader getProvider().getRubyInstanceConfig().setClassloaderDelegate(false); } @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); } } }