📄 property.java
字号:
package org.xmlBlaster.util.property;import org.xmlBlaster.util.FileLocator;import org.xmlBlaster.util.Global;import org.xmlBlaster.util.ReplaceVariable;import org.xmlBlaster.util.XmlBlasterException;import org.xmlBlaster.util.context.ContextNode;import org.xmlBlaster.util.def.ErrorCode;import java.io.*;import java.util.Properties;import java.util.Enumeration;import java.util.StringTokenizer;import java.util.Vector;import java.util.Map;import java.util.TreeMap;import java.util.HashMap;import java.util.Iterator;import java.util.Set;import java.util.HashSet;//import java.util.logging.Logger;import java.net.URL;import java.applet.Applet;/** * Handling properties for your project, e.g. your property file $HOME/cool.properties and command line properties. * <br /> * <p /> * <b>Variable replacement</b> * <p /> * All environment variable (e.g. ${java.io.tmpdir}="/tmp", ${file.separator}="/") can be used * in the properties file and are replaced on occurrence.<br /> * Further, you can use any of your own variables from the properties file or from the * command line with curly braces: ${...}.<br /> * Example:<br /> * A user may specify the MOMS_NAME and use it later as a variable as follows:<br /> * <pre> java -DMOMS_NAME=Joan ...</pre><br /> * or in the properties file:<br /> * <pre> MOMS_NAME=Joan</pre> * or on the command line:<br /> * <pre> java org.MyApp -MOMS_NAME Joan</pre><br /> * and now use it like<br /> * <pre> MOMS_RECIPY=Strawberry cake from ${MONS_NAME} is the best.</pre> * which results to<br /> * <pre> MOMS_RECIPY=Strawberry cake from Joan is the best.</pre> * The maximum replacement (nesting) depth is 50. * <p /> * A user may specify the PROJECT_HOME environment variable, the property file will be * searched there as well. * <p /> * NOTE: These are often helpful variables * <ul> * <li>${user.dir} = The current directory </li> * <li>${user.home} = The users home directory</li> * </ul> * user.dir and user.home are without a path separator at the end * <p /> * The property file settings are the weakest, they are overwritten * by system property settings and finally by command line arguments. * <p> * NOTE: If a variable like ${XYZ} is not resolved an exception is thrown, * you can use the markup $_{XYZ} to avoid the exception in which case the * $_{XYZ} remains as is. * </p> * * <br /> * <p> * <b>Searching the property file</b> * <p /> * This class searches the given property file in typical directories (see findPath() method). * It is searched for in the following order: * <ol> * <li>Command line parameter '-propertyFile', e.g. "-propertyFile /tmp/xy.properties"</li> * <li>Local directory user.dir</li> * <li>In $PROJECT_HOME, e.g. "/opt/myproject"</li> * <li>In user.home - $HOME</li> * <li>In CLASSPATH - $CLASSPATH from your environment. You can stuff the property file into your project jar file</li> * <li>In java.home/lib/ext directory, e.g. "/opt/jdk1.2.2/jre/lib/ext"<br /> * You may use this path for Servlets, demons etc.</li> * <li>In java.home directory, e.g. "/opt/jdk1.2.2/jre/lib"<br /> * You may use this path for Servlets, demons etc.</li> * <li>Fallback: "\jutils" on DOS-WIN$ or "/usr/local/jutils" on UNIX</li> * </ol> * * <br /> * <p> * <b>Array support</b> * <br /> * <br /> * We look for keys containing [] brackets and collect them into a map * </p> * <pre> * val[A]=AAA * val[B]=BBB * </pre> * Accessing the map with the array praefix (here it is "val") * <pre> * Map map = get("val", (Map)null); * </pre> * returns a Map containing keys { "A", "B" } * and values { "AAA", "BBB" } * <br /> * <br /> * Two dimensional arrays are supported as well: * <pre> * val[C][1]=cccc -> map entry with key "C:1" and value "cccc" * </pre> * * * <p> * <b>Very simple array values</b> * <br /> * <br /> * Values of properties may have a separator, example: * </p> * <pre> * names=Joe,Jack,Averell * </pre> * Access the names split to an array: * <pre> * String[] arr = prop.get("array", new String[0], ","); * //arr[0] contains "Joe", arr[1] contains "Jack" and arr[2] contains "Averell" * </pre> * * <br /> * <p> * <b>Listening on property changes</b> * <br /> * <br /> * You can listen on added properties, changed properties or on removed properties, the following code * snippet shows how to do it: * </p> * <pre> * I_PropertyChangeListener ll = prop.addPropertyChangeListener(theKey, new I_PropertyChangeListener() { * public void propertyChanged(PropertyChangeEvent ev) { * System.out.println("propertyChanged: " + ev.toString()); * // key = ev.getKey(); * // old = ev.getOldValue(); * // value = ev.getNewValue(); * } * } * ); * </pre> * Note that setting a property with an equal value is not triggering an event. * * <p /> * JDK 1.1 or higher only. * @author Marcel Ruff * @author Michael Winkler, doubleSlash Net-Business GmbH * @see testsuite.TestProperty */public class Property implements Cloneable { private final static String ME = "Property"; //private static Logger log = Logger.getLogger(Property.class.getName()); private static String separator = null; /** The users home directory */ private static String userHome = null; /** current directory, can it change for each instance or is it final in the JVM? */ private String currentPath = null; /** user supplied path in PROJECT_HOME */ private String projectHomePath = null; /** The java home ext directory, e.g. /opt/jdk1.2.2/jre/lib/ext */ private static String javaHomeExt = null; /** The java home directory, e.g. /opt/jdk1.2.2/jre/lib */ private static String javaHome = null; /** The supplied file name, e.g. cool.properties */ private String propertyFileName = null; /** Holding all found properties */ private Properties properties = null; private final Properties dummyProperties = new Properties(); /** Holding all maps from array properties, e.g. prop[A] */ private Map propMap = new TreeMap(); /** Scan system environment variables? */ private boolean scanSystemProperties = true; /** Replace occurrences of ${key} with the value of key */ private boolean replaceVariables = true; /** Scan for properties with square brackets [] and handle them as array */ private boolean supportArrays = true; /** Was the option '--help' or '-help' or '-h' or '-?' specified? */ private boolean wantsHelp = false; /** Applet handle or null */ private Applet applet = null; /** Map containing as key a property key and as value a * Set of listeners (I_PropertyChangeListener) which wants to be notified on changes */ private HashMap changeListenerMap = new HashMap(); public static final int MAX_NEST = 50; public static final int DEFAULT_VERBOSE=1; /** * Set the verbosity when loading properties (outputs with System.out). * <p /> * 0=nothing, 1=info, 2=trace, configure with * <pre> * java -Dproperty.verbose 2 * * java MyApp -property.verbose 2 * </pre> */ public int verbose = DEFAULT_VERBOSE; /** * Construct a property container from supplied property file and args array. * <p /> * @param fileName The property file name, e.g. "project.properties" * @param scanSystemProperties Scan System.getProperties() as well, you can * add variable to JVM like: java -DmyName=Joe ... * @param args A String array with properties, usually from command line, e.g. * java myApp -logging FINE -name Joe * @param replaceVariables true: replace occurrences of ${key} with the value of key */ public Property(String fileName, boolean scanSystemProperties, String[] args, boolean replaceVariables) throws XmlBlasterException { init(fileName, scanSystemProperties, args, replaceVariables, supportArrays); } /** * Returns the subset of properties found in the properties starting * with the specified prefix. * @param prefix The prefix to use. If null is passed, then all properties * are returned * * @return the subset of properties found. The keys are stripped from their * prefix. The returned keys are returned in alphabetical order. */ public Map getPropertiesStartingWith(String prefix) { TreeMap map = new TreeMap(); synchronized (this.properties) { Enumeration iter = this.properties.keys(); while (iter.hasMoreElements()) { String key = ((String)iter.nextElement()).trim(); if (prefix == null || key.startsWith(prefix)) { Object val = this.properties.get(key); if (prefix != null) key = key.substring(prefix.length()); map.put(key, val); } } } synchronized (this.propMap) { Iterator iter = this.propMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = ((Map.Entry)iter.next()); String key = (String)entry.getKey(); Object val = entry.getValue(); if (prefix == null || key.startsWith(prefix)) { if (prefix != null) key = key.substring(prefix.length()); map.put(key, val); } } } return map; } /** * Returns a map containing all properties of the specified context. * * /node/heron/logging, FINE, * /node/heron/logging/org.xmlBlaster.engine.level, FINE * * Suppose you want to retrieve these values, then the parentCtx is /node/heron and * the shortKey is logging. If you want to retrieve both values you have to pass keyForDefault * which is not null (for example you will pass '__default'. Then you will get: * * __default = FINE * org.xmlBlaster.engine.level = FINE * * two entries. If you pass keyForDefault = null you will only get the second value * * @param ctx * @param shortKey * @param keyForDefault, can be null in which case it will not return the default value. * @return */ public Map getPropertiesForContextNode(ContextNode parentCtx, String shortKey, String keyForDefault) { Map general = getPropertiesStartingWith(shortKey + ContextNode.SEP); if (keyForDefault != null) { Object def = this.properties.getProperty(shortKey); if (def != null) general.put(keyForDefault, def); } if (parentCtx == null) return general; String completePropName = parentCtx.getAbsoluteName() + ContextNode.SEP + shortKey; Map specific1 = getPropertiesStartingWith(completePropName + ContextNode.SEP); Object tmp = this.properties.get(completePropName); if (tmp != null) specific1.put(completePropName, tmp); if (keyForDefault != null) { Object def = this.properties.getProperty(completePropName); if (def != null) specific1.put(keyForDefault, def); } String relativePropName = parentCtx.getRelativeName() + ContextNode.SEP + shortKey; Map specific2 = getPropertiesStartingWith(relativePropName + ContextNode.SEP); if (keyForDefault != null) { Object def = this.properties.getProperty(relativePropName); if (def != null) specific2.put(keyForDefault, def); } Map specific3 = getPropertiesStartingWith(ContextNode.SEP + relativePropName + ContextNode.SEP); if (keyForDefault != null) { Object def = this.properties.getProperty(ContextNode.SEP + relativePropName); if (def != null) specific3.put(keyForDefault, def); } general.putAll(specific1); general.putAll(specific2); general.putAll(specific3); return general; } /** * Construct a property container from supplied property file and enumeration. * <p /> * Usually used by servlets (ServletConfig conf):<br /> * <pre> * Properties extraProps = new Properties(); * Enumeration e = conf.getInitParameterNames(); * while (e.hasMoreElements()) { * String name = (String)e.nextElement(); * extraProps.put(name, conf.getInitParameter(name)); * } * </pre> * * @param fileName The property file name, e.g. "project.properties" * @param scanSystemProperties Scan System.getProperties() as well, you can * add variable to JVM like: java -DmyName=Joe ... * @param args A String array with properties, usually from command line, e.g. * java myApp -trace true -name Joe
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -