GNU Classpath (0.95) | |
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<Object, Object> 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: @Deprecated 374: public void save(OutputStream out, String header) 375: { 376: try 377: { 378: store(out, header); 379: } 380: catch (IOException ex) 381: { 382: } 383: } 384: 385: /** 386: * Writes the key/value pairs to the given output stream, in a format 387: * suitable for <code>load</code>.<br> 388: * 389: * If header is not null, this method writes a comment containing 390: * the header as first line to the stream. The next line (or first 391: * line if header is null) contains a comment with the current date. 392: * Afterwards the key/value pairs are written to the stream in the 393: * following format.<br> 394: * 395: * Each line has the form <code>key = value</code>. Newlines, 396: * Returns and tabs are written as <code>\n,\t,\r</code> resp. 397: * The characters <code>\, !, #, =</code> and <code>:</code> are 398: * preceeded by a backslash. Spaces are preceded with a backslash, 399: * if and only if they are at the beginning of the key. Characters 400: * that are not in the ascii range 33 to 127 are written in the 401: * <code>\</code><code>u</code>xxxx Form.<br> 402: * 403: * Following the listing, the output stream is flushed but left open. 404: * 405: * @param out the output stream 406: * @param header the header written in the first line, may be null 407: * @throws ClassCastException if this property contains any key or 408: * value that isn't a string 409: * @throws IOException if writing to the stream fails 410: * @throws NullPointerException if out is null 411: * @since 1.2 412: */ 413: public void store(OutputStream out, String header) throws IOException 414: { 415: // The spec says that the file must be encoded using ISO-8859-1. 416: PrintWriter writer 417: = new PrintWriter(new OutputStreamWriter(out, "ISO-8859-1")); 418: if (header != null) 419: writer.println("#" + header); 420: writer.println ("#" + Calendar.getInstance ().getTime ()); 421: 422: Iterator iter = entrySet ().iterator (); 423: int i = size (); 424: StringBuilder s = new StringBuilder (); // Reuse the same buffer. 425: while (--i >= 0) 426: { 427: Map.Entry entry = (Map.Entry) iter.next (); 428: formatForOutput ((String) entry.getKey (), s, true); 429: s.append ('='); 430: formatForOutput ((String) entry.getValue (), s, false); 431: writer.println (s); 432: } 433: 434: writer.flush (); 435: } 436: 437: /** 438: * Gets the property with the specified key in this property list. 439: * If the key is not found, the default property list is searched. 440: * If the property is not found in the default, null is returned. 441: * 442: * @param key The key for this property 443: * @return the value for the given key, or null if not found 444: * @throws ClassCastException if this property contains any key or 445: * value that isn't a string 446: * @see #defaults 447: * @see #setProperty(String, String) 448: * @see #getProperty(String, String) 449: */ 450: public String getProperty(String key) 451: { 452: Properties prop = this; 453: // Eliminate tail recursion. 454: do 455: { 456: String value = (String) prop.get(key); 457: if (value != null) 458: return value; 459: prop = prop.defaults; 460: } 461: while (prop != null); 462: return null; 463: } 464: 465: /** 466: * Gets the property with the specified key in this property list. If 467: * the key is not found, the default property list is searched. If the 468: * property is not found in the default, the specified defaultValue is 469: * returned. 470: * 471: * @param key The key for this property 472: * @param defaultValue A default value 473: * @return The value for the given key 474: * @throws ClassCastException if this property contains any key or 475: * value that isn't a string 476: * @see #defaults 477: * @see #setProperty(String, String) 478: */ 479: public String getProperty(String key, String defaultValue) 480: { 481: String prop = getProperty(key); 482: if (prop == null) 483: prop = defaultValue; 484: return prop; 485: } 486: 487: /** 488: * Returns an enumeration of all keys in this property list, including 489: * the keys in the default property list. 490: * 491: * @return an Enumeration of all defined keys 492: */ 493: public Enumeration<?> propertyNames() 494: { 495: // We make a new Set that holds all the keys, then return an enumeration 496: // for that. This prevents modifications from ruining the enumeration, 497: // as well as ignoring duplicates. 498: Properties prop = this; 499: Set s = new HashSet(); 500: // Eliminate tail recursion. 501: do 502: { 503: s.addAll(prop.keySet()); 504: prop = prop.defaults; 505: } 506: while (prop != null); 507: return Collections.enumeration(s); 508: } 509: 510: /** 511: * Prints the key/value pairs to the given print stream. This is 512: * mainly useful for debugging purposes. 513: * 514: * @param out the print stream, where the key/value pairs are written to 515: * @throws ClassCastException if this property contains a key or a 516: * value that isn't a string 517: * @see #list(PrintWriter) 518: */ 519: public void list(PrintStream out) 520: { 521: PrintWriter writer = new PrintWriter (out); 522: list (writer); 523: } 524: 525: /** 526: * Prints the key/value pairs to the given print writer. This is 527: * mainly useful for debugging purposes. 528: * 529: * @param out the print writer where the key/value pairs are written to 530: * @throws ClassCastException if this property contains a key or a 531: * value that isn't a string 532: * @see #list(PrintStream) 533: * @since 1.1 534: */ 535: public void list(PrintWriter out) 536: { 537: out.println ("-- listing properties --"); 538: 539: Iterator iter = entrySet ().iterator (); 540: int i = size (); 541: while (--i >= 0) 542: { 543: Map.Entry entry = (Map.Entry) iter.next (); 544: out.print ((String) entry.getKey () + "="); 545: 546: // JDK 1.3/1.4 restrict the printed value, but not the key, 547: // to 40 characters, including the truncating ellipsis. 548: String s = (String ) entry.getValue (); 549: if (s != null && s.length () > 40) 550: out.println (s.substring (0, 37) + "..."); 551: else 552: out.println (s); 553: } 554: out.flush (); 555: } 556: 557: /** 558: * Formats a key or value for output in a properties file. 559: * See store for a description of the format. 560: * 561: * @param str the string to format 562: * @param buffer the buffer to add it to 563: * @param key true if all ' ' must be escaped for the key, false if only 564: * leading spaces must be escaped for the value 565: * @see #store(OutputStream, String) 566: */ 567: private void formatForOutput(String str, StringBuilder buffer, boolean key) 568: { 569: if (key) 570: { 571: buffer.setLength(0); 572: buffer.ensureCapacity(str.length()); 573: } 574: else 575: buffer.ensureCapacity(buffer.length() + str.length()); 576: boolean head = true; 577: int size = str.length(); 578: for (int i = 0; i < size; i++) 579: { 580: char c = str.charAt(i); 581: switch (c) 582: { 583: case '\n': 584: buffer.append("\\n"); 585: break; 586: case '\r': 587: buffer.append("\\r"); 588: break; 589: case '\t': 590: buffer.append("\\t"); 591: break; 592: case ' ': 593: buffer.append(head ? "\\ " : " "); 594: break; 595: case '\\': 596: case '!': 597: case '#': 598: case '=': 599: case ':': 600: buffer.append('\\').append(c); 601: break; 602: default: 603: if (c < ' ' || c > '~') 604: { 605: String hex = Integer.toHexString(c); 606: buffer.append("\\u0000".substring(0, 6 - hex.length())); 607: buffer.append(hex); 608: } 609: else 610: buffer.append(c); 611: } 612: if (c != ' ') 613: head = key; 614: } 615: } 616: 617: /** 618: * <p> 619: * Encodes the properties as an XML file using the UTF-8 encoding. 620: * The format of the XML file matches the DTD 621: * <a href="http://java.sun.com/dtd/properties.dtd"> 622: * http://java.sun.com/dtd/properties.dtd</a>. 623: * </p> 624: * <p> 625: * Invoking this method provides the same behaviour as invoking 626: * <code>storeToXML(os, comment, "UTF-8")</code>. 627: * </p> 628: * 629: * @param os the stream to output to. 630: * @param comment a comment to include at the top of the XML file, or 631: * <code>null</code> if one is not required. 632: * @throws IOException if the serialization fails. 633: * @throws NullPointerException if <code>os</code> is null. 634: * @since 1.5 635: */ 636: public void storeToXML(OutputStream os, String comment) 637: throws IOException 638: { 639: storeToXML(os, comment, "UTF-8"); 640: } 641: 642: /** 643: * <p> 644: * Encodes the properties as an XML file using the supplied encoding. 645: * The format of the XML file matches the DTD 646: * <a href="http://java.sun.com/dtd/properties.dtd"> 647: * http://java.sun.com/dtd/properties.dtd</a>. 648: * </p> 649: * 650: * @param os the stream to output to. 651: * @param comment a comment to include at the top of the XML file, or 652: * <code>null</code> if one is not required. 653: * @param encoding the encoding to use for the XML output. 654: * @throws IOException if the serialization fails. 655: * @throws NullPointerException if <code>os</code> or <code>encoding</code> 656: * is null. 657: * @since 1.5 658: */ 659: public void storeToXML(OutputStream os, String comment, String encoding) 660: throws IOException 661: { 662: if (os == null) 663: throw new NullPointerException("Null output stream supplied."); 664: if (encoding == null) 665: throw new NullPointerException("Null encoding supplied."); 666: try 667: { 668: DOMImplementationRegistry registry = 669: DOMImplementationRegistry.newInstance(); 670: DOMImplementation domImpl = registry.getDOMImplementation("LS 3.0"); 671: DocumentType doctype = 672: domImpl.createDocumentType("properties", null, 673: "http://java.sun.com/dtd/properties.dtd"); 674: Document doc = domImpl.createDocument(null, "properties", doctype); 675: Element root = doc.getDocumentElement(); 676: if (comment != null) 677: { 678: Element commentElement = doc.createElement("comment"); 679: commentElement.appendChild(doc.createTextNode(comment)); 680: root.appendChild(commentElement); 681: } 682: Iterator iterator = entrySet().iterator(); 683: while (iterator.hasNext()) 684: { 685: Map.Entry entry = (Map.Entry) iterator.next(); 686: Element entryElement = doc.createElement("entry"); 687: entryElement.setAttribute("key", (String) entry.getKey()); 688: entryElement.appendChild(doc.createTextNode((String) 689: entry.getValue())); 690: root.appendChild(entryElement); 691: } 692: DOMImplementationLS loadAndSave = (DOMImplementationLS) domImpl; 693: LSSerializer serializer = loadAndSave.createLSSerializer(); 694: LSOutput output = loadAndSave.createLSOutput(); 695: output.setByteStream(os); 696: output.setEncoding(encoding); 697: serializer.write(doc, output); 698: } 699: catch (ClassNotFoundException e) 700: { 701: throw (IOException) 702: new IOException("The XML classes could not be found.").initCause(e); 703: } 704: catch (InstantiationException e) 705: { 706: throw (IOException) 707: new IOException("The XML classes could not be instantiated.") 708: .initCause(e); 709: } 710: catch (IllegalAccessException e) 711: { 712: throw (IOException) 713: new IOException("The XML classes could not be accessed.") 714: .initCause(e); 715: } 716: } 717: 718: /** 719: * <p> 720: * Decodes the contents of the supplied <code>InputStream</code> as 721: * an XML file, which represents a set of properties. The format of 722: * the XML file must match the DTD 723: * <a href="http://java.sun.com/dtd/properties.dtd"> 724: * http://java.sun.com/dtd/properties.dtd</a>. 725: * </p> 726: * 727: * @param in the input stream from which to receive the XML data. 728: * @throws IOException if an I/O error occurs in reading the input data. 729: * @throws InvalidPropertiesFormatException if the input data does not 730: * constitute an XML properties 731: * file. 732: * @throws NullPointerException if <code>in</code> is null. 733: * @since 1.5 734: */ 735: public void loadFromXML(InputStream in) 736: throws IOException, InvalidPropertiesFormatException 737: { 738: if (in == null) 739: throw new NullPointerException("Null input stream supplied."); 740: try 741: { 742: XMLInputFactory factory = XMLInputFactory.newInstance(); 743: // Don't resolve external entity references 744: factory.setProperty("javax.xml.stream.isSupportingExternalEntities", 745: Boolean.FALSE); 746: XMLStreamReader reader = factory.createXMLStreamReader(in); 747: String name, key = null; 748: StringBuffer buf = null; 749: while (reader.hasNext()) 750: { 751: switch (reader.next()) 752: { 753: case XMLStreamConstants.START_ELEMENT: 754: name = reader.getLocalName(); 755: if (buf == null && "entry".equals(name)) 756: { 757: key = reader.getAttributeValue(null, "key"); 758: if (key == null) 759: { 760: String msg = "missing 'key' attribute"; 761: throw new InvalidPropertiesFormatException(msg); 762: } 763: buf = new StringBuffer(); 764: } 765: else if (!"properties".equals(name) && !"comment".equals(name)) 766: { 767: String msg = "unexpected element name '" + name + "'"; 768: throw new InvalidPropertiesFormatException(msg); 769: } 770: break; 771: case XMLStreamConstants.END_ELEMENT: 772: name = reader.getLocalName(); 773: if (buf != null && "entry".equals(name)) 774: { 775: put(key, buf.toString()); 776: buf = null; 777: } 778: else if (!"properties".equals(name) && !"comment".equals(name)) 779: { 780: String msg = "unexpected element name '" + name + "'"; 781: throw new InvalidPropertiesFormatException(msg); 782: } 783: break; 784: case XMLStreamConstants.CHARACTERS: 785: case XMLStreamConstants.SPACE: 786: case XMLStreamConstants.CDATA: 787: if (buf != null) 788: buf.append(reader.getText()); 789: break; 790: } 791: } 792: reader.close(); 793: } 794: catch (XMLStreamException e) 795: { 796: throw (InvalidPropertiesFormatException) 797: new InvalidPropertiesFormatException("Error in parsing XML."). 798: initCause(e); 799: } 800: } 801: 802: } // class Properties
GNU Classpath (0.95) |