org.jruby.rack.DefaultRackConfig Maven / Gradle / Ivy
/*
* Copyright (c) 2010-2012 Engine Yard, Inc.
* Copyright (c) 2007-2009 Sun Microsystems, Inc.
* This source code is available under the MIT license.
* See the file LICENSE.txt for details.
*/
package org.jruby.rack;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.StringReader;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jruby.CompatVersion;
import org.jruby.rack.logging.OutputStreamLogger;
import org.jruby.rack.logging.StandardOutLogger;
import org.jruby.util.SafePropertyAccessor;
/**
* A base implementation of that retrieves settings from system properties.
*
* @see System#getProperty(String)
* @see RackConfig
*/
@SuppressWarnings("deprecation")
public class DefaultRackConfig implements RackConfig {
private RackLogger logger;
private boolean quiet = false;
private PrintStream out = System.out;
private PrintStream err = System.err;
public PrintStream getOut() {
return out;
}
public void setOut(OutputStream o) {
if (o == null) {
out = System.out;
} else if (o instanceof PrintStream) {
out = (PrintStream) o;
} else {
out = new PrintStream(o);
}
}
public PrintStream getErr() {
return err;
}
public void setErr(OutputStream o) {
if (o == null) {
err = System.err;
} else if (o instanceof PrintStream) {
err = (PrintStream) o;
} else {
err = new PrintStream(o);
}
}
public boolean isQuiet() {
return quiet;
}
public void setQuiet(boolean quiet) {
this.quiet = quiet;
}
public CompatVersion getCompatVersion() {
final String version = getProperty("jruby.compat.version");
if ( version != null ) {
// we handle 1.8, RUBY1_9, --2.0 1_9 2.1.0.dev etc :
final Pattern pattern = Pattern.compile("([123])[._]([8901234567])");
final Matcher matcher = pattern.matcher(version);
if ( matcher.find() ) {
final String name = "RUBY" +
matcher.group(1) + '_' + matcher.group(2);
try {
return Enum.valueOf(CompatVersion.class, name);
}
catch (IllegalArgumentException e) {
getLogger().log(RackLogger.WARN,
"could not resolve compat version from '"+ version +"' will use default", e);
}
}
}
return null;
}
public String getRackup() {
return getProperty("rackup");
}
public String getRackupPath() {
return getProperty("rackup.path");
}
public Integer getRuntimeTimeoutSeconds() {
Integer timeout = getPositiveInteger("jruby.runtime.acquire.timeout");
if (timeout == null) { // backwards compatibility with 1.0.x :
timeout = getPositiveInteger("jruby.runtime.timeout.sec");
}
return timeout;
}
public String[] getRuntimeArguments() {
final String args = getProperty("jruby.runtime.arguments");
return args == null ? null : args.trim().split("\\s+");
}
public Integer getNumInitializerThreads() {
Number threads = getNumberProperty("jruby.runtime.init.threads");
if (threads == null) { // backwards compatibility with 1.0.x :
threads = getNumberProperty("jruby.runtime.initializer.threads");
}
return threads != null ? threads.intValue() : null;
}
public boolean isSerialInitialization() {
Boolean serial = getBooleanProperty("jruby.runtime.init.serial");
if (serial == null) { // backwards compatibility with 1.0.x :
serial = getBooleanProperty("jruby.init.serial");
if (serial == null) { // if initializer threads set to <= 0
Integer threads = getNumInitializerThreads();
if ( threads != null && threads < 0 ) {
serial = Boolean.TRUE;
}
else {
serial = Boolean.FALSE;
}
}
}
return serial.booleanValue();
}
public RackLogger getLogger() {
if (logger == null) {
String loggerClass = getLoggerClassName();
if ( "stdout".equalsIgnoreCase(loggerClass) ) {
logger = new OutputStreamLogger(getOut());
}
else if ( "stderr".equalsIgnoreCase(loggerClass) ) {
logger = new OutputStreamLogger(getErr());
}
else {
final Map loggerTypes = getLoggerTypes();
final String loggerKey = loggerClass.toLowerCase();
if (loggerTypes.containsKey(loggerKey)) {
loggerClass = loggerTypes.get(loggerKey);
}
logger = createLogger(loggerClass);
}
if (logger == null) logger = defaultLogger();
}
return logger;
}
protected RackLogger createLogger(final String loggerClass) {
try {
final Class> klass = Class.forName(loggerClass);
try {
Constructor> ctor = klass.getConstructor(new Class>[] { String.class });
return (RackLogger) ctor.newInstance(new Object[] { getLoggerName() });
} catch (Exception tryAgain) {
return (RackLogger) klass.newInstance();
}
} catch (Exception e) {
if ( ! isQuiet() ) {
err.println("Failed loading logger: " + loggerClass);
e.printStackTrace(err);
}
return null;
}
}
protected RackLogger defaultLogger() {
return new StandardOutLogger(getOut());
}
public boolean isFilterAddsHtml() {
return getBooleanProperty("jruby.rack.filter.adds.html", true);
}
public boolean isFilterVerifiesResource() {
return getBooleanProperty("jruby.rack.filter.verifies.resource", false);
}
public String getJmsConnectionFactory() {
return getProperty("jms.connection.factory");
}
public String getJmsJndiProperties() {
return getProperty("jms.jndi.properties");
}
public String getLoggerName() {
return getProperty("jruby.rack.logging.name", "jruby.rack");
}
public String getLoggerClassName() {
return getProperty("jruby.rack.logging", "servlet_context");
}
public Integer getInitialRuntimes() {
return getRuntimesRangeValue("min", "minIdle");
}
public Integer getMaximumRuntimes() {
return getRuntimesRangeValue("max", "maxActive");
}
public boolean isRewindable() {
return getBooleanProperty("jruby.rack.input.rewindable", true);
}
public Integer getInitialMemoryBufferSize() {
return getPositiveInteger("jruby.rack.request.size.initial.bytes");
}
public Integer getMaximumMemoryBufferSize() {
Integer max = getPositiveInteger("jruby.rack.request.size.maximum.bytes");
if (max == null) { // backwards compatibility with 1.0.x :
max = getPositiveInteger("jruby.rack.request.size.threshold.bytes");
}
return max;
}
public Map getRuntimeEnvironment() {
String env = getProperty("jruby.runtime.env");
if ( env == null ) env = getProperty("jruby.runtime.environment");
final Object envFlag = toStrictBoolean(env, null);
if ( envFlag != null ) {
boolean keep = ((Boolean) envFlag).booleanValue();
// jruby.runtime.env = true keep as is (return null)
// jruby.runtime.env = false clear env (return empty)
//return keep ? null : new HashMap();
if ( keep ) {
return new HashMap(System.getenv());
}
else {
return new HashMap();
}
}
if ( isIgnoreEnvironment() ) return new HashMap();
// TODO maybe support custom value 'servlet' to use init params ?
return toStringMap(env);
}
// NOTE: this is only here to be able to maintain previous behavior
// jruby.rack.ignore.env did ENV.clear but after RUBYOPT has been processed
static boolean isIgnoreRUBYOPT(RackConfig config) {
// RUBYOPT ignored if jruby.runtime.env.rubyopt = false
Boolean rubyopt = config.getBooleanProperty("jruby.runtime.env.rubyopt");
if ( rubyopt == null ) return ! config.isIgnoreEnvironment();
return rubyopt != null && ! rubyopt.booleanValue();
}
public boolean isIgnoreEnvironment() {
return getBooleanProperty("jruby.rack.ignore.env", false);
}
public boolean isThrowInitException() {
return isThrowInitException(this);
}
static boolean isThrowInitException(RackConfig config) {
Boolean error = config.getBooleanProperty("jruby.rack.error");
if ( error != null && ! error.booleanValue() ) {
return true; // jruby.rack.error = false
}
error = config.getBooleanProperty("jruby.rack.exception");
if ( error != null && ! error.booleanValue() ) {
return true; // jruby.rack.exception = false
}
return false;
}
public String getProperty(String key) {
return getProperty(key, null);
}
public String getProperty(String key, String defaultValue) {
return SafePropertyAccessor.getProperty(key, defaultValue);
}
public Boolean getBooleanProperty(String key) {
return getBooleanProperty(key, null);
}
public Boolean getBooleanProperty(String key, Boolean defaultValue) {
return toBoolean(getProperty(key), defaultValue);
}
public Number getNumberProperty(String key) {
return getNumberProperty(key, null);
}
public Number getNumberProperty(String key, Number defaultValue) {
return toNumber(getProperty(key), defaultValue);
}
private Integer getRuntimesRangeValue(String end, String gsValue) {
Integer v = getPositiveInteger("jruby." + end + ".runtimes");
if (v == null) {
v = getPositiveInteger("jruby.pool." + gsValue);
}
return v;
}
private Integer getPositiveInteger(String key) {
final String value = getProperty(key);
if (value == null) return null;
try {
int i = Integer.parseInt(value);
if (i > 0) return Integer.valueOf(i);
} catch (Exception e) { /* ignored */ }
return null;
}
public static Boolean toBoolean(String value, Boolean defaultValue) {
if (value == null) return defaultValue;
try {
return Boolean.valueOf(value);
}
catch (Exception e) { /* ignored */ }
return defaultValue;
}
public static Object toStrictBoolean(String value, Object defaultValue) {
if ( "true".equalsIgnoreCase(value) ) return Boolean.TRUE;
if ( "false".equalsIgnoreCase(value) ) return Boolean.FALSE;
return defaultValue;
}
public static Number toNumber(String value, Number defaultValue) {
if (value == null) return defaultValue;
try {
float number = Float.parseFloat(value);
if ( Float.isInfinite(number) ) {
return Double.parseDouble(value);
}
if ( Float.isNaN(number) ) {
return defaultValue;
}
if ( number == ((int) number) )
if ( number > Integer.MAX_VALUE ) {
return Long.valueOf((long) number);
}
else {
return Integer.valueOf((int) number);
}
return Float.valueOf(number);
}
catch (Exception e) { /* ignored */ }
return defaultValue;
}
private Map toStringMap(final String env) {
if ( env == null ) return null;
/*
USER=kares,TERM=xterm,SHELL=/bin/bash
PATH=/opt/local/rvm/gems/jruby-1.6.8@jruby-rack/bin:/opt/local/rvm/gems/jruby-1.6.8@global/bin
GEM_HOME=/opt/local/rvm/gems/jruby-1.6.8@jruby-rack
*/
LineNumberReader reader = new LineNumberReader(new StringReader(env.trim()));
Map map = new LinkedHashMap(); String line;
try {
while ( (line = reader.readLine()) != null ) {
final String[] entries = line.split(",");
String lastKey = null, lastVal = null;
for ( final String entry : entries ) {
String[] pair = entry.split("=", 2);
if ( pair.length == 1 ) { // no = separator
if ( entry.trim().length() == 0 ) continue;
if ( lastKey == null ) continue; // missing key
map.put( lastKey, lastVal = lastVal + ',' + entry );
}
else {
map.put( lastKey = pair[0], lastVal = pair[1] );
}
}
}
}
catch (IOException e) {
if ( ! isQuiet() ) {
err.println("Failed parsing env: \n" + env);
e.printStackTrace(err);
}
}
return map;
}
private static Map getLoggerTypes() {
final Map loggerTypes = new HashMap();
loggerTypes.put("commons_logging", "org.jruby.rack.logging.CommonsLoggingLogger");
loggerTypes.put("clogging", "org.jruby.rack.logging.CommonsLoggingLogger");
loggerTypes.put("log4j", "org.jruby.rack.logging.Log4jLogger");
loggerTypes.put("slf4j", "org.jruby.rack.logging.Slf4jLogger");
loggerTypes.put("jul", "org.jruby.rack.logging.JulLogger");
loggerTypes.put("servlet_context", "org.jruby.rack.logging.ServletContextLogger");
return loggerTypes;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy