From: pcm <pcm...@us...> - 2005-05-18 06:41:58
|
Update of /cvsroot/javapathfinder/javapathfinder/src/gov/nasa/jpf In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30521/src/gov/nasa/jpf Modified Files: JPF.java Config.java Log Message: this is the advent of the Debug replacement. We are using a conventional log scheme that actually piggybacks on java.util.logging, even though we don't really use logger hierarchies, we have our own initialization scheme, and we use our own log handler class. The reason for this is that we still want to maintain a single configuration scheme, and we want to be able to log to three different output destinations (hostname:port, file, out/err) without requiring to change class names in a logging.properties file. The handler is still very primitive in terms of output formatting, and the config consists of the following entries # what is our default level for unspecified loggers log.level=<defaultLevel> # where to log to log.output=<filename> | out | err | <hostname>:<port> # logger specific levels log.severe=<logger-pattern>{:<logger-pattern> log.warning=.. log.info=.. log.config=.. log.fine=.. log.finer=.. log.finest=.. There is a new class gov.nasa.jpf.tools.LogConsole that can be used to display socket logging. This is now also meant to be used for the SearchMonitor. With this in place, Debug statements will now be replaced with the standard java.util.logging.Logger API, i.e. static Logger log = JPF.getLogger("gov.nasa.jpf.<whatever>"); .. log.severe(msg); .. log.info(msg); .. There is one caveat to notice: since Config results are reported by means of the logging facility, but the logging is configured via Config (single source), the Config initialization (ctor) is not allowed to produce logging output, but rather has to preserve all states, failures etc. for subsequent reporting (by JPF). This is less than optimal from a design point of view (cyclic dependency), but the user-friendly pinciple of a single config source overrides this. Second caveat is that log output should be event based, not line-by-line, which means there is an increased tendency to see hidden StringBuffer use. If there is a good chance the log level will not be set, this should be wrapped for efficiency reasons in if (logger.isLoggable(Level.<whatever>)) { logger.fine("Blah " + gna + '\n' + "another line"); } The scheme could be extended to enable logger specific output (i.e. one console for vm, another one for a listener etc.) , and the console to allow multiple simultaneous connects, but we leave that for later (if it really makes sense). For now it is important that we can replace the Debug statements. Index: JPF.java =================================================================== RCS file: /cvsroot/javapathfinder/javapathfinder/src/gov/nasa/jpf/JPF.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- JPF.java 12 May 2005 06:25:32 -0000 1.3 +++ JPF.java 18 May 2005 06:41:44 -0000 1.4 @@ -20,8 +20,11 @@ import gov.nasa.jpf.util.CoverageManager; import gov.nasa.jpf.util.Debug; +import gov.nasa.jpf.util.LogManager; import java.io.PrintWriter; +import java.util.logging.Level; +import java.util.logging.Logger; /** @@ -33,7 +36,9 @@ /** JPF version, we read this inlater from default.properties */ static String VERSION = "3.?"; - public Config config; + static Logger logger; + + public Config config; /** * the singleton driver object, so that we can override FactoryMethods @@ -56,6 +61,15 @@ */ Path path; + + /** + * use this one to get a Logger that is initialized via our Config mechanism. Note that + * our own Loggers do NOT pass + */ + public static Logger getLogger (String name) { + return LogManager.getLogger( name); + } + /** * create new JPF object. Note this is always guaranteed to return, but the * Search and/or VM object instantiation might have failed (i.e. the JPF @@ -179,7 +193,7 @@ for ( int i=0; i<args.length; i++) { if (args[i] != null) { if (args[i].charAt(0) == '-') { - Debug.println(Debug.ERROR, "! Warning - unknown command line option: " + args[i]); + logger.warning("unknown command line option: " + args[i]); } else { // this is supposed to be the target class name - everything that follows @@ -191,26 +205,30 @@ } public static void printBanner (Config config) { - System.out.print("Java Pathfinder Model Checker v"); - System.out.print(config.getString("jpf.version", "3.1x")); - System.out.println(" - (C) 1999-2005 RIACS/NASA Ames Research Center"); + if (logger.isLoggable(Level.INFO)) { + logger.info("Java Pathfinder Model Checker v" + + config.getString("jpf.version", "3.1x") + + " - (C) 1999-2005 RIACS/NASA Ames Research Center"); + } } + public static void main(String[] args) { Config conf = createConfig(args); + LogManager.init(conf); + logger = getLogger("gov.nasa.jpf"); printBanner(conf); + LogManager.printStatus(logger); + conf.printStatus(logger); + if (isHelpRequest(args)) { showUsage(); } if (isPrintConfigRequest(args)) { - conf.print(); - } - - if (!conf.gotDefaultProperties()) { - Debug.println(Debug.ERROR, "no default properties found (hardcoded defaults might not work)"); + conf.print(logger); } if (conf.getTargetArg() != null) { Index: Config.java =================================================================== RCS file: /cvsroot/javapathfinder/javapathfinder/src/gov/nasa/jpf/Config.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- Config.java 12 May 2005 06:25:32 -0000 1.3 +++ Config.java 18 May 2005 06:41:44 -0000 1.4 @@ -18,131 +18,171 @@ // package gov.nasa.jpf; -import gov.nasa.jpf.util.Debug; - import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; +import java.io.StringWriter; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; import java.util.Properties; import java.util.TreeSet; +import java.util.logging.Level; +import java.util.logging.Logger; /** - * class that encapsulates property-based JPF configuration. This is mainly - * an associative array with various typed accessors, and a structured - * initialization process. - * This implementation has the design constraint that it does not promote - * symbolic information to concrete types, which means that frequently - * accessed data should be promoted and cached in client classes. This in - * turn means we assume the data is not going to change at runtime. - * Major motivation for this mechanism is to avoid 'Option' classes that - * have concrete type fields, and hence are structural bottlenecks, i.e. - * every parameterized user extension (Heuristics, Scheduler etc.) require - * to update this single class. - * Note that Config is also not thread safe with respect to retrieving - * exceptions that occurrred during instantiation + * class that encapsulates property-based JPF configuration. This is mainly an + * associative array with various typed accessors, and a structured + * initialization process. This implementation has the design constraint that it + * does not promote symbolic information to concrete types, which means that + * frequently accessed data should be promoted and cached in client classes. + * This in turn means we assume the data is not going to change at runtime. + * Major motivation for this mechanism is to avoid 'Option' classes that have + * concrete type fields, and hence are structural bottlenecks, i.e. every + * parameterized user extension (Heuristics, Scheduler etc.) require to update + * this single class. Note that Config is also not thread safe with respect to + * retrieving exceptions that occurrred during instantiation + * + * Another important caveat for both implementation and usage of Config is that + * it is supposed to be our master configuration mechanism, i.e. it is also used + * to configure other core services like logging. This means that Config + * initialization should not depend on these services. Initialization has to + * return at all times, recording potential problems for later handling. This is + * why we have to keep the Config data model and initialization fairly simple + * and robust. */ public class Config extends Properties { - - static final String TARGET_KEY="target"; - static final String TARGET_ARGS_KEY="target_args"; - + + static final String TARGET_KEY = "target"; + + static final String TARGET_ARGS_KEY = "target_args"; + /** - * this class wraps the various exceptions we might encounter esp. - * during reflection instantiation + * this class wraps the various exceptions we might encounter esp. during + * reflection instantiation */ public class Exception extends java.lang.Exception { - public Exception (String msg) { + public Exception(String msg) { super(msg); } - - public Exception (String msg, Throwable cause) { + + public Exception(String msg, Throwable cause) { super(msg, cause); } - - public Exception (String key, Class cls, String failure) { - super( "error instantiating class " + cls.getName() + " for entry \"" + - key + "\":" + failure); + + public Exception(String key, Class cls, String failure) { + super("error instantiating class " + cls.getName() + " for entry \"" + + key + "\":" + failure); } - - public Exception (String key, Class cls, String failure, Throwable cause) { - this(key,cls,failure); + + public Exception(String key, Class cls, String failure, Throwable cause) { + this(key, cls, failure); initCause(cause); } - - public String toString () { - StringBuffer sb = new StringBuffer(); + + public String toString() { + StringBuffer sb = new StringBuffer(); sb.append("JPF configuration error: "); sb.append(getMessage()); - + return sb.toString(); } } - + String fileName; - boolean gotProperties; + + Object source; + + boolean gotProperties; /** - * all arguments that are not <key>=<value> pairs + * all arguments that are not <key>= <value>pairs */ String[] freeArgs; - + /** - * this is our internal defaults ctor + * this is our internal defaults ctor */ - private Config (String alternatePath, Class codeBase) { + private Config(String alternatePath, Class codeBase) { gotProperties = loadFile("default.properties", alternatePath, codeBase); } - - public Config (String[] args, String fileName, String alternatePath, Class codeBase) { - super(new Config( alternatePath, (codeBase == null) ? codeBase = getCallerClass(1) : codeBase)); - + + public Config(String[] args, String fileName, String alternatePath, + Class codeBase) { + super(new Config(alternatePath, + (codeBase == null) ? codeBase = getCallerClass(1) : codeBase)); + this.fileName = fileName; gotProperties = loadFile(fileName, alternatePath, codeBase); - + processArgs(args); normalizeValues(); } - - public boolean gotDefaultProperties () { + + public boolean gotDefaultProperties() { if (defaults != null && defaults instanceof Config) { - return ((Config)defaults).gotProperties(); + return ((Config) defaults).gotProperties(); } return false; } - - public boolean gotProperties () { + + public boolean gotProperties() { return gotProperties; } - - public String getFileName () { + + public String getFileName() { return fileName; } - - public String[] getArgs () { + + public String getSourceName() { + if (source == null) { + return null; + } else if (source instanceof File) { + return ((File) source).getAbsolutePath(); + } else if (source instanceof URL) { + return source.toString(); + } else { + return source.toString(); + } + } + + public String getDefaultsSourceName() { + if ((defaults != null) && (defaults instanceof Config)) { + return ((Config) defaults).getSourceName(); + } else { + return null; + } + } + + public Object getSource() { + return source; + } + + public String[] getArgs() { return freeArgs; } - - public void throwException (String msg) throws Exception { + + public void throwException(String msg) throws Exception { throw new Exception(msg); } - + /** * find callers class - * @param up - levels upwards from our caller (NOT counting ourselves) + * + * @param up - + * levels upwards from our caller (NOT counting ourselves) * @return caller class, null if illegal 'up' value */ - public static Class getCallerClass (int up) { - int idx = up+1; // don't count ourselves - + public static Class getCallerClass(int up) { + int idx = up + 1; // don't count ourselves + StackTraceElement[] st = (new Throwable()).getStackTrace(); - if ((up <0) || (idx >= st.length)) { + if ((up < 0) || (idx >= st.length)) { return null; } else { try { @@ -152,7 +192,7 @@ } } } - + boolean loadFile(String fileName, String alternatePath, Class codeBase) { InputStream is = null; @@ -162,23 +202,23 @@ if (!f.exists()) { // Ok, try alternatePath, if fileName wasn't absolute if (!f.isAbsolute() && (alternatePath != null)) { - f = new File(alternatePath, fileName); + f = new File(alternatePath, fileName); } } - + if (f.exists()) { + source = f; is = new FileInputStream(f); - Debug.println(Debug.MESSAGE, "reading config from file: " + f.getAbsolutePath()); - } else { + } else { // if there is no file, try to load as a resource (jar) Class clazz = (codeBase != null) ? codeBase : Config.class; is = clazz.getResourceAsStream(fileName); if (is != null) { - Debug.println(Debug.MESSAGE, "reading config from resource: " + fileName); + source = clazz.getResource(fileName); // a URL } } - if (is != null){ + if (is != null) { load(is); return true; } @@ -190,23 +230,25 @@ } /** - * extract all "+<key>=<val>" parameters, store/overwrite them in our + * extract all "+ <key>= <val>" parameters, store/overwrite them in our * dictionary, collect all other parameters in a String array - * @param args - array of String parameters to process + * + * @param args - + * array of String parameters to process */ void processArgs(String[] args) { int i; String arg; ArrayList list = new ArrayList(); - for (i=0; i<args.length; i++) { + for (i = 0; i < args.length; i++) { String a = args[i]; if (a != null) { if (a.charAt(0) == '+') { int idx = a.indexOf("="); if (idx > 0) { - setProperty( a.substring(1, idx), a.substring(idx + 1)); - } else { + setProperty(a.substring(1, idx), a.substring(idx + 1)); + } else { setProperty(a.substring(1), ""); } } else { @@ -217,18 +259,20 @@ int n = list.size(); freeArgs = new String[n]; - for (i=0; i<n; i++) { + for (i = 0; i < n; i++) { freeArgs[i] = (String) list.get(i); } } /** - * return the index of the first free argument that does not start with an hyphen + * return the index of the first free argument that does not start with an + * hyphen */ - public int getNonOptionArgIndex () { - if ((freeArgs == null) || (freeArgs.length == 0)) return -1; - - for (int i=0; i<freeArgs.length; i++) { + public int getNonOptionArgIndex() { + if ((freeArgs == null) || (freeArgs.length == 0)) + return -1; + + for (int i = 0; i < freeArgs.length; i++) { String a = freeArgs[i]; if (a != null) { char c = a.charAt(0); @@ -237,15 +281,15 @@ } } } - + return -1; } - + /** - * return the first non-option freeArg, or 'null' if there is none - * (usually denotes the application to start) + * return the first non-option freeArg, or 'null' if there is none (usually + * denotes the application to start) */ - public String getTargetArg () { + public String getTargetArg() { int i = getNonOptionArgIndex(); if (i < 0) { return getString(TARGET_KEY); @@ -253,14 +297,14 @@ return freeArgs[i]; } } - + /** - * return all args that follow the first non-option freeArgs - * (usually denotes the parametsr to pass to the application to start) + * return all args that follow the first non-option freeArgs (usually denotes + * the parametsr to pass to the application to start) */ - public String[] getTargetArgParameters () { + public String[] getTargetArgParameters() { int i = getNonOptionArgIndex(); - if (i >= freeArgs.length-1) { + if (i >= freeArgs.length - 1) { String[] a = getStringArray(TARGET_ARGS_KEY); if (a != null) { return a; @@ -268,70 +312,48 @@ return new String[0]; } } else { - int n = freeArgs.length - (i+1); + int n = freeArgs.length - (i + 1); String[] a = new String[n]; - System.arraycopy(freeArgs, i+1, a, 0, n); + System.arraycopy(freeArgs, i + 1, a, 0, n); return a; } } - - public String getArg (int i) { - if (freeArgs == null) return null; - if (freeArgs.length-1 < i) return null; - if (i < 0) return null; - + + public String getArg(int i) { + if (freeArgs == null) + return null; + if (freeArgs.length - 1 < i) + return null; + if (i < 0) + return null; + return freeArgs[i]; } - - public void print () { - PrintWriter pw = new PrintWriter(System.out, true); - pw.println("----------- dictionary contents"); - - // just how much do you have to do to get a sorted printout :( - TreeSet kset = new TreeSet(); - for (Enumeration e=propertyNames(); e.hasMoreElements();) { - kset.add(e.nextElement()); - } - for (Iterator it = kset.iterator(); it.hasNext(); ) { - String key = (String)it.next(); - Object val = getProperty(key); - pw.print(key); - pw.print(" = "); - pw.println(val); - } - if ((freeArgs != null) && (freeArgs.length > 0)) { - pw.println("----------- free arguments"); - for (int i=0; i<freeArgs.length; i++) { - pw.println(freeArgs[i]); - } - } - } - /** * turn standard type values (boolean etc.) into common formats - * ("true"/"false" for booleans) + * ("true"/"false" for booleans) */ - void normalizeValues () { - for (Enumeration keys = keys(); keys.hasMoreElements(); ){ + void normalizeValues() { + for (Enumeration keys = keys(); keys.hasMoreElements();) { String k = (String) keys.nextElement(); String v = getProperty(k); - if ("true".equalsIgnoreCase(v) || "t".equalsIgnoreCase(v) || - "yes".equalsIgnoreCase(v) || "y".equalsIgnoreCase(v)){ + if ("true".equalsIgnoreCase(v) || "t".equalsIgnoreCase(v) + || "yes".equalsIgnoreCase(v) || "y".equalsIgnoreCase(v)) { put(k, "true"); - } else if ("false".equalsIgnoreCase(v) || "f".equalsIgnoreCase(v) || - "no".equalsIgnoreCase(v) || "n".equalsIgnoreCase(v)) { + } else if ("false".equalsIgnoreCase(v) || "f".equalsIgnoreCase(v) + || "no".equalsIgnoreCase(v) || "n".equalsIgnoreCase(v)) { put(k, "false"); } } } - - public boolean getBoolean (String key) { + + public boolean getBoolean(String key) { String v = getProperty(key); return (v != null) && ("true".equals(v)); } - - public boolean getBoolean (String key, boolean def) { + + public boolean getBoolean(String key, boolean def) { String v = getProperty(key); if (v != null) { return ("true".equals(v)); @@ -339,12 +361,12 @@ return def; } } - - public int getInt (String key) { + + public int getInt(String key) { return getInt(key, 0); } - public int getInt (String key, int defValue) { + public int getInt(String key, int defValue) { String v = getProperty(key); if (v != null) { try { @@ -353,15 +375,15 @@ return defValue; } } - - return defValue; + + return defValue; } - - public long getLong (String key) { + + public long getLong(String key) { return getLong(key, 0L); } - - public long getLong (String key, long defValue) { + + public long getLong(String key, long defValue) { String v = getProperty(key); if (v != null) { try { @@ -370,15 +392,15 @@ return defValue; } } - - return defValue; + + return defValue; } - public String getString (String key) { - return getProperty(key); + public String getString(String key) { + return getProperty(key); } - - public String getString (String key, String defValue) { + + public String getString(String key, String defValue) { String s = getProperty(key); if (s != null) { return s; @@ -386,48 +408,50 @@ return defValue; } } - + /** - * same as getString(), except of that we look for '${<key>}' patterns, and replace them - * with values if we find corresponding keys. Expansion is not done recursively (but could be) + * same as getString(), except of that we look for '${ <key>}' patterns, and + * replace them with values if we find corresponding keys. Expansion is not + * done recursively (but could be) */ - public String getExpandedString (String key) { + public String getExpandedString(String key) { int i, j = 0; String s = getString(key); if (s == null || s.length() == 0) { return s; } - + while ((i = s.indexOf("${", j)) >= 0) { if ((j = s.indexOf('}', i)) > 0) { - String k = s.substring(i+2, j); + String k = s.substring(i + 2, j); String v = getString(k, ""); if (v != null) { - s = s.substring(0, i) + v + s.substring(j+1, s.length()); + s = s.substring(0, i) + v + s.substring(j + 1, s.length()); j = i + v.length(); } else { - s = s.substring(0, i) + s.substring(j+1, s.length()); - j = i; + s = s.substring(0, i) + s.substring(j + 1, s.length()); + j = i; } } } return s; } - + /** - * return memory size in bytes, or 'defValue' if not in dictionary. Encoding can have a 'M' or 'k' postfix, - * values have to be positive integers (decimal notation) + * return memory size in bytes, or 'defValue' if not in dictionary. Encoding + * can have a 'M' or 'k' postfix, values have to be positive integers (decimal + * notation) */ - public long getMemorySize (String key, long defValue) { + public long getMemorySize(String key, long defValue) { String v = getProperty(key); - long sz = defValue; - + long sz = defValue; + if (v != null) { - int n = v.length()-1; + int n = v.length() - 1; try { char c = v.charAt(n); - + if ((c == 'M') || (c == 'm')) { sz = Long.parseLong(v.substring(0, n)) << 20; } else if ((c == 'K') || (c == 'k')) { @@ -435,134 +459,135 @@ } else { sz = Long.parseLong(v); } - + } catch (NumberFormatException nfx) { return defValue; } } - + return sz; } - - public String[] getStringArray (String key) { + + public String[] getStringArray(String key) { String v = getProperty(key); if (v != null) { - return v.split("[:;, ]"); + return v.split("[:;, ]+"); } - + return null; } - - public Class getClass (String key) throws Exception { + + public Class getClass(String key) throws Exception { String v = getProperty(key); - if ((v != null) && (v.length() >0)) { + if ((v != null) && (v.length() > 0)) { try { return Class.forName(v); } catch (ClassNotFoundException cfx) { - throw new Exception( "class not found " + v); + throw new Exception("class not found " + v); } catch (ExceptionInInitializerError ix) { - throw new Exception("class initialization of " + v + " failed: " + ix, ix); + throw new Exception("class initialization of " + v + " failed: " + ix, + ix); } } - + return null; } - - public Class getEssentialClass (String key) throws Exception { + + public Class getEssentialClass(String key) throws Exception { Class cls = getClass(key); if (cls == null) { throw new Exception("no classname entry for: \"" + key + "\""); } - + return cls; } - - public Class[] getClasses (String key) throws Exception { + + public Class[] getClasses(String key) throws Exception { String[] v = getStringArray(key); if (v != null) { int n = v.length; Class[] a = new Class[n]; - for (int i=0; i<n; i++) { + for (int i = 0; i < n; i++) { try { a[i] = Class.forName(v[i]); } catch (ClassNotFoundException cnfx) { - throw new Exception( "class not found " + v[i]); + throw new Exception("class not found " + v[i]); } catch (ExceptionInInitializerError ix) { - throw new Exception("class initialization of " + v[i] + " failed: " + ix, ix); + throw new Exception("class initialization of " + v[i] + " failed: " + + ix, ix); } } - + return a; } - + return null; } - - public Object[] getInstances (String key, Class type) throws Exception { + + public Object[] getInstances(String key, Class type) throws Exception { Class[] c = getClasses(key); if (c != null) { Class[] argTypes = { Config.class }; Object[] args = { this }; Object[] a = new Object[c.length]; - - for (int i=0; i<c.length; i++) { + + for (int i = 0; i < c.length; i++) { a[i] = getInstance(key, c[i], type, argTypes, args); } - + return a; } - + return null; } - - public Object getInstance (String key, Class type) throws Exception { + + public Object getInstance(String key, Class type) throws Exception { Class[] argTypes = { Config.class }; Object[] args = { this }; - - return getInstance( key, type, argTypes, args); + + return getInstance(key, type, argTypes, args); } - - public Object getInstance (String key, Class type, Class[] argTypes, Object[] args) throws Exception { + + public Object getInstance(String key, Class type, Class[] argTypes, + Object[] args) throws Exception { Class cls = getClass(key); if (cls != null) { - return getInstance( key, cls, type, argTypes, args); + return getInstance(key, cls, type, argTypes, args); } else { return null; } } - public Object getEssentialInstance (String key, Class type) throws Exception { + public Object getEssentialInstance(String key, Class type) throws Exception { Class[] argTypes = { Config.class }; Object[] args = { this }; - return getEssentialInstance( key, type, argTypes, args); + return getEssentialInstance(key, type, argTypes, args); } - public Object getEssentialInstance (String key, Class type, Class[] argTypes, Object[] args) throws Exception { + public Object getEssentialInstance(String key, Class type, Class[] argTypes, + Object[] args) throws Exception { Class cls = getEssentialClass(key); - return getInstance(key,cls,type,argTypes,args); + return getInstance(key, cls, type, argTypes, args); } - + /** - * this is our private instantiation workhorse - * try to instantiate an object of class 'cls' by using the following ordered set of ctors - * 1. <cls> (<argTypes>) - * 2. <cls> (Config) - * 3. <cls> () - * if all of that fails, or there was a 'type' provided the instantiated object does not - * comply with, return null + * this is our private instantiation workhorse try to instantiate an object of + * class 'cls' by using the following ordered set of ctors 1. <cls>( + * <argTypes>) 2. <cls>(Config) 3. <cls>() if all of that fails, or there was + * a 'type' provided the instantiated object does not comply with, return null */ - Object getInstance (String key, Class cls, Class type, - Class[] argTypes, Object[] args) throws Exception { + Object getInstance(String key, Class cls, Class type, Class[] argTypes, + Object[] args) throws Exception { Object o = null; Constructor ctor = null; - + if (cls == null) { return null; } - + do { try { - ctor = cls.getConstructor(argTypes); + ctor = cls.getConstructor(argTypes); o = ctor.newInstance(args); } catch (NoSuchMethodException nmx) { if (argTypes.length >= 1) { @@ -571,55 +596,56 @@ argTypes = new Class[1]; argTypes[0] = Config.class; args = new Object[1]; - args[0] = this; + args[0] = this; } else { // fallback 2: try the default ctor argTypes = new Class[0]; - args = new Object[0]; + args = new Object[0]; } } else { // Ok, there is no suitable ctor, bail out throw new Exception(key, cls, "no suitable ctor found"); } } catch (IllegalAccessException iacc) { - throw new Exception( key, cls, "\n> ctor not accessible: " + - getMethodSignature(ctor)); + throw new Exception(key, cls, "\n> ctor not accessible: " + + getMethodSignature(ctor)); } catch (IllegalArgumentException iarg) { - throw new Exception( key, cls, "\n> illegal constructor arguments: " + - getMethodSignature(ctor)); + throw new Exception(key, cls, "\n> illegal constructor arguments: " + + getMethodSignature(ctor)); } catch (InvocationTargetException ix) { Throwable tx = ix.getTargetException(); if (tx instanceof Config.Exception) { - throw new Exception( tx.getMessage() + - "\n> used within \"" + key + "\" instantiation of " - + cls); + throw new Exception(tx.getMessage() + "\n> used within \"" + key + + "\" instantiation of " + cls); } else { - throw new Exception( key, cls, "\n> exception in " + - getMethodSignature(ctor) + ":\n>> " + tx, tx); + throw new Exception(key, cls, "\n> exception in " + + getMethodSignature(ctor) + ":\n>> " + tx, tx); } } catch (InstantiationException ivt) { - throw new Exception( key, cls, "\n> abstract class cannot be instantiated"); + throw new Exception(key, cls, + "\n> abstract class cannot be instantiated"); } catch (ExceptionInInitializerError eie) { - throw new Exception( key, cls, "\n> static initialization failed:\n>> " + eie.getException(), - eie.getException()); + throw new Exception(key, cls, "\n> static initialization failed:\n>> " + + eie.getException(), eie.getException()); } } while (o == null); - + // check type if ((type != null) && !type.isInstance(o)) { - throw new Exception( key, cls, "\n> instance not of type: " + type.getName()); + throw new Exception(key, cls, "\n> instance not of type: " + + type.getName()); } - + return o; } - String getMethodSignature (Constructor ctor) { + String getMethodSignature(Constructor ctor) { StringBuffer sb = new StringBuffer(); sb.append(ctor.getName()); sb.append('('); Class[] argTypes = ctor.getParameterTypes(); - for (int i=0; i<argTypes.length; i++) { - if (i >0) { + for (int i = 0; i < argTypes.length; i++) { + if (i > 0) { sb.append(','); } sb.append(argTypes[i].getName()); @@ -627,66 +653,95 @@ sb.append(')'); return sb.toString(); } - + /** * check if any of the freeArgs matches a regular expression - * @param regex - regular expression to check for + * + * @param regex - + * regular expression to check for * @return true if found, false if not found or no freeArgs */ - public boolean hasArg (String regex) { - if (freeArgs == null) { - return false; - } - - for (int i=0; i<freeArgs.length; i++) { - if (freeArgs[i].matches(regex)) { - return true; - } - } - - return false; + public boolean hasArg(String regex) { + if (freeArgs == null) { + return false; + } + + for (int i = 0; i < freeArgs.length; i++) { + if (freeArgs[i].matches(regex)) { + return true; + } + } + + return false; } - public boolean hasValue (String key) { + public boolean hasValue(String key) { String v = getProperty(key); return ((v != null) && (v.length() > 0)); } - - public boolean hasValueIgnoreCase (String key, String value) { + + public boolean hasValueIgnoreCase(String key, String value) { String v = getProperty(key); if (v != null) { return v.equalsIgnoreCase(value); } - + return false; } - - public int getChoiceIndexIgnoreCase (String key, String[] choices) { + + public int getChoiceIndexIgnoreCase(String key, String[] choices) { String v = getProperty(key); - + if ((v != null) && (choices != null)) { - for (int i=0; i<choices.length; i++) { + for (int i = 0; i < choices.length; i++) { if (v.equalsIgnoreCase(choices[i])) { return i; } } } - + return -1; } - - public void printContents (PrintWriter ps) { - ps.println("----- config options -----"); - list(ps); - ps.println("----- free arguments -----"); - if (freeArgs == null) { - ps.println("<null>"); - } else { - for (int i=0; i<freeArgs.length; i++) { - ps.print(freeArgs[i]); - ps.print(' '); - } - ps.println(); - } + + public void print(Logger log) { + if (log.isLoggable(Level.CONFIG)) { + StringWriter sw = new StringWriter(1024); + PrintWriter pw = new PrintWriter(sw, true); + pw.println("----------- dictionary contents"); + + // just how much do you have to do to get a sorted printout :( + TreeSet kset = new TreeSet(); + for (Enumeration e = propertyNames(); e.hasMoreElements();) { + kset.add(e.nextElement()); + } + for (Iterator it = kset.iterator(); it.hasNext();) { + String key = (String) it.next(); + Object val = getProperty(key); + pw.print(key); + pw.print(" = "); + pw.println(val); + } + + if ((freeArgs != null) && (freeArgs.length > 0)) { + pw.println("----------- free arguments"); + for (int i = 0; i < freeArgs.length; i++) { + pw.println(freeArgs[i]); + } + } + + log.config(sw.toString()); + } + } + + public void printStatus(Logger log) { + log.config("configuration initialized from: " + getSourceName()); + + Config def = (Config) defaults; + if (def.source == null) { + log.warning("no defaults.properties found"); + } else { + log.config("default configuration initialized from: " + + def.getSourceName()); + } } } |