1 25 26 27 package com.sslexplorer.agent.client.util; 28 29 import java.io.ByteArrayOutputStream ; 30 import java.io.CharArrayReader ; 31 import java.io.IOException ; 32 import java.io.OutputStreamWriter ; 33 import java.io.Reader ; 34 import java.io.StringReader ; 35 import java.io.Writer ; 36 import java.text.MessageFormat ; 37 import java.util.Enumeration ; 38 import java.util.Hashtable ; 39 import java.util.Vector ; 40 41 42 99 public class XMLElement 100 { 101 102 105 static final long serialVersionUID = 6685035139346394777L; 106 107 108 116 public static final int NANOXML_MAJOR_VERSION = 2; 117 118 119 127 public static final int NANOXML_MINOR_VERSION = 2; 128 129 130 139 private Hashtable attributes; 140 141 142 152 private Vector children; 153 154 155 166 private String name; 167 168 169 178 private String contents; 179 180 181 195 private Hashtable entities; 196 197 198 205 private int lineNr; 206 207 208 212 private boolean ignoreCase; 213 214 215 219 private boolean ignoreWhitespace; 220 221 222 228 private char charReadTooMuch; 229 230 231 239 private Reader reader; 240 241 242 249 private int parserLineNr; 250 251 252 274 public XMLElement() 275 { 276 this(new Hashtable (), false, true, true); 277 } 278 279 280 308 public XMLElement(Hashtable entities) 309 { 310 this(entities, false, true, true); 311 } 312 313 314 340 public XMLElement(boolean skipLeadingWhitespace) 341 { 342 this(new Hashtable (), skipLeadingWhitespace, true, true); 343 } 344 345 346 377 public XMLElement(Hashtable entities, 378 boolean skipLeadingWhitespace) 379 { 380 this(entities, skipLeadingWhitespace, true, true); 381 } 382 383 384 417 public XMLElement(Hashtable entities, 418 boolean skipLeadingWhitespace, 419 boolean ignoreCase) 420 { 421 this(entities, skipLeadingWhitespace, true, ignoreCase); 422 } 423 424 425 464 protected XMLElement(Hashtable entities, 465 boolean skipLeadingWhitespace, 466 boolean fillBasicConversionTable, 467 boolean ignoreCase) 468 { 469 this.ignoreWhitespace = skipLeadingWhitespace; 470 this.ignoreCase = ignoreCase; 471 this.name = null; 472 this.contents = ""; this.attributes = new Hashtable (); 474 this.children = new Vector (); 475 this.entities = entities; 476 this.lineNr = 0; 477 Enumeration e = this.entities.keys(); 478 while (e.hasMoreElements()) { 479 Object key = e.nextElement(); 480 Object value = this.entities.get(key); 481 if (value instanceof String ) { 482 value = ((String ) value).toCharArray(); 483 this.entities.put(key, value); 484 } 485 } 486 if (fillBasicConversionTable) { 487 this.entities.put("amp", new char[] { '&' }); this.entities.put("quot", new char[] { '"' }); this.entities.put("apos", new char[] { '\'' }); this.entities.put("lt", new char[] { '<' }); this.entities.put("gt", new char[] { '>' }); } 493 } 494 495 496 520 public void addChild(XMLElement child) 521 { 522 this.children.addElement(child); 523 } 524 525 526 569 public void setAttribute(String name, 570 Object value) 571 { 572 if (this.ignoreCase) { 573 name = name.toUpperCase(); 574 } 575 this.attributes.put(name, value.toString()); 576 } 577 578 579 590 public void addProperty(String name, 591 Object value) 592 { 593 this.setAttribute(name, value); 594 } 595 596 597 632 public void setIntAttribute(String name, 633 int value) 634 { 635 if (this.ignoreCase) { 636 name = name.toUpperCase(); 637 } 638 this.attributes.put(name, Integer.toString(value)); 639 } 640 641 642 653 public void addProperty(String key, 654 int value) 655 { 656 this.setIntAttribute(key, value); 657 } 658 659 660 695 public void setDoubleAttribute(String name, 696 double value) 697 { 698 if (this.ignoreCase) { 699 name = name.toUpperCase(); 700 } 701 this.attributes.put(name, Double.toString(value)); 702 } 703 704 705 716 public void addProperty(String name, 717 double value) 718 { 719 this.setDoubleAttribute(name, value); 720 } 721 722 723 738 public int countChildren() 739 { 740 return this.children.size(); 741 } 742 743 744 798 public Enumeration enumerateAttributeNames() 799 { 800 return this.attributes.keys(); 801 } 802 803 804 811 public Enumeration enumeratePropertyNames() 812 { 813 return this.enumerateAttributeNames(); 814 } 815 816 817 832 public Enumeration enumerateChildren() 833 { 834 return this.children.elements(); 835 } 836 837 838 854 public Vector getChildren() 855 { 856 try { 857 return (Vector ) this.children.clone(); 858 } catch (Exception e) { 859 return null; 862 } 863 } 864 865 866 872 public String getContents() 873 { 874 return this.getContent(); 875 } 876 877 878 886 public String getContent() 887 { 888 return this.contents; 889 } 890 891 892 901 public int getLineNr() 902 { 903 return this.lineNr; 904 } 905 906 907 931 public Object getAttribute(String name) 932 { 933 return this.getAttribute(name, null); 934 } 935 936 937 962 public Object getAttribute(String name, 963 Object defaultValue) 964 { 965 if (this.ignoreCase) { 966 name = name.toUpperCase(); 967 } 968 Object value = this.attributes.get(name); 969 if (value == null) { 970 value = defaultValue; 971 } 972 return value; 973 } 974 975 976 1014 public Object getAttribute(String name, 1015 Hashtable valueSet, 1016 String defaultKey, 1017 boolean allowLiterals) 1018 { 1019 if (this.ignoreCase) { 1020 name = name.toUpperCase(); 1021 } 1022 Object key = this.attributes.get(name); 1023 Object result; 1024 if (key == null) { 1025 key = defaultKey; 1026 } 1027 result = valueSet.get(key); 1028 if (result == null) { 1029 if (allowLiterals) { 1030 result = key; 1031 } else { 1032 throw this.invalidValue(name, (String ) key); 1033 } 1034 } 1035 return result; 1036 } 1037 1038 1039 1064 public String getStringAttribute(String name) 1065 { 1066 return this.getStringAttribute(name, null); 1067 } 1068 1069 1070 1095 public String getStringAttribute(String name, 1096 String defaultValue) 1097 { 1098 return (String ) this.getAttribute(name, defaultValue); 1099 } 1100 1101 1102 1142 public String getStringAttribute(String name, 1143 Hashtable valueSet, 1144 String defaultKey, 1145 boolean allowLiterals) 1146 { 1147 return (String ) this.getAttribute(name, valueSet, defaultKey, 1148 allowLiterals); 1149 } 1150 1151 1152 1174 public int getIntAttribute(String name) 1175 { 1176 return this.getIntAttribute(name, 0); 1177 } 1178 1179 1180 1203 public int getIntAttribute(String name, 1204 int defaultValue) 1205 { 1206 if (this.ignoreCase) { 1207 name = name.toUpperCase(); 1208 } 1209 String value = (String ) this.attributes.get(name); 1210 if (value == null) { 1211 return defaultValue; 1212 } else { 1213 try { 1214 return Integer.parseInt(value); 1215 } catch (NumberFormatException e) { 1216 throw this.invalidValue(name, value); 1217 } 1218 } 1219 } 1220 1221 1222 1260 public int getIntAttribute(String name, 1261 Hashtable valueSet, 1262 String defaultKey, 1263 boolean allowLiteralNumbers) 1264 { 1265 if (this.ignoreCase) { 1266 name = name.toUpperCase(); 1267 } 1268 Object key = this.attributes.get(name); 1269 Integer result; 1270 if (key == null) { 1271 key = defaultKey; 1272 } 1273 try { 1274 result = (Integer ) valueSet.get(key); 1275 } catch (ClassCastException e) { 1276 throw this.invalidValueSet(name); 1277 } 1278 if (result == null) { 1279 if (! allowLiteralNumbers) { 1280 throw this.invalidValue(name, (String ) key); 1281 } 1282 try { 1283 result = Integer.valueOf((String ) key); 1284 } catch (NumberFormatException e) { 1285 throw this.invalidValue(name, (String ) key); 1286 } 1287 } 1288 return result.intValue(); 1289 } 1290 1291 1292 1314 public double getDoubleAttribute(String name) 1315 { 1316 return this.getDoubleAttribute(name, 0.); 1317 } 1318 1319 1320 1343 public double getDoubleAttribute(String name, 1344 double defaultValue) 1345 { 1346 if (this.ignoreCase) { 1347 name = name.toUpperCase(); 1348 } 1349 String value = (String ) this.attributes.get(name); 1350 if (value == null) { 1351 return defaultValue; 1352 } else { 1353 try { 1354 return Double.valueOf(value).doubleValue(); 1355 } catch (NumberFormatException e) { 1356 throw this.invalidValue(name, value); 1357 } 1358 } 1359 } 1360 1361 1362 1401 public double getDoubleAttribute(String name, 1402 Hashtable valueSet, 1403 String defaultKey, 1404 boolean allowLiteralNumbers) 1405 { 1406 if (this.ignoreCase) { 1407 name = name.toUpperCase(); 1408 } 1409 Object key = this.attributes.get(name); 1410 Double result; 1411 if (key == null) { 1412 key = defaultKey; 1413 } 1414 try { 1415 result = (Double ) valueSet.get(key); 1416 } catch (ClassCastException e) { 1417 throw this.invalidValueSet(name); 1418 } 1419 if (result == null) { 1420 if (! allowLiteralNumbers) { 1421 throw this.invalidValue(name, (String ) key); 1422 } 1423 try { 1424 result = Double.valueOf((String ) key); 1425 } catch (NumberFormatException e) { 1426 throw this.invalidValue(name, (String ) key); 1427 } 1428 } 1429 return result.doubleValue(); 1430 } 1431 1432 1433 1462 public boolean getBooleanAttribute(String name, 1463 String trueValue, 1464 String falseValue, 1465 boolean defaultValue) 1466 { 1467 if (this.ignoreCase) { 1468 name = name.toUpperCase(); 1469 } 1470 Object value = this.attributes.get(name); 1471 if (value == null) { 1472 return defaultValue; 1473 } else if (value.equals(trueValue)) { 1474 return true; 1475 } else if (value.equals(falseValue)) { 1476 return false; 1477 } else { 1478 throw this.invalidValue(name, (String ) value); 1479 } 1480 } 1481 1482 1483 1494 public int getIntProperty(String name, 1495 Hashtable valueSet, 1496 String defaultKey) 1497 { 1498 return this.getIntAttribute(name, valueSet, defaultKey, false); 1499 } 1500 1501 1502 1510 public String getProperty(String name) 1511 { 1512 return this.getStringAttribute(name); 1513 } 1514 1515 1516 1525 public String getProperty(String name, 1526 String defaultValue) 1527 { 1528 return this.getStringAttribute(name, defaultValue); 1529 } 1530 1531 1532 1541 public int getProperty(String name, 1542 int defaultValue) 1543 { 1544 return this.getIntAttribute(name, defaultValue); 1545 } 1546 1547 1548 1557 public double getProperty(String name, 1558 double defaultValue) 1559 { 1560 return this.getDoubleAttribute(name, defaultValue); 1561 } 1562 1563 1564 1576 public boolean getProperty(String key, 1577 String trueValue, 1578 String falseValue, 1579 boolean defaultValue) 1580 { 1581 return this.getBooleanAttribute(key, trueValue, falseValue, 1582 defaultValue); 1583 } 1584 1585 1586 1597 public Object getProperty(String name, 1598 Hashtable valueSet, 1599 String defaultKey) 1600 { 1601 return this.getAttribute(name, valueSet, defaultKey, false); 1602 } 1603 1604 1605 1616 public String getStringProperty(String name, 1617 Hashtable valueSet, 1618 String defaultKey) 1619 { 1620 return this.getStringAttribute(name, valueSet, defaultKey, false); 1621 } 1622 1623 1624 1635 public int getSpecialIntProperty(String name, 1636 Hashtable valueSet, 1637 String defaultKey) 1638 { 1639 return this.getIntAttribute(name, valueSet, defaultKey, true); 1640 } 1641 1642 1643 1654 public double getSpecialDoubleProperty(String name, 1655 Hashtable valueSet, 1656 String defaultKey) 1657 { 1658 return this.getDoubleAttribute(name, valueSet, defaultKey, true); 1659 } 1660 1661 1662 1668 public String getName() 1669 { 1670 return this.name; 1671 } 1672 1673 1674 1680 public String getTagName() 1681 { 1682 return this.getName(); 1683 } 1684 1685 1686 1709 public void parseFromReader(Reader reader) 1710 throws IOException , XMLParseException 1711 { 1712 this.parseFromReader(reader, 1); 1713 } 1714 1715 1716 1741 public void parseFromReader(Reader reader, 1742 int startingLineNr) 1743 throws IOException , XMLParseException 1744 { 1745 this.charReadTooMuch = '\0'; 1746 this.reader = reader; 1747 this.parserLineNr = startingLineNr; 1748 1749 for (;;) { 1750 char ch = this.scanWhitespace(); 1751 1752 if (ch != '<') { 1753 throw this.expectedInput("<"); } 1755 1756 ch = this.readChar(); 1757 1758 if ((ch == '!') || (ch == '?')) { 1759 this.skipSpecialTag(0); 1760 } else { 1761 this.unreadChar(ch); 1762 this.scanElement(this); 1763 return; 1764 } 1765 } 1766 } 1767 1768 1769 1787 public void parseString(String string) 1788 throws XMLParseException 1789 { 1790 try { 1791 this.parseFromReader(new StringReader (string), 1792 1); 1793 } catch (IOException e) { 1794 } 1796 } 1797 1798 1799 1818 public void parseString(String string, 1819 int offset) 1820 throws XMLParseException 1821 { 1822 this.parseString(string.substring(offset)); 1823 } 1824 1825 1826 1850 public void parseString(String string, 1851 int offset, 1852 int end) 1853 throws XMLParseException 1854 { 1855 this.parseString(string.substring(offset, end)); 1856 } 1857 1858 1859 1886 public void parseString(String string, 1887 int offset, 1888 int end, 1889 int startingLineNr) 1890 throws XMLParseException 1891 { 1892 string = string.substring(offset, end); 1893 try { 1894 this.parseFromReader(new StringReader (string), startingLineNr); 1895 } catch (IOException e) { 1896 } 1898 } 1899 1900 1901 1925 public void parseCharArray(char[] input, 1926 int offset, 1927 int end) 1928 throws XMLParseException 1929 { 1930 this.parseCharArray(input, offset, end, 1); 1931 } 1932 1933 1934 1960 public void parseCharArray(char[] input, 1961 int offset, 1962 int end, 1963 int startingLineNr) 1964 throws XMLParseException 1965 { 1966 try { 1967 Reader reader = new CharArrayReader (input, offset, end); 1968 this.parseFromReader(reader, startingLineNr); 1969 } catch (IOException e) { 1970 } 1972 } 1973 1974 1975 1998 public void removeChild(XMLElement child) 1999 { 2000 this.children.removeElement(child); 2001 } 2002 2003 2004 2066 public void removeAttribute(String name) 2067 { 2068 if (this.ignoreCase) { 2069 name = name.toUpperCase(); 2070 } 2071 this.attributes.remove(name); 2072 } 2073 2074 2075 2084 public void removeProperty(String name) 2085 { 2086 this.removeAttribute(name); 2087 } 2088 2089 2090 2099 public void removeChild(String name) 2100 { 2101 this.removeAttribute(name); 2102 } 2103 2104 2105 2110 protected XMLElement createAnotherElement() 2111 { 2112 return new XMLElement(this.entities, 2113 this.ignoreWhitespace, 2114 false, 2115 this.ignoreCase); 2116 } 2117 2118 2119 2125 public void setContent(String content) 2126 { 2127 this.contents = content; 2128 } 2129 2130 2131 2139 public void setTagName(String name) 2140 { 2141 this.setName(name); 2142 } 2143 2144 2145 2158 public void setName(String name) 2159 { 2160 this.name = name; 2161 } 2162 2163 2164 2169 public String toString() 2170 { 2171 try { 2172 ByteArrayOutputStream out = new ByteArrayOutputStream (); 2173 OutputStreamWriter writer = new OutputStreamWriter (out); 2174 this.write(writer); 2175 writer.flush(); 2176 return new String (out.toByteArray()); 2177 } catch (IOException e) { 2178 return super.toString(); 2180 } 2181 } 2182 2183 2184 2200 public void write(Writer writer) 2201 throws IOException 2202 { 2203 if (this.name == null) { 2204 this.writeEncoded(writer, this.contents); 2205 return; 2206 } 2207 writer.write('<'); 2208 writer.write(this.name); 2209 if (! this.attributes.isEmpty()) { 2210 Enumeration e = this.attributes.keys(); 2211 while (e.hasMoreElements()) { 2212 writer.write(' '); 2213 String key = (String ) e.nextElement(); 2214 String value = (String ) this.attributes.get(key); 2215 writer.write(key); 2216 writer.write('='); writer.write('"'); 2217 this.writeEncoded(writer, value); 2218 writer.write('"'); 2219 } 2220 } 2221 if ((this.contents != null) && (this.contents.length() > 0)) { 2222 writer.write('>'); 2223 this.writeEncoded(writer, this.contents); 2224 writer.write('<'); writer.write('/'); 2225 writer.write(this.name); 2226 writer.write('>'); 2227 } else if (this.children.isEmpty()) { 2228 writer.write('/'); writer.write('>'); 2229 } else { 2230 writer.write('>'); 2231 Enumeration e = this.enumerateChildren(); 2232 while (e.hasMoreElements()) { 2233 XMLElement child = (XMLElement) e.nextElement(); 2234 child.write(writer); 2235 } 2236 writer.write('<'); writer.write('/'); 2237 writer.write(this.name); 2238 writer.write('>'); 2239 } 2240 } 2241 2242 2243 2257 protected void writeEncoded(Writer writer, 2258 String str) 2259 throws IOException 2260 { 2261 for (int i = 0; i < str.length(); i += 1) { 2262 char ch = str.charAt(i); 2263 switch (ch) { 2264 case '<': 2265 writer.write('&'); writer.write('l'); writer.write('t'); 2266 writer.write(';'); 2267 break; 2268 case '>': 2269 writer.write('&'); writer.write('g'); writer.write('t'); 2270 writer.write(';'); 2271 break; 2272 case '&': 2273 writer.write('&'); writer.write('a'); writer.write('m'); 2274 writer.write('p'); writer.write(';'); 2275 break; 2276 case '"': 2277 writer.write('&'); writer.write('q'); writer.write('u'); 2278 writer.write('o'); writer.write('t'); writer.write(';'); 2279 break; 2280 case '\'': 2281 writer.write('&'); writer.write('a'); writer.write('p'); 2282 writer.write('o'); writer.write('s'); writer.write(';'); 2283 break; 2284 default: 2285 int unicode = (int) ch; 2286 if ((unicode < 32) || (unicode > 126)) { 2287 writer.write('&'); writer.write('#'); 2288 writer.write('x'); 2289 writer.write(Integer.toString(unicode, 16)); 2290 writer.write(';'); 2291 } else { 2292 writer.write(ch); 2293 } 2294 } 2295 } 2296 } 2297 2298 2299 2317 protected void scanIdentifier(StringBuffer result) 2318 throws IOException 2319 { 2320 for (;;) { 2321 char ch = this.readChar(); 2322 if (((ch < 'A') || (ch > 'Z')) && ((ch < 'a') || (ch > 'z')) 2323 && ((ch < '0') || (ch > '9')) && (ch != '_') && (ch != '.') 2324 && (ch != ':') && (ch != '-') && (ch <= '\u007E')) { 2325 this.unreadChar(ch); 2326 return; 2327 } 2328 result.append(ch); 2329 } 2330 } 2331 2332 2333 2338 protected char scanWhitespace() 2339 throws IOException 2340 { 2341 for (;;) { 2342 char ch = this.readChar(); 2343 switch (ch) { 2344 case ' ': 2345 case '\t': 2346 case '\n': 2347 case '\r': 2348 break; 2349 default: 2350 return ch; 2351 } 2352 } 2353 } 2354 2355 2356 2366 protected char scanWhitespace(StringBuffer result) 2367 throws IOException 2368 { 2369 for (;;) { 2370 char ch = this.readChar(); 2371 switch (ch) { 2372 case ' ': 2373 case '\t': 2374 case '\n': 2375 result.append(ch); 2376 case '\r': 2377 break; 2378 default: 2379 return ch; 2380 } 2381 } 2382 } 2383 2384 2385 2395 protected void scanString(StringBuffer string) 2396 throws IOException 2397 { 2398 char delimiter = this.readChar(); 2399 if ((delimiter != '\'') && (delimiter != '"')) { 2400 throw this.expectedInput("' or \""); } 2402 for (;;) { 2403 char ch = this.readChar(); 2404 if (ch == delimiter) { 2405 return; 2406 } else if (ch == '&') { 2407 this.resolveEntity(string); 2408 } else { 2409 string.append(ch); 2410 } 2411 } 2412 } 2413 2414 2415 2424 protected void scanPCData(StringBuffer data) 2425 throws IOException 2426 { 2427 for (;;) { 2428 char ch = this.readChar(); 2429 if (ch == '<') { 2430 ch = this.readChar(); 2431 if (ch == '!') { 2432 this.checkCDATA(data); 2433 } else { 2434 this.unreadChar(ch); 2435 return; 2436 } 2437 } else if (ch == '&') { 2438 this.resolveEntity(data); 2439 } else { 2440 data.append(ch); 2441 } 2442 } 2443 } 2444 2445 2446 2455 protected boolean checkCDATA(StringBuffer buf) 2456 throws IOException 2457 { 2458 char ch = this.readChar(); 2459 if (ch != '[') { 2460 this.unreadChar(ch); 2461 this.skipSpecialTag(0); 2462 return false; 2463 } else if (! this.checkLiteral("CDATA[")) { this.skipSpecialTag(1); return false; 2466 } else { 2467 int delimiterCharsSkipped = 0; 2468 while (delimiterCharsSkipped < 3) { 2469 ch = this.readChar(); 2470 switch (ch) { 2471 case ']': 2472 if (delimiterCharsSkipped < 2) { 2473 delimiterCharsSkipped += 1; 2474 } else { 2475 buf.append(']'); 2476 buf.append(']'); 2477 delimiterCharsSkipped = 0; 2478 } 2479 break; 2480 case '>': 2481 if (delimiterCharsSkipped < 2) { 2482 for (int i = 0; i < delimiterCharsSkipped; i++) { 2483 buf.append(']'); 2484 } 2485 delimiterCharsSkipped = 0; 2486 buf.append('>'); 2487 } else { 2488 delimiterCharsSkipped = 3; 2489 } 2490 break; 2491 default: 2492 for (int i = 0; i < delimiterCharsSkipped; i += 1) { 2493 buf.append(']'); 2494 } 2495 buf.append(ch); 2496 delimiterCharsSkipped = 0; 2497 } 2498 } 2499 return true; 2500 } 2501 } 2502 2503 2504 2511 protected void skipComment() 2512 throws IOException 2513 { 2514 int dashesToRead = 2; 2515 while (dashesToRead > 0) { 2516 char ch = this.readChar(); 2517 if (ch == '-') { 2518 dashesToRead -= 1; 2519 } else { 2520 dashesToRead = 2; 2521 } 2522 } 2523 if (this.readChar() != '>') { 2524 throw this.expectedInput(">"); } 2526 } 2527 2528 2529 2540 protected void skipSpecialTag(int bracketLevel) 2541 throws IOException 2542 { 2543 int tagLevel = 1; char stringDelimiter = '\0'; 2545 if (bracketLevel == 0) { 2546 char ch = this.readChar(); 2547 if (ch == '[') { 2548 bracketLevel += 1; 2549 } else if (ch == '-') { 2550 ch = this.readChar(); 2551 if (ch == '[') { 2552 bracketLevel += 1; 2553 } else if (ch == ']') { 2554 bracketLevel -= 1; 2555 } else if (ch == '-') { 2556 this.skipComment(); 2557 return; 2558 } 2559 } 2560 } 2561 while (tagLevel > 0) { 2562 char ch = this.readChar(); 2563 if (stringDelimiter == '\0') { 2564 if ((ch == '"') || (ch == '\'')) { 2565 stringDelimiter = ch; 2566 } else if (bracketLevel <= 0) { 2567 if (ch == '<') { 2568 tagLevel += 1; 2569 } else if (ch == '>') { 2570 tagLevel -= 1; 2571 } 2572 } 2573 if (ch == '[') { 2574 bracketLevel += 1; 2575 } else if (ch == ']') { 2576 bracketLevel -= 1; 2577 } 2578 } else { 2579 if (ch == stringDelimiter) { 2580 stringDelimiter = '\0'; 2581 } 2582 } 2583 } 2584 } 2585 2586 2587 2598 protected boolean checkLiteral(String literal) 2599 throws IOException 2600 { 2601 int length = literal.length(); 2602 for (int i = 0; i < length; i += 1) { 2603 if (this.readChar() != literal.charAt(i)) { 2604 return false; 2605 } 2606 } 2607 return true; 2608 } 2609 2610 2611 2614 protected char readChar() 2615 throws IOException 2616 { 2617 if (this.charReadTooMuch != '\0') { 2618 char ch = this.charReadTooMuch; 2619 this.charReadTooMuch = '\0'; 2620 return ch; 2621 } else { 2622 int i = this.reader.read(); 2623 if (i < 0) { 2624 throw this.unexpectedEndOfData(); 2625 } else if (i == 10) { 2626 this.parserLineNr += 1; 2627 return '\n'; 2628 } else { 2629 return (char) i; 2630 } 2631 } 2632 } 2633 2634 2635 2645 protected void scanElement(XMLElement elt) 2646 throws IOException 2647 { 2648 StringBuffer buf = new StringBuffer (); 2649 this.scanIdentifier(buf); 2650 String name = buf.toString(); 2651 elt.setName(name); 2652 char ch = this.scanWhitespace(); 2653 while ((ch != '>') && (ch != '/')) { 2654 buf.setLength(0); 2655 this.unreadChar(ch); 2656 this.scanIdentifier(buf); 2657 String key = buf.toString(); 2658 ch = this.scanWhitespace(); 2659 if (ch != '=') { 2660 throw this.expectedInput("="); } 2662 this.unreadChar(this.scanWhitespace()); 2663 buf.setLength(0); 2664 this.scanString(buf); 2665 elt.setAttribute(key, buf); 2666 ch = this.scanWhitespace(); 2667 } 2668 if (ch == '/') { 2669 ch = this.readChar(); 2670 if (ch != '>') { 2671 throw this.expectedInput(">"); } 2673 return; 2674 } 2675 buf.setLength(0); 2676 ch = this.scanWhitespace(buf); 2677 if (ch != '<') { 2678 this.unreadChar(ch); 2679 this.scanPCData(buf); 2680 } else { 2681 for (;;) { 2682 ch = this.readChar(); 2683 if (ch == '!') { 2684 if (this.checkCDATA(buf)) { 2685 this.scanPCData(buf); 2686 break; 2687 } else { 2688 ch = this.scanWhitespace(buf); 2689 if (ch != '<') { 2690 this.unreadChar(ch); 2691 this.scanPCData(buf); 2692 break; 2693 } 2694 } 2695 } else { 2696 buf.setLength(0); 2697 break; 2698 } 2699 } 2700 } 2701 if (buf.length() == 0) { 2702 while (ch != '/') { 2703 if (ch == '!') { 2704 ch = this.readChar(); 2705 if (ch != '-') { 2706 throw this.expectedInput(Messages.getString("XMLElement.commentOrElement")); } 2708 ch = this.readChar(); 2709 if (ch != '-') { 2710 throw this.expectedInput(Messages.getString("XMLElement.commentOrElement")); } 2712 this.skipComment(); 2713 } else { 2714 this.unreadChar(ch); 2715 XMLElement child = this.createAnotherElement(); 2716 this.scanElement(child); 2717 elt.addChild(child); 2718 } 2719 ch = this.scanWhitespace(); 2720 if (ch != '<') { 2721 throw this.expectedInput("<"); } 2723 ch = this.readChar(); 2724 } 2725 this.unreadChar(ch); 2726 } else { 2727 if (this.ignoreWhitespace) { 2728 elt.setContent(buf.toString().trim()); 2729 } else { 2730 elt.setContent(buf.toString()); 2731 } 2732 } 2733 ch = this.readChar(); 2734 if (ch != '/') { 2735 throw this.expectedInput("/"); } 2737 this.unreadChar(this.scanWhitespace()); 2738 if (! this.checkLiteral(name)) { 2739 throw this.expectedInput(name); 2740 } 2741 if (this.scanWhitespace() != '>') { 2742 throw this.expectedInput(">"); } 2744 } 2745 2746 2747 2758 protected void resolveEntity(StringBuffer buf) 2759 throws IOException 2760 { 2761 char ch = '\0'; 2762 StringBuffer keyBuf = new StringBuffer (); 2763 for (;;) { 2764 ch = this.readChar(); 2765 if (ch == ';') { 2766 break; 2767 } 2768 keyBuf.append(ch); 2769 } 2770 String key = keyBuf.toString(); 2771 if (key.charAt(0) == '#') { 2772 try { 2773 if (key.charAt(1) == 'x') { 2774 ch = (char) Integer.parseInt(key.substring(2), 16); 2775 } else { 2776 ch = (char) Integer.parseInt(key.substring(1), 10); 2777 } 2778 } catch (NumberFormatException e) { 2779 throw this.unknownEntity(key); 2780 } 2781 buf.append(ch); 2782 } else { 2783 char[] value = (char[]) this.entities.get(key); 2784 if (value == null) { 2785 throw this.unknownEntity(key); 2786 } 2787 buf.append(value); 2788 } 2789 } 2790 2791 2792 2802 protected void unreadChar(char ch) 2803 { 2804 this.charReadTooMuch = ch; 2805 } 2806 2807 2808 2818 protected XMLParseException invalidValueSet(String name) 2819 { 2820 String msg = MessageFormat.format(Messages.getString("XMLElement.invalidValueSet"), new Object [] { name } ) ; return new XMLParseException(this.getName(), this.parserLineNr, msg); 2822 } 2823 2824 2825 2837 protected XMLParseException invalidValue(String name, 2838 String value) 2839 { 2840 String msg = MessageFormat.format(Messages.getString("XMLElement.invalidValueInAttribute"), new Object [] { name } ); return new XMLParseException(this.getName(), this.parserLineNr, msg); 2842 } 2843 2844 2845 2849 protected XMLParseException unexpectedEndOfData() 2850 { 2851 String msg = Messages.getString("XMLElement.unexpectedEndOfData"); return new XMLParseException(this.getName(), this.parserLineNr, msg); 2853 } 2854 2855 2856 2866 protected XMLParseException syntaxError(String context) 2867 { 2868 String msg = MessageFormat.format(Messages.getString("XMLElement.parsingSyntaxError"), new Object [] { context } ); return new XMLParseException(this.getName(), this.parserLineNr, msg); 2870 } 2871 2872 2873 2885 protected XMLParseException expectedInput(String charSet) 2886 { 2887 String msg = MessageFormat.format(Messages.getString("XMLElement.expected"), new Object [] { charSet } ); return new XMLParseException(this.getName(), this.parserLineNr, msg); 2889 } 2890 2891 2892 2902 protected XMLParseException unknownEntity(String name) 2903 { 2904 String msg = Messages.getString("XMLElement.unknownOrInvalidEntity") + name + ";"; return new XMLParseException(this.getName(), this.parserLineNr, msg); 2906 } 2907 2908} 2909 | Popular Tags |