1 28 29 package com.caucho.xml; 30 31 import com.caucho.vfs.Depend; 32 import com.caucho.vfs.Path; 33 34 import org.w3c.dom.*; 35 36 import java.io.IOException ; 37 import java.util.ArrayList ; 38 import java.util.HashMap ; 39 import java.util.Iterator ; 40 41 44 public class QDocument extends QDocumentFragment implements CauchoDocument { 45 QDOMImplementation _implementation; 46 QDocumentType _dtd; 47 QElement _element; HashMap <String ,String > _attributes; 49 String _encoding = "UTF-8"; 50 String _version; 51 52 private String _systemId; 53 54 private HashMap <String ,String > _namespaces; 55 56 private transient HashMap <NameKey,QName> _nameCache = new HashMap <NameKey,QName>(); 57 private transient NameKey _nameKey = new NameKey(); 58 private transient ArrayList <Path> _depends; 59 private transient ArrayList <Depend> _dependList; 60 61 int _changeCount; 62 63 String _rootFilename; 66 private boolean _standalone; 67 68 public QDocument() 69 { 70 _implementation = new QDOMImplementation(); 71 _owner = this; 72 } 73 74 public QDocument(DocumentType docType) 75 { 76 _owner = this; 77 setDoctype(docType); 78 } 79 80 public QDocument(QDOMImplementation impl) 81 { 82 _implementation = impl; 83 _owner = this; 84 } 85 86 void setAttribute(String name, String value) 87 { 88 if (name.equals("version")) 89 _version = value; 90 else if (name.equals("encoding")) 91 _encoding = value; 92 else { 93 if (_attributes == null) 94 _attributes = new HashMap <String ,String >(); 95 _attributes.put(name, value); 96 } 97 } 98 99 public String getRootFilename() 100 { 101 return _rootFilename; 102 } 103 104 public void setRootFilename(String filename) 105 { 106 _rootFilename = filename; 107 } 108 109 public void setSystemId(String systemId) 110 { 111 _systemId = systemId; 112 } 113 114 public String getSystemId() 115 { 116 return _systemId; 117 } 118 119 122 public String getBaseURI() 123 { 124 return getSystemId(); 125 } 126 127 public Document getOwnerDocument() 128 { 129 return null; 130 } 131 132 public DOMConfiguration getDomConfig() 133 { 134 return null; 135 } 136 137 public boolean isSupported(String feature, String version) 138 { 139 return _owner.getImplementation().hasFeature(feature, version); 140 } 141 142 145 public String getNodeName() 146 { 147 return "#document"; 148 } 149 150 public short getNodeType() 151 { 152 return DOCUMENT_NODE; 153 } 154 155 protected Node copyNode(QDocument newNode, boolean deep) 156 { 157 newNode._dtd = _dtd; 158 newNode._element = _element; 159 160 return newNode; 161 } 162 163 168 public Node cloneNode(boolean deep) 169 { 170 QDocument newDoc = new QDocument(); 171 172 newDoc._implementation = _implementation; 173 newDoc._dtd = _dtd; 174 if (_attributes != null) 175 newDoc._attributes = (HashMap ) _attributes.clone(); 176 newDoc._encoding = _encoding; 177 newDoc._version = _version; 178 179 if (_namespaces != null) 180 newDoc._namespaces = (HashMap ) _namespaces.clone(); 181 182 if (deep) { 183 for (Node node = getFirstChild(); 184 node != null; 185 node = node.getNextSibling()) { 186 newDoc.appendChild(newDoc.importNode(node, true)); 187 } 188 } 189 190 return newDoc; 191 } 192 193 Node importNode(QDocument doc, boolean deep) 194 { 195 return null; 196 } 197 198 206 public Node importNode(Node node, boolean deep) 207 { 208 if (node == null) 209 return null; 210 211 QName name; 212 213 switch (node.getNodeType()) { 214 case ELEMENT_NODE: 215 return importElement((Element) node, deep); 216 217 case ATTRIBUTE_NODE: 218 Attr attr = (Attr) node; 219 name = createName(attr.getNamespaceURI(), attr.getNodeName()); 220 QAttr newAttr = new QAttr(name, attr.getNodeValue()); 221 newAttr._owner = this; 222 return newAttr; 223 224 case TEXT_NODE: 225 QText newText = new QText(node.getNodeValue()); 226 newText._owner = this; 227 return newText; 228 229 case CDATA_SECTION_NODE: 230 QCdata newCData = new QCdata(node.getNodeValue()); 231 newCData._owner = this; 232 return newCData; 233 234 case ENTITY_REFERENCE_NODE: 235 QEntityReference newER = new QEntityReference(node.getNodeName()); 236 newER._owner = this; 237 return newER; 238 239 case ENTITY_NODE: 240 Entity oldEntity = (Entity) node; 241 QEntity newEntity = new QEntity(oldEntity.getNodeName(), 242 oldEntity.getNodeValue(), 243 oldEntity.getPublicId(), 244 oldEntity.getSystemId()); 245 newEntity._owner = this; 246 return newEntity; 247 248 case PROCESSING_INSTRUCTION_NODE: 249 QProcessingInstruction newPI; 250 newPI = new QProcessingInstruction(node.getNodeName(), 251 node.getNodeValue()); 252 253 newPI._owner = this; 254 return newPI; 255 256 case COMMENT_NODE: 257 QComment newComment = new QComment(node.getNodeValue()); 258 newComment._owner = this; 259 return newComment; 260 261 case DOCUMENT_FRAGMENT_NODE: 262 return importFragment((DocumentFragment) node, deep); 263 264 default: 265 throw new UnsupportedOperationException (String.valueOf(node)); 266 } 267 } 268 269 272 private Element importElement(Element elt, boolean deep) 273 { 274 QElement newElt = new QElement(createName(elt.getNamespaceURI(), 275 elt.getNodeName())); 276 QElement oldElt = null; 277 278 if (elt instanceof QElement) 279 oldElt = (QElement) elt; 280 281 newElt._owner = this; 282 283 if (oldElt != null) { 284 newElt._filename = oldElt._filename; 285 newElt._line = oldElt._line; 286 } 287 288 NamedNodeMap attrs = elt.getAttributes(); 289 290 int len = attrs.getLength(); 291 for (int i = 0; i < len; i++) { 292 Attr attr = (Attr) attrs.item(i); 293 294 newElt.setAttributeNode((Attr) importNode(attr, deep)); 295 } 296 297 if (! deep) 298 return newElt; 299 300 for (Node node = elt.getFirstChild(); 301 node != null; 302 node = node.getNextSibling()) { 303 newElt.appendChild(importNode(node, true)); 304 } 305 306 return newElt; 307 } 308 309 312 private DocumentFragment importFragment(DocumentFragment elt, boolean deep) 313 { 314 QDocumentFragment newFrag = new QDocumentFragment(); 315 316 newFrag._owner = this; 317 318 if (! deep) 319 return newFrag; 320 321 for (Node node = elt.getFirstChild(); 322 node != null; 323 node = node.getNextSibling()) { 324 newFrag.appendChild(importNode(node, true)); 325 } 326 327 return newFrag; 328 } 329 330 public DocumentType getDoctype() { return _dtd; } 331 332 public void setDoctype(DocumentType dtd) 333 { 334 QDocumentType qdtd = (QDocumentType) dtd; 335 336 _dtd = qdtd; 337 if (qdtd != null) 338 qdtd._owner = this; 339 } 340 341 public String getEncoding() 342 { 343 if (_encoding == null) 344 return null; 345 else 346 return _encoding; 347 } 348 349 public DOMImplementation getImplementation() 350 { 351 return _implementation; 352 } 353 354 public Element getDocumentElement() 355 { 356 return _element; 357 } 358 359 public void setDocumentElement(Element elt) 360 { 361 _element = (QElement) elt; 362 } 363 364 367 public Element createElement(String tagName) 368 throws DOMException 369 { 370 if (! isNameValid(tagName)) 371 throw new QDOMException(DOMException.INVALID_CHARACTER_ERR, 372 "illegal tag `" + tagName + "'"); 373 374 QElement elt = new QElement(createName(null, tagName)); 375 elt._owner = this; 376 377 return elt; 378 } 379 380 383 public Element createElementNS(String namespaceURI, String name) 384 throws DOMException 385 { 386 QName qname = createName(namespaceURI, name); 387 388 validateName(qname); 389 addNamespace(qname); 390 391 QElement elt = new QElement(qname); 392 elt._owner = this; 393 394 return elt; 395 } 396 397 public void validateName(QName qname) 398 throws DOMException 399 { 400 String prefix = qname.getPrefix(); 401 String namespaceURI = qname.getNamespaceURI(); 402 403 if (qname.getPrefix() == "") { 404 } 405 else if (prefix == "xml" && 406 namespaceURI != "http://www.w3.org/XML/1998/namespace") 407 throw new DOMException(DOMException.NAMESPACE_ERR, 408 L.l("`xml' prefix expects namespace uri 'http://www.w3.org/XML/1998/namespace'")); 409 else if (prefix != "" && prefix != null && namespaceURI == null) 410 throw new DOMException(DOMException.NAMESPACE_ERR, 411 L.l("`{0}' prefix expects a namespace uri", 412 prefix)); 413 414 } 415 416 419 public Element createElement(String prefix, String local, String url) 420 throws DOMException 421 { 422 QName name = new QName(prefix, local, url); 423 addNamespace(name); 424 425 QElement elt = new QElement(name); 426 elt._owner = this; 427 428 return elt; 429 } 430 431 public Element createElementByName(QName name) 432 throws DOMException 433 { 434 QElement elt = new QElement(name); 435 elt._owner = this; 436 437 return elt; 438 } 439 440 443 public DocumentFragment createDocumentFragment() 444 { 445 QDocumentFragment frag = new QDocumentFragment(); 446 frag._owner = this; 447 448 return frag; 449 } 450 451 454 public Text createTextNode(String data) 455 { 456 if (data == null) 457 data = ""; 458 459 QText text = new QText(data); 460 text._owner = this; 461 462 return text; 463 } 464 465 public Text createUnescapedTextNode(String data) 466 { 467 if (data == null) 468 data = ""; 469 470 QText text = new QUnescapedText(data); 471 text._owner = this; 472 473 return text; 474 } 475 476 public Comment createComment(String data) 477 { 478 if (data == null) 479 data = ""; 480 481 QComment comment = new QComment(data); 482 comment._owner = this; 483 484 return comment; 485 } 486 487 public CDATASection createCDATASection(String data) 488 { 489 if (data == null) 490 data = ""; 491 492 QCdata cdata = new QCdata(data); 493 cdata._owner = this; 494 495 return cdata; 496 } 497 498 public ProcessingInstruction createProcessingInstruction(String target, 499 String data) 500 throws DOMException 501 { 502 if (target == null || target.length() == 0) 503 throw new QDOMException(DOMException.INVALID_CHARACTER_ERR, 504 L.l("Empty processing instruction name. The processing instruction syntax is: <?name ... ?>")); 505 506 if (! isNameValid(target)) 507 throw new QDOMException(DOMException.INVALID_CHARACTER_ERR, 508 L.l("`{0}' is an invalid processing instruction name. The processing instruction syntax is: <?name ... ?>", target)); 509 510 if (data == null) 511 data = ""; 512 513 QProcessingInstruction pi = new QProcessingInstruction(target, data); 514 pi._owner = this; 515 516 return pi; 517 } 518 519 public Attr createAttribute(String name, String value) 520 throws DOMException 521 { 522 if (! isNameValid(name)) 523 throw new QDOMException(DOMException.INVALID_CHARACTER_ERR, 524 "illegal attribute `" + name + "'"); 525 526 if (value == null) 527 value = ""; 528 529 QAttr attr = new QAttr(new QName(null, name, null), value); 530 attr._owner = this; 531 532 return attr; 533 } 534 535 public Attr createAttribute(String name) 536 throws DOMException 537 { 538 return createAttribute(name, null); 539 } 540 541 544 public Attr createAttribute(String prefix, String local, String url) 545 throws DOMException 546 { 547 QName name = new QName(prefix, local, url); 548 if (url != null && ! url.equals("")) 549 addNamespace(prefix, url); 550 551 QAttr attr = new QAttr(name, null); 552 attr._owner = this; 553 554 return attr; 555 } 556 557 560 public Attr createAttributeNS(String namespaceURI, String qualifiedName) 561 throws DOMException 562 { 563 QName qname = createName(namespaceURI, qualifiedName); 564 565 validateName(qname); 566 addNamespace(qname); 567 568 574 575 QAttr attr = new QAttr(qname, null); 576 attr._owner = this; 577 578 return attr; 579 } 580 581 public QName createName(String uri, String name) 582 { 583 _nameKey.init(name, uri); 584 QName qName = _nameCache.get(_nameKey); 585 586 if (qName != null) 587 return qName; 588 589 if (uri == null) { 590 qName = new QName(null, name, null); 591 } 592 else { 593 int p = name.indexOf(':'); 594 String prefix; 595 String local; 596 if (p < 0) { 597 prefix = null; 598 local = name; 599 } 600 else { 601 prefix = name.substring(0, p); 602 local = name.substring(p + 1); 603 } 604 605 qName = new QName(prefix, local, uri); 606 } 607 608 _nameCache.put(new NameKey(name, uri), qName); 609 610 return qName; 611 } 612 613 616 public Attr createAttribute(QName name, String value) 617 throws DOMException 618 { 619 String url = name.getNamespace(); 620 621 if (url != null && url != "") { 622 addNamespace(name.getPrefix(), url); 623 } 624 625 QAttr attr = new QAttr(name, value); 626 attr._owner = this; 627 628 return attr; 629 } 630 631 public EntityReference createEntityReference(String name) 632 throws DOMException 633 { 634 if (! isNameValid(name)) 635 throw new QDOMException(DOMException.INVALID_CHARACTER_ERR, 636 "illegal entityReference `" + name + "'"); 637 638 QEntityReference er = new QEntityReference(name); 639 er._owner = this; 640 641 return er; 642 } 643 644 647 public NodeList getElementsByTagName(String name) 648 { 649 if (_element == null) 650 return new QDeepNodeList(null, null, null); 651 else 652 return new QDeepNodeList(_element, _element, new QElement.TagPredicate(name)); 653 } 654 655 public NodeList getElementsByTagNameNS(String uri, String name) 656 { 657 if (_element == null) 658 return new QDeepNodeList(null, null, null); 659 else 660 return new QDeepNodeList(_element, _element, new QElement.NSTagPredicate(uri, name)); 661 } 662 663 public Element getElementById(String name) 664 { 665 Node node = _element; 666 667 for (; node != null; node = XmlUtil.getNext(node)) { 668 if (node instanceof Element) { 669 Element elt = (Element) node; 670 671 String id = elt.getAttribute("id"); 672 673 if (name.equals(id)) 674 return elt; 675 } 676 } 677 678 return null; 679 } 680 681 static public Document create() 682 { 683 QDocument doc = new QDocument(); 684 doc._masterDoc = doc; 685 686 return doc; 687 } 688 689 void setAttributes(HashMap <String ,String > attributes) 690 { 691 _attributes = attributes; 692 } 693 694 public Node appendChild(Node newChild) throws DOMException 695 { 696 if (newChild instanceof Element) { 697 _element = (QElement) newChild; 698 699 if (false && _namespaces != null) { 701 Iterator <String > iter = _namespaces.keySet().iterator(); 702 703 while (iter.hasNext()) { 704 String prefix = iter.next(); 705 String ns = _namespaces.get(prefix); 706 707 String xmlns; 708 709 if (prefix.equals("")) 710 xmlns = "xmlns"; 711 else 712 xmlns = "xmlns:" + prefix; 713 714 if (_element.getAttribute(xmlns).equals("")) { 715 QName qName = new QName(xmlns, XmlParser.XMLNS); 716 _element.setAttributeNode(createAttribute(qName, ns)); 717 } 718 } 719 } 720 } 721 722 return super.appendChild(newChild); 723 } 724 725 public Node removeChild(Node oldChild) throws DOMException 726 { 727 Node value = super.removeChild(oldChild); 728 if (oldChild == _element) 729 _element = null; 730 return value; 731 } 732 733 735 public void addNamespace(QName qname) 736 { 737 addNamespace(qname.getPrefix(), qname.getNamespaceURI()); 738 } 739 740 744 public void addNamespace(String prefix, String url) 745 { 746 if (url == null 747 || url.length() == 0 748 || XmlParser.XMLNS.equals(url) 749 || XmlParser.XML.equals(url)) 750 { 751 return; 752 } 753 754 if (prefix == null) 755 prefix = ""; 756 757 if (_namespaces == null) 758 _namespaces = new HashMap <String ,String >(); 759 760 String old = _namespaces.get(prefix); 761 if (old == null) 762 _namespaces.put(prefix, url.intern()); 763 } 764 765 public HashMap <String ,String > getNamespaces() 766 { 767 return _namespaces; 768 } 769 770 773 public String getNamespace(String prefix) 774 { 775 if (_namespaces == null) 776 return null; 777 else 778 return _namespaces.get(prefix); 779 } 780 781 784 public Iterator <String > getNamespaceKeys() 785 { 786 if (_namespaces == null) 787 return null; 788 789 return _namespaces.keySet().iterator(); 790 } 791 792 public Object getProperty(String name) 793 { 794 if (name.equals(DEPENDS)) 795 return _depends; 796 else 797 return null; 798 } 799 800 public ArrayList <Path> getDependList() 801 { 802 return _depends; 803 } 804 805 public ArrayList <Depend> getDependencyList() 806 { 807 return _dependList; 808 } 809 810 public void setProperty(String name, Object value) 811 { 812 if (name.equals(DEPENDS)) 813 _depends = (ArrayList ) value; 814 } 815 816 public String getActualEncoding() 818 { 819 throw new UnsupportedOperationException (); 820 } 821 822 public void setActualEncoding(String actualEncoding) 823 { 824 throw new UnsupportedOperationException (); 825 } 826 832 833 public void setEncoding(String encoding) 834 { 835 throw new UnsupportedOperationException (); 836 } 837 838 public boolean getStandalone() 839 { 840 return _standalone; 841 } 842 843 public void setStandalone(boolean standalone) 844 { 845 _standalone = true; 846 } 847 848 public String getXmlVersion() 849 { 850 return _version; 851 } 852 853 public void setXmlVersion(String version) 854 throws DOMException 855 { 856 _version = version; 857 } 858 859 public void setXmlStandalone(boolean value) 860 throws DOMException 861 { 862 } 863 864 public TypeInfo getSchemaTypeInfo() 865 { 866 return null; 867 } 868 869 public String getXmlEncoding() 870 { 871 return null; 872 } 873 874 public String getInputEncoding() 875 { 876 return null; 877 } 878 879 public boolean getXmlStandalone() 880 throws DOMException 881 { 882 return false; 883 } 884 885 public boolean getStrictErrorChecking() 886 { 887 throw new UnsupportedOperationException (); 888 } 889 890 public void setStrictErrorChecking(boolean strictErrorChecking) 891 { 892 throw new UnsupportedOperationException (); 893 } 894 895 public DOMErrorHandler getErrorHandler() 896 { 897 throw new UnsupportedOperationException (); 898 } 899 900 public void setErrorHandler(DOMErrorHandler errorHandler) 901 { 902 throw new UnsupportedOperationException (); 903 } 904 905 public String getDocumentURI() 906 { 907 throw new UnsupportedOperationException (); 908 } 909 910 public void setDocumentURI(String documentURI) 911 { 912 throw new UnsupportedOperationException (); 913 } 914 915 public Node adoptNode(Node source) 916 throws DOMException 917 { 918 throw new UnsupportedOperationException (); 919 } 920 921 public void normalizeDocument() 922 { 923 throw new UnsupportedOperationException (); 924 } 925 926 public boolean canSetNormalizationFeature(String name, 927 boolean state) 928 { 929 throw new UnsupportedOperationException (); 930 } 931 932 public void setNormalizationFeature(String name, 933 boolean state) 934 throws DOMException 935 { 936 throw new UnsupportedOperationException (); 937 } 938 939 public boolean getNormalizationFeature(String name) 940 throws DOMException 941 { 942 throw new UnsupportedOperationException (); 943 } 944 945 public Node renameNode(Node n, 946 String namespaceURI, 947 String name) 948 throws DOMException 949 { 950 throw new UnsupportedOperationException (); 951 } 952 953 955 public void addDepend(Path path) 956 { 957 if (path == null) 958 return; 959 960 if (_depends == null) 961 _depends = new ArrayList <Path>(); 962 963 if (! _depends.contains(path)) { 964 _depends.add(path); 965 966 if (_dependList == null) 967 _dependList = new ArrayList <Depend>(); 968 969 _dependList.add(new Depend(path)); 970 } 971 } 972 973 public boolean isModified() 974 { 975 if (_dependList == null) 976 return false; 977 978 for (int i = 0; i < _dependList.size(); i++) { 979 Depend depend = _dependList.get(i); 980 981 if (depend.isModified()) 982 return true; 983 } 984 985 return false; 986 } 987 988 void print(XmlPrinter os) throws IOException 989 { 990 os.startDocument(this); 991 992 if (_namespaces != null) { 993 Iterator <String > iter = _namespaces.keySet().iterator(); 994 while (iter.hasNext()) { 995 String prefix = iter.next(); 996 String url = _namespaces.get(prefix); 997 998 if (prefix.equals("")) 999 os.attribute(null, prefix, "xmlns", url); 1000 else 1001 os.attribute(null, prefix, "xmlns:" + prefix, url); 1002 } 1003 } 1004 1005 if (getFirstChild() == null) 1006 os.printHeader(null); 1007 1008 for (Node node = getFirstChild(); 1009 node != null; 1010 node = node.getNextSibling()) { 1011 ((QAbstractNode) node).print(os); 1012 if (os.isPretty()) 1013 os.println(); 1014 } 1015 1016 os.endDocument(); 1017 } 1018 1019 public String toString() 1020 { 1021 String topElt = _element == null ? "XXX:top" : _element.getNodeName(); 1022 1023 if (_dtd == null) 1024 return "Document[" + topElt + "]"; 1025 1026 if (_dtd.getPublicId() != null && _dtd.getSystemId() != null) 1027 return ("Document[" + topElt + " PUBLIC '" + _dtd.getPublicId() + "' '" + 1028 _dtd.getSystemId() + "']"); 1029 else if (_dtd._publicId != null) 1030 return "Document[" + topElt + " PUBLIC '" + _dtd.getPublicId() + "']"; 1031 else if (_dtd.getSystemId() != null) 1032 return "Document[" + topElt + " SYSTEM '" + _dtd.getSystemId() + "']"; 1033 else 1034 return "Document[" + topElt + "]"; 1035 } 1036 1037 static class NameKey { 1038 String _qName; 1039 String _url; 1040 1041 NameKey() 1042 { 1043 } 1044 1045 NameKey(String qName, String url) 1046 { 1047 init(qName, url); 1048 } 1049 1050 void init(String qName, String url) 1051 { 1052 if (qName == null) 1053 throw new NullPointerException (); 1054 1055 if (url == null) 1056 url = ""; 1057 1058 _qName = qName; 1059 _url = url; 1060 } 1061 1062 public int hashCode() 1063 { 1064 return 65521 * _url.hashCode() + _qName.hashCode(); 1065 } 1066 1067 public boolean equals(Object b) 1068 { 1069 if (! (b instanceof NameKey)) 1070 return false; 1071 1072 NameKey key = (NameKey) b; 1073 1074 return _qName.equals(key._qName) && _url.equals(key._url); 1075 } 1076 } 1077 1078 private Object writeReplace() 1079 { 1080 return new SerializedXml(this); 1081 } 1082} 1083 | Popular Tags |