Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft for reading configuration from config files #1722

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.mozilla.javascript.JavaScriptException;
import org.mozilla.javascript.Kit;
import org.mozilla.javascript.NativeArray;
import org.mozilla.javascript.RhinoConfig;
import org.mozilla.javascript.RhinoException;
import org.mozilla.javascript.Script;
import org.mozilla.javascript.Scriptable;
Expand Down Expand Up @@ -132,7 +133,7 @@ public void quit(Context cx, int exitCode) {
*/
public static void main(String args[]) {
try {
if (Boolean.getBoolean("rhino.use_java_policy_security")) {
if (RhinoConfig.DEFAULT.useJavaPolicySecurity()) {
initJavaPolicySecuritySupport();
}
} catch (SecurityException ex) {
Expand Down
237 changes: 237 additions & 0 deletions rhino/src/main/java/org/mozilla/javascript/RhinoConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
package org.mozilla.javascript;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;

/**
* Utility class to read current rhino configuration.
*
* <p>Rhino properties typically begins with "rhino." (properties) or "RHINO_" (env)
*
* <p>The configuration is read from these locations:
*
* <ol>
* <li>rhino.config file from current class' classpath
* <li>rhino.config file from current threas's classpath
* <li>rhino.config file from current directory
* <li>System-properties starting with "rhino."
* <li>env variables starting with "RHINO_" (underscores are replaced by '.' and string is
* </ol>
*
* <p>The config files are in UTF-8 format and all keys in this configuration are case-insensitive
* and dot/underscore-insensitive.
*
* <p>This means, "rhino.use_java_policy_security" is equvalent to "RHINO_USE_JAVA_POLICY_SECURITY"
*
* @author Roland Praml, Foconis Analytics GmbH
*/
public class RhinoConfig {

public static final RhinoConfig DEFAULT =
AccessController.doPrivileged((PrivilegedAction<RhinoConfig>) () -> init());

private static RhinoConfig init() {
RhinoConfig config = new RhinoConfig();
// we parse the following locations
config.loadFromClasspath(RhinoConfig.class.getClassLoader());
config.loadFromClasspath(Thread.currentThread().getContextClassLoader());
config.loadFromFile(new File("rhino.config"));
config.load(System.getProperties(), "System.properties");
config.load(System.getenv(), "System.env");
return config;
}

private void loadFromFile(File config) {
if (!config.exists()) {
return;
}
try (InputStream in = new FileInputStream(config)) {
Properties props = new Properties();
props.load(new InputStreamReader(in, StandardCharsets.UTF_8));
load(props, config.getAbsolutePath());
} catch (IOException e) {
System.err.println(
"Error loading rhino.config from "
+ config.getAbsolutePath()
+ ": "
+ e.getMessage());
}
}

@SuppressWarnings("unchecked")
private void loadFromClasspath(ClassLoader cl) {
if (cl == null) {
return;
}
URL resource = cl.getResource("rhino.config");
if (resource == null) {
return;
}
try (InputStream in = resource.openStream()) {
Properties props = new Properties();
props.load(new InputStreamReader(in, StandardCharsets.UTF_8));
load(props, resource.toString());
} catch (IOException e) {
System.err.println(
"Error loading rhino.config from " + resource + ": " + e.getMessage());
}
}

/** Replacement for {@link System#getProperty(String)}. */
public static String getProperty(String key) {
return null;
}

/** Replacement for {@link System#getProperty(String, String)}. */
public static String getProperty(String key, String defaultValue) {
String val = getProperty(key);
return (val == null) ? defaultValue : val;
}

/** Replacement for {@link Boolean#getBoolean(String)}. */
public static boolean getBoolean(String name) {
boolean result = false;
try {
result = Boolean.parseBoolean(getProperty(name));
} catch (IllegalArgumentException | NullPointerException e) {
}
return result;
}

/** Replacement for {@link Integer#getInteger(String, Integer)}. */
public static Integer getInteger(String nm, Integer val) {
String v = null;
try {
v = getProperty(nm);
} catch (IllegalArgumentException | NullPointerException e) {
}
if (v != null) {
try {
return Integer.decode(v);
} catch (NumberFormatException e) {
}
}
return val;
}

/** Replacement for {@link Integer#getInteger(String, int)}. */
public static Integer getInteger(String nm, int val) {
Integer result = getInteger(nm, null);
return (result == null) ? Integer.valueOf(val) : result;
}

/** Replacement for {@link Integer#getInteger(String)}. */
public static Integer getInteger(String nm) {
return getInteger(nm, null);
}

/** Returns the property as string. */
private String get(Map map, String property, String defaultValue) {
Object ret = find(map, property);
if (ret == null) {
return defaultValue;
} else {
return ret.toString();
}
}

/** Returns the property as enum. */
private <T extends Enum<T>> T get(Map map, String property, T defaultValue) {
Object ret = map.get(property);
if (ret == null) {
return defaultValue;
} else {
Class<T> enumType = (Class<T>) defaultValue.getClass();
return Enum.valueOf(enumType, ret.toString().toUpperCase(Locale.ROOT));
}
}

/** Returns the property as boolean. */
private boolean get(Map map, String property, boolean defaultValue) {
Object ret = map.get(property);
if (ret == null) {
return defaultValue;
} else if (ret instanceof Boolean) {
return (Boolean) ret;
} else {
return "1".equals(ret) || "true".equals(ret);
}
}

/**
* Tries to find the property in the map. It tries the property first, then it tries the camel
* upper version.
*/
private Object find(Map map, String property) {
Object ret = map.get(property);
if (ret != null) {
return ret;
}
return map.get(toCamelUpper(property));
}

private String toCamelUpper(String property) {
String s = property.replace('.', '_');
StringBuilder sb = new StringBuilder(s.length() + 5);
for (int i = 0; i < s.length(); ++i) {
char c = s.charAt(i);
if (i > 0 && Character.isUpperCase(c) && Character.isLowerCase(s.charAt(i - 1))) {
sb.append('_');
}
sb.append(Character.toUpperCase(c));
}
return sb.toString();
}

private void load(Map map, String location) {
stackStyle = get(map, "rhino.stack.style", stackStyle);
useJavaPolicySecurity = get(map, "rhino.use_java_policy_security", useJavaPolicySecurity);
printTrees = get(map, "rhino.printTrees", printTrees);
printICodes = get(map, "rhino.printICodes", printICodes);
debugStack = get(map, "rhino.debugStack", debugStack);
debugLinker = get(map, "rhino.debugLinker", debugStack);
}

/** "rhino.stack.style" */
private StackStyle stackStyle = StackStyle.RHINO;

private boolean useJavaPolicySecurity;
private boolean printTrees = false;
private boolean printICodes = false;
private boolean debugStack = false;
private boolean debugLinker = false;

public StackStyle stackStyle() {
return stackStyle;
}

public boolean useJavaPolicySecurity() {
return useJavaPolicySecurity;
}

public boolean printTrees() {
return printTrees;
}

public boolean printICodes() {
return printICodes;
}

public boolean debugStack() {
return debugStack;
}

public boolean debugLinker() {
return debugLinker;
}
}
26 changes: 3 additions & 23 deletions rhino/src/main/java/org/mozilla/javascript/RhinoException.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import java.io.FilenameFilter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
Expand Down Expand Up @@ -221,11 +220,11 @@ static String formatStackTrace(ScriptStackElement[] stack, String message) {
/**
* Get a string representing the script stack of this exception.
*
* @deprecated the filter argument is ignored as we are able to recognize script stack elements
* by our own. Use #getScriptStackTrace() instead.
* @param filter ignored
* @return a script stack dump
* @since 1.6R6
* @deprecated the filter argument is ignored as we are able to recognize script stack elements
* by our own. Use #getScriptStackTrace() instead.
*/
@Deprecated
public String getScriptStackTrace(FilenameFilter filter) {
Expand Down Expand Up @@ -375,7 +374,7 @@ public static StackStyle getStackStyle() {
private static final long serialVersionUID = 1883500631321581169L;

// Just for testing!
private static StackStyle stackStyle = StackStyle.RHINO;
private static StackStyle stackStyle = RhinoConfig.DEFAULT.stackStyle();

private String sourceName;
private int lineNumber;
Expand All @@ -384,23 +383,4 @@ public static StackStyle getStackStyle() {

Object interpreterStackInfo;
int[] interpreterLineData;

// Allow us to override default stack style for debugging.
static {
try {
String style = System.getProperty("rhino.stack.style");
if (style != null) {
if ("Rhino".equalsIgnoreCase(style)) {
stackStyle = StackStyle.RHINO;
} else if ("Mozilla".equalsIgnoreCase(style)) {
stackStyle = StackStyle.MOZILLA;
} else if ("V8".equalsIgnoreCase(style)) {
stackStyle = StackStyle.V8;
}
}
} catch (AccessControlException ace) {
// ignore. We will land here, if SecurityManager is in place and error is lazily
// initialized
}
}
}
4 changes: 2 additions & 2 deletions rhino/src/main/java/org/mozilla/javascript/Token.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ public static enum CommentType {
}

// debug flags
public static final boolean printTrees = false;
static final boolean printICode = false;
public static final boolean printTrees = RhinoConfig.DEFAULT.printTrees();
static final boolean printICode = RhinoConfig.DEFAULT.printICodes();
static final boolean printNames = printTrees || printICode;

/** Token types. These values correspond to JSTokenType values in jsscan.c. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import jdk.dynalink.linker.LinkerServices;
import org.mozilla.javascript.Callable;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.RhinoConfig;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.Token;
Expand All @@ -22,15 +23,7 @@
*/
@SuppressWarnings("AndroidJdkLibsChecker")
class DefaultLinker implements GuardingDynamicLinker {
static final boolean DEBUG;

static {
String debugVal = System.getProperty("RHINO_DEBUG_LINKER");
if (debugVal == null) {
debugVal = System.getenv("RHINO_DEBUG_LINKER");
}
DEBUG = Boolean.parseBoolean(debugVal);
}
static final boolean DEBUG = RhinoConfig.DEFAULT.debugLinker();

@Override
public GuardedInvocation getGuardedInvocation(LinkRequest req, LinkerServices svc)
Expand Down
1 change: 1 addition & 0 deletions tests/rhino.config
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rhino.helloFromFile=true
1 change: 1 addition & 0 deletions tests/src/test/resources/rhino.config
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rhino.helloFromClasspath=true
Loading