com.sun.grizzly.jruby.rack.RackApplicationChooser Maven / Gradle / Ivy
package com.sun.grizzly.jruby.rack;
import com.sun.grizzly.http.SelectorThread;
import com.sun.grizzly.jruby.RailsAdapter;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.logging.Logger;
/**
* @author Jacob Kessler
* Attempts to determine the RackApplicationFactory most suited to handle
* the given application directory
*/
public class RackApplicationChooser {
public static RackAdapter getFactory(String appPath, RailsAdapter adapter) {
Logger theLog = adapter.getLogger();
String appType = System.getProperty("jruby.applicationType");
RackAdapter rack;
if (appType != null) {
rack = handleUserSpecifiedFramework(adapter, appPath, appType, theLog);
if (rack != null) {
return rack;
} else {
rack = handleUserSpecifiedStartupScript(appType, adapter, theLog);
if (rack != null) {
return rack;
}
}
}
// User has not overridden the detection process
if (appPath.endsWith(".rb")) {
File appFile = new File(appPath);
rack = detectSinatra(appFile, theLog, adapter);
if (rack != null) {
return rack;
}
}
theLog.fine("Path is " + appPath + ", checking for Rails");
rack = detectRails(appPath, theLog, adapter);
if (rack != null) {
return rack;
}
theLog.fine("Rails not found, checking for Merb");
rack = detectMerb(appPath, theLog, adapter);
if (rack != null) {
return rack;
}
// Other frameworks go here
theLog.fine("Merb not found, checking for Sinatra");
rack = findSinatra(appPath, theLog, adapter);
if (rack != null) {
return rack;
}
// Check for a launch script
theLog.info("Unable to find a supported framework! Checking for .ru files");
String rackUp = findRackup(appPath);
if (rackUp != null) {
theLog.info("Discovered a .ru file, attempting to launch a framework from that.");
rack = handleUserSpecifiedStartupScript (rackUp, adapter, theLog);
if (rack != null) {
return rack;
}
}
// No framework found
SelectorThread.logger().severe("Framework autodetection failed! Please set -Djruby.rackup_script to the path to a script that will start your framework");
throw new IllegalStateException("No framework to start!");
}
private static String inhale (File f, Logger theLog) {
String app = "";
if (f.exists()) {
try {
BufferedReader in = new BufferedReader(new FileReader(f));
String s;
while ((s = in.readLine()) != null) {
// read the file
app = app + s + "\n";
}
} catch (IOException e) {
theLog.severe("IO Exception determining framework for " + f.getAbsolutePath() + ": " + e);
}
} else {
theLog.severe("Was told to read nonexistant file " + f.getAbsolutePath());
}
return app;
}
private static RackAdapter findSinatra (String appPath, Logger theLog, RailsAdapter adapter) {
File appDir = new File(appPath);
if (appDir.isDirectory()) {
File[] files = appDir.listFiles();
RackAdapter rack;
for (File file : files) {
if (file.getAbsolutePath().endsWith(".rb")) {
theLog.fine("Checking " + file.getName());
// Check for require. This is expensive and we don't want to.
rack = detectSinatra(file, theLog, adapter);
if (rack != null) {
theLog.fine("Found Sinatra in " + file.getAbsolutePath());
return rack;
}
}
}
}
return null;
}
private static String findRackup (String appPath) {
File appDir = new File(appPath);
if (appDir.isDirectory()) {
File[] files = appDir.listFiles();
for (File file : files) {
if (file.getAbsolutePath().endsWith(".ru")) {
return file.getPath();
}
}
}
return null;
}
private static RackAdapter handleUserSpecifiedFramework(RailsAdapter adapter, String appPath, String appType, Logger theLog) {
// User has told us what to look for, so we don't need to guess
if (appType.equalsIgnoreCase("rails")) {
RackApplicationFactory myFactory = new RailsApplicationFactory(adapter);
if (System.getProperty("jruby.MTsafe") != null && System.getProperty("jruby.MTsafe").equalsIgnoreCase("true")) {
theLog.info("User has specified rails in threadsafe mode, initializing multithreaded rails");
return new MultiThreadedRackAdapter(myFactory, adapter);
} else {
theLog.info("User has specified rails in non-threadsafe mode, initializing pooled rails");
return new SingleThreadedRackAdapter(myFactory, adapter);
}
} else if (appType.equalsIgnoreCase("merb")) {
theLog.info("User has specified merb, initializing merb");
RackApplicationFactory myFactory = new MerbApplicationFactory(adapter);
return new MultiThreadedRackAdapter(myFactory, adapter);
} else if (appType.equalsIgnoreCase("sinatra")) {
theLog.info("User has specified Sinatra, locating Sinatra file and initializing");
if (appPath.endsWith(".rb")) {
RackApplicationFactory myFactory = new SinatraApplicationFactory(adapter, appPath);
return new MultiThreadedRackAdapter(myFactory, adapter);
} else {
RackAdapter sinatra = findSinatra(appPath, theLog, adapter); // Well, maybe we need to guess a little
if (sinatra != null) {
theLog.info("Found Sinatra in " + sinatra + ", launching");
return sinatra;
} else {
theLog.severe("User specified a Sinatra application, but no sinatra application was found in the deployment directory. Falling back to autodetection");
}
}
} else {
theLog.severe("Unknown framework specified as appType, falling back to autodetection");
}
return null;
}
private static RackAdapter handleUserSpecifiedStartupScript (String rackUp, RailsAdapter adapter, Logger theLog) {
// User has specified a file to run.
RackApplicationFactory myFactory = new GenericApplicationFactory(rackUp, adapter);
if (System.getProperty("jruby.MTsafe") != null && System.getProperty("jruby.MTsafe").equalsIgnoreCase("true")) {
theLog.info("Running a user-provided rackup script in thread-safe mode");
return new MultiThreadedRackAdapter(myFactory, adapter);
} else {
theLog.info("Running a user-provided rackup script in pooled mode");
return new SingleThreadedRackAdapter(myFactory, adapter);
}
}
private static RackAdapter detectSinatra(File appFile, Logger theLog, RailsAdapter adapter) {
// Sinatra may not have a rake file. Check if we were given a .rb file
theLog.fine("attempting to detect sinatra in " + appFile.getPath());
String app = inhale(appFile, theLog);
if (app.contains("require 'sinatra'")) {
RackApplicationFactory myFactory = new SinatraApplicationFactory(adapter, appFile.getPath());
theLog.info("Detected Sinatra application");
// Sinatra is thread-safe
return new MultiThreadedRackAdapter(myFactory, adapter);
}
return null;
}
private static RackAdapter detectRails(String appPath, Logger theLog, RailsAdapter adapter) {
File boot = new File(appPath, "config/boot.rb");
if (boot.exists()) {
String bootFile = inhale(boot, theLog);
if (bootFile.contains("RAILS_ROOT")) {
RackApplicationFactory myFactory = new RailsApplicationFactory(adapter);
theLog.info("Detected Rails application");
// Check rails thread safety
boolean multithreaded = false;
String environment = "";
if (System.getProperty("rails.env") == null || "development".compareTo(System.getProperty("rails.env")) == 0) {
// Grab the development environment file
environment = inhale(new File(appPath+"/config/environments/development.rb"), theLog);
} else if ("production".compareTo(System.getProperty("rails.env")) == 0) {
// if we are in production mode
environment = inhale(new File(appPath+"/config/environments/production.rb"), theLog);
} else if ("testing".compareTo(System.getProperty("rails.env")) == 0) {
environment = inhale(new File(appPath+"/config/environments/testing.rb"), theLog);
}
if (environment.matches("(?s)(?m).*^[^#]*config\\.threadsafe!.*")) { // If there is a non-commented line with config.threadsafe! in it
multithreaded = true;
}
if (multithreaded) {
theLog.info("config.threadsafe sighted! All hands prepare for multithread mode!");
return new MultiThreadedRackAdapter(myFactory, adapter);
} else {
theLog.info("Rails not in thread-safe mode, starting in single-thread mode");
return new SingleThreadedRackAdapter(myFactory, adapter);
}
}
}
return null;
}
private static RackAdapter detectMerb(String appPath, Logger theLog, RailsAdapter adapter) {
File init = new File (appPath, "config/init.rb");
if (!(init.exists())) {
// Init can also be at root/init.rb
init = new File (appPath, "root/init.rb");
if (!(init.exists())) {
// Still no init file: Not a standard merb app
return null;
}
}
// Thus, init exists
String initFile = inhale(init, theLog);
if (initFile.contains("Merb::Config")) {
RackApplicationFactory myFactory = new MerbApplicationFactory(adapter);
theLog.info("Detected merb application");
// Merb is thread-safe
return new MultiThreadedRackAdapter(myFactory, adapter);
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy