📄 basicproperties.java
字号:
/*
* (c) Copyright Hewlett-Packard Company 2001
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE and no warranty
* that the program does not infringe the Intellectual Property rights of
* a third party. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*/
package jade.util;
//#MIDP_EXCLUDE_FILE
// DO NOT ADD ANY IMPORTS FOR CLASSES NOT DEFINED IN J2ME CLDC!
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Date;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.io.PrintStream;
import java.io.IOException;
import java.io.EOFException;
import jade.util.leap.Properties;
/**
* Provides the foundation class for property management. It
* is designed to be usable in the restrictive J2ME CLDC environment. It
* provides enhanced property management as well as providing support for
* values containing strings of the form <b><tt>${key}</tt></b>.
* <p>
* A property may be set such that it can't be altered by ending the key value
* with a '!'. For example:
* <pre>
* agentClass!=com.hp.agent.Foo
* </pre>
* One still references this property as ${agentClass}.
* <p>
* This class relates to four others as follows:
* <ol>
* <li> ImportableProperties - This abstract class extends BasicProperties and
* serves as a basis for supporting the ability to import properties from files.
* Those files may also contain further import dirrectives. It is also usable in
* the restrictive J2ME CLDC environment. Since file support will be handled
* differently in different environments, it contains one abstract method
* <b><tt>fileReader</tt></b> which given the name of a file (its URL) must
* return a Reader object. Extending classes will provide that method in a
* suitable fashion. For example, in the desktop world this would be:
* <pre>
* return new InputStreamReader(new FileInputStream(aFileName));
* </pre>
* whereas in the CLDC environment it would be:
* <pre>
* return new InputStreamReader(Connector.openInputStream(aFileName));
* </pre>
* <li> EnhancedProperties - Provides a concrete implementation of ImportableProperties
* useable in the J2SE (desktop) world.
* <li> ExpandedProperties - Extends EnhancedProperties and adds support for fetching
* system environment variables (those usable from the OS shell). This class would need
* to be carefully considered in different environments.
* <li> PropertiesException - Extends RuntimeException and is thrown under various
* error conditions by these classes.
</ol>
* Properties presented via parseArgs or read from an input stream may be specified in
* either of two formats:
* <b>key=value</b> or <b>key:value</b>.
* To substitute the value of a key in a value use the format <b><tt>${key}</tt></b>.
* @author Dick Cowan - HP Labs
*/
public class BasicProperties extends Properties {
boolean CRState = false;
Hashtable keyNames = null; // for detecting circular definitions
Vector sortVector = null; // only used by sortedKeys
/**
* For testing. Simply pass command line arguments to constructor then display
* all key=value pairs using sorted enumeration.
*/
public static void main(String[] args) {
BasicProperties prop = new BasicProperties(args);
prop.list(System.out);
}
/**
* Construct empty property collection.
*/
public BasicProperties() {
}
/**
* Construct properties from arguments.
* @param theArgs The applications original arguments.
*/
public BasicProperties(String[] theArgs) {
this();
parseArgs(theArgs);
}
/**
* Add properties from a specified InputStream. Properties
* will be added to any existing collection.
* @param aFileName The name of the file.
* @throws IOException if anything goes wrong.
*/
public synchronized void load(InputStream inStream) throws IOException {
addFromReader(new InputStreamReader(inStream, "8859_1"));
}
/**
* Writes this property collection to the output stream in a format suitable for
* loading into a Properties table using the load method.
* @param out An output stream.
* @param header A description of the property list - may be null.
* @throws IOException if anything goes wrong.
*/
public synchronized void store(OutputStream out, String header) throws IOException
{
String lineSeparator = System.getProperty("line.separator");
Writer writer = new OutputStreamWriter(out, "8859_1");
if (header != null) {
writer.write("#" + header);
writer.write(lineSeparator);
}
writer.write("#" + new Date().toString());
writer.write(lineSeparator);
for (Enumeration e = sortedKeys(); e.hasMoreElements();) {
String key = (String)e.nextElement();
Object data = super.get(key);
if (data != null) {
writer.write(key + "=" + data.toString());
writer.write(lineSeparator);
}
}
writer.flush();
}
/**
* Return a sorted enumertion of this properties keys.
* @return Enumeration Sorted enumeration.
*/
public synchronized Enumeration sortedKeys() {
if (sortVector == null) {
sortVector = new Vector();
} else {
sortVector.removeAllElements();
}
for (Enumeration e = super.keys(); e.hasMoreElements(); ) {
String key = (String) e.nextElement();
int i = 0;
while (i < sortVector.size()) {
if (key.compareTo((String)sortVector.elementAt(i)) < 0) {
break;
}
i++;
}
sortVector.insertElementAt(key, i);
}
return new Enumeration() {
Enumeration en = BasicProperties.this.sortVector.elements();
public boolean hasMoreElements() {
return en.hasMoreElements();
}
public Object nextElement() {
return en.nextElement();
}
};
}
/**
* Parse the arguments and place them in this properties collection.
* This method uses a number of protected helper methods to accomplish
* its parsing. This enables an extending class to easily change its
* behavior without completely replacing this method. For additional
* understanding see prepareArgs, isCandidate, specialHandling, isolateKey,
* isolateValue, and nextArgIndex.
* @param args The array of arguments - typically from a command line.
* If null, this method does nothing.
*/
public synchronized void parseArgs(String[] args) {
if (args != null) {
int argIndex = 0;
String[] newArgs = prepareArgs(args);
while (argIndex < newArgs.length) {
String arg = newArgs[argIndex];
parseArgument(arg);
argIndex = nextArgIndex(newArgs, argIndex);
if ((argIndex < 0) || (argIndex >= newArgs.length)) {
return; // stop parsing
}
}
}
}
/**
* Called to handle either an argument or line from an import file.
* @param arg The argument or line. Typically of the form key=value.
*/
protected void parseArgument(String arg) {
if (isCandidate(arg)) {
String key = isolateKey(arg);
String value = isolateValue(arg);
if (storableProperty(key, value)) {
setProperty(key, value);
}
} else {
specialHandling(arg);
}
}
/**
* Called by parseArgs to perform any preprocessing of the arguments.
* By default this method does nothing and simply returns the parameter its passed.
* However an extending class could override this method to modify the original
* arguments if necessary.
* @param args The original arguments passed to parseArgs.
* @return String[] The collection which parseArgs will actually use.
*/
protected String[] prepareArgs(String[] args) {
return args;
}
/**
* Used by isCandidate, isolateKey and isolateValue to determine
* the index of the separation character (':' or '=') within an argument string.
* @param arg The argument being processed.
*/
protected int getSeparatorIndex(String arg) {
int idxA = arg.indexOf('=');
int idxB = arg.indexOf(':');
if (idxA == -1) // key:value
return idxB;
if (idxB == -1) // key=value
return idxA;
if (idxA < idxB) // key=value with :
return idxA;
else // key:value with =
return idxB;
}
/**
* Called by parseArgument to determine if an argument is a candidate key, value combination.
* By default this method will return true if the argument similar
* to any of the following:
* <ol>
* <li>key=value
* <li>key:value
* <li>-key This form is a shorthand for key:true
* </ol>
* An extending class may override this method to implement a different
* strategy for recognizing candidates.
* @param arg The argument being processed.
* @return True if it is a candidate, false if not.
*/
protected boolean isCandidate(String arg) {
if (getSeparatorIndex(arg) > 0) { // key=value or key:value
return true;
}
if ((arg.length() > 1) && (arg.startsWith("-"))) { // "-x" -> "arg=true"
return true;
}
return false;
}
/**
* Called by parseArgument when the isCandidate method returns false.
* This allows an extending class to override this method
* and provide whatever special processing may be required.
* The default behavior is simply to throw a PropertiesException
* indicating which property was unrecognized.
* @param arg The argument being processed.
*/
protected void specialHandling(String arg) {
throw new PropertiesException("Unrecognized: " + arg);
}
/**
* Called by parseArgument to extract the key component from an argument.
* @param arg The argument being processed.
* @param index Index into args of current argument.
*/
protected String isolateKey(String arg) {
int separatorIndex = getSeparatorIndex(arg); // key=value or key:value
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -