Properties.java revision 0
2362N/A * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 0N/A * published by the Free Software Foundation. Sun designates this 0N/A * particular file as subject to the "Classpath" exception as provided 0N/A * by Sun in the LICENSE file that accompanied this code. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 2362N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 0N/A * CA 95054 USA or visit www.sun.com if you need additional information or 0N/A * have any questions. 0N/A * The <code>Properties</code> class represents a persistent set of 0N/A * properties. The <code>Properties</code> can be saved to a stream 0N/A * or loaded from a stream. Each key and its corresponding value in 0N/A * the property list is a string. 0N/A * A property list can contain another property list as its 0N/A * "defaults"; this second property list is searched if 0N/A * the property key is not found in the original property list. 0N/A * Because <code>Properties</code> inherits from <code>Hashtable</code>, the 0N/A * <code>put</code> and <code>putAll</code> methods can be applied to a 0N/A * <code>Properties</code> object. Their use is strongly discouraged as they 0N/A * allow the caller to insert entries whose keys or values are not 0N/A * <code>Strings</code>. The <code>setProperty</code> method should be used 0N/A * instead. If the <code>store</code> or <code>save</code> method is called 0N/A * on a "compromised" <code>Properties</code> object that contains a 0N/A * non-<code>String</code> key or value, the call will fail. Similarly, 0N/A * the call to the <code>propertyNames</code> or <code>list</code> method 0N/A * will fail if it is called on a "compromised" <code>Properties</code> 0N/A * object that contains a non-<code>String</code> key. 0N/A * The {@link #load(java.io.Reader) load(Reader)} <tt>/</tt> 0N/A * {@link #store(java.io.Writer, java.lang.String) store(Writer, String)} 0N/A * methods load and store properties from and to a character based stream 0N/A * in a simple line-oriented format specified below. 0N/A * The {@link #load(java.io.InputStream) load(InputStream)} <tt>/</tt> 0N/A * {@link #store(java.io.OutputStream, java.lang.String) store(OutputStream, String)} 0N/A * methods work the same way as the load(Reader)/store(Writer, String) pair, except 0N/A * the input/output stream is encoded in ISO 8859-1 character encoding. 0N/A * Characters that cannot be directly represented in this encoding can be written using 0N/A * ; only a single 'u' character is allowed in an escape 0N/A * sequence. The native2ascii tool can be used to convert property files to and 0N/A * from other character encodings. 0N/A * <p> The {@link #loadFromXML(InputStream)} and {@link 0N/A * #storeToXML(OutputStream, String, String)} methods load and store properties 0N/A * in a simple XML format. By default the UTF-8 character encoding is used, 0N/A * however a specific encoding may be specified if required. An XML properties 0N/A * document has the following DOCTYPE declaration: 0N/A * <i>not</i> accessed when exporting or importing properties; it merely 0N/A * serves as a string to uniquely identify the DTD, which is: 0N/A * <?xml version="1.0" encoding="UTF-8"?> 0N/A * <!-- DTD for properties --> 0N/A * <!ELEMENT properties ( comment?, entry* ) > 0N/A * <!ATTLIST properties version CDATA #FIXED "1.0"> 0N/A * <!ELEMENT comment (#PCDATA) > 0N/A * <!ELEMENT entry (#PCDATA) > 0N/A * <!ATTLIST entry key CDATA #REQUIRED> 0N/A * <p>This class is thread-safe: multiple threads can share a single 0N/A * <tt>Properties</tt> object without the need for external synchronization. 0N/A * @author Arthur van Hoff 0N/A * @author Michael McCloskey 0N/A * @author Xueming Shen 0N/A * use serialVersionUID from JDK 1.1.X for interoperability 0N/A * A property list that contains default values for any keys not 0N/A * found in this property list. 0N/A * Creates an empty property list with no default values. 0N/A * Creates an empty property list with the specified defaults. 0N/A * @param defaults the defaults. 0N/A * Calls the <tt>Hashtable</tt> method <code>put</code>. Provided for 0N/A * parallelism with the <tt>getProperty</tt> method. Enforces use of 0N/A * strings for property keys and values. The value returned is the 0N/A * result of the <tt>Hashtable</tt> call to <code>put</code>. 0N/A * @param key the key to be placed into this property list. 0N/A * @param value the value corresponding to <tt>key</tt>. 0N/A * @return the previous value of the specified key in this property 0N/A * list, or <code>null</code> if it did not have one. 0N/A * Reads a property list (key and element pairs) from the input 0N/A * character stream in a simple line-oriented format. 0N/A * Properties are processed in terms of lines. There are two 0N/A * kinds of line, <i>natural lines</i> and <i>logical lines</i>. 0N/A * A natural line is defined as a line of 0N/A * characters that is terminated either by a set of line terminator 0N/A * characters (<code>\n</code> or <code>\r</code> or <code>\r\n</code>) 0N/A * or by the end of the stream. A natural line may be either a blank line, 0N/A * a comment line, or hold all or some of a key-element pair. A logical 0N/A * line holds all the data of a key-element pair, which may be spread 0N/A * out across several adjacent natural lines by escaping 0N/A * the line terminator sequence with a backslash character 0N/A * <code>\</code>. Note that a comment line cannot be extended 0N/A * in this manner; every natural line that is a comment must have 0N/A * its own comment indicator, as described below. Lines are read from 0N/A * input until the end of the stream is reached. 0N/A * A natural line that contains only white space characters is 0N/A * considered blank and is ignored. A comment line has an ASCII 0N/A * <code>'#'</code> or <code>'!'</code> as its first non-white 0N/A * space character; comment lines are also ignored and do not 0N/A * encode key-element information. In addition to line 0N/A * terminators, this format considers the characters space 0N/A * (<code>' '</code>, <code>'\u0020'</code>), tab 0N/A * (<code>'\t'</code>, <code>'\u0009'</code>), and form feed 0N/A * (<code>'\f'</code>, <code>'\u000C'</code>) to be white 0N/A * If a logical line is spread across several natural lines, the 0N/A * backslash escaping the line terminator sequence, the line 0N/A * terminator sequence, and any white space at the start of the 0N/A * following line have no affect on the key or element values. 0N/A * The remainder of the discussion of key and element parsing 0N/A * (when loading) will assume all the characters constituting 0N/A * the key and element appear on a single natural line after 0N/A * line continuation characters have been removed. Note that 0N/A * it is <i>not</i> sufficient to only examine the character 0N/A * preceding a line terminator sequence to decide if the line 0N/A * terminator is escaped; there must be an odd number of 0N/A * contiguous backslashes for the line terminator to be escaped. 0N/A * Since the input is processed from left to right, a 0N/A * non-zero even number of 2<i>n</i> contiguous backslashes 0N/A * before a line terminator (or elsewhere) encodes <i>n</i> 0N/A * backslashes after escape processing. 0N/A * The key contains all of the characters in the line starting 0N/A * with the first non-white space character and up to, but not 0N/A * including, the first unescaped <code>'='</code>, 0N/A * <code>':'</code>, or white space character other than a line 0N/A * terminator. All of these key termination characters may be 0N/A * included in the key by escaping them with a preceding backslash 0N/A * character; for example,<p> 0N/A * <code>\:\=</code><p> 0N/A * would be the two-character key <code>":="</code>. Line 0N/A * terminator characters can be included using <code>\r</code> and 0N/A * <code>\n</code> escape sequences. Any white space after the 0N/A * key is skipped; if the first non-white space character after 0N/A * the key is <code>'='</code> or <code>':'</code>, then it is 0N/A * ignored and any white space characters after it are also 0N/A * skipped. All remaining characters on the line become part of 0N/A * the associated element string; if there are no remaining 0N/A * characters, the element is the empty string 0N/A * <code>""</code>. Once the raw character sequences 0N/A * constituting the key and element are identified, escape 0N/A * processing is performed as described above. 0N/A * As an example, each of the following three lines specifies the key 0N/A * <code>"Truth"</code> and the associated element value 0N/A * <code>"Beauty"</code>: 0N/A * As another example, the following three lines specify a single 0N/A * fruits apple, banana, pear, \ 0N/A * cantaloupe, watermelon, \ 0N/A * The key is <code>"fruits"</code> and the associated element is: 0N/A * <pre>"apple, banana, pear, cantaloupe, watermelon, kiwi, mango"</pre> 0N/A * Note that a space appears before each <code>\</code> so that a space 0N/A * will appear after each comma in the final result; the <code>\</code>, 0N/A * line terminator, and leading white space on the continuation line are 0N/A * merely discarded and are <i>not</i> replaced by one or more other 0N/A * As a third example, the line: 0N/A * specifies that the key is <code>"cheeses"</code> and the associated 0N/A * element is the empty string <code>""</code>.<p> 0N/A * <a name="unicodeescapes"></a> 0N/A * Characters in keys and elements can be represented in escape 0N/A * sequences similar to those used for character and string literals 0N/A * of the <i>Java Language Specification</i>). 0N/A * The differences from the character escape sequences and Unicode 0N/A * escapes used for characters and strings are: 0N/A * <li> Octal escapes are not recognized. 0N/A * <li> The character sequence <code>\b</code> does <i>not</i> 0N/A * represent a backspace character. 0N/A * <li> The method does not treat a backslash character, 0N/A * <code>\</code>, before a non-valid escape character as an 0N/A * error; the backslash is silently dropped. For example, in a 0N/A * Java string the sequence <code>"\z"</code> would cause a 0N/A * compile time error. In contrast, this method silently drops 0N/A * the backslash. Therefore, this method treats the two character 0N/A * sequence <code>"\b"</code> as equivalent to the single 0N/A * character <code>'b'</code>. 0N/A * <li> Escapes are not necessary for single and double quotes; 0N/A * however, by the rule above, single and double quote characters 0N/A * preceded by a backslash still yield single and double quote 0N/A * characters, respectively. 0N/A * <li> Only a single 'u' character is allowed in a Uniocde escape 0N/A * The specified stream remains open after this method returns. 0N/A * @param reader the input character stream. 0N/A * @throws IOException if an error occurred when reading from the 0N/A * @throws IllegalArgumentException if a malformed Unicode escape 0N/A * appears in the input. 0N/A * Reads a property list (key and element pairs) from the input 0N/A * byte stream. The input stream is in a simple line-oriented 0N/A * format as specified in 0N/A * {@link #load(java.io.Reader) load(Reader)} and is assumed to use 0N/A * the ISO 8859-1 character encoding; that is each byte is one Latin1 0N/A * character. Characters not in Latin1, and certain special characters, 0N/A * are represented in keys and elements using 0N/A * The specified stream remains open after this method returns. 0N/A * @param inStream the input stream. 0N/A * @exception IOException if an error occurred when reading from the 0N/A * @throws IllegalArgumentException if the input stream contains a 0N/A * malformed Unicode escape sequence. 0N/A //System.out.println("line=<" + new String(lineBuf, 0, limit) + ">"); 0N/A //need check if escaped. 0N/A if (c !=
' ' && c !=
'\t' && c !=
'\f') {
* and blank lines and filter out those leading whitespace characters * (\u0020, \u0009 and \u000c) from the beginning of a "natural line". * Method returns the char length of the "logical line" and stores //The line below is equivalent to calling a if (c ==
' ' || c ==
'\t' || c ==
'\f') {
if (c ==
'#' || c ==
'!') {
if (c !=
'\n' && c !=
'\r') {
//flip the preceding backslash flag //skip the leading whitespace characters in following line * Converts encoded \uxxxx to unicode chars * and changes special saved chars to their original forms for (
int i=
0; i<
4; i++) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
"Malformed \\uxxxx encoding.");
* Converts unicodes to encoded \uxxxx and escapes * special characters with a preceding slash for(
int x=
0; x<
len; x++) {
// Handle common case first, selecting largest block that // avoids the specials below case '=':
// Fall through case ':':
// Fall through case '#':
// Fall through if (c >
'\u00ff' || c ==
'\n' || c ==
'\r') {
* Calls the <code>store(OutputStream out, String comments)</code> method * and suppresses IOExceptions that were thrown. * @deprecated This method does not throw an IOException if an I/O error * occurs while saving the property list. The preferred way to save a * properties list is via the <code>store(OutputStream out, * String comments)</code> method or the * <code>storeToXML(OutputStream os, String comment)</code> method. * @param out an output stream. * @param comments a description of the property list. * @exception ClassCastException if this <code>Properties</code> object * contains any keys or values that are not * Writes this property list (key and element pairs) in this * <code>Properties</code> table to the output character stream in a * format suitable for using the {@link #load(java.io.Reader) load(Reader)} * Properties from the defaults table of this <code>Properties</code> * table (if any) are <i>not</i> written out by this method. * If the comments argument is not null, then an ASCII <code>#</code> * character, the comments string, and a line separator are first written * to the output stream. Thus, the <code>comments</code> can serve as an * identifying comment. Any one of a line feed ('\n'), a carriage * return ('\r'), or a carriage return followed immediately by a line feed * in comments is replaced by a line separator generated by the <code>Writer</code> * and if the next character in comments is not character <code>#</code> or * character <code>!</code> then an ASCII <code>#</code> is written out * after that line separator. * Next, a comment line is always written, consisting of an ASCII * <code>#</code> character, the current date and time (as if produced * by the <code>toString</code> method of <code>Date</code> for the * current time), and a line separator as generated by the <code>Writer</code>. * Then every entry in this <code>Properties</code> table is * written out, one per line. For each entry the key string is * written, then an ASCII <code>=</code>, then the associated * element string. For the key, all space characters are * written with a preceding <code>\</code> character. For the * element, leading space characters, but not embedded or trailing * space characters, are written with a preceding <code>\</code> * character. The key and element characters <code>#</code>, * <code>!</code>, <code>=</code>, and <code>:</code> are written * with a preceding backslash to ensure that they are properly loaded. * After the entries have been written, the output stream is flushed. * The output stream remains open after this method returns. * @param writer an output character stream writer. * @param comments a description of the property list. * @exception IOException if writing this property list to the specified * output stream throws an <tt>IOException</tt>. * @exception ClassCastException if this <code>Properties</code> object * contains any keys or values that are not <code>Strings</code>. * @exception NullPointerException if <code>writer</code> is null. * Writes this property list (key and element pairs) in this * <code>Properties</code> table to the output stream in a format suitable * for loading into a <code>Properties</code> table using the * {@link #load(InputStream) load(InputStream)} method. * Properties from the defaults table of this <code>Properties</code> * table (if any) are <i>not</i> written out by this method. * This method outputs the comments, properties keys and values in * the same format as specified in * {@link #store(java.io.Writer, java.lang.String) store(Writer)}, * with the following differences: * <li>The stream is written using the ISO 8859-1 character encoding. * <li>Characters not in Latin-1 in the comments are written as * <code>\u</code><i>xxxx</i> for their appropriate unicode * hexadecimal value <i>xxxx</i>. * <li>Characters less than <code>\u0020</code> and characters greater * than <code>\u007E</code> in property keys or values are written * as <code>\u</code><i>xxxx</i> for the appropriate hexadecimal * After the entries have been written, the output stream is flushed. * The output stream remains open after this method returns. * @param out an output stream. * @param comments a description of the property list. * @exception IOException if writing this property list to the specified * output stream throws an <tt>IOException</tt>. * @exception ClassCastException if this <code>Properties</code> object * contains any keys or values that are not <code>Strings</code>. * @exception NullPointerException if <code>out</code> is null. /* No need to escape embedded and trailing spaces for value, hence * Loads all of the properties represented by the XML document on the * specified input stream into this properties table. * <p>The XML document must have the following DOCTYPE declaration: * Furthermore, the document must satisfy the properties DTD described * <p>The specified stream is closed after this method returns. * @param in the input stream from which to read the XML document. * @throws IOException if reading from the specified input stream * results in an <tt>IOException</tt>. * @throws InvalidPropertiesFormatException Data on input stream does not * constitute a valid XML document with the mandated document type. * @throws NullPointerException if <code>in</code> is null. * @see #storeToXML(OutputStream, String, String) * Emits an XML document representing all of the properties contained * <p> An invocation of this method of the form <tt>props.storeToXML(os, * comment)</tt> behaves in exactly the same way as the invocation * <tt>props.storeToXML(os, comment, "UTF-8");</tt>. * @param os the output stream on which to emit the XML document. * @param comment a description of the property list, or <code>null</code> * if no comment is desired. * @throws IOException if writing to the specified output stream * results in an <tt>IOException</tt>. * @throws NullPointerException if <code>os</code> is null. * @throws ClassCastException if this <code>Properties</code> object * contains any keys or values that are not * @see #loadFromXML(InputStream) * Emits an XML document representing all of the properties contained * in this table, using the specified encoding. * <p>The XML document will have the following DOCTYPE declaration: *<p>If the specified comment is <code>null</code> then no comment * will be stored in the document. * <p>The specified stream remains open after this method returns. * @param os the output stream on which to emit the XML document. * @param comment a description of the property list, or <code>null</code> * if no comment is desired. * @throws IOException if writing to the specified output stream * results in an <tt>IOException</tt>. * @throws NullPointerException if <code>os</code> is <code>null</code>, * or if <code>encoding</code> is <code>null</code>. * @throws ClassCastException if this <code>Properties</code> object * contains any keys or values that are not * @see #loadFromXML(InputStream) * Searches for the property with the specified key in this property list. * If the key is not found in this property list, the default property list, * and its defaults, recursively, are then checked. The method returns * <code>null</code> if the property is not found. * @param key the property key. * @return the value in this property list with the specified key value. * Searches for the property with the specified key in this property list. * If the key is not found in this property list, the default property list, * and its defaults, recursively, are then checked. The method returns the * default value argument if the property is not found. * @param key the hashtable key. * @param defaultValue a default value. * @return the value in this property list with the specified key value. * Returns an enumeration of all the keys in this property list, * including distinct keys in the default property list if a key * of the same name has not already been found from the main * @return an enumeration of all the keys in this property list, including * the keys in the default property list. * @throws ClassCastException if any key in this property list * @see java.util.Enumeration * @see #stringPropertyNames * Returns a set of keys in this property list where * the key and its corresponding value are strings, * including distinct keys in the default property list if a key * of the same name has not already been found from the main * properties list. Properties whose key or value is not * of type <tt>String</tt> are omitted. * The returned set is not backed by the <tt>Properties</tt> object. * Changes to this <tt>Properties</tt> are not reflected in the set, * @return a set of keys in this property list where * the key and its corresponding value are strings, * including the keys in the default property list. * Prints this property list out to the specified output stream. * This method is useful for debugging. * @param out an output stream. * @throws ClassCastException if any key in this property list * Prints this property list out to the specified output stream. * This method is useful for debugging. * @param out an output stream. * @throws ClassCastException if any key in this property list * Rather than use an anonymous inner class to share common code, this * method is duplicated in order to ensure that a non-1.1 compiler can * Enumerates all key/value pairs in the specified hashtable. * @throws ClassCastException if any of the property keys * Enumerates all key/value pairs in the specified hashtable * and omits the property if the key or value is not a string. * Convert a nibble to a hex character * @param nibble the nibble to convert. /** A table of hex digits */ private static final char[]
hexDigit = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F'