1 25 26 27 package com.sslexplorer.boot; 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.util.Enumeration ; 37 import java.util.Hashtable ; 38 import java.util.Vector ; 39 40 41 98 public class XMLElement 99 { 100 101 104 static final long serialVersionUID = 6685035139346394777L; 105 106 107 115 public static final int NANOXML_MAJOR_VERSION = 2; 116 117 118 126 public static final int NANOXML_MINOR_VERSION = 2; 127 128 129 138 private Hashtable attributes; 139 140 141 151 private Vector children; 152 153 154 165 private String name; 166 167 168 177 private String contents; 178 179 180 194 private Hashtable entities; 195 196 197 204 private int lineNr; 205 206 207 211 private boolean ignoreCase; 212 213 214 218 private boolean ignoreWhitespace; 219 220 221 227 private char charReadTooMuch; 228 229 230 238 private Reader reader; 239 240 241 248 private int parserLineNr; 249 250 251 273 public XMLElement() 274 { 275 this(new Hashtable (), false, true, true); 276 } 277 278 279 307 public XMLElement(Hashtable entities) 308 { 309 this(entities, false, true, true); 310 } 311 312 313 339 public XMLElement(boolean skipLeadingWhitespace) 340 { 341 this(new Hashtable (), skipLeadingWhitespace, true, true); 342 } 343 344 345 376 public XMLElement(Hashtable entities, 377 boolean skipLeadingWhitespace) 378 { 379 this(entities, skipLeadingWhitespace, true, true); 380 } 381 382 383 416 public XMLElement(Hashtable entities, 417 boolean skipLeadingWhitespace, 418 boolean ignoreCase) 419 { 420 this(entities, skipLeadingWhitespace, true, ignoreCase); 421 } 422 423 424 463 protected XMLElement(Hashtable entities, 464 boolean skipLeadingWhitespace, 465 boolean fillBasicConversionTable, 466 boolean ignoreCase) 467 { 468 this.ignoreWhitespace = skipLeadingWhitespace; 469 this.ignoreCase = ignoreCase; 470 this.name = null; 471 this.contents = ""; 472 this.attributes = new Hashtable (); 473 this.children = new Vector (); 474 this.entities = entities; 475 this.lineNr = 0; 476 Enumeration e = this.entities.keys(); 477 while (e.hasMoreElements()) { 478 Object key = e.nextElement(); 479 Object value = this.entities.get(key); 480 if (value instanceof String ) { 481 value = ((String ) value).toCharArray(); 482 this.entities.put(key, value); 483 } 484 } 485 if (fillBasicConversionTable) { 486 this.entities.put("amp", new char[] { '&' }); 487 this.entities.put("quot", new char[] { '"' }); 488 this.entities.put("apos", new char[] { '\'' }); 489 this.entities.put("lt", new char[] { '<' }); 490 this.entities.put("gt", new char[] { '>' }); 491 } 492 } 493 494 495 519 public void addChild(XMLElement child) 520 { 521 this.children.addElement(child); 522 } 523 524 525 568 public void setAttribute(String name, 569 Object value) 570 { 571 if (this.ignoreCase) { 572 name = name.toUpperCase(); 573 } 574 this.attributes.put(name, value.toString()); 575 } 576 577 578 589 public void addProperty(String name, 590 Object value) 591 { 592 this.setAttribute(name, value); 593 } 594 595 596 631 public void setIntAttribute(String name, 632 int value) 633 { 634 if (this.ignoreCase) { 635 name = name.toUpperCase(); 636 } 637 this.attributes.put(name, Integer.toString(value)); 638 } 639 640 641 652 public void addProperty(String key, 653 int value) 654 { 655 this.setIntAttribute(key, value); 656 } 657 658 659 694 public void setDoubleAttribute(String name, 695 double value) 696 { 697 if (this.ignoreCase) { 698 name = name.toUpperCase(); 699 } 700 this.attributes.put(name, Double.toString(value)); 701 } 702 703 704 715 public void addProperty(String name, 716 double value) 717 { 718 this.setDoubleAttribute(name, value); 719 } 720 721 722 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 873 public String getContents() 874 { 875 return this.getContent(); 876 } 877 878 879 887 public String getContent() 888 { 889 return this.contents; 890 } 891 892 893 903 public int getLineNr() 904 { 905 return this.lineNr; 906 } 907 908 909 933 public Object getAttribute(String name) 934 { 935 return this.getAttribute(name, null); 936 } 937 938 939 965 public Object getAttribute(String name, 966 Object defaultValue) 967 { 968 if (this.ignoreCase) { 969 name = name.toUpperCase(); 970 } 971 Object value = this.attributes.get(name); 972 if (value == null) { 973 value = defaultValue; 974 } 975 return value; 976 } 977 978 979 1017 public Object getAttribute(String name, 1018 Hashtable valueSet, 1019 String defaultKey, 1020 boolean allowLiterals) 1021 { 1022 if (this.ignoreCase) { 1023 name = name.toUpperCase(); 1024 } 1025 Object key = this.attributes.get(name); 1026 Object result; 1027 if (key == null) { 1028 key = defaultKey; 1029 } 1030 result = valueSet.get(key); 1031 if (result == null) { 1032 if (allowLiterals) { 1033 result = key; 1034 } else { 1035 throw this.invalidValue(name, (String ) key); 1036 } 1037 } 1038 return result; 1039 } 1040 1041 1042 1067 public String getStringAttribute(String name) 1068 { 1069 return this.getStringAttribute(name, null); 1070 } 1071 1072 1073 1098 public String getStringAttribute(String name, 1099 String defaultValue) 1100 { 1101 return (String ) this.getAttribute(name, defaultValue); 1102 } 1103 1104 1105 1145 public String getStringAttribute(String name, 1146 Hashtable valueSet, 1147 String defaultKey, 1148 boolean allowLiterals) 1149 { 1150 return (String ) this.getAttribute(name, valueSet, defaultKey, 1151 allowLiterals); 1152 } 1153 1154 1155 1177 public int getIntAttribute(String name) 1178 { 1179 return this.getIntAttribute(name, 0); 1180 } 1181 1182 1183 1206 public int getIntAttribute(String name, 1207 int defaultValue) 1208 { 1209 if (this.ignoreCase) { 1210 name = name.toUpperCase(); 1211 } 1212 String value = (String ) this.attributes.get(name); 1213 if (value == null) { 1214 return defaultValue; 1215 } else { 1216 try { 1217 return Integer.parseInt(value); 1218 } catch (NumberFormatException e) { 1219 throw this.invalidValue(name, value); 1220 } 1221 } 1222 } 1223 1224 1225 1263 public int getIntAttribute(String name, 1264 Hashtable valueSet, 1265 String defaultKey, 1266 boolean allowLiteralNumbers) 1267 { 1268 if (this.ignoreCase) { 1269 name = name.toUpperCase(); 1270 } 1271 Object key = this.attributes.get(name); 1272 Integer result; 1273 if (key == null) { 1274 key = defaultKey; 1275 } 1276 try { 1277 result = (Integer ) valueSet.get(key); 1278 } catch (ClassCastException e) { 1279 throw this.invalidValueSet(name); 1280 } 1281 if (result == null) { 1282 if (! allowLiteralNumbers) { 1283 throw this.invalidValue(name, (String ) key); 1284 } 1285 try { 1286 result = Integer.valueOf((String ) key); 1287 } catch (NumberFormatException e) { 1288 throw this.invalidValue(name, (String ) key); 1289 } 1290 } 1291 return result.intValue(); 1292 } 1293 1294 1295 1317 public double getDoubleAttribute(String name) 1318 { 1319 return this.getDoubleAttribute(name, 0.); 1320 } 1321 1322 1323 1346 public double getDoubleAttribute(String name, 1347 double defaultValue) 1348 { 1349 if (this.ignoreCase) { 1350 name = name.toUpperCase(); 1351 } 1352 String value = (String ) this.attributes.get(name); 1353 if (value == null) { 1354 return defaultValue; 1355 } else { 1356 try { 1357 return Double.valueOf(value).doubleValue(); 1358 } catch (NumberFormatException e) { 1359 throw this.invalidValue(name, value); 1360 } 1361 } 1362 } 1363 1364 1365 1404 public double getDoubleAttribute(String name, 1405 Hashtable valueSet, 1406 String defaultKey, 1407 boolean allowLiteralNumbers) 1408 { 1409 if (this.ignoreCase) { 1410 name = name.toUpperCase(); 1411 } 1412 Object key = this.attributes.get(name); 1413 Double result; 1414 if (key == null) { 1415 key = defaultKey; 1416 } 1417 try { 1418 result = (Double ) valueSet.get(key); 1419 } catch (ClassCastException e) { 1420 throw this.invalidValueSet(name); 1421 } 1422 if (result == null) { 1423 if (! allowLiteralNumbers) { 1424 throw this.invalidValue(name, (String ) key); 1425 } 1426 try { 1427 result = Double.valueOf((String ) key); 1428 } catch (NumberFormatException e) { 1429 throw this.invalidValue(name, (String ) key); 1430 } 1431 } 1432 return result.doubleValue(); 1433 } 1434 1435 1436 1465 public boolean getBooleanAttribute(String name, 1466 String trueValue, 1467 String falseValue, 1468 boolean defaultValue) 1469 { 1470 if (this.ignoreCase) { 1471 name = name.toUpperCase(); 1472 } 1473 Object value = this.attributes.get(name); 1474 if (value == null) { 1475 return defaultValue; 1476 } else if (value.equals(trueValue)) { 1477 return true; 1478 } else if (value.equals(falseValue)) { 1479 return false; 1480 } else { 1481 throw this.invalidValue(name, (String ) value); 1482 } 1483 } 1484 1485 1486 1498 public int getIntProperty(String name, 1499 Hashtable valueSet, 1500 String defaultKey) 1501 { 1502 return this.getIntAttribute(name, valueSet, defaultKey, false); 1503 } 1504 1505 1506 1515 public String getProperty(String name) 1516 { 1517 return this.getStringAttribute(name); 1518 } 1519 1520 1521 1531 public String getProperty(String name, 1532 String defaultValue) 1533 { 1534 return this.getStringAttribute(name, defaultValue); 1535 } 1536 1537 1538 1548 public int getProperty(String name, 1549 int defaultValue) 1550 { 1551 return this.getIntAttribute(name, defaultValue); 1552 } 1553 1554 1555 1564 public double getProperty(String name, 1565 double defaultValue) 1566 { 1567 return this.getDoubleAttribute(name, defaultValue); 1568 } 1569 1570 1571 1584 public boolean getProperty(String key, 1585 String trueValue, 1586 String falseValue, 1587 boolean defaultValue) 1588 { 1589 return this.getBooleanAttribute(key, trueValue, falseValue, 1590 defaultValue); 1591 } 1592 1593 1594 1606 public Object getProperty(String name, 1607 Hashtable valueSet, 1608 String defaultKey) 1609 { 1610 return this.getAttribute(name, valueSet, defaultKey, false); 1611 } 1612 1613 1614 1626 public String getStringProperty(String name, 1627 Hashtable valueSet, 1628 String defaultKey) 1629 { 1630 return this.getStringAttribute(name, valueSet, defaultKey, false); 1631 } 1632 1633 1634 1645 public int getSpecialIntProperty(String name, 1646 Hashtable valueSet, 1647 String defaultKey) 1648 { 1649 return this.getIntAttribute(name, valueSet, defaultKey, true); 1650 } 1651 1652 1653 1665 public double getSpecialDoubleProperty(String name, 1666 Hashtable valueSet, 1667 String defaultKey) 1668 { 1669 return this.getDoubleAttribute(name, valueSet, defaultKey, true); 1670 } 1671 1672 1673 1679 public String getName() 1680 { 1681 return this.name; 1682 } 1683 1684 1685 1691 public String getTagName() 1692 { 1693 return this.getName(); 1694 } 1695 1696 1697 1720 public void parseFromReader(Reader reader) 1721 throws IOException , XMLParseException 1722 { 1723 this.parseFromReader(reader, 1); 1724 } 1725 1726 1727 1752 public void parseFromReader(Reader reader, 1753 int startingLineNr) 1754 throws IOException , XMLParseException 1755 { 1756 this.charReadTooMuch = '\0'; 1757 this.reader = reader; 1758 this.parserLineNr = startingLineNr; 1759 1760 for (;;) { 1761 char ch = this.scanWhitespace(); 1762 1763 if (ch != '<') { 1764 throw this.expectedInput("<"); 1765 } 1766 1767 ch = this.readChar(); 1768 1769 if ((ch == '!') || (ch == '?')) { 1770 this.skipSpecialTag(0); 1771 } else { 1772 this.unreadChar(ch); 1773 this.scanElement(this); 1774 return; 1775 } 1776 } 1777 } 1778 1779 1780 1799 public void parseString(String string) 1800 throws XMLParseException 1801 { 1802 try { 1803 this.parseFromReader(new StringReader (string), 1804 1); 1805 } catch (IOException e) { 1806 } 1808 } 1809 1810 1811 1833 public void parseString(String string, 1834 int offset) 1835 throws XMLParseException 1836 { 1837 this.parseString(string.substring(offset)); 1838 } 1839 1840 1841 1867 public void parseString(String string, 1868 int offset, 1869 int end) 1870 throws XMLParseException 1871 { 1872 this.parseString(string.substring(offset, end)); 1873 } 1874 1875 1876 1904 public void parseString(String string, 1905 int offset, 1906 int end, 1907 int startingLineNr) 1908 throws XMLParseException 1909 { 1910 string = string.substring(offset, end); 1911 try { 1912 this.parseFromReader(new StringReader (string), startingLineNr); 1913 } catch (IOException e) { 1914 } 1916 } 1917 1918 1919 1945 public void parseCharArray(char[] input, 1946 int offset, 1947 int end) 1948 throws XMLParseException 1949 { 1950 this.parseCharArray(input, offset, end, 1); 1951 } 1952 1953 1954 1982 public void parseCharArray(char[] input, 1983 int offset, 1984 int end, 1985 int startingLineNr) 1986 throws XMLParseException 1987 { 1988 try { 1989 Reader reader = new CharArrayReader (input, offset, end); 1990 this.parseFromReader(reader, startingLineNr); 1991 } catch (IOException e) { 1992 } 1994 } 1995 1996 1997 2020 public void removeChild(XMLElement child) 2021 { 2022 this.children.removeElement(child); 2023 } 2024 2025 2026 2088 public void removeAttribute(String name) 2089 { 2090 if (this.ignoreCase) { 2091 name = name.toUpperCase(); 2092 } 2093 this.attributes.remove(name); 2094 } 2095 2096 2097 2106 public void removeProperty(String name) 2107 { 2108 this.removeAttribute(name); 2109 } 2110 2111 2112 2121 public void removeChild(String name) 2122 { 2123 this.removeAttribute(name); 2124 } 2125 2126 2127 2134 protected XMLElement createAnotherElement() 2135 { 2136 return new XMLElement(this.entities, 2137 this.ignoreWhitespace, 2138 false, 2139 this.ignoreCase); 2140 } 2141 2142 2143 2149 public void setContent(String content) 2150 { 2151 this.contents = content; 2152 } 2153 2154 2155 2163 public void setTagName(String name) 2164 { 2165 this.setName(name); 2166 } 2167 2168 2169 2182 public void setName(String name) 2183 { 2184 this.name = name; 2185 } 2186 2187 2188 2193 public String toString() 2194 { 2195 try { 2196 ByteArrayOutputStream out = new ByteArrayOutputStream (); 2197 OutputStreamWriter writer = new OutputStreamWriter (out); 2198 this.write(writer); 2199 writer.flush(); 2200 return new String (out.toByteArray()); 2201 } catch (IOException e) { 2202 return super.toString(); 2204 } 2205 } 2206 2207 2208 2224 public void write(Writer writer) 2225 throws IOException 2226 { 2227 if (this.name == null) { 2228 this.writeEncoded(writer, this.contents); 2229 return; 2230 } 2231 writer.write('<'); 2232 writer.write(this.name); 2233 if (! this.attributes.isEmpty()) { 2234 Enumeration e = this.attributes.keys(); 2235 while (e.hasMoreElements()) { 2236 writer.write(' '); 2237 String key = (String ) e.nextElement(); 2238 String value = (String ) this.attributes.get(key); 2239 writer.write(key); 2240 writer.write('='); writer.write('"'); 2241 this.writeEncoded(writer, value); 2242 writer.write('"'); 2243 } 2244 } 2245 if ((this.contents != null) && (this.contents.length() > 0)) { 2246 writer.write('>'); 2247 this.writeEncoded(writer, this.contents); 2248 writer.write('<'); writer.write('/'); 2249 writer.write(this.name); 2250 writer.write('>'); 2251 } else if (this.children.isEmpty()) { 2252 writer.write('/'); writer.write('>'); 2253 } else { 2254 writer.write('>'); 2255 Enumeration e = this.enumerateChildren(); 2256 while (e.hasMoreElements()) { 2257 XMLElement child = (XMLElement) e.nextElement(); 2258 child.write(writer); 2259 } 2260 writer.write('<'); writer.write('/'); 2261 writer.write(this.name); 2262 writer.write('>'); 2263 } 2264 } 2265 2266 2267 2282 protected void writeEncoded(Writer writer, 2283 String str) 2284 throws IOException 2285 { 2286 for (int i = 0; i < str.length(); i += 1) { 2287 char ch = str.charAt(i); 2288 switch (ch) { 2289 case '<': 2290 writer.write('&'); writer.write('l'); writer.write('t'); 2291 writer.write(';'); 2292 break; 2293 case '>': 2294 writer.write('&'); writer.write('g'); writer.write('t'); 2295 writer.write(';'); 2296 break; 2297 case '&': 2298 writer.write('&'); writer.write('a'); writer.write('m'); 2299 writer.write('p'); writer.write(';'); 2300 break; 2301 case '"': 2302 writer.write('&'); writer.write('q'); writer.write('u'); 2303 writer.write('o'); writer.write('t'); writer.write(';'); 2304 break; 2305 case '\'': 2306 writer.write('&'); writer.write('a'); writer.write('p'); 2307 writer.write('o'); writer.write('s'); writer.write(';'); 2308 break; 2309 default: 2310 int unicode = (int) ch; 2311 if ((unicode < 32) || (unicode > 126)) { 2312 writer.write('&'); writer.write('#'); 2313 writer.write('x'); 2314 writer.write(Integer.toString(unicode, 16)); 2315 writer.write(';'); 2316 } else { 2317 writer.write(ch); 2318 } 2319 } 2320 } 2321 } 2322 2323 2324 2343 protected void scanIdentifier(StringBuffer result) 2344 throws IOException 2345 { 2346 for (;;) { 2347 char ch = this.readChar(); 2348 if (((ch < 'A') || (ch > 'Z')) && ((ch < 'a') || (ch > 'z')) 2349 && ((ch < '0') || (ch > '9')) && (ch != '_') && (ch != '.') 2350 && (ch != ':') && (ch != '-') && (ch <= '\u007E')) { 2351 this.unreadChar(ch); 2352 return; 2353 } 2354 result.append(ch); 2355 } 2356 } 2357 2358 2359 2365 protected char scanWhitespace() 2366 throws IOException 2367 { 2368 for (;;) { 2369 char ch = this.readChar(); 2370 switch (ch) { 2371 case ' ': 2372 case '\t': 2373 case '\n': 2374 case '\r': 2375 break; 2376 default: 2377 return ch; 2378 } 2379 } 2380 } 2381 2382 2383 2395 protected char scanWhitespace(StringBuffer result) 2396 throws IOException 2397 { 2398 for (;;) { 2399 char ch = this.readChar(); 2400 switch (ch) { 2401 case ' ': 2402 case '\t': 2403 case '\n': 2404 result.append(ch); 2405 case '\r': 2406 break; 2407 default: 2408 return ch; 2409 } 2410 } 2411 } 2412 2413 2414 2427 protected void scanString(StringBuffer string) 2428 throws IOException 2429 { 2430 char delimiter = this.readChar(); 2431 if ((delimiter != '\'') && (delimiter != '"')) { 2432 throw this.expectedInput("' or \""); 2433 } 2434 for (;;) { 2435 char ch = this.readChar(); 2436 if (ch == delimiter) { 2437 return; 2438 } else if (ch == '&') { 2439 this.resolveEntity(string); 2440 } else { 2441 string.append(ch); 2442 } 2443 } 2444 } 2445 2446 2447 2459 protected void scanPCData(StringBuffer data) 2460 throws IOException 2461 { 2462 for (;;) { 2463 char ch = this.readChar(); 2464 if (ch == '<') { 2465 ch = this.readChar(); 2466 if (ch == '!') { 2467 this.checkCDATA(data); 2468 } else { 2469 this.unreadChar(ch); 2470 return; 2471 } 2472 } else if (ch == '&') { 2473 this.resolveEntity(data); 2474 } else { 2475 data.append(ch); 2476 } 2477 } 2478 } 2479 2480 2481 2494 protected boolean checkCDATA(StringBuffer buf) 2495 throws IOException 2496 { 2497 char ch = this.readChar(); 2498 if (ch != '[') { 2499 this.unreadChar(ch); 2500 this.skipSpecialTag(0); 2501 return false; 2502 } else if (! this.checkLiteral("CDATA[")) { 2503 this.skipSpecialTag(1); return false; 2505 } else { 2506 int delimiterCharsSkipped = 0; 2507 while (delimiterCharsSkipped < 3) { 2508 ch = this.readChar(); 2509 switch (ch) { 2510 case ']': 2511 if (delimiterCharsSkipped < 2) { 2512 delimiterCharsSkipped += 1; 2513 } else { 2514 buf.append(']'); 2515 buf.append(']'); 2516 delimiterCharsSkipped = 0; 2517 } 2518 break; 2519 case '>': 2520 if (delimiterCharsSkipped < 2) { 2521 for (int i = 0; i < delimiterCharsSkipped; i++) { 2522 buf.append(']'); 2523 } 2524 delimiterCharsSkipped = 0; 2525 buf.append('>'); 2526 } else { 2527 delimiterCharsSkipped = 3; 2528 } 2529 break; 2530 default: 2531 for (int i = 0; i < delimiterCharsSkipped; i += 1) { 2532 buf.append(']'); 2533 } 2534 buf.append(ch); 2535 delimiterCharsSkipped = 0; 2536 } 2537 } 2538 return true; 2539 } 2540 } 2541 2542 2543 2552 protected void skipComment() 2553 throws IOException 2554 { 2555 int dashesToRead = 2; 2556 while (dashesToRead > 0) { 2557 char ch = this.readChar(); 2558 if (ch == '-') { 2559 dashesToRead -= 1; 2560 } else { 2561 dashesToRead = 2; 2562 } 2563 } 2564 if (this.readChar() != '>') { 2565 throw this.expectedInput(">"); 2566 } 2567 } 2568 2569 2570 2583 protected void skipSpecialTag(int bracketLevel) 2584 throws IOException 2585 { 2586 int tagLevel = 1; char stringDelimiter = '\0'; 2588 if (bracketLevel == 0) { 2589 char ch = this.readChar(); 2590 if (ch == '[') { 2591 bracketLevel += 1; 2592 } else if (ch == '-') { 2593 ch = this.readChar(); 2594 if (ch == '[') { 2595 bracketLevel += 1; 2596 } else if (ch == ']') { 2597 bracketLevel -= 1; 2598 } else if (ch == '-') { 2599 this.skipComment(); 2600 return; 2601 } 2602 } 2603 } 2604 while (tagLevel > 0) { 2605 char ch = this.readChar(); 2606 if (stringDelimiter == '\0') { 2607 if ((ch == '"') || (ch == '\'')) { 2608 stringDelimiter = ch; 2609 } else if (bracketLevel <= 0) { 2610 if (ch == '<') { 2611 tagLevel += 1; 2612 } else if (ch == '>') { 2613 tagLevel -= 1; 2614 } 2615 } 2616 if (ch == '[') { 2617 bracketLevel += 1; 2618 } else if (ch == ']') { 2619 bracketLevel -= 1; 2620 } 2621 } else { 2622 if (ch == stringDelimiter) { 2623 stringDelimiter = '\0'; 2624 } 2625 } 2626 } 2627 } 2628 2629 2630 2644 protected boolean checkLiteral(String literal) 2645 throws IOException 2646 { 2647 int length = literal.length(); 2648 for (int i = 0; i < length; i += 1) { 2649 if (this.readChar() != literal.charAt(i)) { 2650 return false; 2651 } 2652 } 2653 return true; 2654 } 2655 2656 2657 2663 protected char readChar() 2664 throws IOException 2665 { 2666 if (this.charReadTooMuch != '\0') { 2667 char ch = this.charReadTooMuch; 2668 this.charReadTooMuch = '\0'; 2669 return ch; 2670 } else { 2671 int i = this.reader.read(); 2672 if (i < 0) { 2673 throw this.unexpectedEndOfData(); 2674 } else if (i == 10) { 2675 this.parserLineNr += 1; 2676 return '\n'; 2677 } else { 2678 return (char) i; 2679 } 2680 } 2681 } 2682 2683 2684 2696 protected void scanElement(XMLElement elt) 2697 throws IOException 2698 { 2699 StringBuffer buf = new StringBuffer (); 2700 this.scanIdentifier(buf); 2701 String name = buf.toString(); 2702 elt.setName(name); 2703 char ch = this.scanWhitespace(); 2704 while ((ch != '>') && (ch != '/')) { 2705 buf.setLength(0); 2706 this.unreadChar(ch); 2707 this.scanIdentifier(buf); 2708 String key = buf.toString(); 2709 ch = this.scanWhitespace(); 2710 if (ch != '=') { 2711 throw this.expectedInput("="); 2712 } 2713 this.unreadChar(this.scanWhitespace()); 2714 buf.setLength(0); 2715 this.scanString(buf); 2716 elt.setAttribute(key, buf); 2717 ch = this.scanWhitespace(); 2718 } 2719 if (ch == '/') { 2720 ch = this.readChar(); 2721 if (ch != '>') { 2722 throw this.expectedInput(">"); 2723 } 2724 return; 2725 } 2726 buf.setLength(0); 2727 ch = this.scanWhitespace(buf); 2728 if (ch != '<') { 2729 this.unreadChar(ch); 2730 this.scanPCData(buf); 2731 } else { 2732 for (;;) { 2733 ch = this.readChar(); 2734 if (ch == '!') { 2735 if (this.checkCDATA(buf)) { 2736 this.scanPCData(buf); 2737 break; 2738 } else { 2739 ch = this.scanWhitespace(buf); 2740 if (ch != '<') { 2741 this.unreadChar(ch); 2742 this.scanPCData(buf); 2743 break; 2744 } 2745 } 2746 } else { 2747 buf.setLength(0); 2748 break; 2749 } 2750 } 2751 } 2752 if (buf.length() == 0) { 2753 while (ch != '/') { 2754 if (ch == '!') { 2755 ch = this.readChar(); 2756 if (ch != '-') { 2757 throw this.expectedInput("Comment or Element"); 2758 } 2759 ch = this.readChar(); 2760 if (ch != '-') { 2761 throw this.expectedInput("Comment or Element"); 2762 } 2763 this.skipComment(); 2764 } else { 2765 this.unreadChar(ch); 2766 XMLElement child = this.createAnotherElement(); 2767 this.scanElement(child); 2768 elt.addChild(child); 2769 } 2770 ch = this.scanWhitespace(); 2771 if (ch != '<') { 2772 throw this.expectedInput("<"); 2773 } 2774 ch = this.readChar(); 2775 } 2776 this.unreadChar(ch); 2777 } else { 2778 if (this.ignoreWhitespace) { 2779 elt.setContent(buf.toString().trim()); 2780 } else { 2781 elt.setContent(buf.toString()); 2782 } 2783 } 2784 ch = this.readChar(); 2785 if (ch != '/') { 2786 throw this.expectedInput("/"); 2787 } 2788 this.unreadChar(this.scanWhitespace()); 2789 if (! this.checkLiteral(name)) { 2790 throw this.expectedInput(name); 2791 } 2792 if (this.scanWhitespace() != '>') { 2793 throw this.expectedInput(">"); 2794 } 2795 } 2796 2797 2798 2811 protected void resolveEntity(StringBuffer buf) 2812 throws IOException 2813 { 2814 char ch = '\0'; 2815 StringBuffer keyBuf = new StringBuffer (); 2816 for (;;) { 2817 ch = this.readChar(); 2818 if (ch == ';') { 2819 break; 2820 } 2821 keyBuf.append(ch); 2822 } 2823 String key = keyBuf.toString(); 2824 if (key.charAt(0) == '#') { 2825 try { 2826 if (key.charAt(1) == 'x') { 2827 ch = (char) Integer.parseInt(key.substring(2), 16); 2828 } else { 2829 ch = (char) Integer.parseInt(key.substring(1), 10); 2830 } 2831 } catch (NumberFormatException e) { 2832 throw this.unknownEntity(key); 2833 } 2834 buf.append(ch); 2835 } else { 2836 char[] value = (char[]) this.entities.get(key); 2837 if (value == null) { 2838 throw this.unknownEntity(key); 2839 } 2840 buf.append(value); 2841 } 2842 } 2843 2844 2845 2855 protected void unreadChar(char ch) 2856 { 2857 this.charReadTooMuch = ch; 2858 } 2859 2860 2861 2873 protected XMLParseException invalidValueSet(String name) 2874 { 2875 String msg = "Invalid value set (entity name = \"" + name + "\")"; 2876 return new XMLParseException(this.getName(), this.parserLineNr, msg); 2877 } 2878 2879 2880 2894 protected XMLParseException invalidValue(String name, 2895 String value) 2896 { 2897 String msg = "Attribute \"" + name + "\" does not contain a valid " 2898 + "value (\"" + value + "\")"; 2899 return new XMLParseException(this.getName(), this.parserLineNr, msg); 2900 } 2901 2902 2903 2909 protected XMLParseException unexpectedEndOfData() 2910 { 2911 String msg = "Unexpected end of data reached"; 2912 return new XMLParseException(this.getName(), this.parserLineNr, msg); 2913 } 2914 2915 2916 2928 protected XMLParseException syntaxError(String context) 2929 { 2930 String msg = "Syntax error while parsing " + context; 2931 return new XMLParseException(this.getName(), this.parserLineNr, msg); 2932 } 2933 2934 2935 2949 protected XMLParseException expectedInput(String charSet) 2950 { 2951 String msg = "Expected: " + charSet; 2952 return new XMLParseException(this.getName(), this.parserLineNr, msg); 2953 } 2954 2955 2956 2968 protected XMLParseException unknownEntity(String name) 2969 { 2970 String msg = "Unknown or invalid entity: &" + name + ";"; 2971 return new XMLParseException(this.getName(), this.parserLineNr, msg); 2972 } 2973 2974} 2975 | Popular Tags |