diff options
Diffstat (limited to 'libjava/classpath/gnu/xml/dom')
-rw-r--r-- | libjava/classpath/gnu/xml/dom/Consumer.java | 16 | ||||
-rw-r--r-- | libjava/classpath/gnu/xml/dom/DomDocument.java | 25 | ||||
-rw-r--r-- | libjava/classpath/gnu/xml/dom/DomElement.java | 33 | ||||
-rw-r--r-- | libjava/classpath/gnu/xml/dom/DomNamedNodeMap.java | 2 | ||||
-rw-r--r-- | libjava/classpath/gnu/xml/dom/DomNode.java | 215 | ||||
-rw-r--r-- | libjava/classpath/gnu/xml/dom/ls/DomLSParser.java | 1 | ||||
-rw-r--r-- | libjava/classpath/gnu/xml/dom/ls/SAXEventSink.java | 182 |
7 files changed, 272 insertions, 202 deletions
diff --git a/libjava/classpath/gnu/xml/dom/Consumer.java b/libjava/classpath/gnu/xml/dom/Consumer.java index f99e221e998..026e2754ef9 100644 --- a/libjava/classpath/gnu/xml/dom/Consumer.java +++ b/libjava/classpath/gnu/xml/dom/Consumer.java @@ -301,22 +301,6 @@ public class Consumer extends DomConsumer doc.setBuilding(true); } - /** - * Required by DOM Level 3 to report document parameters - */ - public void xmlDecl(String version, - String encoding, - boolean standalone, - String inputEncoding) - throws SAXException - { - super.xmlDecl(version, encoding, standalone, inputEncoding); - - DomDocument doc = (DomDocument) getDocument(); - doc.setXmlEncoding(encoding); - doc.setInputEncoding(inputEncoding); - } - public void endDocument () throws SAXException { diff --git a/libjava/classpath/gnu/xml/dom/DomDocument.java b/libjava/classpath/gnu/xml/dom/DomDocument.java index 29b8dc72e53..900d03ac3dc 100644 --- a/libjava/classpath/gnu/xml/dom/DomDocument.java +++ b/libjava/classpath/gnu/xml/dom/DomDocument.java @@ -1313,6 +1313,31 @@ public class DomDocument return config; } + public boolean isEqualNode(Node arg) + { + if (!super.isEqualNode(arg)) + return false; + Document d = (Document) arg; + String dversion = d.getXmlVersion(); + if (dversion == null || !dversion.equals(version)) + return false; + boolean dstandalone = d.getXmlStandalone(); + if (dstandalone != standalone) + return false; + String dencoding = d.getXmlEncoding(); + if (dencoding == null || dencoding.equalsIgnoreCase("UTF-8")) + { + if (encoding != null && !encoding.equalsIgnoreCase("UTF-8")) + return false; + } + else + { + if (!dencoding.equals(encoding)) + return false; + } + return true; + } + public void normalizeDocument() { boolean save = building; diff --git a/libjava/classpath/gnu/xml/dom/DomElement.java b/libjava/classpath/gnu/xml/dom/DomElement.java index 34509f647bc..f55b084cc94 100644 --- a/libjava/classpath/gnu/xml/dom/DomElement.java +++ b/libjava/classpath/gnu/xml/dom/DomElement.java @@ -519,5 +519,38 @@ public class DomElement Attr attr = (Attr) attrs.getNamedItemNS(namespaceURI, localName); setIdAttributeNode(attr, isId); } + + public boolean isEqualNode(Node arg) + { + if (!super.isEqualNode(arg)) + return false; + getAttributes(); + NamedNodeMap argAttrs = arg.getAttributes(); + int len = argAttrs.getLength(); + if (argAttrs == null || (len != attributes.length)) + return false; + for (int i = 0; i < len; i++) + { + Node argCtx = argAttrs.item(i); + // Don't compare namespace nodes + if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI + .equals(argCtx.getNamespaceURI())) + continue; + // Find corresponding attribute node + DomNode ctx = attributes.first; + for (; ctx != null; ctx = ctx.next) + { + if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI + .equals(ctx.getNamespaceURI())) + continue; + if (!ctx.isEqualNode(argCtx)) + continue; + break; + } + if (ctx == null) + return false; // not found + } + return true; + } } diff --git a/libjava/classpath/gnu/xml/dom/DomNamedNodeMap.java b/libjava/classpath/gnu/xml/dom/DomNamedNodeMap.java index 6f224029ac3..e3f08e4b4b7 100644 --- a/libjava/classpath/gnu/xml/dom/DomNamedNodeMap.java +++ b/libjava/classpath/gnu/xml/dom/DomNamedNodeMap.java @@ -319,7 +319,7 @@ public class DomNamedNodeMap if (ns) { String tln = ctx.getLocalName(); - if (tln.equals(name)) + if (name != null && name.equals(tln)) { String tu = ctx.getNamespaceURI(); if ((tu == null && uri == null) || diff --git a/libjava/classpath/gnu/xml/dom/DomNode.java b/libjava/classpath/gnu/xml/dom/DomNode.java index 3f29fb1283d..93f7c6f64f3 100644 --- a/libjava/classpath/gnu/xml/dom/DomNode.java +++ b/libjava/classpath/gnu/xml/dom/DomNode.java @@ -38,6 +38,7 @@ exception statement from your version. */ package gnu.xml.dom; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.Map; @@ -149,7 +150,7 @@ public abstract class DomNode boolean readonly; // event registrations - private ListenerRecord[] listeners; + private HashSet listeners; private int nListeners; // DOM Level 3 userData dictionary. @@ -167,19 +168,6 @@ public abstract class DomNode */ public void compact() { - if (listeners != null && listeners.length != nListeners) - { - if (nListeners == 0) - { - listeners = null; - } - else - { - ListenerRecord[] l = new ListenerRecord[nListeners]; - System.arraycopy(listeners, 0, l, 0, nListeners); - listeners = l; - } - } } /** @@ -201,6 +189,7 @@ public abstract class DomNode } } this.owner = owner; + this.listeners = new HashSet(); } @@ -372,6 +361,16 @@ public abstract class DomNode return; } break; + case DOCUMENT_TYPE_NODE: + if (!owner.building) + break; + switch (childNodeType) + { + case COMMENT_NODE: + case PROCESSING_INSTRUCTION_NODE: + return; + } + break; } if (owner.checkingWellformedness) { @@ -960,12 +959,6 @@ public abstract class DomNode */ public void trimToSize() { - if (listeners != null && listeners.length != nListeners) - { - ListenerRecord[] newKids = new ListenerRecord[length]; - System.arraycopy(listeners, 0, newKids, 0, nListeners); - listeners = newKids; - } } /** @@ -1175,7 +1168,7 @@ public abstract class DomNode node.next = null; node.readonly = false; - node.listeners = null; + node.listeners = new HashSet(); node.nListeners = 0; return node; @@ -1264,16 +1257,17 @@ public abstract class DomNode elementName = name; matchAnyURI = "*".equals(uri); matchAnyName = "*".equals(name); - + DomNode.this.addEventListener("DOMNodeInserted", this, true); DomNode.this.addEventListener("DOMNodeRemoved", this, true); } void detach() { - current.detach(); + if (current != null) + current.detach(); current = null; - + DomNode.this.removeEventListener("DOMNodeInserted", this, true); DomNode.this.removeEventListener("DOMNodeRemoved", this, true); } @@ -1336,6 +1330,8 @@ public abstract class DomNode return; } + if (current != null) + current.detach(); current = null; } @@ -1354,6 +1350,7 @@ public abstract class DomNode lastIndex--; } Node ret = current.previousNode (); + current.detach(); current = null; return ret; } @@ -1361,9 +1358,11 @@ public abstract class DomNode // somewhere after last node while (++lastIndex != index) current.nextNode (); - Node ret = current.nextNode (); - current = null; - return ret; + + Node ret = current.nextNode (); + current.detach(); + current = null; + return ret; } public int getLength() @@ -1375,7 +1374,7 @@ public abstract class DomNode { retval++; } - current = null; + iter.detach(); return retval; } @@ -1403,13 +1402,18 @@ public abstract class DomNode this.useCapture = useCapture; } - boolean equals(ListenerRecord rec) + public boolean equals(Object o) { + ListenerRecord rec = (ListenerRecord)o; return listener == rec.listener && useCapture == rec.useCapture && type == rec.type; } + public int hashCode() + { + return listener.hashCode() ^ type.hashCode(); + } } /** @@ -1464,30 +1468,12 @@ public abstract class DomNode EventListener listener, boolean useCapture) { - if (listeners == null) - { - listeners = new ListenerRecord[1]; - } - else if (nListeners == listeners.length) - { - ListenerRecord[] newListeners = - new ListenerRecord[listeners.length + NKIDS_DELTA]; - System.arraycopy(listeners, 0, newListeners, 0, nListeners); - listeners = newListeners; - } - // prune duplicates ListenerRecord record; record = new ListenerRecord(type, listener, useCapture); - for (int i = 0; i < nListeners; i++) - { - if (record.equals(listeners[i])) - { - return; - } - } - listeners [nListeners++] = record; + listeners.add(record); + nListeners = listeners.size(); } // XXX this exception should be discarded from DOM @@ -1672,11 +1658,14 @@ public abstract class DomNode ListenerRecord[] notificationSet) { int count = 0; + Iterator iter; + + iter = current.listeners.iterator(); // do any of this set of listeners get notified? - for (int i = 0; i < current.nListeners; i++) + while (iter.hasNext()) { - ListenerRecord rec = current.listeners[i]; + ListenerRecord rec = (ListenerRecord)iter.next(); if (rec.useCapture != capture) { @@ -1697,6 +1686,7 @@ public abstract class DomNode } notificationSet[count++] = rec; } + iter = null; // Notify just those listeners e.currentNode = current; @@ -1704,18 +1694,21 @@ public abstract class DomNode { try { + iter = current.listeners.iterator(); // Late in the DOM CR process (3rd or 4th CR?) the // removeEventListener spec became asymmetric with respect // to addEventListener ... effect is now immediate. - for (int j = 0; j < current.nListeners; j++) + while (iter.hasNext()) { - if (current.listeners[j].equals(notificationSet[i])) + ListenerRecord rec = (ListenerRecord)iter.next(); + + if (rec.equals(notificationSet[i])) { notificationSet[i].listener.handleEvent(e); break; } } - + iter = null; } catch (Exception x) { @@ -1733,36 +1726,8 @@ public abstract class DomNode EventListener listener, boolean useCapture) { - for (int i = 0; i < nListeners; i++) - { - if (listeners[i].listener != listener) - { - continue; - } - if (listeners[i].useCapture != useCapture) - { - continue; - } - if (!listeners[i].type.equals(type)) - { - continue; - } - - if (nListeners == 1) - { - listeners = null; - nListeners = 0; - } - else - { - for (int j = i + 1; j < nListeners; j++) - { - listeners[i++] = listeners[j++]; - } - listeners[--nListeners] = null; - } - break; - } + listeners.remove(new ListenerRecord(type, listener, useCapture)); + nListeners = listeners.size(); // no exceptions reported } @@ -1779,10 +1744,15 @@ public abstract class DomNode readonly = false; for (DomNode ctx = first; ctx != null; ctx = ctx.next) { + boolean saved2 = ctx.readonly; + ctx.readonly = false; switch (ctx.nodeType) { case TEXT_NODE: - while (ctx.next != null && ctx.next.nodeType == TEXT_NODE) + case CDATA_SECTION_NODE: + while (ctx.next != null && + (ctx.next.nodeType == TEXT_NODE || + ctx.next.nodeType == CDATA_SECTION_NODE)) { Text text = (Text) ctx; text.appendData(ctx.next.getNodeValue()); @@ -1794,7 +1764,11 @@ public abstract class DomNode int len = attrs.getLength(); for (int i = 0; i < len; i++) { - attrs.item(i).normalize(); + DomNode attr = (DomNode) attrs.item(i); + boolean saved3 = attr.readonly; + attr.readonly = false; + attr.normalize(); + attr.readonly = saved3; } // Fall through case DOCUMENT_NODE: @@ -1804,6 +1778,7 @@ public abstract class DomNode ctx.normalize(); break; } + ctx.readonly = saved2; } readonly = saved; } @@ -2017,39 +1992,56 @@ public abstract class DomNode public boolean isEqualNode(Node arg) { if (this == arg) - { - return true; - } + return true; if (arg == null) + return false; + if (nodeType != arg.getNodeType()) + return false; + switch (nodeType) { - return false; - } - if (nodeType != arg.getNodeType() || - !equal(getNodeName(), arg.getNodeName()) || - !equal(getLocalName(), arg.getLocalName()) || - !equal(getNamespaceURI(), arg.getNamespaceURI()) || - !equal(getPrefix(), arg.getPrefix()) || - !equal(getNodeValue(), arg.getNodeValue())) - { - return false; + case ELEMENT_NODE: + case ATTRIBUTE_NODE: + if (!equal(getLocalName(), arg.getLocalName()) || + !equal(getNamespaceURI(), arg.getNamespaceURI())) + return false; + break; + case PROCESSING_INSTRUCTION_NODE: + if (!equal(getNodeName(), arg.getNodeName()) || + !equal(getNodeValue(), arg.getNodeValue())) + return false; + break; + case COMMENT_NODE: + case TEXT_NODE: + case CDATA_SECTION_NODE: + if (!equal(getNodeValue(), arg.getNodeValue())) + return false; + break; } // Children Node argCtx = arg.getFirstChild(); getFirstChild(); // because of DomAttr lazy children - for (DomNode ctx = first; ctx != null; ctx = ctx.next) + DomNode ctx = first; + for (; ctx != null && argCtx != null; ctx = ctx.next) { - if (!ctx.isEqualNode(argCtx)) + if (nodeType == DOCUMENT_NODE) { - return false; + // Ignore whitespace outside document element + while (ctx != null && ctx.nodeType == TEXT_NODE) + ctx = ctx.next; + while (argCtx != null && ctx.getNodeType() == TEXT_NODE) + argCtx = argCtx.getNextSibling(); + if (ctx == null && argCtx != null) + return false; + else if (argCtx == null && ctx != null) + return false; } + if (!ctx.isEqualNode(argCtx)) + return false; argCtx = argCtx.getNextSibling(); } - if (argCtx != null) - { - return false; - } + if (ctx != null || argCtx != null) + return false; - // TODO Attr NamedNodeMap // TODO DocumentType return true; } @@ -2185,5 +2177,14 @@ public abstract class DomNode } } + public void list(java.io.PrintStream out, int indent) + { + for (int i = 0; i < indent; i++) + out.print(" "); + out.println(toString()); + for (DomNode ctx = first; ctx != null; ctx = ctx.next) + ctx.list(out, indent + 1); + } + } diff --git a/libjava/classpath/gnu/xml/dom/ls/DomLSParser.java b/libjava/classpath/gnu/xml/dom/ls/DomLSParser.java index eb7c1c49f3a..7ac4cc749fc 100644 --- a/libjava/classpath/gnu/xml/dom/ls/DomLSParser.java +++ b/libjava/classpath/gnu/xml/dom/ls/DomLSParser.java @@ -260,6 +260,7 @@ public class DomLSParser eventSink.coalescing = coalescing; // get and configure reader XMLReader reader = getXMLReader(); + eventSink.reader = reader; try { reader.setContentHandler(eventSink); diff --git a/libjava/classpath/gnu/xml/dom/ls/SAXEventSink.java b/libjava/classpath/gnu/xml/dom/ls/SAXEventSink.java index a850460b1e2..aad5ac76e70 100644 --- a/libjava/classpath/gnu/xml/dom/ls/SAXEventSink.java +++ b/libjava/classpath/gnu/xml/dom/ls/SAXEventSink.java @@ -37,6 +37,7 @@ exception statement from your version. */ package gnu.xml.dom.ls; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -45,20 +46,26 @@ import org.w3c.dom.Attr; import org.w3c.dom.DocumentType; import org.w3c.dom.Element; import org.w3c.dom.Entity; +import org.w3c.dom.EntityReference; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.Text; import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; import org.xml.sax.DTDHandler; import org.xml.sax.Locator; import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.XMLReader; import org.xml.sax.ext.Attributes2; import org.xml.sax.ext.DeclHandler; import org.xml.sax.ext.LexicalHandler; -import gnu.xml.aelfred2.ContentHandler2; +import org.xml.sax.ext.Locator2; import gnu.xml.dom.DomAttr; import gnu.xml.dom.DomDocument; import gnu.xml.dom.DomDoctype; +import gnu.xml.dom.DomNode; /** * A SAX content and lexical handler used to construct a DOM document. @@ -66,17 +73,28 @@ import gnu.xml.dom.DomDoctype; * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> */ class SAXEventSink - implements ContentHandler2, LexicalHandler, DTDHandler, DeclHandler + implements ContentHandler, LexicalHandler, DTDHandler, DeclHandler { private static final String XMLNS_URI = XMLConstants.XMLNS_ATTRIBUTE_NS_URI; private static final String XMLNS_PREFIX = XMLConstants.XMLNS_ATTRIBUTE; + private static final HashSet PREDEFINED_ENTITIES = new HashSet(); + static + { + PREDEFINED_ENTITIES.add("amp"); + PREDEFINED_ENTITIES.add("lt"); + PREDEFINED_ENTITIES.add("gt"); + PREDEFINED_ENTITIES.add("quot"); + PREDEFINED_ENTITIES.add("apos"); + } boolean namespaceAware; boolean ignoreWhitespace; boolean expandEntityReferences; boolean ignoreComments; boolean coalescing; + + XMLReader reader; // reference back to the parser to get features DomDocument doc; // document being constructed Node ctx; // current context (parent node) @@ -110,20 +128,42 @@ class SAXEventSink doc.setStrictErrorChecking(false); doc.setBuilding(true); ctx = doc; - } - public void xmlDecl(String version, String encoding, boolean standalone, - String inputEncoding) - throws SAXException - { - if (interrupted) + final String FEATURES = "http://xml.org/sax/features/"; + final String PROPERTIES = "http://xml.org/sax/properties/"; + final String GNU_PROPERTIES = "http://gnu.org/sax/properties/"; + + boolean standalone = reader.getFeature(FEATURES + "is-standalone"); + doc.setXmlStandalone(standalone); + try + { + String version = (String) reader.getProperty(PROPERTIES + + "document-xml-version"); + doc.setXmlVersion(version); + } + catch (SAXNotRecognizedException e) + { + } + catch (SAXNotSupportedException e) + { + } + if (locator != null && locator instanceof Locator2) + { + String encoding = ((Locator2) locator).getEncoding(); + doc.setInputEncoding(encoding); + } + try + { + String encoding = (String) reader.getProperty(GNU_PROPERTIES + + "document-xml-encoding"); + doc.setXmlEncoding(encoding); + } + catch (SAXNotRecognizedException e) + { + } + catch (SAXNotSupportedException e) { - return; } - doc.setXmlVersion(version); - doc.setXmlEncoding(encoding); - doc.setXmlStandalone(standalone); - doc.setInputEncoding(inputEncoding); } public void endDocument() @@ -265,7 +305,7 @@ class SAXEventSink public void characters(char[] c, int off, int len) throws SAXException { - if (interrupted) + if (interrupted || len < 1) { return; } @@ -301,11 +341,8 @@ class SAXEventSink { return; } - if (!inDTD) - { - Node pi = createProcessingInstruction(target, data); - ctx.appendChild(pi); - } + Node pi = createProcessingInstruction(target, data); + ctx.appendChild(pi); } protected Node createProcessingInstruction(String target, String data) @@ -354,6 +391,8 @@ class SAXEventSink public void startEntity(String name) throws SAXException { + if (interrupted) + return; DocumentType doctype = doc.getDoctype(); if (doctype == null) { @@ -361,19 +400,9 @@ class SAXEventSink "reference to entity in undeclared doctype"); } if ("[dtd]".equals(name) || name.charAt(0) == '%') - { - // Ignore DTD and parameter entities - ctx = doctype; - return; - } - if ("lt".equals(name) || - "gt".equals(name) || - "amp".equals(name) || - "apos".equals(name) || - "quot".equals(name)) - { - return; - } + return; + if (PREDEFINED_ENTITIES.contains(name)) + return; // Get entity NamedNodeMap entities = doctype.getEntities(); Entity entity = (Entity) entities.getNamedItem(name); @@ -382,59 +411,47 @@ class SAXEventSink throw new SAXException("SAX parser error: " + "reference to undeclared entity: " + name); } - pushEntity(entity); + EntityReference ref = doc.createEntityReference(name); + // DomDocument populates with the entity replacement text, remove this + Node child = ref.getFirstChild(); + while (child != null) + { + Node nextChild = child.getNextSibling(); + ref.removeChild(child); + child = nextChild; + } + ctx.appendChild(ref); + ctx = ref; } public void endEntity(String name) throws SAXException { + if (interrupted) + return; if ("[dtd]".equals(name) || name.charAt(0) == '%') - { - // Ignore DTD and parameter entities - return; - } - if ("lt".equals(name) || - "gt".equals(name) || - "amp".equals(name) || - "apos".equals(name) || - "quot".equals(name)) - { - return; - } - // Get entity - Entity entity = popEntity(); - // TODO resolve external entities to ensure that entity has content + return; + if (PREDEFINED_ENTITIES.contains(name)) + return; + // Get entity reference + EntityReference ref = (EntityReference) ctx; + if (!ref.getNodeName().equals(name)) + throw new SAXException("expecting end of "+ref.getNodeName()+" entity"); + ctx = ctx.getParentNode(); + if (ref instanceof DomNode) + ((DomNode) ref).makeReadonly(); if (expandEntityReferences) { - // Get entity content - for (Node child = entity.getFirstChild(); child != null; - child = child.getNextSibling()) + // Move entity content from reference node onto context + Node child = ref.getFirstChild(); + while (child != null) { + Node nextChild = child.getNextSibling(); ctx.appendChild(child); + child = nextChild; } + ctx.removeChild(ref); } - else - { - Node entityReference = doc.createEntityReference(name); - ctx.appendChild(entityReference); - } - } - - void pushEntity(Node entity) - { - if (entityCtx == null) - { - entityCtx = new LinkedList(); - } - entityCtx.addLast(ctx); - ctx = entity; - } - - Entity popEntity() - { - Entity ret = (Entity) ctx; - ctx = (Node) entityCtx.removeLast(); - return ret; } public void startCDATA() @@ -456,11 +473,8 @@ class SAXEventSink { return; } - if (!inDTD) - { - Node comment = createComment(c, off, len); - ctx.appendChild(comment); - } + Node comment = createComment(c, off, len); + ctx.appendChild(comment); } protected Node createComment(char[] c, int off, int len) @@ -477,6 +491,8 @@ class SAXEventSink { return; } + if (!inDTD) + throw new SAXException("notation decl outside DTD"); DomDoctype doctype = (DomDoctype) ctx; doctype.declareNotation(name, publicId, systemId); } @@ -489,6 +505,8 @@ class SAXEventSink { return; } + if (!inDTD) + throw new SAXException("unparsed entity decl outside DTD"); DomDoctype doctype = (DomDoctype) ctx; Entity entity = doctype.declareEntity(name, publicId, systemId, notationName); @@ -503,6 +521,8 @@ class SAXEventSink { return; } + if (!inDTD) + throw new SAXException("element decl outside DTD"); // Ignore fake element declarations generated by ValidationConsumer. // If an element is not really declared in the DTD it will not be // declared in the document model. @@ -522,6 +542,8 @@ class SAXEventSink { return; } + if (!inDTD) + throw new SAXException("attribute decl outside DTD"); DomDoctype doctype = (DomDoctype) ctx; doctype.attributeDecl(eName, aName, type, mode, value); } @@ -533,6 +555,8 @@ class SAXEventSink { return; } + if (!inDTD) + throw new SAXException("internal entity decl outside DTD"); DomDoctype doctype = (DomDoctype) ctx; Entity entity = doctype.declareEntity(name, null, null, null); if (entity != null) @@ -549,6 +573,8 @@ class SAXEventSink { return; } + if (!inDTD) + throw new SAXException("external entity decl outside DTD"); DomDoctype doctype = (DomDoctype) ctx; Entity entity = doctype.declareEntity(name, publicId, systemId, null); } |