| /* 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 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 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 |
| * <code>\</code><code>u00e4</code> is the german umlaut) |
| * |
| * |
| <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> |
| * |
| * <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>. |
| * |
| * 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<Object, Object> |
| { |
| // 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 an input stream. The stream should |
| * have the following format: <br> |
| * |
| * An empty line or a line starting with <code>#</code> or |
| * <code>!</code> is ignored. An backslash (<code>\</code>) 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. <br> |
| * |
| * 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 (<code>\</code>). The key is followed by optional |
| * whitespaces, optionally one <code>=</code> or <code>:</code>, |
| * and optionally some more whitespaces. The rest of the line is |
| * the resource belonging to the key. <br> |
| * |
| * Escape sequences <code>\t, \n, \r, \\, \", \', \!, \#, \ </code>(a |
| * space), and unicode characters with the |
| * <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:\\u0020</pre> |
| * |
| * @param inStream the input stream |
| * @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; |
| // 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; |
| StringBuilder key = needsEscape ? new StringBuilder() : 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()); |
| } |
| } |
| |
| /** |
| * Calls <code>store(OutputStream out, String header)</code> 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 <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> |
| * |
| * Each line has the form <code>key = value</code>. Newlines, |
| * Returns and tabs are written as <code>\n,\t,\r</code> resp. |
| * The characters <code>\, !, #, =</code> and <code>:</code> 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 |
| * <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 |
| * @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 (); |
| StringBuilder s = new StringBuilder (); // 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, StringBuilder 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; |
| } |
| } |
| |
| /** |
| * <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 |
| { |
| 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; |
| StringBuffer 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 StringBuffer(); |
| } |
| 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 |