GNU Classpath (0.20) | |
Frames | No Frames |
1: /* Properties.java -- a set of persistent properties 2: Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.util; 40: 41: import java.io.BufferedReader; 42: import java.io.IOException; 43: import java.io.InputStream; 44: import java.io.InputStreamReader; 45: import java.io.OutputStream; 46: import java.io.OutputStreamWriter; 47: import java.io.PrintStream; 48: import java.io.PrintWriter; 49: 50: import javax.xml.stream.XMLInputFactory; 51: import javax.xml.stream.XMLStreamConstants; 52: import javax.xml.stream.XMLStreamException; 53: import javax.xml.stream.XMLStreamReader; 54: 55: import org.w3c.dom.Document; 56: import org.w3c.dom.DocumentType; 57: import org.w3c.dom.DOMImplementation; 58: import org.w3c.dom.Element; 59: import org.w3c.dom.bootstrap.DOMImplementationRegistry; 60: import org.w3c.dom.ls.DOMImplementationLS; 61: import org.w3c.dom.ls.LSOutput; 62: import org.w3c.dom.ls.LSSerializer; 63: 64: /** 65: * A set of persistent properties, which can be saved or loaded from a stream. 66: * A property list may also contain defaults, searched if the main list 67: * does not contain a property for a given key. 68: * 69: * An example of a properties file for the german language is given 70: * here. This extends the example given in ListResourceBundle. 71: * Create a file MyResource_de.properties with the following contents 72: * and put it in the CLASSPATH. (The character 73: * <code>\</code><code>u00e4</code> is the german umlaut) 74: * 75: * 76: <pre>s1=3 77: s2=MeineDisk 78: s3=3. M\<code></code>u00e4rz 96 79: s4=Die Diskette ''{1}'' enth\<code></code>u00e4lt {0} in {2}. 80: s5=0 81: s6=keine Dateien 82: s7=1 83: s8=eine Datei 84: s9=2 85: s10={0,number} Dateien 86: s11=Das Formatieren schlug fehl mit folgender Exception: {0} 87: s12=FEHLER 88: s13=Ergebnis 89: s14=Dialog 90: s15=Auswahlkriterium 91: s16=1,3</pre> 92: * 93: * <p>Although this is a sub class of a hash table, you should never 94: * insert anything other than strings to this property, or several 95: * methods, that need string keys and values, will fail. To ensure 96: * this, you should use the <code>get/setProperty</code> method instead 97: * of <code>get/put</code>. 98: * 99: * Properties are saved in ISO 8859-1 encoding, using Unicode escapes with 100: * a single <code>u</code> for any character which cannot be represented. 101: * 102: * @author Jochen Hoenicke 103: * @author Eric Blake (ebb9@email.byu.edu) 104: * @see PropertyResourceBundle 105: * @status updated to 1.4 106: */ 107: public class Properties extends Hashtable 108: { 109: // WARNING: Properties is a CORE class in the bootstrap cycle. See the 110: // comments in vm/reference/java/lang/Runtime for implications of this fact. 111: 112: /** 113: * The property list that contains default values for any keys not 114: * in this property list. 115: * 116: * @serial the default properties 117: */ 118: protected Properties defaults; 119: 120: /** 121: * Compatible with JDK 1.0+. 122: */ 123: private static final long serialVersionUID = 4112578634029874840L; 124: 125: /** 126: * Creates a new empty property list with no default values. 127: */ 128: public Properties() 129: { 130: } 131: 132: /** 133: * Create a new empty property list with the specified default values. 134: * 135: * @param defaults a Properties object containing the default values 136: */ 137: public Properties(Properties defaults) 138: { 139: this.defaults = defaults; 140: } 141: 142: /** 143: * Adds the given key/value pair to this properties. This calls 144: * the hashtable method put. 145: * 146: * @param key the key for this property 147: * @param value the value for this property 148: * @return The old value for the given key 149: * @see #getProperty(String) 150: * @since 1.2 151: */ 152: public Object setProperty(String key, String value) 153: { 154: return put(key, value); 155: } 156: 157: /** 158: * Reads a property list from an input stream. The stream should 159: * have the following format: <br> 160: * 161: * An empty line or a line starting with <code>#</code> or 162: * <code>!</code> is ignored. An backslash (<code>\</code>) at the 163: * end of the line makes the line continueing on the next line 164: * (but make sure there is no whitespace after the backslash). 165: * Otherwise, each line describes a key/value pair. <br> 166: * 167: * The chars up to the first whitespace, = or : are the key. You 168: * can include this caracters in the key, if you precede them with 169: * a backslash (<code>\</code>). The key is followed by optional 170: * whitespaces, optionally one <code>=</code> or <code>:</code>, 171: * and optionally some more whitespaces. The rest of the line is 172: * the resource belonging to the key. <br> 173: * 174: * Escape sequences <code>\t, \n, \r, \\, \", \', \!, \#, \ </code>(a 175: * space), and unicode characters with the 176: * <code>\\u</code><em>xxxx</em> notation are detected, and 177: * converted to the corresponding single character. <br> 178: * 179: * 180: <pre># This is a comment 181: key = value 182: k\:5 \ a string starting with space and ending with newline\n 183: # This is a multiline specification; note that the value contains 184: # no white space. 185: weekdays: Sunday,Monday,Tuesday,Wednesday,\\ 186: Thursday,Friday,Saturday 187: # The safest way to include a space at the end of a value: 188: label = Name:\\u0020</pre> 189: * 190: * @param inStream the input stream 191: * @throws IOException if an error occurred when reading the input 192: * @throws NullPointerException if in is null 193: */ 194: public void load(InputStream inStream) throws IOException 195: { 196: // The spec says that the file must be encoded using ISO-8859-1. 197: BufferedReader reader = 198: new BufferedReader(new InputStreamReader(inStream, "ISO-8859-1")); 199: String line; 200: 201: while ((line = reader.readLine()) != null) 202: { 203: char c = 0; 204: int pos = 0; 205: // Leading whitespaces must be deleted first. 206: while (pos < line.length() 207: && Character.isWhitespace(c = line.charAt(pos))) 208: pos++; 209: 210: // If empty line or begins with a comment character, skip this line. 211: if ((line.length() - pos) == 0 212: || line.charAt(pos) == '#' || line.charAt(pos) == '!') 213: continue; 214: 215: // The characters up to the next Whitespace, ':', or '=' 216: // describe the key. But look for escape sequences. 217: // Try to short-circuit when there is no escape char. 218: int start = pos; 219: boolean needsEscape = line.indexOf('\\', pos) != -1; 220: StringBuilder key = needsEscape ? new StringBuilder() : null; 221: while (pos < line.length() 222: && ! Character.isWhitespace(c = line.charAt(pos++)) 223: && c != '=' && c != ':') 224: { 225: if (needsEscape && c == '\\') 226: { 227: if (pos == line.length()) 228: { 229: // The line continues on the next line. If there 230: // is no next line, just treat it as a key with an 231: // empty value. 232: line = reader.readLine(); 233: if (line == null) 234: line = ""; 235: pos = 0; 236: while (pos < line.length() 237: && Character.isWhitespace(c = line.charAt(pos))) 238: pos++; 239: } 240: else 241: { 242: c = line.charAt(pos++); 243: switch (c) 244: { 245: case 'n': 246: key.append('\n'); 247: break; 248: case 't': 249: key.append('\t'); 250: break; 251: case 'r': 252: key.append('\r'); 253: break; 254: case 'u': 255: if (pos + 4 <= line.length()) 256: { 257: char uni = (char) Integer.parseInt 258: (line.substring(pos, pos + 4), 16); 259: key.append(uni); 260: pos += 4; 261: } // else throw exception? 262: break; 263: default: 264: key.append(c); 265: break; 266: } 267: } 268: } 269: else if (needsEscape) 270: key.append(c); 271: } 272: 273: boolean isDelim = (c == ':' || c == '='); 274: 275: String keyString; 276: if (needsEscape) 277: keyString = key.toString(); 278: else if (isDelim || Character.isWhitespace(c)) 279: keyString = line.substring(start, pos - 1); 280: else 281: keyString = line.substring(start, pos); 282: 283: while (pos < line.length() 284: && Character.isWhitespace(c = line.charAt(pos))) 285: pos++; 286: 287: if (! isDelim && (c == ':' || c == '=')) 288: { 289: pos++; 290: while (pos < line.length() 291: && Character.isWhitespace(c = line.charAt(pos))) 292: pos++; 293: } 294: 295: // Short-circuit if no escape chars found. 296: if (!needsEscape) 297: { 298: put(keyString, line.substring(pos)); 299: continue; 300: } 301: 302: // Escape char found so iterate through the rest of the line. 303: StringBuilder element = new StringBuilder(line.length() - pos); 304: while (pos < line.length()) 305: { 306: c = line.charAt(pos++); 307: if (c == '\\') 308: { 309: if (pos == line.length()) 310: { 311: // The line continues on the next line. 312: line = reader.readLine(); 313: 314: // We might have seen a backslash at the end of 315: // the file. The JDK ignores the backslash in 316: // this case, so we follow for compatibility. 317: if (line == null) 318: break; 319: 320: pos = 0; 321: while (pos < line.length() 322: && Character.isWhitespace(c = line.charAt(pos))) 323: pos++; 324: element.ensureCapacity(line.length() - pos + 325: element.length()); 326: } 327: else 328: { 329: c = line.charAt(pos++); 330: switch (c) 331: { 332: case 'n': 333: element.append('\n'); 334: break; 335: case 't': 336: element.append('\t'); 337: break; 338: case 'r': 339: element.append('\r'); 340: break; 341: case 'u': 342: if (pos + 4 <= line.length()) 343: { 344: char uni = (char) Integer.parseInt 345: (line.substring(pos, pos + 4), 16); 346: element.append(uni); 347: pos += 4; 348: } // else throw exception? 349: break; 350: default: 351: element.append(c); 352: break; 353: } 354: } 355: } 356: else 357: element.append(c); 358: } 359: put(keyString, element.toString()); 360: } 361: } 362: 363: /** 364: * Calls <code>store(OutputStream out, String header)</code> and 365: * ignores the IOException that may be thrown. 366: * 367: * @param out the stream to write to 368: * @param header a description of the property list 369: * @throws ClassCastException if this property contains any key or 370: * value that are not strings 371: * @deprecated use {@link #store(OutputStream, String)} instead 372: */ 373: public void save(OutputStream out, String header) 374: { 375: try 376: { 377: store(out, header); 378: } 379: catch (IOException ex) 380: { 381: } 382: } 383: 384: /** 385: * Writes the key/value pairs to the given output stream, in a format 386: * suitable for <code>load</code>.<br> 387: * 388: * If header is not null, this method writes a comment containing 389: * the header as first line to the stream. The next line (or first 390: * line if header is null) contains a comment with the current date. 391: * Afterwards the key/value pairs are written to the stream in the 392: * following format.<br> 393: * 394: * Each line has the form <code>key = value</code>. Newlines, 395: * Returns and tabs are written as <code>\n,\t,\r</code> resp. 396: * The characters <code>\, !, #, =</code> and <code>:</code> are 397: * preceeded by a backslash. Spaces are preceded with a backslash, 398: * if and only if they are at the beginning of the key. Characters 399: * that are not in the ascii range 33 to 127 are written in the 400: * <code>\</code><code>u</code>xxxx Form.<br> 401: * 402: * Following the listing, the output stream is flushed but left open. 403: * 404: * @param out the output stream 405: * @param header the header written in the first line, may be null 406: * @throws ClassCastException if this property contains any key or 407: * value that isn't a string 408: * @throws IOException if writing to the stream fails 409: * @throws NullPointerException if out is null 410: * @since 1.2 411: */ 412: public void store(OutputStream out, String header) throws IOException 413: { 414: // The spec says that the file must be encoded using ISO-8859-1. 415: PrintWriter writer 416: = new PrintWriter(new OutputStreamWriter(out, "ISO-8859-1")); 417: if (header != null) 418: writer.println("#" + header); 419: writer.println ("#" + Calendar.getInstance ().getTime ()); 420: 421: Iterator iter = entrySet ().iterator (); 422: int i = size (); 423: StringBuilder s = new StringBuilder (); // Reuse the same buffer. 424: while (--i >= 0) 425: { 426: Map.Entry entry = (Map.Entry) iter.next (); 427: formatForOutput ((String) entry.getKey (), s, true); 428: s.append ('='); 429: formatForOutput ((String) entry.getValue (), s, false); 430: writer.println (s); 431: } 432: 433: writer.flush (); 434: } 435: 436: /** 437: * Gets the property with the specified key in this property list. 438: * If the key is not found, the default property list is searched. 439: * If the property is not found in the default, null is returned. 440: * 441: * @param key The key for this property 442: * @return the value for the given key, or null if not found 443: * @throws ClassCastException if this property contains any key or 444: * value that isn't a string 445: * @see #defaults 446: * @see #setProperty(String, String) 447: * @see #getProperty(String, String) 448: */ 449: public String getProperty(String key) 450: { 451: Properties prop = this; 452: // Eliminate tail recursion. 453: do 454: { 455: String value = (String) prop.get(key); 456: if (value != null) 457: return value; 458: prop = prop.defaults; 459: } 460: while (prop != null); 461: return null; 462: } 463: 464: /** 465: * Gets the property with the specified key in this property list. If 466: * the key is not found, the default property list is searched. If the 467: * property is not found in the default, the specified defaultValue is 468: * returned. 469: * 470: * @param key The key for this property 471: * @param defaultValue A default value 472: * @return The value for the given key 473: * @throws ClassCastException if this property contains any key or 474: * value that isn't a string 475: * @see #defaults 476: * @see #setProperty(String, String) 477: */ 478: public String getProperty(String key, String defaultValue) 479: { 480: String prop = getProperty(key); 481: if (prop == null) 482: prop = defaultValue; 483: return prop; 484: } 485: 486: /** 487: * Returns an enumeration of all keys in this property list, including 488: * the keys in the default property list. 489: * 490: * @return an Enumeration of all defined keys 491: */ 492: public Enumeration propertyNames() 493: { 494: // We make a new Set that holds all the keys, then return an enumeration 495: // for that. This prevents modifications from ruining the enumeration, 496: // as well as ignoring duplicates. 497: Properties prop = this; 498: Set s = new HashSet(); 499: // Eliminate tail recursion. 500: do 501: { 502: s.addAll(prop.keySet()); 503: prop = prop.defaults; 504: } 505: while (prop != null); 506: return Collections.enumeration(s); 507: } 508: 509: /** 510: * Prints the key/value pairs to the given print stream. This is 511: * mainly useful for debugging purposes. 512: * 513: * @param out the print stream, where the key/value pairs are written to 514: * @throws ClassCastException if this property contains a key or a 515: * value that isn't a string 516: * @see #list(PrintWriter) 517: */ 518: public void list(PrintStream out) 519: { 520: PrintWriter writer = new PrintWriter (out); 521: list (writer); 522: } 523: 524: /** 525: * Prints the key/value pairs to the given print writer. This is 526: * mainly useful for debugging purposes. 527: * 528: * @param out the print writer where the key/value pairs are written to 529: * @throws ClassCastException if this property contains a key or a 530: * value that isn't a string 531: * @see #list(PrintStream) 532: * @since 1.1 533: */ 534: public void list(PrintWriter out) 535: { 536: out.println ("-- listing properties --"); 537: 538: Iterator iter = entrySet ().iterator (); 539: int i = size (); 540: while (--i >= 0) 541: { 542: Map.Entry entry = (Map.Entry) iter.next (); 543: out.print ((String) entry.getKey () + "="); 544: 545: // JDK 1.3/1.4 restrict the printed value, but not the key, 546: // to 40 characters, including the truncating ellipsis. 547: String s = (String ) entry.getValue (); 548: if (s != null && s.length () > 40) 549: out.println (s.substring (0, 37) + "..."); 550: else 551: out.println (s); 552: } 553: out.flush (); 554: } 555: 556: /** 557: * Formats a key or value for output in a properties file. 558: * See store for a description of the format. 559: * 560: * @param str the string to format 561: * @param buffer the buffer to add it to 562: * @param key true if all ' ' must be escaped for the key, false if only 563: * leading spaces must be escaped for the value 564: * @see #store(OutputStream, String) 565: */ 566: private void formatForOutput(String str, StringBuilder buffer, boolean key) 567: { 568: if (key) 569: { 570: buffer.setLength(0); 571: buffer.ensureCapacity(str.length()); 572: } 573: else 574: buffer.ensureCapacity(buffer.length() + str.length()); 575: boolean head = true; 576: int size = str.length(); 577: for (int i = 0; i < size; i++) 578: { 579: char c = str.charAt(i); 580: switch (c) 581: { 582: case '\n': 583: buffer.append("\\n"); 584: break; 585: case '\r': 586: buffer.append("\\r"); 587: break; 588: case '\t': 589: buffer.append("\\t"); 590: break; 591: case ' ': 592: buffer.append(head ? "\\ " : " "); 593: break; 594: case '\\': 595: case '!': 596: case '#': 597: case '=': 598: case ':': 599: buffer.append('\\').append(c); 600: break; 601: default: 602: if (c < ' ' || c > '~') 603: { 604: String hex = Integer.toHexString(c); 605: buffer.append("\\u0000".substring(0, 6 - hex.length())); 606: buffer.append(hex); 607: } 608: else 609: buffer.append(c); 610: } 611: if (c != ' ') 612: head = key; 613: } 614: } 615: 616: /** 617: * <p> 618: * Encodes the properties as an XML file using the UTF-8 encoding. 619: * The format of the XML file matches the DTD 620: * <a href="http://java.sun.com/dtd/properties.dtd"> 621: * http://java.sun.com/dtd/properties.dtd</a>. 622: * </p> 623: * <p> 624: * Invoking this method provides the same behaviour as invoking 625: * <code>storeToXML(os, comment, "UTF-8")</code>. 626: * </p> 627: * 628: * @param os the stream to output to. 629: * @param comment a comment to include at the top of the XML file, or 630: * <code>null</code> if one is not required. 631: * @throws IOException if the serialization fails. 632: * @throws NullPointerException if <code>os</code> is null. 633: * @since 1.5 634: */ 635: public void storeToXML(OutputStream os, String comment) 636: throws IOException 637: { 638: storeToXML(os, comment, "UTF-8"); 639: } 640: 641: /** 642: * <p> 643: * Encodes the properties as an XML file using the supplied encoding. 644: * The format of the XML file matches the DTD 645: * <a href="http://java.sun.com/dtd/properties.dtd"> 646: * http://java.sun.com/dtd/properties.dtd</a>. 647: * </p> 648: * 649: * @param os the stream to output to. 650: * @param comment a comment to include at the top of the XML file, or 651: * <code>null</code> if one is not required. 652: * @param encoding the encoding to use for the XML output. 653: * @throws IOException if the serialization fails. 654: * @throws NullPointerException if <code>os</code> or <code>encoding</code> 655: * is null. 656: * @since 1.5 657: */ 658: public void storeToXML(OutputStream os, String comment, String encoding) 659: throws IOException 660: { 661: if (os == null) 662: throw new NullPointerException("Null output stream supplied."); 663: if (encoding == null) 664: throw new NullPointerException("Null encoding supplied."); 665: try 666: { 667: DOMImplementationRegistry registry = 668: DOMImplementationRegistry.newInstance(); 669: DOMImplementation domImpl = registry.getDOMImplementation("LS 3.0"); 670: DocumentType doctype = 671: domImpl.createDocumentType("properties", null, 672: "http://java.sun.com/dtd/properties.dtd"); 673: Document doc = domImpl.createDocument(null, "properties", doctype); 674: Element root = doc.getDocumentElement(); 675: if (comment != null) 676: { 677: Element commentElement = doc.createElement("comment"); 678: commentElement.appendChild(doc.createTextNode(comment)); 679: root.appendChild(commentElement); 680: } 681: Iterator iterator = entrySet().iterator(); 682: while (iterator.hasNext()) 683: { 684: Map.Entry entry = (Map.Entry) iterator.next(); 685: Element entryElement = doc.createElement("entry"); 686: entryElement.setAttribute("key", (String) entry.getKey()); 687: entryElement.appendChild(doc.createTextNode((String) 688: entry.getValue())); 689: root.appendChild(entryElement); 690: } 691: DOMImplementationLS loadAndSave = (DOMImplementationLS) domImpl; 692: LSSerializer serializer = loadAndSave.createLSSerializer(); 693: LSOutput output = loadAndSave.createLSOutput(); 694: output.setByteStream(os); 695: output.setEncoding(encoding); 696: serializer.write(doc, output); 697: } 698: catch (ClassNotFoundException e) 699: { 700: throw (IOException) 701: new IOException("The XML classes could not be found.").initCause(e); 702: } 703: catch (InstantiationException e) 704: { 705: throw (IOException) 706: new IOException("The XML classes could not be instantiated.") 707: .initCause(e); 708: } 709: catch (IllegalAccessException e) 710: { 711: throw (IOException) 712: new IOException("The XML classes could not be accessed.") 713: .initCause(e); 714: } 715: } 716: 717: /** 718: * <p> 719: * Decodes the contents of the supplied <code>InputStream</code> as 720: * an XML file, which represents a set of properties. The format of 721: * the XML file must match the DTD 722: * <a href="http://java.sun.com/dtd/properties.dtd"> 723: * http://java.sun.com/dtd/properties.dtd</a>. 724: * </p> 725: * 726: * @param in the input stream from which to receive the XML data. 727: * @throws IOException if an I/O error occurs in reading the input data. 728: * @throws InvalidPropertiesFormatException if the input data does not 729: * constitute an XML properties 730: * file. 731: * @throws NullPointerException if <code>in</code> is null. 732: * @since 1.5 733: */ 734: public void loadFromXML(InputStream in) 735: throws IOException, InvalidPropertiesFormatException 736: { 737: if (in == null) 738: throw new NullPointerException("Null input stream supplied."); 739: try 740: { 741: XMLInputFactory factory = XMLInputFactory.newInstance(); 742: // Don't resolve external entity references 743: factory.setProperty("javax.xml.stream.isSupportingExternalEntities", 744: Boolean.FALSE); 745: XMLStreamReader reader = factory.createXMLStreamReader(in); 746: String name, key = null; 747: StringBuffer buf = null; 748: while (reader.hasNext()) 749: { 750: switch (reader.next()) 751: { 752: case XMLStreamConstants.START_ELEMENT: 753: name = reader.getLocalName(); 754: if (buf == null && "entry".equals(name)) 755: { 756: key = reader.getAttributeValue(null, "key"); 757: if (key == null) 758: { 759: String msg = "missing 'key' attribute"; 760: throw new InvalidPropertiesFormatException(msg); 761: } 762: buf = new StringBuffer(); 763: } 764: else if (!"properties".equals(name) && !"comment".equals(name)) 765: { 766: String msg = "unexpected element name '" + name + "'"; 767: throw new InvalidPropertiesFormatException(msg); 768: } 769: break; 770: case XMLStreamConstants.END_ELEMENT: 771: name = reader.getLocalName(); 772: if (buf != null && "entry".equals(name)) 773: { 774: put(key, buf.toString()); 775: buf = null; 776: } 777: else if (!"properties".equals(name) && !"comment".equals(name)) 778: { 779: String msg = "unexpected element name '" + name + "'"; 780: throw new InvalidPropertiesFormatException(msg); 781: } 782: break; 783: case XMLStreamConstants.CHARACTERS: 784: case XMLStreamConstants.SPACE: 785: case XMLStreamConstants.CDATA: 786: if (buf != null) 787: buf.append(reader.getText()); 788: break; 789: } 790: } 791: reader.close(); 792: } 793: catch (XMLStreamException e) 794: { 795: throw (InvalidPropertiesFormatException) 796: new InvalidPropertiesFormatException("Error in parsing XML."). 797: initCause(e); 798: } 799: } 800: 801: } // class Properties
GNU Classpath (0.20) |