Skip to content

Commit

Permalink
Draft for reading configuration from config files
Browse files Browse the repository at this point in the history
  • Loading branch information
rPraml committed Nov 8, 2024
1 parent 59eb197 commit dd2bf28
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 17 deletions.
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.getBoolean("rhino.use_java_policy_security")) {
initJavaPolicySecuritySupport();
}
} catch (SecurityException ex) {
Expand Down
167 changes: 167 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,167 @@
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.nio.charset.StandardCharsets;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.Comparator;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;

/**
* 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>
*
* 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 {
private static final Map<String, String> PROPERTIES =
AccessController.doPrivileged((PrivilegedAction<Map<String, String>>) () -> init());

private static Map<String, String> init() {
// we have to add a comparator at least for environment: TODO: can this done simpler
Comparator<String> comparator =
(s1, s2) -> {
s1 = s1.toLowerCase(Locale.ROOT).replace('_', '.');
s2 = s2.toLowerCase(Locale.ROOT).replace('_', '.');
return s1.compareTo(s2);
};
Map<String, String> map = new TreeMap<>(comparator);

// load from classpaths
map.putAll(loadFromClasspath(RhinoConfig.class.getClassLoader()));
map.putAll(loadFromClasspath(Thread.currentThread().getContextClassLoader()));
map.putAll(loadFromFile(new File("rhino.config")));
copyMap(System.getProperties(), map);
copyMap(System.getenv(), map);
System.out.println("Current config: " + map);
return map;
}

/** Copies all rhino relevant properties. */
private static void copyMap(Map<?, ?> src, Map<String, String> dst) {
for (Map.Entry<?, ?> entry : src.entrySet()) {
if (entry.getKey() instanceof String && entry.getValue() instanceof String) {
String key = (String) entry.getKey();
if (key.startsWith("rhino.") || key.startsWith("RHINO_")) {
dst.put(key, (String) entry.getValue());
}
}
}
}

@SuppressWarnings("unchecked")
private static Map<String, String> loadFromFile(File config) {
if (config.exists()) {
try (InputStream in = new FileInputStream(config)) {
if (in != null) {
Properties props = new Properties();
props.load(new InputStreamReader(in, StandardCharsets.UTF_8));
System.out.println(
"Loaded rhino.config from "
+ config.getAbsolutePath()); // TODO: remove these prints
return (Map) props;
}
} catch (IOException e) {
System.err.println(
"Error loading rhino.config from "
+ config.getAbsolutePath()
+ ": "
+ e.getMessage());
}
}
return Collections.emptyMap();
}

@SuppressWarnings("unchecked")
private static Map<String, String> loadFromClasspath(ClassLoader cl) {
if (cl != null) {
try (InputStream in = cl.getResourceAsStream("rhino.config")) {
if (in != null) {
Properties props = new Properties();
props.load(new InputStreamReader(in, StandardCharsets.UTF_8));
System.out.println(
"Loaded "
+ props.size()
+ " proerties from rhino.config in classpath"); // TODO: remove
// these prints
return (Map) props;
}
} catch (IOException e) {
System.err.println("Error loading rhino.config from classpath: " + e.getMessage());
}
}
return Collections.emptyMap();
}

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

/** 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);
}
}
26 changes: 10 additions & 16 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 @@ -387,20 +386,15 @@ public static StackStyle getStackStyle() {

// 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;
}
String style = RhinoConfig.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
}
}
}
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

0 comments on commit dd2bf28

Please sign in to comment.