Skip to content

Commit

Permalink
Initialize the Ruby runtime directly without the ScriptingContainer. F…
Browse files Browse the repository at this point in the history
…ixes jruby#34
  • Loading branch information
calavera committed Apr 29, 2011
1 parent 1b58f23 commit 385ae17
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 54 deletions.
55 changes: 13 additions & 42 deletions src/main/java/org/jruby/rack/DefaultRackApplicationFactory.java
Expand Up @@ -10,13 +10,10 @@
import org.jruby.Ruby;
import org.jruby.RubyInstanceConfig;
import org.jruby.exceptions.RaiseException;
import org.jruby.embed.ScriptingContainer;
import org.jruby.embed.LocalContextScope;
import org.jruby.javasupport.JavaUtil;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ClassCache;

import java.lang.reflect.Method;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
Expand All @@ -35,20 +32,13 @@ public class DefaultRackApplicationFactory implements RackApplicationFactory {
private String rackupScript, rackupLocation;
private RackContext rackContext;
private RubyInstanceConfig defaultConfig;
private ClassCache classCache;
private RackApplication errorApplication;
private Method getRequiredLibraries;

public void init(RackContext rackContext) {
this.rackContext = rackContext;
this.rackupScript = findRackupScript();
this.defaultConfig = createDefaultConfig();
rackContext.log(defaultConfig.getVersionString());
try {
this.getRequiredLibraries = RubyInstanceConfig.class.getMethod("requiredLibraries", new Class[0]);
} catch (Exception e) {
throw (Error) (new NoSuchMethodError("JRuby is missing RubyInstanceConfig#requiredLibraries").initCause(e));
}
}

public RackApplication newApplication() throws RackInitializationException {
Expand Down Expand Up @@ -180,62 +170,43 @@ private RubyInstanceConfig createDefaultConfig() {
return config;
}

@SuppressWarnings("unchecked")
private void configureContainer(ScriptingContainer container) throws RackInitializationException {
container.setClassLoader(defaultConfig.getLoader());
container.setClassCache(defaultConfig.getClassCache());
container.setCompatVersion(defaultConfig.getCompatVersion());
container.setHomeDirectory(defaultConfig.getJRubyHome());
container.setEnvironment(defaultConfig.getEnvironment());
container.setLoadPaths(defaultConfig.loadPaths());
// Reflection hack due to sig change of requiredLibraries between
// 1.5 and 1.6: remove when JRuby 1.7 is available
try {
Collection defLibraries = (Collection) getRequiredLibraries.invoke(defaultConfig, new Object[0]);
Collection containerLibraries = (Collection) getRequiredLibraries.invoke(container.getProvider().getRubyInstanceConfig(), new Object[0]);
containerLibraries.addAll(defLibraries);
} catch (Exception e) {
throw new RackInitializationException("Error configuring new scripting container", e);
}
}

private void initializeContainer(ScriptingContainer container) throws RackInitializationException {
private void initializeRuntime(Ruby runtime) throws RackInitializationException {
try {
container.put("$servlet_context", rackContext);
IRubyObject context = JavaUtil.convertJavaToRuby(runtime, rackContext);
runtime.getGlobalVariables().set("$servlet_context", context);
if (rackContext.getConfig().isIgnoreEnvironment()) {
container.runScriptlet("ENV.clear");
runtime.evalScriptlet("ENV.clear");
}
container.runScriptlet("require 'rack/handler/servlet'");
runtime.evalScriptlet("require 'rack/handler/servlet'");
} catch (RaiseException re) {
throw new RackInitializationException(re);
}
}

/** This method is only public for unit tests */
public ScriptingContainer newContainer() throws RackInitializationException {
ScriptingContainer container = new ScriptingContainer(LocalContextScope.SINGLETHREAD);
configureContainer(container);
initializeContainer(container);
return container;
public Ruby newRuntime() throws RackInitializationException {
Ruby runtime = Ruby.newInstance(defaultConfig);
initializeRuntime(runtime);
return runtime;
}

private RackApplication createApplication(final ApplicationObjectFactory appfact)
throws RackInitializationException {
try {
final ScriptingContainer container = newContainer();
final Ruby runtime = newRuntime();
return new DefaultRackApplication() {
@Override
public void init() throws RackInitializationException {
try {
setApplication(appfact.create(container.getProvider().getRuntime()));
setApplication(appfact.create(runtime));
} catch (RaiseException re) {
captureMessage(re);
throw new RackInitializationException(re);
}
}
@Override
public void destroy() {
container.terminate();
runtime.tearDown(false);
}
};
} catch (RackInitializationException rie) {
Expand Down
28 changes: 16 additions & 12 deletions src/spec/ruby/rack/application_spec.rb
Expand Up @@ -91,30 +91,34 @@
end
end

describe "newContainer" do
it "should create a new Ruby container with the rack environment pre-loaded" do
container = app_factory.newContainer
container.runScriptlet("defined?(::Rack)").should be_true
container.runScriptlet("defined?(::Rack::Handler::Servlet)").should be_true
container.runScriptlet("defined?(Rack::Handler::Bogus)").should_not be_true
describe "newRuntime" do
it "should create a new Ruby runtime with the rack environment pre-loaded" do
runtime = app_factory.new_runtime
lambda { runtime.evalScriptlet("defined?(::Rack)") != nil }.should be_true
lambda { runtime.evalScriptlet("defined?(::Rack::Handler::Servlet)") != nil }.should be_true
lambda { runtime.evalScriptlet("defined?(Rack::Handler::Bogus)") == nil }.should be_true
end

it "should initialize the $servlet_context global variable" do
container = app_factory.newContainer
container.runScriptlet("defined?($servlet_context)").should_not be_empty
runtime = app_factory.new_runtime
lambda { runtime.evalScriptlet("defined?($servlet_context)") != nil }.should be_true
end

it "should handle jruby.compat.version == '1.9' and start up in 1.9 mode" do
@rack_config.stub!(:getCompatVersion).and_return org.jruby.CompatVersion::RUBY1_9
container = app_factory.newContainer
container.compat_version.should == org.jruby.CompatVersion::RUBY1_9
runtime = app_factory.new_runtime
runtime.is1_9.should be_true
end

it "should have environment variables cleared if the configuration ignores the environment" do
ENV["HOME"].should_not == ""
@rack_config.stub!(:isIgnoreEnvironment).and_return true
container = app_factory.newContainer
container.runScriptlet('ENV["HOME"]').should be_nil
runtime = app_factory.new_runtime
lambda { runtime.evalScriptlet('ENV["HOME"]') == nil }.should be_true
end

def eval_should_be_true(value, expected)
(value == expected).should be_true
end
end
end
Expand Down

0 comments on commit 385ae17

Please sign in to comment.