From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository. --- libjava/classpath/java/util/Properties.java | 822 ++++++++++++++++++++++++++++ 1 file changed, 822 insertions(+) create mode 100644 libjava/classpath/java/util/Properties.java (limited to 'libjava/classpath/java/util/Properties.java') diff --git a/libjava/classpath/java/util/Properties.java b/libjava/classpath/java/util/Properties.java new file mode 100644 index 000000000..b0f436f42 --- /dev/null +++ b/libjava/classpath/java/util/Properties.java @@ -0,0 +1,822 @@ +/* Properties.java -- a set of persistent properties + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.util; + +import gnu.java.lang.CPStringBuilder; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.Reader; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Element; +import org.w3c.dom.bootstrap.DOMImplementationRegistry; +import org.w3c.dom.ls.DOMImplementationLS; +import org.w3c.dom.ls.LSOutput; +import org.w3c.dom.ls.LSSerializer; + +/** + * 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 + * \u00e4 is the german umlaut) + * + * +
s1=3
+s2=MeineDisk
+s3=3. M\u00e4rz 96
+s4=Die Diskette ''{1}'' enth\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
+ * + *

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 get/setProperty method instead + * of get/put. + * + * Properties are saved in ISO 8859-1 encoding, using Unicode escapes with + * a single u 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. + * + * @serial the default properties + */ + protected Properties defaults; + + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 4112578634029874840L; + + /** + * Creates a new empty property list with no default values. + */ + public Properties() + { + } + + /** + * Create a new empty property list with the specified default values. + * + * @param defaults a Properties object containing the default values + */ + public Properties(Properties defaults) + { + this.defaults = defaults; + } + + /** + * 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 a character stream. The stream should + * have the following format:
+ * + * An empty line or a line starting with # or + * ! is ignored. An backslash (\) at the + * end of the line makes the line continueing on the next line + * (but make sure there is no whitespace after the backslash). + * Otherwise, each line describes a key/value pair.
+ * + * The chars up to the first whitespace, = or : are the key. You + * can include this caracters in the key, if you precede them with + * a backslash (\). The key is followed by optional + * whitespaces, optionally one = or :, + * and optionally some more whitespaces. The rest of the line is + * the resource belonging to the key.
+ * + * Escape sequences \t, \n, \r, \\, \", \', \!, \#, \ (a + * space), and unicode characters with the + * \\uxxxx notation are detected, and + * converted to the corresponding single character.
+ * + * +

# 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
+ * + * @param inReader the input {@link java.io.Reader}. + * @throws IOException if an error occurred when reading the input + * @throws NullPointerException if in is null + * @since 1.6 + */ + public void load(Reader inReader) throws IOException + { + BufferedReader reader = new BufferedReader(inReader); + String line; + + while ((line = reader.readLine()) != null) + { + char c = 0; + int pos = 0; + // Leading whitespaces must be deleted first. + while (pos < line.length() + && Character.isWhitespace(c = line.charAt(pos))) + pos++; + + // If empty line or begins with a comment character, skip this line. + if ((line.length() - pos) == 0 + || line.charAt(pos) == '#' || line.charAt(pos) == '!') + continue; + + // The characters up to the next Whitespace, ':', or '=' + // describe the key. But look for escape sequences. + // Try to short-circuit when there is no escape char. + int start = pos; + boolean needsEscape = line.indexOf('\\', pos) != -1; + CPStringBuilder key = needsEscape ? new CPStringBuilder() : null; + while (pos < line.length() + && ! Character.isWhitespace(c = line.charAt(pos++)) + && c != '=' && c != ':') + { + if (needsEscape && c == '\\') + { + if (pos == line.length()) + { + // The line continues on the next line. If there + // is no next line, just treat it as a key with an + // empty value. + line = reader.readLine(); + if (line == null) + line = ""; + 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 if (needsEscape) + key.append(c); + } + + boolean isDelim = (c == ':' || c == '='); + + String keyString; + if (needsEscape) + keyString = key.toString(); + else if (isDelim || Character.isWhitespace(c)) + keyString = line.substring(start, pos - 1); + else + keyString = line.substring(start, 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++; + } + + // Short-circuit if no escape chars found. + if (!needsEscape) + { + put(keyString, line.substring(pos)); + continue; + } + + // Escape char found so iterate through the rest of the line. + StringBuilder element = new StringBuilder(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(); + + // We might have seen a backslash at the end of + // the file. The JDK ignores the backslash in + // this case, so we follow for compatibility. + if (line == null) + break; + + 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(keyString, element.toString()); + } + } + + /** + * Reads a property list from the supplied input stream. + * This method has the same functionality as {@link #load(Reader)} + * but the character encoding is assumed to be ISO-8859-1. + * Unicode characters not within the Latin1 set supplied by + * ISO-8859-1 should be escaped using '\\uXXXX' where XXXX + * is the UTF-16 code unit in hexadecimal. + * + * @param inStream the byte stream to read the property list from. + * @throws IOException if an I/O error occurs. + * @see #load(Reader) + * @since 1.2 + */ + public void load(InputStream inStream) throws IOException + { + load(new InputStreamReader(inStream, "ISO-8859-1")); + } + + /** + * Calls store(OutputStream out, String header) and + * ignores the IOException that may be thrown. + * + * @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 + */ + @Deprecated + public void save(OutputStream out, String header) + { + try + { + store(out, header); + } + catch (IOException ex) + { + } + } + + /** + * Writes the key/value pairs to the given output stream, in a format + * suitable for load.
+ * + * 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.
+ * + * Each line has the form key = value. Newlines, + * Returns and tabs are written as \n,\t,\r resp. + * The characters \, !, #, = and : are + * 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 + * \uxxxx Form.
+ * + * 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 + * @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")); + if (header != null) + writer.println("#" + header); + writer.println ("#" + Calendar.getInstance ().getTime ()); + + Iterator iter = entrySet ().iterator (); + int i = size (); + CPStringBuilder s = new CPStringBuilder (); // Reuse the same buffer. + while (--i >= 0) + { + Map.Entry entry = (Map.Entry) iter.next (); + formatForOutput ((String) entry.getKey (), s, true); + s.append ('='); + formatForOutput ((String) entry.getValue (), s, false); + writer.println (s); + } + + writer.flush (); + } + + /** + * 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 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) + { + Properties prop = this; + // Eliminate tail recursion. + do + { + String value = (String) prop.get(key); + if (value != null) + return value; + prop = prop.defaults; + } + while (prop != null); + return null; + } + + /** + * 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 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) + { + String prop = getProperty(key); + if (prop == null) + prop = defaultValue; + return prop; + } + + /** + * 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 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); + } + + /** + * Prints the key/value pairs to the given print stream. This is + * mainly useful for debugging purposes. + * + * @param out the print stream, where the key/value pairs are written to + * @throws ClassCastException if this property contains a key or a + * value that isn't a string + * @see #list(PrintWriter) + */ + public void list(PrintStream out) + { + PrintWriter writer = new PrintWriter (out); + list (writer); + } + + /** + * Prints the key/value pairs to the given print writer. This is + * mainly useful for debugging purposes. + * + * @param out the print writer where the key/value pairs are written to + * @throws ClassCastException if this property contains a key or a + * value that isn't a string + * @see #list(PrintStream) + * @since 1.1 + */ + public void list(PrintWriter out) + { + out.println ("-- listing properties --"); + + Iterator iter = entrySet ().iterator (); + int i = size (); + while (--i >= 0) + { + Map.Entry entry = (Map.Entry) iter.next (); + out.print ((String) entry.getKey () + "="); + + // JDK 1.3/1.4 restrict the printed value, but not the key, + // to 40 characters, including the truncating ellipsis. + String s = (String ) entry.getValue (); + if (s != null && s.length () > 40) + out.println (s.substring (0, 37) + "..."); + else + out.println (s); + } + out.flush (); + } + + /** + * 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) + */ + private void formatForOutput(String str, CPStringBuilder buffer, boolean key) + { + 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++) + { + 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); + break; + 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; + } + } + + /** + *

+ * Encodes the properties as an XML file using the UTF-8 encoding. + * The format of the XML file matches the DTD + * + * http://java.sun.com/dtd/properties.dtd. + *

+ *

+ * Invoking this method provides the same behaviour as invoking + * storeToXML(os, comment, "UTF-8"). + *

+ * + * @param os the stream to output to. + * @param comment a comment to include at the top of the XML file, or + * null if one is not required. + * @throws IOException if the serialization fails. + * @throws NullPointerException if os is null. + * @since 1.5 + */ + public void storeToXML(OutputStream os, String comment) + throws IOException + { + storeToXML(os, comment, "UTF-8"); + } + + /** + *

+ * Encodes the properties as an XML file using the supplied encoding. + * The format of the XML file matches the DTD + * + * http://java.sun.com/dtd/properties.dtd. + *

+ * + * @param os the stream to output to. + * @param comment a comment to include at the top of the XML file, or + * null if one is not required. + * @param encoding the encoding to use for the XML output. + * @throws IOException if the serialization fails. + * @throws NullPointerException if os or encoding + * is null. + * @since 1.5 + */ + public void storeToXML(OutputStream os, String comment, String encoding) + throws IOException + { + if (os == null) + throw new NullPointerException("Null output stream supplied."); + if (encoding == null) + throw new NullPointerException("Null encoding supplied."); + try + { + DOMImplementationRegistry registry = + DOMImplementationRegistry.newInstance(); + DOMImplementation domImpl = registry.getDOMImplementation("LS 3.0"); + DocumentType doctype = + domImpl.createDocumentType("properties", null, + "http://java.sun.com/dtd/properties.dtd"); + Document doc = domImpl.createDocument(null, "properties", doctype); + Element root = doc.getDocumentElement(); + if (comment != null) + { + Element commentElement = doc.createElement("comment"); + commentElement.appendChild(doc.createTextNode(comment)); + root.appendChild(commentElement); + } + Iterator iterator = entrySet().iterator(); + while (iterator.hasNext()) + { + Map.Entry entry = (Map.Entry) iterator.next(); + Element entryElement = doc.createElement("entry"); + entryElement.setAttribute("key", (String) entry.getKey()); + entryElement.appendChild(doc.createTextNode((String) + entry.getValue())); + root.appendChild(entryElement); + } + DOMImplementationLS loadAndSave = (DOMImplementationLS) domImpl; + LSSerializer serializer = loadAndSave.createLSSerializer(); + LSOutput output = loadAndSave.createLSOutput(); + output.setByteStream(os); + output.setEncoding(encoding); + serializer.write(doc, output); + } + catch (ClassNotFoundException e) + { + throw (IOException) + new IOException("The XML classes could not be found.").initCause(e); + } + catch (InstantiationException e) + { + throw (IOException) + new IOException("The XML classes could not be instantiated.") + .initCause(e); + } + catch (IllegalAccessException e) + { + throw (IOException) + new IOException("The XML classes could not be accessed.") + .initCause(e); + } + } + + /** + *

+ * Decodes the contents of the supplied InputStream as + * an XML file, which represents a set of properties. The format of + * the XML file must match the DTD + * + * http://java.sun.com/dtd/properties.dtd. + *

+ * + * @param in the input stream from which to receive the XML data. + * @throws IOException if an I/O error occurs in reading the input data. + * @throws InvalidPropertiesFormatException if the input data does not + * constitute an XML properties + * file. + * @throws NullPointerException if in is null. + * @since 1.5 + */ + public void loadFromXML(InputStream in) + throws IOException, InvalidPropertiesFormatException + { + if (in == null) + throw new NullPointerException("Null input stream supplied."); + try + { + XMLInputFactory factory = XMLInputFactory.newInstance(); + // Don't resolve external entity references + factory.setProperty("javax.xml.stream.isSupportingExternalEntities", + Boolean.FALSE); + XMLStreamReader reader = factory.createXMLStreamReader(in); + String name, key = null; + CPStringBuilder buf = null; + while (reader.hasNext()) + { + switch (reader.next()) + { + case XMLStreamConstants.START_ELEMENT: + name = reader.getLocalName(); + if (buf == null && "entry".equals(name)) + { + key = reader.getAttributeValue(null, "key"); + if (key == null) + { + String msg = "missing 'key' attribute"; + throw new InvalidPropertiesFormatException(msg); + } + buf = new CPStringBuilder(); + } + else if (!"properties".equals(name) && !"comment".equals(name)) + { + String msg = "unexpected element name '" + name + "'"; + throw new InvalidPropertiesFormatException(msg); + } + break; + case XMLStreamConstants.END_ELEMENT: + name = reader.getLocalName(); + if (buf != null && "entry".equals(name)) + { + put(key, buf.toString()); + buf = null; + } + else if (!"properties".equals(name) && !"comment".equals(name)) + { + String msg = "unexpected element name '" + name + "'"; + throw new InvalidPropertiesFormatException(msg); + } + break; + case XMLStreamConstants.CHARACTERS: + case XMLStreamConstants.SPACE: + case XMLStreamConstants.CDATA: + if (buf != null) + buf.append(reader.getText()); + break; + } + } + reader.close(); + } + catch (XMLStreamException e) + { + throw (InvalidPropertiesFormatException) + new InvalidPropertiesFormatException("Error in parsing XML."). + initCause(e); + } + } + +} // class Properties -- cgit v1.2.3