1 29 30 package com.caucho.quercus.lib.xml; 31 32 import com.caucho.quercus.annotation.Optional; 33 import com.caucho.quercus.annotation.Reference; 34 import com.caucho.quercus.env.*; 35 import com.caucho.util.L10N; 36 37 import org.xml.sax.Attributes ; 38 import org.xml.sax.InputSource ; 39 import org.xml.sax.SAXException ; 40 import org.xml.sax.helpers.DefaultHandler ; 41 42 import javax.xml.parsers.ParserConfigurationException ; 43 import javax.xml.parsers.SAXParser ; 44 import javax.xml.parsers.SAXParserFactory ; 45 import java.io.IOException ; 46 import java.io.StringReader ; 47 import java.util.ArrayList ; 48 import java.util.HashMap ; 49 import java.util.logging.Level ; 50 import java.util.logging.Logger ; 51 52 55 public class Xml { 56 private static final Logger log = Logger.getLogger(Xml.class.getName()); 57 private static final L10N L = new L10N(Xml.class); 58 59 65 private boolean _xmlOptionCaseFolding = true; 66 67 private String _xmlOptionTargetEncoding; 68 69 75 private long _xmlOptionSkipTagstart = 0; 76 77 80 private boolean _xmlOptionSkipWhite = false; 81 82 private Env _env; 83 84 89 private String _separator; 90 91 private int _errorCode = XmlModule.XML_ERROR_NONE; 92 private String _errorString; 93 94 private Callback _startElementHandler; 95 private Callback _endElementHandler; 96 private Callback _characterDataHandler; 97 private Callback _processingInstructionHandler; 98 private Callback _defaultHandler; 99 private Callback _startNamespaceDeclHandler; 100 private Callback _endNamespaceDeclHandler; 101 private Callback _notationDeclHandler; 102 private Callback _unparsedEntityDeclHandler; 103 104 private Value _parser; 105 private Value _obj; 106 107 SAXParserFactory _factory = SAXParserFactory.newInstance(); 108 109 private StringBuilder _xmlString = new StringBuilder (); 110 111 public Xml(Env env, 112 String outputEncoding, 113 String separator) 114 { 115 _env = env; 116 _xmlOptionTargetEncoding = outputEncoding; 117 _parser = _env.wrapJava(this); 118 _separator = separator; 119 } 120 121 public int getErrorCode() 122 { 123 return _errorCode; 124 } 125 126 public String getErrorString() 127 { 128 return _errorString; 129 } 130 131 138 139 public boolean xml_set_element_handler(Value startElementHandler, 140 Value endElementHandler) 141 { 142 if (_obj == null) { 143 _startElementHandler = _env.createCallback(startElementHandler); 144 _endElementHandler = _env.createCallback(endElementHandler); 145 } else { 146 Value value = new ArrayValueImpl(); 147 value.put(_obj); 148 value.put(startElementHandler); 149 _startElementHandler = _env.createCallback(value); 150 151 value = new ArrayValueImpl(); 152 value.put(_obj); 153 value.put(endElementHandler); 154 _endElementHandler = _env.createCallback(value); 155 } 156 return true; 157 } 158 159 165 public boolean xml_set_character_data_handler(Value handler) 166 { 167 if (_obj == null) { 168 _characterDataHandler = _env.createCallback(handler); 169 } else { 170 Value value = new ArrayValueImpl(); 171 value.put(_obj); 172 value.put(handler); 173 _characterDataHandler = _env.createCallback(value); 174 } 175 176 return true; 177 } 178 179 194 public boolean xml_set_default_handler(Value handler) 195 { 196 if (_obj == null) { 197 _defaultHandler = _env.createCallback(handler); 198 } else { 199 Value value = new ArrayValueImpl(); 200 value.put(_obj); 201 value.put(handler); 202 _defaultHandler = _env.createCallback(value); 203 } 204 return true; 205 } 206 207 213 public boolean xml_set_processing_instruction_handler(Value processingInstructionHandler) 214 { 215 if (_obj == null) { 216 _processingInstructionHandler = _env.createCallback(processingInstructionHandler); 217 } else { 218 Value value = new ArrayValueImpl(); 219 value.put(_obj); 220 value.put(processingInstructionHandler); 221 _processingInstructionHandler = _env.createCallback(value); 222 } 223 return true; 224 } 225 226 232 public boolean xml_set_start_namespace_decl_handler(Value startNamespaceDeclHandler) 233 { 234 if (_obj == null) { 235 _startNamespaceDeclHandler = _env.createCallback(startNamespaceDeclHandler); 236 } else { 237 Value value = new ArrayValueImpl(); 238 value.put(_obj); 239 value.put(startNamespaceDeclHandler); 240 _startNamespaceDeclHandler = _env.createCallback(value); 241 } 242 return true; 243 } 244 245 251 public boolean xml_set_unparsed_entity_decl_handler(Value handler) 252 { 253 if (_obj == null) { 254 _unparsedEntityDeclHandler = _env.createCallback(handler); 255 } else { 256 Value value = new ArrayValueImpl(); 257 value.put(_obj); 258 value.put(handler); 259 _unparsedEntityDeclHandler = _env.createCallback(value); 260 } 261 return true; 262 } 263 264 270 public boolean xml_set_end_namespace_decl_handler(Value endNamespaceDeclHandler) 271 { 272 if (_obj == null) { 273 _endNamespaceDeclHandler = _env.createCallback(endNamespaceDeclHandler); 274 } else { 275 Value value = new ArrayValueImpl(); 276 value.put(_obj); 277 value.put(endNamespaceDeclHandler); 278 _endNamespaceDeclHandler = _env.createCallback(value); 279 } 280 return true; 281 } 282 283 289 public boolean xml_set_notation_decl_handler(Value handler) 290 { 291 if (_obj == null) { 292 _notationDeclHandler = _env.createCallback(handler); 293 } else { 294 Value value = new ArrayValueImpl(); 295 value.put(_obj); 296 value.put(handler); 297 _notationDeclHandler = _env.createCallback(value); 298 } 299 return true; 300 } 301 302 308 public boolean xml_set_object(Value obj) 309 { 310 if (obj == null) 311 return false; 312 313 _obj = obj; 314 315 return true; 316 } 317 318 329 public boolean xml_parse(Env env, String data, 330 @Optional("true") boolean isFinal) 331 throws Exception  332 { 333 _xmlString.append(data); 334 335 if (isFinal) { 336 InputSource is = new InputSource (new StringReader (_xmlString.toString())); 337 if (_xmlOptionTargetEncoding == null) 338 _xmlOptionTargetEncoding = is.getEncoding(); 339 340 try { 341 _errorCode = XmlModule.XML_ERROR_NONE; 342 _errorString = null; 343 344 SAXParser saxParser = _factory.newSAXParser(); 345 saxParser.parse(is, new XmlHandler()); 346 } catch (Exception ex) { 347 ArrayValue array = new ArrayValueImpl(); 348 _errorCode = XmlModule.XML_ERROR_SYNTAX; 349 350 throw ex; 351 } 352 } 353 354 return true; 355 } 356 357 365 public int xml_parse_into_struct(String data, 366 @Reference Value valsV, 367 @Optional @Reference Value indexV) 368 throws Exception  369 { 370 _xmlString.append(data); 371 372 InputSource is = new InputSource (new StringReader (_xmlString.toString())); 373 374 ArrayValueImpl valueArray = new ArrayValueImpl(); 375 ArrayValueImpl indexArray = new ArrayValueImpl(); 376 377 try { 378 SAXParser saxParser = _factory.newSAXParser(); 379 saxParser.parse(is, new StructHandler(valueArray, indexArray)); 380 } catch (Exception ex) { 381 log.log(Level.FINE, ex.toString(), ex); 382 throw new Exception (L.l(ex.getMessage())); 383 } 384 385 valsV.set(valueArray); 386 indexV.set(indexArray); 387 388 return 1; 389 } 390 391 404 public boolean xml_parser_set_option(int option, 405 Value value) 406 { 407 switch(option) { 408 case XmlModule.XML_OPTION_CASE_FOLDING: 409 if (value instanceof BooleanValue) { 410 _xmlOptionCaseFolding = value.toBoolean(); 411 return true; 412 } else { 413 return false; 414 } 415 case XmlModule.XML_OPTION_SKIP_TAGSTART: 416 if (value instanceof LongValue) { 417 _xmlOptionSkipTagstart = value.toLong(); 418 return true; 419 } else { 420 return false; 421 } 422 case XmlModule.XML_OPTION_SKIP_WHITE: 423 if (value instanceof BooleanValue) { 424 _xmlOptionSkipWhite = value.toBoolean(); 425 return true; 426 } else { 427 return false; 428 } 429 case XmlModule.XML_OPTION_TARGET_ENCODING: 430 if (value instanceof StringValue) { 431 _xmlOptionTargetEncoding = value.toString(); 432 return true; 433 } else { 434 return false; 435 } 436 default: 437 return false; 438 } 439 } 440 441 446 public Value xml_parser_get_option(int option) 447 { 448 switch (option) { 449 case XmlModule.XML_OPTION_CASE_FOLDING: 450 return (_xmlOptionCaseFolding ? BooleanValue.TRUE : BooleanValue.FALSE); 451 case XmlModule.XML_OPTION_SKIP_TAGSTART: 452 return new LongValue(_xmlOptionSkipTagstart); 453 case XmlModule.XML_OPTION_SKIP_WHITE: 454 return (_xmlOptionSkipWhite ? BooleanValue.TRUE : BooleanValue.FALSE); 455 case XmlModule.XML_OPTION_TARGET_ENCODING: 456 return new StringValueImpl(_xmlOptionTargetEncoding); 457 default: 458 return BooleanValue.FALSE; 459 } 460 } 461 462 public String toString() 463 { 464 return "Xml[]"; 465 } 466 467 470 class StructHandler extends DefaultHandler { 471 private ArrayValueImpl _valueArray; 472 private ArrayValueImpl _indexArray; 473 474 private int _level = 1; 477 478 private HashMap <Integer , String > _paramHashMap = new HashMap <Integer , String > (); 479 private HashMap <StringValue, ArrayValueImpl> _indexArrayHashMap = new HashMap <StringValue, ArrayValueImpl>(); 480 private ArrayList <StringValue> _indexArrayKeys = new ArrayList <StringValue>(); 481 482 private boolean _isComplete = true; 484 private boolean _isOutside = true; 485 486 private int _valueArrayIndex = 0; 487 488 public StructHandler(ArrayValueImpl valueArray, 489 ArrayValueImpl indexArray) 490 { 491 _valueArray = valueArray; 492 _indexArray = indexArray; 493 } 494 495 500 private ArrayValueImpl createAttributeArray(Attributes attrs) 501 { 502 ArrayValueImpl result = new ArrayValueImpl(); 503 504 for (int i = 0; i < attrs.getLength(); i++) { 506 String aName = attrs.getLocalName(i); if ("".equals(aName)) aName = attrs.getQName(i); 508 if (_xmlOptionCaseFolding) aName = aName.toUpperCase(); 509 result.put(new StringValueImpl(aName), new StringValueImpl(attrs.getValue(i))); 510 } 511 512 return result; 513 } 514 515 public void endDocument() 516 throws SAXException  517 { 518 for(StringValue sv : _indexArrayKeys) { 519 _indexArray.put(sv, _indexArrayHashMap.get(sv)); 520 } 521 } 522 523 public void startElement(String namespaceURI, 524 String lName, 525 String qName, 526 Attributes attrs) 527 throws SAXException  528 { 529 Value elementArray = new ArrayValueImpl(); 530 531 String eName = lName; if ("".equals(eName)) eName = qName; 533 if (_xmlOptionCaseFolding) eName = eName.toUpperCase(); 534 535 elementArray.put(new StringValueImpl("tag"), new StringValueImpl(eName)); 536 elementArray.put(new StringValueImpl("type"), new StringValueImpl("open")); 537 elementArray.put(new StringValueImpl("level"), new DoubleValue((double) _level)); 538 _paramHashMap.put(_level, eName); 539 540 if (attrs.getLength() > 0) { 541 elementArray.put(new StringValueImpl("attributes"), createAttributeArray(attrs)); 542 } 543 544 _valueArray.put(new DoubleValue((double)_valueArrayIndex), elementArray); 545 546 addToIndexArrayHashMap(eName); 547 548 _valueArrayIndex++; 549 _level++; 550 _isComplete = true; 551 _isOutside = false; 552 } 553 554 public void endElement(String namespaceURI, 555 String sName, 556 String qName) 557 throws SAXException  558 { 559 Value elementArray; 560 561 _level--; 562 563 if (_isComplete) { 564 elementArray = _valueArray.get(new DoubleValue((double) _valueArrayIndex - 1)); 565 elementArray.put(new StringValueImpl("type"), new StringValueImpl("complete")); 566 } else { 567 elementArray = new ArrayValueImpl(); 568 String eName = sName; if ("".equals(sName)) eName = qName; 570 if (_xmlOptionCaseFolding) eName = eName.toUpperCase(); 571 elementArray.put(new StringValueImpl("tag"), new StringValueImpl(eName)); 572 elementArray.put(new StringValueImpl("type"), new StringValueImpl("close")); 573 elementArray.put(new StringValueImpl("level"), new DoubleValue((double) _level)); 574 _valueArray.put(new DoubleValue((double)_valueArrayIndex), elementArray); 575 576 addToIndexArrayHashMap(eName); 577 _valueArrayIndex++; 578 } 579 580 _isComplete = false; 581 _isOutside = true; 582 } 583 584 private void addToIndexArrayHashMap(String eName) 585 { 586 StringValue key = new StringValueImpl(eName); 587 ArrayValueImpl indexArray = _indexArrayHashMap.get(key); 588 589 if (indexArray == null) { 590 indexArray = new ArrayValueImpl(); 591 _indexArrayKeys.add(key); 592 } 593 594 indexArray.put(new DoubleValue((double) _valueArrayIndex)); 595 _indexArrayHashMap.put(key, indexArray); 596 } 597 598 public void characters(char[] ch, 599 int start, 600 int length) 601 throws SAXException  602 { 603 String s = new String (ch, start, length); 604 605 if (_isOutside) { 606 Value elementArray = new ArrayValueImpl(); 607 elementArray.put(new StringValueImpl("tag"), new StringValueImpl(_paramHashMap.get(_level - 1))); 608 elementArray.put(new StringValueImpl("value"), new StringValueImpl(s)); 609 elementArray.put(new StringValueImpl("type"), new StringValueImpl("cdata")); 610 elementArray.put(new StringValueImpl("level"), new DoubleValue((double) _level - 1)); 611 _valueArray.put(new DoubleValue((double)_valueArrayIndex), elementArray); 612 613 Value indexArray = _indexArray.get(new StringValueImpl(_paramHashMap.get(_level - 1))); 614 indexArray.put(new DoubleValue((double) _valueArrayIndex)); 615 616 _valueArrayIndex++; 617 } else { 618 Value elementArray = _valueArray.get(new DoubleValue((double) _valueArrayIndex - 1)); 619 elementArray.put(new StringValueImpl("value"), new StringValueImpl(s)); 620 } 621 } 622 } 623 624 class XmlHandler extends DefaultHandler { 625 626 635 public void startElement(String namespaceURI, 636 String lName, 637 String qName, 638 Attributes attrs) 639 throws SAXException  640 { 641 650 Value[] args = new Value[3]; 651 652 args[0] = _parser; 653 654 String eName = lName; if ("".equals(eName)) eName = qName; 656 if (_xmlOptionCaseFolding) eName = eName.toUpperCase(); 657 args[1] = new StringValueImpl(eName); 658 659 args[2] = new ArrayValueImpl(); 661 for (int i = 0; i < attrs.getLength(); i++) { 662 String aName = attrs.getLocalName(i); if ("".equals(aName)) aName = attrs.getQName(i); 664 if (_xmlOptionCaseFolding) aName = aName.toUpperCase(); 665 args[2].put(new StringValueImpl(aName), new StringValueImpl(attrs.getValue(i))); 666 } 667 668 try { 669 if (_startElementHandler != null) 670 _startElementHandler.call(_env,args); 671 else 672 throw new Throwable ("start element handler is not set"); 673 } catch (Throwable t) { 674 log.log(Level.FINE, t.toString(), t); 675 throw new SAXException (L.l(t.getMessage())); 676 } 677 } 678 679 687 public void endElement(String namespaceURI, 688 String sName, 689 String qName) 690 throws SAXException  691 { 692 try { 693 String eName = sName; if ("".equals(eName)) eName = qName; 695 if (_xmlOptionCaseFolding) eName = eName.toUpperCase(); 696 697 if (_endElementHandler != null) 698 _endElementHandler.call(_env, _parser, new StringValueImpl(eName)); 699 else 700 throw new Throwable ("end element handler is not set"); 701 } catch (Throwable t) { 702 log.log(Level.FINE, t.toString(), t); 703 throw new SAXException (L.l(t.getMessage())); 704 } 705 } 706 707 715 public void characters(char[] ch, 716 int start, 717 int length) 718 throws SAXException  719 { 720 String s = new String (ch,start,length); 721 722 try { 723 if (_characterDataHandler != null) 724 _characterDataHandler.call(_env, _parser, new StringValueImpl(s)); 725 else if (_defaultHandler != null) 726 _defaultHandler.call(_env, _parser, new StringValueImpl(s)); 727 else 728 throw new Throwable ("neither character data handler nor default handler is set"); 729 } catch (Throwable t) { 730 log.log(Level.FINE, t.toString(), t); 731 throw new SAXException (L.l(t.getMessage())); 732 } 733 } 734 735 741 public void processingInstruction(String target, 742 String data) 743 throws SAXException  744 { 745 try { 746 if (_processingInstructionHandler != null) 747 _processingInstructionHandler.call(_env, _parser, new StringValueImpl(target), new StringValueImpl(data)); 748 else 749 throw new Throwable ("processing instruction handler is not set"); 750 } catch (Throwable t) { 751 log.log(Level.FINE, t.toString(), t); 752 throw new SAXException (L.l(t.getMessage())); 753 } 754 } 755 756 762 public void startPrefixMapping (String prefix, 763 String uri) 764 throws SAXException  765 { 766 try { 767 if (_startNamespaceDeclHandler != null) 768 _startNamespaceDeclHandler.call(_env, new StringValueImpl(prefix), new StringValueImpl(uri)); 769 else 770 throw new Throwable ("start namespace decl handler is not set"); 771 } catch (Throwable t) { 772 log.log(Level.FINE, t.toString(), t); 773 throw new SAXException (L.l(t.getMessage())); 774 } 775 } 776 777 783 public void endPrefixMapping(String prefix) 784 throws SAXException  785 { 786 try { 787 if (_endNamespaceDeclHandler != null) 788 _endNamespaceDeclHandler.call(_env, new StringValueImpl(prefix)); 789 else 790 throw new Throwable ("end namespace decl handler is not set"); 791 } catch (Throwable t) { 792 log.log(Level.FINE, t.toString(), t); 793 throw new SAXException (L.l(t.getMessage())); 794 } 795 } 796 797 public void notationDecl(String name, 798 String publicId, 799 String systemId) 800 throws SAXException  801 { 802 try { 803 if (_notationDeclHandler != null) 804 _notationDeclHandler.call(_env, 805 _parser, 806 new StringValueImpl(name), 807 new StringValueImpl(""), 808 new StringValueImpl(systemId), 809 new StringValueImpl(publicId)); 810 else 811 throw new Throwable ("notation declaration handler is not set"); 812 } catch (Throwable t) { 813 log.log(Level.FINE, t.toString(), t); 814 throw new SAXException (L.l(t.getMessage())); 815 } 816 } 817 818 @Override  819 public void unparsedEntityDecl(String name, 820 String publicId, 821 String systemId, 822 String notationName) 823 throws SAXException  824 { 825 833 Value[] args = new Value[6]; 834 835 args[0] = _parser; 836 args[1] = new StringValueImpl(name); 837 args[2] = new StringValueImpl(""); 838 args[3] = new StringValueImpl(systemId); 839 args[4] = new StringValueImpl(publicId); 840 args[5] = new StringValueImpl(notationName); 841 842 try { 843 if (_unparsedEntityDeclHandler != null) 844 _unparsedEntityDeclHandler.call(_env, args); 845 else 846 throw new Exception ("unparsed entity declaration handler is not set"); 847 } catch (Throwable t) { 848 log.log(Level.FINE, t.toString(), t); 849 throw new SAXException (L.l(t.getMessage())); 850 } 851 } 852 } 853 } 854 | Popular Tags |