diff options
author | Tom Tromey <tromey@redhat.com> | 2002-06-18 15:40:16 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2002-06-18 15:40:16 +0000 |
commit | 3831381763ca5f41d6f7406d590e1e38a8531e1c (patch) | |
tree | 6b8dcd38b7dbb7c4c618080eb1958b6f042d581c /libjava/java/util/Properties.java | |
parent | 0fd534ed06e92a7232b2373321f113ee8dd482c4 (diff) | |
download | gcc-3831381763ca5f41d6f7406d590e1e38a8531e1c.zip gcc-3831381763ca5f41d6f7406d590e1e38a8531e1c.tar.gz gcc-3831381763ca5f41d6f7406d590e1e38a8531e1c.tar.bz2 |
javaprims.h: Updated class declaration list.
* gcj/javaprims.h: Updated class declaration list.
* Makefile.in: Rebuilt.
* Makefile.am (core_java_source_files): Added
PropertyPermissionCollection.java.
* java/lang/Thread.java (group, name): Now package-private.
* java/lang/ThreadGroup.java: Re-merge with Classpath.
* java/util/AbstractList.java: Likewise.
* java/util/AbstractMap.java: Likewise.
* java/util/Calendar.java: Likewise.
* java/util/Collections.java: Likewise.
* java/util/HashMap.java: Likewise.
* java/util/Hashtable.java: Likewise.
* java/util/LinkedHashMap.java: Likewise.
* java/util/LinkedList.java: Likewise.
* java/util/List.java: Likewise.
* java/util/ListResourceBundle.java: Likewise.
* java/util/Map.java: Likewise.
* java/util/Observable.java: Likewise.
* java/util/Properties.java: Likewise.
* java/util/PropertyPermission.java: Likewise.
* java/util/PropertyPermissionCollection.java: Likewise.
* java/util/PropertyResourceBundle.java: Likewise.
* java/util/Random.java: Likewise.
* java/util/SimpleTimeZone.java: Likewise.
* java/util/StringTokenizer.java: Likewise.
* java/util/TimerTask.java: Likewise.
* java/util/TreeMap.java: Likewise.
* java/util/WeakHashMap.java: Likewise.
* java/util/jar/Attributes.java: Likewise.
* java/util/jar/JarException.java: Likewise.
* java/util/jar/Manifest.java: Likewise.
From-SVN: r54743
Diffstat (limited to 'libjava/java/util/Properties.java')
-rw-r--r-- | libjava/java/util/Properties.java | 696 |
1 files changed, 349 insertions, 347 deletions
diff --git a/libjava/java/util/Properties.java b/libjava/java/util/Properties.java index fa3a754..adad250 100644 --- a/libjava/java/util/Properties.java +++ b/libjava/java/util/Properties.java @@ -1,5 +1,5 @@ -/* java.util.Properties - Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +/* Properties.java -- a set of persistent properties + Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -37,64 +37,88 @@ exception statement from your version. */ package java.util; -import java.io.*; + +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.PrintStream; +import java.io.OutputStreamWriter; /** + * A set of persistent properties, which can be saved or loaded from a stream. + * A property list may also contain defaults, searched if the main list + * does not contain a property for a given key. + * * An example of a properties file for the german language is given * here. This extends the example given in ListResourceBundle. * Create a file MyResource_de.properties with the following contents * and put it in the CLASSPATH. (The character * <code>\</code><code>u00e4</code> is the german ä) + * * - * <pre> - * s1=3 - * s2=MeineDisk - * s3=3. M\<code></code>u00e4rz 96 - * s4=Die Diskette ''{1}'' enth\<code></code>u00e4lt {0} in {2}. - * s5=0 - * s6=keine Dateien - * s7=1 - * s8=eine Datei - * s9=2 - * s10={0,number} Dateien - * s11=Das Formatieren schlug fehl mit folgender Exception: {0} - * s12=FEHLER - * s13=Ergebnis - * s14=Dialog - * s15=Auswahlkriterium - * s16=1,3 - * </pre> +<pre>s1=3 +s2=MeineDisk +s3=3. M\<code></code>u00e4rz 96 +s4=Die Diskette ''{1}'' enth\<code></code>u00e4lt {0} in {2}. +s5=0 +s6=keine Dateien +s7=1 +s8=eine Datei +s9=2 +s10={0,number} Dateien +s11=Das Formatieren schlug fehl mit folgender Exception: {0} +s12=FEHLER +s13=Ergebnis +s14=Dialog +s15=Auswahlkriterium +s16=1,3</pre> * - * Although this is a sub class of a hash table, you should never + * <p>Although this is a sub class of a hash table, you should never * insert anything other than strings to this property, or several * methods, that need string keys and values, will fail. To ensure * this, you should use the <code>get/setProperty</code> method instead * of <code>get/put</code>. * - * @see PropertyResourceBundle + * Properties are saved in ISO 8859-1 encoding, using Unicode escapes with + * a single <code>u</code> for any character which cannot be represented. + * * @author Jochen Hoenicke + * @author Eric Blake <ebb9@email.byu.edu> + * @see PropertyResourceBundle + * @status updated to 1.4 */ public class Properties extends Hashtable { + // WARNING: Properties is a CORE class in the bootstrap cycle. See the + // comments in vm/reference/java/lang/Runtime for implications of this fact. + /** * The property list that contains default values for any keys not - * in this property list. + * in this property list. + * + * @serial the default properties */ protected Properties defaults; + /** + * Compatible with JDK 1.0+. + */ private static final long serialVersionUID = 4112578634029874840L; /** - * Creates a new empty property list. + * Creates a new empty property list with no default values. */ public Properties() { - this.defaults = null; } /** * Create a new empty property list with the specified default values. - * @param defaults a Properties object containing the default values. + * + * @param defaults a Properties object containing the default values */ public Properties(Properties defaults) { @@ -102,6 +126,21 @@ public class Properties extends Hashtable } /** + * Adds the given key/value pair to this properties. This calls + * the hashtable method put. + * + * @param key the key for this property + * @param value the value for this property + * @return The old value for the given key + * @see #getProperty(String) + * @since 1.2 + */ + public Object setProperty(String key, String value) + { + return put(key, value); + } + + /** * Reads a property list from an input stream. The stream should * have the following format: <br> * @@ -120,173 +159,176 @@ public class Properties extends Hashtable * * Escape sequences <code>\t, \n, \r, \\, \", \', \!, \#, \ </code>(a * space), and unicode characters with the - * <code>\</code><code>u</code>xxxx notation are detected, and + * <code>\\u</code><em>xxxx</em> notation are detected, and * converted to the corresponding single character. <br> * - * <pre> - * # This is a comment - * key = value - * k\:5 \ a string starting with space and ending with newline\n - * # This is a multiline specification; note that the value contains - * # no white space. - * weekdays: Sunday,Monday,Tuesday,Wednesday,\ - * Thursday,Friday,Saturday - * # The safest way to include a space at the end of a value: - * label = Name:\<code></code>u0020 - * </pre> + * +<pre># This is a comment +key = value +k\:5 \ a string starting with space and ending with newline\n +# This is a multiline specification; note that the value contains +# no white space. +weekdays: Sunday,Monday,Tuesday,Wednesday,\\ + Thursday,Friday,Saturday +# The safest way to include a space at the end of a value: +label = Name:\\u0020</pre> * * @param in the input stream - * @exception IOException if an error occurred when reading - * from the input. */ + * @throws IOException if an error occurred when reading the input + * @throws NullPointerException if in is null + */ public void load(InputStream inStream) throws IOException { // The spec says that the file must be encoded using ISO-8859-1. BufferedReader reader = new BufferedReader(new InputStreamReader(inStream, "ISO-8859-1")); String line; - + while ((line = reader.readLine()) != null) { - char c = 0; - int pos = 0; - while (pos < line.length() - && Character.isWhitespace(c = line.charAt(pos))) - pos++; + char c = 0; + int pos = 0; + while (pos < line.length() + && Character.isWhitespace(c = line.charAt(pos))) + pos++; - // If line is empty or begins with a comment character, - // skip this line. - if (pos == line.length() || c == '#' || c == '!') - continue; + // If line is empty or begins with a comment character, + // skip this line. + if (pos == line.length() || c == '#' || c == '!') + continue; - // The characters up to the next Whitespace, ':', or '=' - // describe the key. But look for escape sequences. - StringBuffer key = new StringBuffer(); - while (pos < line.length() - && !Character.isWhitespace(c = line.charAt(pos++)) - && c != '=' && c != ':') - { - if (c == '\\') - { - if (pos == line.length()) - { - // The line continues on the next line. - line = reader.readLine(); - pos = 0; - while (pos < line.length() - && Character.isWhitespace(c = line.charAt(pos))) - pos++; - } - else - { - c = line.charAt(pos++); - switch (c) - { - case 'n': - key.append('\n'); - break; - case 't': - key.append('\t'); - break; - case 'r': - key.append('\r'); - break; - case 'u': - if (pos + 4 <= line.length()) - { - char uni = (char) Integer.parseInt - (line.substring(pos, pos + 4), 16); - key.append(uni); - pos += 4; - } // else throw exception? - break; - default: - key.append(c); - break; - } - } - } - else - key.append(c); - } + // The characters up to the next Whitespace, ':', or '=' + // describe the key. But look for escape sequences. + StringBuffer key = new StringBuffer(); + while (pos < line.length() + && ! Character.isWhitespace(c = line.charAt(pos++)) + && c != '=' && c != ':') + { + if (c == '\\') + { + if (pos == line.length()) + { + // The line continues on the next line. + line = reader.readLine(); + pos = 0; + while (pos < line.length() + && Character.isWhitespace(c = line.charAt(pos))) + pos++; + } + else + { + c = line.charAt(pos++); + switch (c) + { + case 'n': + key.append('\n'); + break; + case 't': + key.append('\t'); + break; + case 'r': + key.append('\r'); + break; + case 'u': + if (pos + 4 <= line.length()) + { + char uni = (char) Integer.parseInt + (line.substring(pos, pos + 4), 16); + key.append(uni); + pos += 4; + } // else throw exception? + break; + default: + key.append(c); + break; + } + } + } + else + key.append(c); + } - boolean isDelim = (c == ':' || c == '='); - while (pos < line.length() - && Character.isWhitespace(c = line.charAt(pos))) - pos++; + boolean isDelim = (c == ':' || c == '='); + while (pos < line.length() + && Character.isWhitespace(c = line.charAt(pos))) + pos++; - if (!isDelim && (c == ':' || c == '=')) - { - pos++; - while (pos < line.length() - && Character.isWhitespace(c = line.charAt(pos))) - pos++; - } + if (! isDelim && (c == ':' || c == '=')) + { + pos++; + while (pos < line.length() + && Character.isWhitespace(c = line.charAt(pos))) + pos++; + } - StringBuffer element = new StringBuffer(line.length() - pos); - while (pos < line.length()) - { - c = line.charAt(pos++); - if (c == '\\') - { - if (pos == line.length()) - { - // The line continues on the next line. - line = reader.readLine(); - pos = 0; - while (pos < line.length() - && Character.isWhitespace(c = line.charAt(pos))) - pos++; - element.ensureCapacity(line.length() - pos + - element.length()); - } - else - { - c = line.charAt(pos++); - switch (c) - { - case 'n': - element.append('\n'); - break; - case 't': - element.append('\t'); - break; - case 'r': - element.append('\r'); - break; - case 'u': - if (pos + 4 <= line.length()) - { - char uni = (char) Integer.parseInt - (line.substring(pos, pos + 4), 16); - element.append(uni); - pos += 4; - } // else throw exception? - break; - default: - element.append(c); - break; - } - } - } - else - element.append(c); - } - put(key.toString(), element.toString()); + StringBuffer element = new StringBuffer(line.length() - pos); + while (pos < line.length()) + { + c = line.charAt(pos++); + if (c == '\\') + { + if (pos == line.length()) + { + // The line continues on the next line. + line = reader.readLine(); + pos = 0; + while (pos < line.length() + && Character.isWhitespace(c = line.charAt(pos))) + pos++; + element.ensureCapacity(line.length() - pos + + element.length()); + } + else + { + c = line.charAt(pos++); + switch (c) + { + case 'n': + element.append('\n'); + break; + case 't': + element.append('\t'); + break; + case 'r': + element.append('\r'); + break; + case 'u': + if (pos + 4 <= line.length()) + { + char uni = (char) Integer.parseInt + (line.substring(pos, pos + 4), 16); + element.append(uni); + pos += 4; + } // else throw exception? + break; + default: + element.append(c); + break; + } + } + } + else + element.append(c); + } + put(key.toString(), element.toString()); } } /** * Calls <code>store(OutputStream out, String header)</code> and * ignores the IOException that may be thrown. - * @deprecated use store instead. - * @exception ClassCastException if this property contains any key or - * value that isn't a string. + * + * @param out the stream to write to + * @param header a description of the property list + * @throws ClassCastException if this property contains any key or + * value that are not strings + * @deprecated use {@link #store(OutputStream, String)} instead */ public void save(OutputStream out, String header) { try { - store(out, header); + store(out, header); } catch (IOException ex) { @@ -294,13 +336,14 @@ public class Properties extends Hashtable } /** - * Writes the key/value pairs to the given output stream. <br> + * Writes the key/value pairs to the given output stream, in a format + * suitable for <code>load</code>.<br> * * If header is not null, this method writes a comment containing * the header as first line to the stream. The next line (or first * line if header is null) contains a comment with the current date. * Afterwards the key/value pairs are written to the stream in the - * following format. <br> + * following format.<br> * * Each line has the form <code>key = value</code>. Newlines, * Returns and tabs are written as <code>\n,\t,\r</code> resp. @@ -308,47 +351,42 @@ public class Properties extends Hashtable * preceeded by a backslash. Spaces are preceded with a backslash, * if and only if they are at the beginning of the key. Characters * that are not in the ascii range 33 to 127 are written in the - * <code>\</code><code>u</code>xxxx Form. + * <code>\</code><code>u</code>xxxx Form.<br> + * + * Following the listing, the output stream is flushed but left open. * * @param out the output stream - * @param header the header written in the first line, may be null. - * @exception ClassCastException if this property contains any key or - * value that isn't a string. + * @param header the header written in the first line, may be null + * @throws ClassCastException if this property contains any key or + * value that isn't a string + * @throws IOException if writing to the stream fails + * @throws NullPointerException if out is null + * @since 1.2 */ public void store(OutputStream out, String header) throws IOException { // The spec says that the file must be encoded using ISO-8859-1. PrintWriter writer - = new PrintWriter(new OutputStreamWriter (out, "ISO-8859-1")); + = new PrintWriter(new OutputStreamWriter(out, "ISO-8859-1")); if (header != null) writer.println("#" + header); - writer.println("#" + new Date().toString()); + writer.println("#" + new Date()); list(writer); writer.flush(); } /** - * Adds the given key/value pair to this properties. This calls - * the hashtable method put. - * @param key the key for this property - * @param value the value for this property - * @return The old value for the given key. - * @since JDK1.2 */ - public Object setProperty(String key, String value) - { - return put(key, value); - } - - /** * Gets the property with the specified key in this property list. * If the key is not found, the default property list is searched. - * If the property is not found in default or the default of - * default, null is returned. - * @param key The key for this property. - * @param defaulValue A default value - * @return The value for the given key, or null if not found. - * @exception ClassCastException if this property contains any key or - * value that isn't a string. + * If the property is not found in the default, null is returned. + * + * @param key The key for this property + * @return the value for the given key, or null if not found + * @throws ClassCastException if this property contains any key or + * value that isn't a string + * @see #defaults + * @see #setProperty(String, String) + * @see #getProperty(String, String) */ public String getProperty(String key) { @@ -358,13 +396,16 @@ public class Properties extends Hashtable /** * Gets the property with the specified key in this property list. If * the key is not found, the default property list is searched. If the - * property is not found in default or the default of default, the - * specified defaultValue is returned. - * @param key The key for this property. - * @param defaulValue A default value - * @return The value for the given key. - * @exception ClassCastException if this property contains any key or - * value that isn't a string. + * property is not found in the default, the specified defaultValue is + * returned. + * + * @param key The key for this property + * @param defaultValue A default value + * @return The value for the given key + * @throws ClassCastException if this property contains any key or + * value that isn't a string + * @see #defaults + * @see #setProperty(String, String) */ public String getProperty(String key, String defaultValue) { @@ -372,184 +413,145 @@ public class Properties extends Hashtable // Eliminate tail recursion. do { - String value = (String) prop.get(key); - if (value != null) - return value; - prop = prop.defaults; + String value = (String) prop.get(key); + if (value != null) + return value; + prop = prop.defaults; } while (prop != null); return defaultValue; } - private final void addHashEntries(Hashtable base) - { - if (defaults != null) - defaults.addHashEntries(base); - Enumeration keys = keys(); - while (keys.hasMoreElements()) - base.put(keys.nextElement(), base); - } - /** * Returns an enumeration of all keys in this property list, including * the keys in the default property list. + * + * @return an Enumeration of all defined keys */ public Enumeration propertyNames() { - // We make a new Hashtable that holds all the keys. Then we - // return an enumeration for this hash. We do this because we - // don't want modifications to be reflected in the enumeration - // (per JCL), and because there doesn't seem to be a - // particularly better way to ensure that duplicates are - // ignored. - Hashtable t = new Hashtable(); - addHashEntries(t); - return t.keys(); + // We make a new Set that holds all the keys, then return an enumeration + // for that. This prevents modifications from ruining the enumeration, + // as well as ignoring duplicates. + Properties prop = this; + Set s = new HashSet(); + // Eliminate tail recursion. + do + { + s.addAll(prop.keySet()); + prop = prop.defaults; + } + while (prop != null); + return Collections.enumeration(s); } /** - * Formats a key/value pair for output in a properties file. - * See store for a description of the format. - * @param key the key. - * @param value the value. - * @see #store + * Writes the key/value pairs to the given print stream. They are + * written in the way described in the method store. This does not visit + * the keys in the default properties. + * + * @param out the stream, where the key/value pairs are written to + * @throws ClassCastException if this property contains any key or + * value that isn't a string + * @see #store(OutputStream, String) */ - private String formatForOutput(String key, String value) + public void list(PrintStream out) { - // This is a simple approximation of the expected line size. - StringBuffer result = - new StringBuffer(key.length() + value.length() + 16); - boolean head = true; - for (int i = 0; i < key.length(); i++) + Iterator iter = entrySet().iterator(); + int i = size(); + StringBuffer s = new StringBuffer(); // Reuse the same buffer. + while (--i >= 0) { - char c = key.charAt(i); - switch (c) - { - case '\n': - result.append("\\n"); - break; - case '\r': - result.append("\\r"); - break; - case '\t': - result.append("\\t"); - break; - case '\\': - result.append("\\\\"); - break; - case '!': - result.append("\\!"); - break; - case '#': - result.append("\\#"); - break; - case '=': - result.append("\\="); - break; - case ':': - result.append("\\:"); - break; - case ' ': - result.append("\\ "); - break; - default: - if (c < 32 || c > '~') - { - String hex = Integer.toHexString(c); - result.append("\\u0000".substring(0, 6 - hex.length())); - result.append(hex); - } - else - result.append(c); - } - if (c != 32) - head = false; + Map.Entry entry = (Map.Entry) iter.next(); + formatForOutput((String) entry.getKey(), s, true); + s.append('='); + formatForOutput((String) entry.getValue(), s, false); + out.println(s); } - result.append('='); - head = true; - for (int i = 0; i < value.length(); i++) - { - char c = value.charAt(i); - switch (c) - { - case '\n': - result.append("\\n"); - break; - case '\r': - result.append("\\r"); - break; - case '\t': - result.append("\\t"); - break; - case '\\': - result.append("\\\\"); - break; - case '!': - result.append("\\!"); - break; - case '#': - result.append("\\#"); - break; - case ' ': - result.append(head ? "\\ " : " "); - break; - default: - if (c < 32 || c > '~') - { - String hex = Integer.toHexString(c); - result.append("\\u0000".substring(0, 6 - hex.length())); - result.append(hex); - } - else - result.append(c); - } - if (c != 32) - head = false; - } - return result.toString(); } /** - * Writes the key/value pairs to the given print stream. They are + * Writes the key/value pairs to the given print writer. They are * written in the way, described in the method store. - * @param out the stream, where the key/value pairs are written to. - * @exception ClassCastException if this property contains any key or - * value that isn't a string. - * @see #store + * + * @param out the writer, where the key/value pairs are written to + * @throws ClassCastException if this property contains any key or + * value that isn't a string + * @see #store(OutputStream, String) + * @see #list(PrintStream) + * @since 1.1 */ - public void list(PrintStream out) + public void list(PrintWriter out) { - Enumeration keys = keys(); - Enumeration elts = elements(); - while (keys.hasMoreElements()) + Iterator iter = entrySet().iterator(); + int i = size(); + StringBuffer s = new StringBuffer(); // Reuse the same buffer. + while (--i >= 0) { - String key = (String) keys.nextElement(); - String elt = (String) elts.nextElement(); - String output = formatForOutput(key, elt); - out.println(output); + Map.Entry entry = (Map.Entry) iter.next(); + formatForOutput((String) entry.getKey(), s, true); + s.append('='); + formatForOutput((String) entry.getValue(), s, false); + out.println(s); } } /** - * Writes the key/value pairs to the given print writer. They are - * written in the way, described in the method store. - * @param out the writer, where the key/value pairs are written to. - * @exception ClassCastException if this property contains any key or - * value that isn't a string. - * @see #store - * @see #list(java.io.PrintStream) - * @since JDK1.1 + * Formats a key or value for output in a properties file. + * See store for a description of the format. + * + * @param str the string to format + * @param buffer the buffer to add it to + * @param key true if all ' ' must be escaped for the key, false if only + * leading spaces must be escaped for the value + * @see #store(OutputStream, String) */ - public void list(PrintWriter out) + private void formatForOutput(String str, StringBuffer buffer, boolean key) { - Enumeration keys = keys(); - Enumeration elts = elements(); - while (keys.hasMoreElements()) + if (key) + { + buffer.setLength(0); + buffer.ensureCapacity(str.length()); + } + else + buffer.ensureCapacity(buffer.length() + str.length()); + boolean head = true; + int size = str.length(); + for (int i = 0; i < size; i++) { - String key = (String) keys.nextElement(); - String elt = (String) elts.nextElement(); - String output = formatForOutput(key, elt); - out.println(output); + char c = str.charAt(i); + switch (c) + { + case '\n': + buffer.append("\\n"); + break; + case '\r': + buffer.append("\\r"); + break; + case '\t': + buffer.append("\\t"); + break; + case ' ': + buffer.append(head ? "\\ " : " "); + break; + case '\\': + case '!': + case '#': + case '=': + case ':': + buffer.append('\\').append(c); + default: + if (c < ' ' || c > '~') + { + String hex = Integer.toHexString(c); + buffer.append("\\u0000".substring(0, 6 - hex.length())); + buffer.append(hex); + } + else + buffer.append(c); + } + if (c != ' ') + head = key; } } -} +} // class Properties |