diff options
author | mark <mark@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-11-15 23:20:01 +0000 |
---|---|---|
committer | mark <mark@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-11-15 23:20:01 +0000 |
commit | 3b3101d8b5ae4f08a16c0b7111da6cad41bbd282 (patch) | |
tree | a5eb7cf42a51869cc8aa1fad7ad6a90cca47fdd8 /libjava/classpath/java/util/Properties.java | |
parent | 7e55c49d7d91ef9f09e93c1100119b1ab3652446 (diff) | |
download | ppe42-gcc-3b3101d8b5ae4f08a16c0b7111da6cad41bbd282.tar.gz ppe42-gcc-3b3101d8b5ae4f08a16c0b7111da6cad41bbd282.zip |
Imported GNU Classpath 0.19 + gcj-import-20051115.
* sources.am: Regenerated.
* Makefile.in: Likewise.
* scripts/makemake.tcl: Use glob -nocomplain.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@107049 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/classpath/java/util/Properties.java')
-rw-r--r-- | libjava/classpath/java/util/Properties.java | 348 |
1 files changed, 341 insertions, 7 deletions
diff --git a/libjava/classpath/java/util/Properties.java b/libjava/classpath/java/util/Properties.java index f00615ba0bf..7c468da8b4f 100644 --- a/libjava/classpath/java/util/Properties.java +++ b/libjava/classpath/java/util/Properties.java @@ -47,6 +47,25 @@ import java.io.OutputStreamWriter; import java.io.PrintStream; import java.io.PrintWriter; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.ext.DefaultHandler2; + +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 @@ -200,12 +219,15 @@ label = Name:\\u0020</pre> // The characters up to the next Whitespace, ':', or '=' // describe the key. But look for escape sequences. - StringBuffer key = new StringBuffer(); + // Try to short-circuit when there is no escape char. + int start = pos; + boolean needsEscape = line.indexOf('\\', pos) != -1; + StringBuilder key = needsEscape ? new StringBuilder() : null; while (pos < line.length() && ! Character.isWhitespace(c = line.charAt(pos++)) && c != '=' && c != ':') { - if (c == '\\') + if (needsEscape && c == '\\') { if (pos == line.length()) { @@ -249,11 +271,20 @@ label = Name:\\u0020</pre> } } } - else + 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++; @@ -266,7 +297,15 @@ label = Name:\\u0020</pre> pos++; } - StringBuffer element = new StringBuffer(line.length() - 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++); @@ -322,7 +361,7 @@ label = Name:\\u0020</pre> else element.append(c); } - put(key.toString(), element.toString()); + put(keyString, element.toString()); } } @@ -386,7 +425,7 @@ label = Name:\\u0020</pre> Iterator iter = entrySet ().iterator (); int i = size (); - StringBuffer s = new StringBuffer (); // Reuse the same buffer. + StringBuilder s = new StringBuilder (); // Reuse the same buffer. while (--i >= 0) { Map.Entry entry = (Map.Entry) iter.next (); @@ -529,7 +568,7 @@ label = Name:\\u0020</pre> * leading spaces must be escaped for the value * @see #store(OutputStream, String) */ - private void formatForOutput(String str, StringBuffer buffer, boolean key) + private void formatForOutput(String str, StringBuilder buffer, boolean key) { if (key) { @@ -578,4 +617,299 @@ label = Name:\\u0020</pre> head = key; } } + + /** + * <p> + * Encodes the properties as an XML file using the UTF-8 encoding. + * The format of the XML file matches the DTD + * <a href="http://java.sun.com/dtd/properties.dtd"> + * http://java.sun.com/dtd/properties.dtd</a>. + * </p> + * <p> + * Invoking this method provides the same behaviour as invoking + * <code>storeToXML(os, comment, "UTF-8")</code>. + * </p> + * + * @param os the stream to output to. + * @param comment a comment to include at the top of the XML file, or + * <code>null</code> if one is not required. + * @throws IOException if the serialization fails. + * @throws NullPointerException if <code>os</code> is null. + * @since 1.5 + */ + public void storeToXML(OutputStream os, String comment) + throws IOException + { + storeToXML(os, comment, "UTF-8"); + } + + /** + * <p> + * Encodes the properties as an XML file using the supplied encoding. + * The format of the XML file matches the DTD + * <a href="http://java.sun.com/dtd/properties.dtd"> + * http://java.sun.com/dtd/properties.dtd</a>. + * </p> + * + * @param os the stream to output to. + * @param comment a comment to include at the top of the XML file, or + * <code>null</code> if one is not required. + * @param encoding the encoding to use for the XML output. + * @throws IOException if the serialization fails. + * @throws NullPointerException if <code>os</code> or <code>encoding</code> + * 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); + } + } + + /** + * <p> + * Decodes the contents of the supplied <code>InputStream</code> as + * an XML file, which represents a set of properties. The format of + * the XML file must match the DTD + * <a href="http://java.sun.com/dtd/properties.dtd"> + * http://java.sun.com/dtd/properties.dtd</a>. + * </p> + * + * @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 <code>in</code> is null. + * @since 1.5 + */ + public void loadFromXML(InputStream in) + throws IOException, InvalidPropertiesFormatException + { + if (in == null) + throw new NullPointerException("Null input stream supplied."); + try + { + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setValidating(false); /* Don't use the URI */ + XMLReader parser = factory.newSAXParser().getXMLReader(); + PropertiesHandler handler = new PropertiesHandler(); + parser.setContentHandler(handler); + parser.setProperty("http://xml.org/sax/properties/lexical-handler", + handler); + parser.parse(new InputSource(in)); + } + catch (SAXException e) + { + throw (InvalidPropertiesFormatException) + new InvalidPropertiesFormatException("Error in parsing XML."). + initCause(e); + } + catch (ParserConfigurationException e) + { + throw (IOException) + new IOException("An XML parser could not be found."). + initCause(e); + } + } + + /** + * This class deals with the parsing of XML using + * <a href="http://java.sun.com/dtd/properties.dtd"> + * http://java.sun.com/dtd/properties.dtd</a>. + * + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @since 1.5 + */ + private class PropertiesHandler + extends DefaultHandler2 + { + + /** + * The current key. + */ + private String key; + + /** + * The current value. + */ + private String value; + + /** + * A flag to check whether a valid DTD declaration has been seen. + */ + private boolean dtdDeclSeen; + + /** + * Constructs a new Properties handler. + */ + public PropertiesHandler() + { + key = null; + value = null; + dtdDeclSeen = false; + } + + /** + * <p> + * Captures the start of the DTD declarations, if they exist. + * A valid properties file must declare the following doctype: + * </p> + * <p> + * <code>!DOCTYPE properties SYSTEM + * "http://java.sun.com/dtd/properties.dtd"</code> + * </p> + * + * @param name the name of the document type. + * @param publicId the public identifier that was declared, or + * null if there wasn't one. + * @param systemId the system identifier that was declared, or + * null if there wasn't one. + * @throws SAXException if some error occurs in parsing. + */ + public void startDTD(String name, String publicId, String systemId) + throws SAXException + { + if (name.equals("properties") && + publicId == null && + systemId.equals("http://java.sun.com/dtd/properties.dtd")) + { + dtdDeclSeen = true; + } + else + throw new SAXException("Invalid DTD declaration: " + name); + } + + /** + * Captures the start of an XML element. + * + * @param uri the namespace URI. + * @param localName the local name of the element inside the namespace. + * @param qName the local name qualified with the namespace URI. + * @param attributes the attributes of this element. + * @throws SAXException if some error occurs in parsing. + */ + public void startElement(String uri, String localName, + String qName, Attributes attributes) + throws SAXException + { + if (qName.equals("entry")) + { + int index = attributes.getIndex("key"); + if (index != -1) + key = attributes.getValue(index); + } + else if (qName.equals("comment") || qName.equals("properties")) + { + /* Ignore it */ + } + else + throw new SAXException("Invalid tag: " + qName); + } + + /** + * Captures characters within an XML element. + * + * @param ch the array of characters. + * @param start the start index of the characters to use. + * @param length the number of characters to use from the start index on. + * @throws SAXException if some error occurs in parsing. + */ + public void characters(char[] ch, int start, int length) + throws SAXException + { + if (key != null) + value = new String(ch,start,length); + } + + /** + * Captures the end of an XML element. + * + * @param uri the namespace URI. + * @param localName the local name of the element inside the namespace. + * @param qName the local name qualified with the namespace URI. + * @throws SAXException if some error occurs in parsing. + */ + public void endElement(String uri, String localName, + String qName) + throws SAXException + { + if (qName.equals("entry")) + { + if (value == null) + value = ""; + setProperty(key, value); + key = null; + value = null; + } + } + + /** + * Captures the end of the XML document. If a DTD declaration has + * not been seen, the document is erroneous and an exception is thrown. + * + * @throws SAXException if the correct DTD declaration didn't appear. + */ + public void endDocument() + throws SAXException + { + if (!dtdDeclSeen) + throw new SAXException("No appropriate DTD declaration was seen."); + } + + } // class PropertiesHandler + } // class Properties |