8222743: Xerces 2.12.0: DOM Implementation

Reviewed-by: lancea
This commit is contained in:
Joe Wang 2019-04-25 15:54:21 -07:00
parent 0465104af6
commit f50047aa8e
16 changed files with 1385 additions and 1061 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved.
*/ */
/* /*
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
@ -110,6 +110,7 @@ import org.w3c.dom.Text;
* @author Joe Kesselman, IBM * @author Joe Kesselman, IBM
* @author Andy Clark, IBM * @author Andy Clark, IBM
* @since PR-DOM-Level-1-19980818. * @since PR-DOM-Level-1-19980818.
* @LastModified: Apr 2019
* *
*/ */
public class AttrImpl public class AttrImpl
@ -140,8 +141,6 @@ public class AttrImpl
// REVISIT: we are losing the type information in DOM during serialization // REVISIT: we are losing the type information in DOM during serialization
transient Object type; transient Object type;
protected TextImpl textNode = null;
// //
// Constructors // Constructors
// //
@ -192,7 +191,7 @@ public class AttrImpl
* NON-DOM * NON-DOM
* set the ownerDocument of this node and its children * set the ownerDocument of this node and its children
*/ */
void setOwnerDocument(CoreDocumentImpl doc) { protected void setOwnerDocument(CoreDocumentImpl doc) {
if (needsSyncChildren()) { if (needsSyncChildren()) {
synchronizeChildren(); synchronizeChildren();
} }
@ -349,6 +348,8 @@ public class AttrImpl
Element ownerElement = getOwnerElement(); Element ownerElement = getOwnerElement();
String oldvalue = ""; String oldvalue = "";
TextImpl textNode = null;
if (needsSyncData()) { if (needsSyncData()) {
synchronizeData(); synchronizeData();
} }
@ -363,13 +364,7 @@ public class AttrImpl
oldvalue = (String) value; oldvalue = (String) value;
// create an actual text node as our child so // create an actual text node as our child so
// that we can use it in the event // that we can use it in the event
if (textNode == null) { textNode = (TextImpl) ownerDocument.createTextNode((String) value);
textNode = (TextImpl)
ownerDocument.createTextNode((String) value);
}
else {
textNode.data = (String) value;
}
value = textNode; value = textNode;
textNode.isFirstChild(true); textNode.isFirstChild(true);
textNode.previousSibling = textNode; textNode.previousSibling = textNode;
@ -414,9 +409,16 @@ public class AttrImpl
// since we need to combine the remove and insert. // since we need to combine the remove and insert.
isSpecified(true); isSpecified(true);
if (ownerDocument.getMutationEvents()) { if (ownerDocument.getMutationEvents()) {
// if there are any event handlers create a real node // if there are any event handlers create a real node or
internalInsertBefore(ownerDocument.createTextNode(newvalue), // reuse the one we synthesized for the remove notifications
null, true); // if it exists.
if (textNode == null) {
textNode = (TextImpl) ownerDocument.createTextNode(newvalue);
}
else {
textNode.data = newvalue;
}
internalInsertBefore(textNode, null, true);
hasStringValue(false); hasStringValue(false);
// notify document // notify document
ownerDocument.modifiedAttrValue(this, oldvalue); ownerDocument.modifiedAttrValue(this, oldvalue);
@ -1034,7 +1036,7 @@ public class AttrImpl
* NodeList method: Return the Nth immediate child of this node, or * NodeList method: Return the Nth immediate child of this node, or
* null if the index is out of bounds. * null if the index is out of bounds.
* @return org.w3c.dom.Node * @return org.w3c.dom.Node
* @param Index int * @param index int
*/ */
public Node item(int index) { public Node item(int index) {
@ -1076,12 +1078,12 @@ public class AttrImpl
* Checks if a type is derived from another by restriction. See: * Checks if a type is derived from another by restriction. See:
* http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom * http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom
* *
* @param ancestorNS * @param typeNamespaceArg
* The namspace of the ancestor type declaration * The namspace of the ancestor type declaration
* @param ancestorName * @param typeNameArg
* The name of the ancestor type declaration * The name of the ancestor type declaration
* @param type * @param derivationMethod
* The reference type definition * The derivation method
* *
* @return boolean True if the type is derived by restriciton for the * @return boolean True if the type is derived by restriciton for the
* reference type * reference type

View File

@ -147,30 +147,6 @@ public class AttrNSImpl
setName(namespaceURI, qualifiedName); setName(namespaceURI, qualifiedName);
} }
/**
* NON-DOM: resets this node and sets specified values for the node
*
* @param ownerDocument
* @param namespaceURI
* @param qualifiedName
* @param localName
*/
public void setValues (CoreDocumentImpl ownerDocument,
String namespaceURI,
String qualifiedName,
String localName){
super.textNode = null;
super.flags = 0;
isSpecified(true);
hasStringValue(true);
super.setOwnerDocument(ownerDocument);
this.localName = localName;
this.namespaceURI = namespaceURI;
super.name = qualifiedName;
super.value = null;
}
// //
// DOM2: Namespace methods // DOM2: Namespace methods
// //
@ -314,14 +290,14 @@ public class AttrNSImpl
* Checks if a type is derived from another by restriction. See: * Checks if a type is derived from another by restriction. See:
* http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom * http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom
* *
* @param ancestorNS * @param typeNamespaceArg
* The namspace of the ancestor type declaration * The namspace of the ancestor type declaration
* @param ancestorName * @param typeNameArg
* The name of the ancestor type declaration * The name of the ancestor type declaration
* @param type * @param derivationMethod
* The reference type definition * The derivation method
* *
* @return boolean True if the type is derived by restriciton for the * @return boolean True if the type is derived by restriction for the
* reference type * reference type
*/ */
public boolean isDerivedFrom(String typeNamespaceArg, public boolean isDerivedFrom(String typeNamespaceArg,

View File

@ -40,8 +40,6 @@ public abstract class ChildNode
/** Serialization version. */ /** Serialization version. */
static final long serialVersionUID = -6112455738802414002L; static final long serialVersionUID = -6112455738802414002L;
transient StringBuffer fBufferStr = null;
// //
// Data // Data
// //

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
*/ */
/* /*
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
@ -20,11 +20,18 @@
package com.sun.org.apache.xerces.internal.dom; package com.sun.org.apache.xerces.internal.dom;
import com.sun.org.apache.xerces.internal.impl.RevalidationHandler; import com.sun.org.apache.xerces.internal.impl.RevalidationHandler;
import com.sun.org.apache.xerces.internal.impl.dtd.XML11DTDProcessor;
import com.sun.org.apache.xerces.internal.impl.dtd.XML11DTDValidator;
import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDLoader;
import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator;
import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator;
import com.sun.org.apache.xerces.internal.parsers.DOMParserImpl; import com.sun.org.apache.xerces.internal.parsers.DOMParserImpl;
import com.sun.org.apache.xerces.internal.parsers.DTDConfiguration; import com.sun.org.apache.xerces.internal.parsers.DTDConfiguration;
import com.sun.org.apache.xerces.internal.parsers.XIncludeAwareParserConfiguration; import com.sun.org.apache.xerces.internal.parsers.XIncludeAwareParserConfiguration;
import com.sun.org.apache.xerces.internal.parsers.XML11DTDConfiguration;
import com.sun.org.apache.xerces.internal.util.XMLChar; import com.sun.org.apache.xerces.internal.util.XMLChar;
import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription; import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
import java.lang.ref.SoftReference;
import org.w3c.dom.DOMException; import org.w3c.dom.DOMException;
import org.w3c.dom.DOMImplementation; import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document; import org.w3c.dom.Document;
@ -51,21 +58,39 @@ import org.w3c.dom.ls.LSSerializer;
* @xerces.internal * @xerces.internal
* *
* @since PR-DOM-Level-1-19980818. * @since PR-DOM-Level-1-19980818.
* @LastModified: Apr 2019
*/ */
@SuppressWarnings({"rawtypes", "unchecked"}) //SoftReference array
public class CoreDOMImplementationImpl public class CoreDOMImplementationImpl
implements DOMImplementation, DOMImplementationLS { implements DOMImplementation, DOMImplementationLS {
// //
// Data // Data
// //
// validators pool // validator pools
private static final int SIZE = 2; private static final int SIZE = 2;
private RevalidationHandler validators[] = new RevalidationHandler[SIZE];
private RevalidationHandler dtdValidators[] = new RevalidationHandler[SIZE]; private SoftReference schemaValidators[] = new SoftReference[SIZE];
private int freeValidatorIndex = -1; private SoftReference xml10DTDValidators[] = new SoftReference[SIZE];
private int freeDTDValidatorIndex = -1; private SoftReference xml11DTDValidators[] = new SoftReference[SIZE];
private int currentSize = SIZE;
private int freeSchemaValidatorIndex = -1;
private int freeXML10DTDValidatorIndex = -1;
private int freeXML11DTDValidatorIndex = -1;
private int schemaValidatorsCurrentSize = SIZE;
private int xml10DTDValidatorsCurrentSize = SIZE;
private int xml11DTDValidatorsCurrentSize = SIZE;
private SoftReference xml10DTDLoaders[] = new SoftReference[SIZE];
private SoftReference xml11DTDLoaders[] = new SoftReference[SIZE];
private int freeXML10DTDLoaderIndex = -1;
private int freeXML11DTDLoaderIndex = -1;
private int xml10DTDLoaderCurrentSize = SIZE;
private int xml11DTDLoaderCurrentSize = SIZE;
// Document and doctype counter. Used to assign order to documents and // Document and doctype counter. Used to assign order to documents and
// doctypes without owners, on an demand basis. Used for // doctypes without owners, on an demand basis. Used for
@ -74,8 +99,8 @@ public class CoreDOMImplementationImpl
// static // static
/** Dom implementation singleton. */ /** Dom implementation singleton. */
static CoreDOMImplementationImpl singleton = static final CoreDOMImplementationImpl singleton = new CoreDOMImplementationImpl();
new CoreDOMImplementationImpl();
// //
// Public methods // Public methods
// //
@ -118,6 +143,10 @@ public class CoreDOMImplementationImpl
|| version.equals("1.0") || version.equals("1.0")
|| version.equals("2.0") || version.equals("2.0")
|| version.equals("3.0"))) || version.equals("3.0")))
|| (feature.equalsIgnoreCase("XMLVersion")
&& (anyVersion
|| version.equals("1.0")
|| version.equals("1.1")))
|| (feature.equalsIgnoreCase("LS") || (feature.equalsIgnoreCase("LS")
&& (anyVersion && (anyVersion
|| version.equals("3.0"))) || version.equals("3.0")))
@ -244,12 +273,19 @@ public class CoreDOMImplementationImpl
null); null);
throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg); throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
} }
CoreDocumentImpl doc = new CoreDocumentImpl(doctype); CoreDocumentImpl doc = createDocument(doctype);
// If namespaceURI and qualifiedName are null return a Document with no document element.
if (qualifiedName != null || namespaceURI != null) {
Element e = doc.createElementNS(namespaceURI, qualifiedName); Element e = doc.createElementNS(namespaceURI, qualifiedName);
doc.appendChild(e); doc.appendChild(e);
}
return doc; return doc;
} }
protected CoreDocumentImpl createDocument(DocumentType doctype) {
return new CoreDocumentImpl(doctype);
}
/** /**
* DOM Level 3 WD - Experimental. * DOM Level 3 WD - Experimental.
*/ */
@ -318,7 +354,7 @@ public class CoreDOMImplementationImpl
} }
if (schemaType != null if (schemaType != null
&& schemaType.equals("http://www.w3.org/TR/REC-xml")) { && schemaType.equals("http://www.w3.org/TR/REC-xml")) {
return new DOMParserImpl(new DTDConfiguration(), return new DOMParserImpl(new XML11DTDConfiguration(),
schemaType); schemaType);
} }
else { else {
@ -358,57 +394,205 @@ public class CoreDOMImplementationImpl
// Protected methods // Protected methods
// //
/** NON-DOM: retrieve validator. */ /** NON-DOM: retrieve validator. */
synchronized RevalidationHandler getValidator(String schemaType) { synchronized RevalidationHandler getValidator(String schemaType, String xmlVersion) {
// REVISIT: implement retrieving DTD validator
if (schemaType == XMLGrammarDescription.XML_SCHEMA) { if (schemaType == XMLGrammarDescription.XML_SCHEMA) {
// create new validator - we should not attempt // create new validator - we should not attempt
// to restrict the number of validation handlers being // to restrict the number of validation handlers being
// requested // requested
if(freeValidatorIndex < 0) { while (freeSchemaValidatorIndex >= 0) {
return new com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator();
}
// return first available validator // return first available validator
RevalidationHandler val = validators[freeValidatorIndex]; SoftReference ref = schemaValidators[freeSchemaValidatorIndex];
validators[freeValidatorIndex--] = null; RevalidationHandlerHolder holder = (RevalidationHandlerHolder) ref.get();
if (holder != null && holder.handler != null) {
RevalidationHandler val = holder.handler;
holder.handler = null;
--freeSchemaValidatorIndex;
return val; return val;
} }
schemaValidators[freeSchemaValidatorIndex--] = null;
}
return new XMLSchemaValidator();
}
else if(schemaType == XMLGrammarDescription.XML_DTD) { else if(schemaType == XMLGrammarDescription.XML_DTD) {
if(freeDTDValidatorIndex < 0) { // return an instance of XML11DTDValidator
return new com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator(); if ("1.1".equals(xmlVersion)) {
} while (freeXML11DTDValidatorIndex >= 0) {
// return first available validator // return first available validator
RevalidationHandler val = dtdValidators[freeDTDValidatorIndex]; SoftReference ref = xml11DTDValidators[freeXML11DTDValidatorIndex];
dtdValidators[freeDTDValidatorIndex--] = null; RevalidationHandlerHolder holder = (RevalidationHandlerHolder) ref.get();
if (holder != null && holder.handler != null) {
RevalidationHandler val = holder.handler;
holder.handler = null;
--freeXML11DTDValidatorIndex;
return val; return val;
} }
xml11DTDValidators[freeXML11DTDValidatorIndex--] = null;
}
return new XML11DTDValidator();
}
// return an instance of XMLDTDValidator
else {
while (freeXML10DTDValidatorIndex >= 0) {
// return first available validator
SoftReference ref = xml10DTDValidators[freeXML10DTDValidatorIndex];
RevalidationHandlerHolder holder = (RevalidationHandlerHolder) ref.get();
if (holder != null && holder.handler != null) {
RevalidationHandler val = holder.handler;
holder.handler = null;
--freeXML10DTDValidatorIndex;
return val;
}
xml10DTDValidators[freeXML10DTDValidatorIndex--] = null;
}
return new XMLDTDValidator();
}
}
return null; return null;
} }
/** NON-DOM: release validator */ /** NON-DOM: release validator */
synchronized void releaseValidator(String schemaType, synchronized void releaseValidator(String schemaType, String xmlVersion,
RevalidationHandler validator) { RevalidationHandler validator) {
// REVISIT: implement support for DTD validators as well
if (schemaType == XMLGrammarDescription.XML_SCHEMA) { if (schemaType == XMLGrammarDescription.XML_SCHEMA) {
++freeValidatorIndex; ++freeSchemaValidatorIndex;
if (validators.length == freeValidatorIndex ){ if (schemaValidators.length == freeSchemaValidatorIndex) {
// resize size of the validators // resize size of the validators
currentSize+=SIZE; schemaValidatorsCurrentSize += SIZE;
RevalidationHandler newarray[] = new RevalidationHandler[currentSize]; SoftReference newarray[] = new SoftReference[schemaValidatorsCurrentSize];
System.arraycopy(validators, 0, newarray, 0, validators.length); System.arraycopy(schemaValidators, 0, newarray, 0, schemaValidators.length);
validators = newarray; schemaValidators = newarray;
} }
validators[freeValidatorIndex]=validator; SoftReference ref = schemaValidators[freeSchemaValidatorIndex];
if (ref != null) {
RevalidationHandlerHolder holder = (RevalidationHandlerHolder) ref.get();
if (holder != null) {
holder.handler = validator;
return;
}
}
schemaValidators[freeSchemaValidatorIndex] = new SoftReference(new RevalidationHandlerHolder(validator));
} }
else if (schemaType == XMLGrammarDescription.XML_DTD) { else if (schemaType == XMLGrammarDescription.XML_DTD) {
++freeDTDValidatorIndex; // release an instance of XML11DTDValidator
if (dtdValidators.length == freeDTDValidatorIndex ){ if ("1.1".equals(xmlVersion)) {
++freeXML11DTDValidatorIndex;
if (xml11DTDValidators.length == freeXML11DTDValidatorIndex) {
// resize size of the validators // resize size of the validators
currentSize+=SIZE; xml11DTDValidatorsCurrentSize += SIZE;
RevalidationHandler newarray[] = new RevalidationHandler[currentSize]; SoftReference [] newarray = new SoftReference[xml11DTDValidatorsCurrentSize];
System.arraycopy(dtdValidators, 0, newarray, 0, dtdValidators.length); System.arraycopy(xml11DTDValidators, 0, newarray, 0, xml11DTDValidators.length);
dtdValidators = newarray; xml11DTDValidators = newarray;
} }
dtdValidators[freeDTDValidatorIndex]=validator; SoftReference ref = xml11DTDValidators[freeXML11DTDValidatorIndex];
if (ref != null) {
RevalidationHandlerHolder holder = (RevalidationHandlerHolder) ref.get();
if (holder != null) {
holder.handler = validator;
return;
}
}
xml11DTDValidators[freeXML11DTDValidatorIndex] = new SoftReference(new RevalidationHandlerHolder(validator));
}
// release an instance of XMLDTDValidator
else {
++freeXML10DTDValidatorIndex;
if (xml10DTDValidators.length == freeXML10DTDValidatorIndex) {
// resize size of the validators
xml10DTDValidatorsCurrentSize += SIZE;
SoftReference [] newarray = new SoftReference[xml10DTDValidatorsCurrentSize];
System.arraycopy(xml10DTDValidators, 0, newarray, 0, xml10DTDValidators.length);
xml10DTDValidators = newarray;
}
SoftReference ref = xml10DTDValidators[freeXML10DTDValidatorIndex];
if (ref != null) {
RevalidationHandlerHolder holder = (RevalidationHandlerHolder) ref.get();
if (holder != null) {
holder.handler = validator;
return;
}
}
xml10DTDValidators[freeXML10DTDValidatorIndex] = new SoftReference(new RevalidationHandlerHolder(validator));
}
}
}
/** NON-DOM: retrieve DTD loader */
synchronized final XMLDTDLoader getDTDLoader(String xmlVersion) {
// return an instance of XML11DTDProcessor
if ("1.1".equals(xmlVersion)) {
while (freeXML11DTDLoaderIndex >= 0) {
// return first available DTD loader
SoftReference ref = xml11DTDLoaders[freeXML11DTDLoaderIndex];
XMLDTDLoaderHolder holder = (XMLDTDLoaderHolder) ref.get();
if (holder != null && holder.loader != null) {
XMLDTDLoader val = holder.loader;
holder.loader = null;
--freeXML11DTDLoaderIndex;
return val;
}
xml11DTDLoaders[freeXML11DTDLoaderIndex--] = null;
}
return new XML11DTDProcessor();
}
// return an instance of XMLDTDLoader
else {
while (freeXML10DTDLoaderIndex >= 0) {
// return first available DTD loader
SoftReference ref = xml10DTDLoaders[freeXML10DTDLoaderIndex];
XMLDTDLoaderHolder holder = (XMLDTDLoaderHolder) ref.get();
if (holder != null && holder.loader != null) {
XMLDTDLoader val = holder.loader;
holder.loader = null;
--freeXML10DTDLoaderIndex;
return val;
}
xml10DTDLoaders[freeXML10DTDLoaderIndex--] = null;
}
return new XMLDTDLoader();
}
}
/** NON-DOM: release DTD loader */
synchronized final void releaseDTDLoader(String xmlVersion, XMLDTDLoader loader) {
// release an instance of XMLDTDLoader
if ("1.1".equals(xmlVersion)) {
++freeXML11DTDLoaderIndex;
if (xml11DTDLoaders.length == freeXML11DTDLoaderIndex) {
// resize size of the DTD loaders
xml11DTDLoaderCurrentSize += SIZE;
SoftReference [] newarray = new SoftReference[xml11DTDLoaderCurrentSize];
System.arraycopy(xml11DTDLoaders, 0, newarray, 0, xml11DTDLoaders.length);
xml11DTDLoaders = newarray;
}
SoftReference ref = xml11DTDLoaders[freeXML11DTDLoaderIndex];
if (ref != null) {
XMLDTDLoaderHolder holder = (XMLDTDLoaderHolder) ref.get();
if (holder != null) {
holder.loader = loader;
return;
}
}
xml11DTDLoaders[freeXML11DTDLoaderIndex] = new SoftReference(new XMLDTDLoaderHolder(loader));
}
// release an instance of XMLDTDLoader
else {
++freeXML10DTDLoaderIndex;
if (xml10DTDLoaders.length == freeXML10DTDLoaderIndex) {
// resize size of the DTD loaders
xml10DTDLoaderCurrentSize += SIZE;
SoftReference [] newarray = new SoftReference[xml10DTDLoaderCurrentSize];
System.arraycopy(xml10DTDLoaders, 0, newarray, 0, xml10DTDLoaders.length);
xml10DTDLoaders = newarray;
}
SoftReference ref = xml10DTDLoaders[freeXML10DTDLoaderIndex];
if (ref != null) {
XMLDTDLoaderHolder holder = (XMLDTDLoaderHolder) ref.get();
if (holder != null) {
holder.loader = loader;
return;
}
}
xml10DTDLoaders[freeXML10DTDLoaderIndex] = new SoftReference(new XMLDTDLoaderHolder(loader));
} }
} }
@ -416,6 +600,7 @@ public class CoreDOMImplementationImpl
protected synchronized int assignDocumentNumber() { protected synchronized int assignDocumentNumber() {
return ++docAndDoctypeCounter; return ++docAndDoctypeCounter;
} }
/** NON-DOM: increment document/doctype counter */ /** NON-DOM: increment document/doctype counter */
protected synchronized int assignDocTypeNumber() { protected synchronized int assignDocTypeNumber() {
return ++docAndDoctypeCounter; return ++docAndDoctypeCounter;
@ -427,11 +612,33 @@ public class CoreDOMImplementationImpl
* <code>LSOutput.characterStream</code>, * <code>LSOutput.characterStream</code>,
* <code>LSOutput.byteStream</code>, <code>LSOutput.systemId</code>, * <code>LSOutput.byteStream</code>, <code>LSOutput.systemId</code>,
* <code>LSOutput.encoding</code> are null. * <code>LSOutput.encoding</code> are null.
* @return The newly created output object. * @return The newly created output object.
*/ */
public LSOutput createLSOutput() { public LSOutput createLSOutput() {
return new DOMOutputImpl(); return new DOMOutputImpl();
} }
/**
* A holder for RevalidationHandlers. This allows us to reuse
* SoftReferences which haven't yet been cleared by the garbage
* collector.
*/
static final class RevalidationHandlerHolder {
RevalidationHandlerHolder(RevalidationHandler handler) {
this.handler = handler;
}
RevalidationHandler handler;
}
/**
* A holder for XMLDTDLoaders. This allows us to reuse SoftReferences
* which haven't yet been cleared by the garbage collector.
*/
static final class XMLDTDLoaderHolder {
XMLDTDLoaderHolder(XMLDTDLoader loader) {
this.loader = loader;
}
XMLDTDLoader loader;
}
} // class DOMImplementationImpl } // class DOMImplementationImpl

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
*/ */
/* /*
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
@ -32,7 +32,6 @@ import com.sun.org.apache.xerces.internal.util.MessageFormatter;
import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings; import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings;
import com.sun.org.apache.xerces.internal.util.PropertyState; import com.sun.org.apache.xerces.internal.util.PropertyState;
import com.sun.org.apache.xerces.internal.util.SymbolTable; import com.sun.org.apache.xerces.internal.util.SymbolTable;
import com.sun.org.apache.xerces.internal.utils.ObjectFactory;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler; import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler;
@ -52,6 +51,7 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.StringTokenizer;
import javax.xml.XMLConstants; import javax.xml.XMLConstants;
import javax.xml.catalog.CatalogFeatures; import javax.xml.catalog.CatalogFeatures;
import jdk.xml.internal.JdkXmlUtils; import jdk.xml.internal.JdkXmlUtils;
@ -70,7 +70,7 @@ import org.w3c.dom.ls.LSResourceResolver;
* *
* @author Elena Litani, IBM * @author Elena Litani, IBM
* @author Neeraj Bajaj, Sun Microsystems. * @author Neeraj Bajaj, Sun Microsystems.
* @LastModified: Oct 2017 * @LastModified: Apr 2019
*/ */
public class DOMConfigurationImpl extends ParserConfigurationSettings public class DOMConfigurationImpl extends ParserConfigurationSettings
implements XMLParserConfiguration, DOMConfiguration { implements XMLParserConfiguration, DOMConfiguration {
@ -79,6 +79,9 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
// Constants // Constants
// //
protected static final String XML11_DATATYPE_VALIDATOR_FACTORY =
"com.sun.org.apache.xerces.internal.impl.dv.dtd.XML11DTDDVFactoryImpl";
// feature identifiers // feature identifiers
/** Feature identifier: validation. */ /** Feature identifier: validation. */
@ -101,12 +104,41 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
protected static final String NORMALIZE_DATA = protected static final String NORMALIZE_DATA =
Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_NORMALIZED_VALUE; Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_NORMALIZED_VALUE;
/** Feature identifier: send element default value via characters() */
protected static final String SCHEMA_ELEMENT_DEFAULT =
Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_ELEMENT_DEFAULT;
/** sending psvi in the pipeline */ /** sending psvi in the pipeline */
protected static final String SEND_PSVI = protected static final String SEND_PSVI =
Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_AUGMENT_PSVI; Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_AUGMENT_PSVI;
protected final static String DTD_VALIDATOR_FACTORY_PROPERTY = /** Feature: generate synthetic annotations */
Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY; protected static final String GENERATE_SYNTHETIC_ANNOTATIONS =
Constants.XERCES_FEATURE_PREFIX + Constants.GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE;
/** Feature identifier: validate annotations */
protected static final String VALIDATE_ANNOTATIONS =
Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATE_ANNOTATIONS_FEATURE;
/** Feature identifier: honour all schemaLocations */
protected static final String HONOUR_ALL_SCHEMALOCATIONS =
Constants.XERCES_FEATURE_PREFIX + Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE;
/** Feature identifier: use grammar pool only */
protected static final String USE_GRAMMAR_POOL_ONLY =
Constants.XERCES_FEATURE_PREFIX + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE;
/** Feature identifier: load external DTD. */
protected static final String DISALLOW_DOCTYPE_DECL_FEATURE =
Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE;
/** Feature identifier: balance syntax trees. */
protected static final String BALANCE_SYNTAX_TREES =
Constants.XERCES_FEATURE_PREFIX + Constants.BALANCE_SYNTAX_TREES;
/** Feature identifier: warn on duplicate attribute definition. */
protected static final String WARN_ON_DUPLICATE_ATTDEF =
Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE;
/** Feature identifier: namespace growth */ /** Feature identifier: namespace growth */
protected static final String NAMESPACE_GROWTH = protected static final String NAMESPACE_GROWTH =
@ -133,7 +165,7 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
protected static final String SYMBOL_TABLE = protected static final String SYMBOL_TABLE =
Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY; Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
/** Property id: Grammar pool*/ /** Property id: Grammar pool. */
protected static final String GRAMMAR_POOL = protected static final String GRAMMAR_POOL =
Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY; Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
@ -153,9 +185,25 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
protected static final String JAXP_SCHEMA_SOURCE = protected static final String JAXP_SCHEMA_SOURCE =
Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE; Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE;
/** Property identifier: DTD validator. */
protected final static String DTD_VALIDATOR_PROPERTY =
Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_VALIDATOR_PROPERTY;
/** Property identifier: datatype validator factory. */
protected static final String DTD_VALIDATOR_FACTORY_PROPERTY =
Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY;
protected static final String VALIDATION_MANAGER = protected static final String VALIDATION_MANAGER =
Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY; Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
/** Property identifier: schema location. */
protected static final String SCHEMA_LOCATION =
Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_LOCATION;
/** Property identifier: no namespace schema location. */
protected static final String SCHEMA_NONS_LOCATION =
Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_NONS_LOCATION;
/** Property identifier: Schema DV Factory */ /** Property identifier: Schema DV Factory */
protected static final String SCHEMA_DV_FACTORY = protected static final String SCHEMA_DV_FACTORY =
Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY; Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY;
@ -209,8 +257,18 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
protected final DOMErrorHandlerWrapper fErrorHandlerWrapper = protected final DOMErrorHandlerWrapper fErrorHandlerWrapper =
new DOMErrorHandlerWrapper(); new DOMErrorHandlerWrapper();
/** Current Datatype validator factory. */
protected DTDDVFactory fCurrentDVFactory;
/** The XML 1.0 Datatype validator factory. */
protected DTDDVFactory fDatatypeValidatorFactory;
/** The XML 1.1 Datatype validator factory. **/
protected DTDDVFactory fXML11DatatypeFactory;
// private data // private data
private String fSchemaLocation = null;
private DOMStringList fRecognizedParameters; private DOMStringList fRecognizedParameters;
@ -256,7 +314,16 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
SCHEMA_FULL_CHECKING, SCHEMA_FULL_CHECKING,
DYNAMIC_VALIDATION, DYNAMIC_VALIDATION,
NORMALIZE_DATA, NORMALIZE_DATA,
SCHEMA_ELEMENT_DEFAULT,
SEND_PSVI, SEND_PSVI,
GENERATE_SYNTHETIC_ANNOTATIONS,
VALIDATE_ANNOTATIONS,
HONOUR_ALL_SCHEMALOCATIONS,
USE_GRAMMAR_POOL_ONLY,
DISALLOW_DOCTYPE_DECL_FEATURE,
BALANCE_SYNTAX_TREES,
WARN_ON_DUPLICATE_ATTDEF,
PARSER_SETTINGS,
NAMESPACE_GROWTH, NAMESPACE_GROWTH,
TOLERATE_DUPLICATES, TOLERATE_DUPLICATES,
XMLConstants.USE_CATALOG, XMLConstants.USE_CATALOG,
@ -270,9 +337,19 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
setFeature(SCHEMA_FULL_CHECKING, false); setFeature(SCHEMA_FULL_CHECKING, false);
setFeature(DYNAMIC_VALIDATION, false); setFeature(DYNAMIC_VALIDATION, false);
setFeature(NORMALIZE_DATA, false); setFeature(NORMALIZE_DATA, false);
setFeature(SCHEMA_ELEMENT_DEFAULT, false);
setFeature(XERCES_NAMESPACES, true); setFeature(XERCES_NAMESPACES, true);
setFeature(SEND_PSVI, true); setFeature(SEND_PSVI, true);
setFeature(GENERATE_SYNTHETIC_ANNOTATIONS, false);
setFeature(VALIDATE_ANNOTATIONS, false);
setFeature(HONOUR_ALL_SCHEMALOCATIONS, false);
setFeature(USE_GRAMMAR_POOL_ONLY, false);
setFeature(DISALLOW_DOCTYPE_DECL_FEATURE, false);
setFeature(BALANCE_SYNTAX_TREES, false);
setFeature(WARN_ON_DUPLICATE_ATTDEF, false);
setFeature(PARSER_SETTINGS, true);
setFeature(NAMESPACE_GROWTH, false); setFeature(NAMESPACE_GROWTH, false);
setFeature(TOLERATE_DUPLICATES, false);
setFeature(XMLConstants.USE_CATALOG, JdkXmlUtils.USE_CATALOG_DEFAULT); setFeature(XMLConstants.USE_CATALOG, JdkXmlUtils.USE_CATALOG_DEFAULT);
setFeature(JdkXmlUtils.OVERRIDE_PARSER, JdkXmlUtils.OVERRIDE_PARSER_DEFAULT); setFeature(JdkXmlUtils.OVERRIDE_PARSER, JdkXmlUtils.OVERRIDE_PARSER_DEFAULT);
@ -288,6 +365,9 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
GRAMMAR_POOL, GRAMMAR_POOL,
JAXP_SCHEMA_SOURCE, JAXP_SCHEMA_SOURCE,
JAXP_SCHEMA_LANGUAGE, JAXP_SCHEMA_LANGUAGE,
SCHEMA_LOCATION,
SCHEMA_NONS_LOCATION,
DTD_VALIDATOR_PROPERTY,
DTD_VALIDATOR_FACTORY_PROPERTY, DTD_VALIDATOR_FACTORY_PROPERTY,
SCHEMA_DV_FACTORY, SCHEMA_DV_FACTORY,
SECURITY_MANAGER, SECURITY_MANAGER,
@ -321,7 +401,10 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
setProperty(ERROR_REPORTER, fErrorReporter); setProperty(ERROR_REPORTER, fErrorReporter);
addComponent(fErrorReporter); addComponent(fErrorReporter);
setProperty(DTD_VALIDATOR_FACTORY_PROPERTY, DTDDVFactory.getInstance()); fDatatypeValidatorFactory = DTDDVFactory.getInstance();
fXML11DatatypeFactory = DTDDVFactory.getInstance(XML11_DATATYPE_VALIDATOR_FACTORY);
fCurrentDVFactory = fDatatypeValidatorFactory;
setProperty(DTD_VALIDATOR_FACTORY_PROPERTY, fCurrentDVFactory);
XMLEntityManager manager = new XMLEntityManager(); XMLEntityManager manager = new XMLEntityManager();
setProperty(ENTITY_MANAGER, manager); setProperty(ENTITY_MANAGER, manager);
@ -348,8 +431,7 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
if (fErrorReporter.getMessageFormatter("http://www.w3.org/TR/xml-schema-1") == null) { if (fErrorReporter.getMessageFormatter("http://www.w3.org/TR/xml-schema-1") == null) {
MessageFormatter xmft = null; MessageFormatter xmft = null;
try { try {
xmft = (MessageFormatter)( xmft = new com.sun.org.apache.xerces.internal.impl.xs.XSMessageFormatter();
ObjectFactory.newInstance("com.sun.org.apache.xerces.internal.impl.xs.XSMessageFormatter", true));
} catch (Exception exception){ } catch (Exception exception){
} }
@ -396,7 +478,7 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
* has ended. If a client application wants to terminate * has ended. If a client application wants to terminate
* parsing early, it should throw an exception. * parsing early, it should throw an exception.
* *
* @param source The input source for the top-level of the * @param inputSource The input source for the top-level of the
* XML document. * XML document.
* *
* @exception XNIException Any XNI exception, possibly wrapping * @exception XNIException Any XNI exception, possibly wrapping
@ -462,9 +544,7 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
* uninstall the currently installed resolver. * uninstall the currently installed resolver.
*/ */
public void setEntityResolver(XMLEntityResolver resolver) { public void setEntityResolver(XMLEntityResolver resolver) {
if (resolver !=null) {
fProperties.put(ENTITY_RESOLVER, resolver); fProperties.put(ENTITY_RESOLVER, resolver);
}
} // setEntityResolver(XMLEntityResolver) } // setEntityResolver(XMLEntityResolver)
/** /**
@ -513,6 +593,26 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
return (XMLErrorHandler)fProperties.get(ERROR_HANDLER); return (XMLErrorHandler)fProperties.get(ERROR_HANDLER);
} // getErrorHandler():XMLErrorHandler } // getErrorHandler():XMLErrorHandler
/**
* Returns the state of a feature.
*
* @param featureId The feature identifier.
* @return true if the feature is supported
*
* @throws XMLConfigurationException Thrown for configuration error.
* In general, components should
* only throw this exception if
* it is <strong>really</strong>
* a critical error.
*/
public boolean getFeature(String featureId)
throws XMLConfigurationException {
if (featureId.equals(PARSER_SETTINGS)) {
return true;
}
return super.getFeature(featureId);
}
/** /**
* Set the state of a feature. * Set the state of a feature.
* *
@ -625,22 +725,12 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
|| name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION) || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
) { ) {
if (state) { // true is not supported if (state) { // true is not supported
String msg = throw newFeatureNotSupportedError(name);
DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"FEATURE_NOT_SUPPORTED",
new Object[] { name });
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
} }
} }
else if ( name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)) { else if ( name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)) {
if (!state) { // false is not supported if (!state) { // false is not supported
String msg = throw newFeatureNotSupportedError(name);
DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"FEATURE_NOT_SUPPORTED",
new Object[] { name });
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
} }
} }
else if (name.equalsIgnoreCase(SEND_PSVI) ){ else if (name.equalsIgnoreCase(SEND_PSVI) ){
@ -648,12 +738,7 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
// because in this case we won't be able to retrieve element // because in this case we won't be able to retrieve element
// default value. // default value.
if (!state) { // false is not supported if (!state) { // false is not supported
String msg = throw newFeatureNotSupportedError(name);
DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"FEATURE_NOT_SUPPORTED",
new Object[] { name });
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
} }
} }
else if (name.equalsIgnoreCase(Constants.DOM_PSVI)){ else if (name.equalsIgnoreCase(Constants.DOM_PSVI)){
@ -681,15 +766,8 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
fErrorHandlerWrapper.setErrorHandler((DOMErrorHandler)value); fErrorHandlerWrapper.setErrorHandler((DOMErrorHandler)value);
setErrorHandler(fErrorHandlerWrapper); setErrorHandler(fErrorHandlerWrapper);
} }
else { else {
// REVISIT: type mismatch throw newTypeMismatchError(name);
String msg =
DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"TYPE_MISMATCH_ERR",
new Object[] { name });
throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
} }
} }
else if (name.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)) { else if (name.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)) {
@ -700,36 +778,45 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
catch (XMLConfigurationException e) {} catch (XMLConfigurationException e) {}
} }
else { else {
// REVISIT: type mismatch throw newTypeMismatchError(name);
String msg =
DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"TYPE_MISMATCH_ERR",
new Object[] { name });
throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
} }
} }
else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)) { else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)) {
if (value instanceof String || value == null) { if (value instanceof String || value == null) {
try { try {
// map DOM schema-location to JAXP schemaSource property if (value == null) {
fSchemaLocation = null;
setProperty ( setProperty (
Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE, Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE,
value); null);
}
else {
fSchemaLocation = (String) value;
// map DOM schema-location to JAXP schemaSource property
// tokenize location string
StringTokenizer t = new StringTokenizer(fSchemaLocation, " \n\t\r");
if (t.hasMoreTokens()) {
List<String> locations = new ArrayList<>();
locations.add(t.nextToken());
while (t.hasMoreTokens()) {
locations.add (t.nextToken());
}
setProperty (
Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE,
locations.toArray(new String[locations.size()]));
}
else {
setProperty (
Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE,
new String [] {(String) value});
}
}
} }
catch (XMLConfigurationException e) {} catch (XMLConfigurationException e) {}
} }
else { else {
// REVISIT: type mismatch throw newTypeMismatchError(name);
String msg =
DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"TYPE_MISMATCH_ERR",
new Object[] { name });
throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
} }
} }
else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)) { else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)) {
if (value instanceof String || value == null) { if (value instanceof String || value == null) {
@ -754,14 +841,19 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
catch (XMLConfigurationException e) {} catch (XMLConfigurationException e) {}
} }
else { else {
String msg = throw newTypeMismatchError(name);
DOMMessageFormatter.formatMessage( }
DOMMessageFormatter.DOM_DOMAIN, }
"TYPE_MISMATCH_ERR", else if (name.equalsIgnoreCase(ENTITY_RESOLVER)) {
new Object[] { name }); if (value instanceof XMLEntityResolver || value == null) {
throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg); try {
setEntityResolver((XMLEntityResolver) value);
}
catch (XMLConfigurationException e) {}
}
else {
throw newTypeMismatchError(name);
} }
} }
else if (name.equalsIgnoreCase(SYMBOL_TABLE)) { else if (name.equalsIgnoreCase(SYMBOL_TABLE)) {
// Xerces Symbol Table // Xerces Symbol Table
@ -769,42 +861,23 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
setProperty(SYMBOL_TABLE, value); setProperty(SYMBOL_TABLE, value);
} }
else { else {
// REVISIT: type mismatch throw newTypeMismatchError(name);
String msg =
DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"TYPE_MISMATCH_ERR",
new Object[] { name });
throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
} }
} }
else if (name.equalsIgnoreCase (GRAMMAR_POOL)) { else if (name.equalsIgnoreCase (GRAMMAR_POOL)) {
if (value instanceof XMLGrammarPool){ if (value instanceof XMLGrammarPool || value == null) {
setProperty(GRAMMAR_POOL, value); setProperty(GRAMMAR_POOL, value);
} }
else { else {
// REVISIT: type mismatch throw newTypeMismatchError(name);
String msg =
DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"TYPE_MISMATCH_ERR",
new Object[] { name });
throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
} }
} }
else { else {
// REVISIT: check if this is a boolean parameter -- type mismatch should be thrown. // REVISIT: check if this is a boolean parameter -- type mismatch should be thrown.
//parameter is not recognized //parameter is not recognized
String msg = throw newFeatureNotFoundError(name);
DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"FEATURE_NOT_FOUND",
new Object[] { name });
throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
} }
} }
} }
@ -878,7 +951,10 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
return getProperty(Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE); return getProperty(Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE);
} }
else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)) { else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)) {
return getProperty(Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE); return fSchemaLocation;
}
else if (name.equalsIgnoreCase(ENTITY_RESOLVER)) {
return getEntityResolver();
} }
else if (name.equalsIgnoreCase(SYMBOL_TABLE)) { else if (name.equalsIgnoreCase(SYMBOL_TABLE)) {
return getProperty(SYMBOL_TABLE); return getProperty(SYMBOL_TABLE);
@ -886,15 +962,12 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
else if (name.equalsIgnoreCase(GRAMMAR_POOL)) { else if (name.equalsIgnoreCase(GRAMMAR_POOL)) {
return getProperty(GRAMMAR_POOL); return getProperty(GRAMMAR_POOL);
} }
else { else if (name.equalsIgnoreCase(SECURITY_MANAGER)) {
String msg = return getProperty(SECURITY_MANAGER);
DOMMessageFormatter.formatMessage( }
DOMMessageFormatter.DOM_DOMAIN, else {
"FEATURE_NOT_FOUND", throw newFeatureNotFoundError(name);
new Object[] { name });
throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
} }
} }
/** /**
@ -966,8 +1039,12 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
} }
else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)) { else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)) {
// REVISIT: should null value be supported? // REVISIT: should null value be supported?
//as of now we are only supporting W3C XML Schema // as of now we are only supporting W3C XML Schema and DTD.
return ( (value instanceof String) && value.equals(Constants.NS_XMLSCHEMA) ) ? true : false ; return ((value instanceof String) &&
(value.equals(Constants.NS_XMLSCHEMA) || value.equals(Constants.NS_DTD))) ? true : false;
}
else if (name.equalsIgnoreCase(ENTITY_RESOLVER)) {
return (value instanceof XMLEntityResolver) ? true : false;
} }
else if (name.equalsIgnoreCase(SYMBOL_TABLE)) { else if (name.equalsIgnoreCase(SYMBOL_TABLE)) {
// Xerces Symbol Table // Xerces Symbol Table
@ -1022,11 +1099,14 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
parameters.add(Constants.DOM_RESOURCE_RESOLVER); parameters.add(Constants.DOM_RESOURCE_RESOLVER);
//Add recognized xerces features and properties //Add recognized xerces features and properties
parameters.add(ENTITY_RESOLVER);
parameters.add(GRAMMAR_POOL); parameters.add(GRAMMAR_POOL);
parameters.add(SECURITY_MANAGER);
parameters.add(SYMBOL_TABLE); parameters.add(SYMBOL_TABLE);
parameters.add(SEND_PSVI); parameters.add(SEND_PSVI);
fRecognizedParameters = new DOMStringListImpl(parameters); fRecognizedParameters = new DOMStringListImpl(parameters);
} }
return fRecognizedParameters; return fRecognizedParameters;
@ -1061,6 +1141,7 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
* @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the
* requested feature is not known or supported. * requested feature is not known or supported.
*/ */
@Override
protected PropertyState checkProperty(String propertyId) protected PropertyState checkProperty(String propertyId)
throws XMLConfigurationException { throws XMLConfigurationException {
@ -1115,4 +1196,44 @@ public class DOMConfigurationImpl extends ParserConfigurationSettings
return new ValidationManager(); return new ValidationManager();
} }
} // class XMLParser protected final void setDTDValidatorFactory(String version) {
if ("1.1".equals(version)) {
if (fCurrentDVFactory != fXML11DatatypeFactory) {
fCurrentDVFactory = fXML11DatatypeFactory;
setProperty(DTD_VALIDATOR_FACTORY_PROPERTY, fCurrentDVFactory);
}
}
else if (fCurrentDVFactory != fDatatypeValidatorFactory) {
fCurrentDVFactory = fDatatypeValidatorFactory;
setProperty(DTD_VALIDATOR_FACTORY_PROPERTY, fCurrentDVFactory);
}
}
private static DOMException newFeatureNotSupportedError(String name) {
String msg =
DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"FEATURE_NOT_SUPPORTED",
new Object[] { name });
return new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
}
private static DOMException newFeatureNotFoundError(String name) {
String msg =
DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"FEATURE_NOT_FOUND",
new Object[] { name });
return new DOMException(DOMException.NOT_FOUND_ERR, msg);
}
private static DOMException newTypeMismatchError(String name) {
String msg =
DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"TYPE_MISMATCH_ERR",
new Object[] { name });
return new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
}
} // class DOMConfigurationImpl

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
*/ */
/* /*
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
@ -22,21 +22,17 @@ package com.sun.org.apache.xerces.internal.dom;
import com.sun.org.apache.xerces.internal.dom.AbortException;
import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.Constants;
import com.sun.org.apache.xerces.internal.impl.RevalidationHandler; import com.sun.org.apache.xerces.internal.impl.RevalidationHandler;
import com.sun.org.apache.xerces.internal.impl.dtd.DTDGrammar; import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDLoader;
import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDDescription;
import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator; import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator;
import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType; import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
import com.sun.org.apache.xerces.internal.impl.xs.util.SimpleLocator; import com.sun.org.apache.xerces.internal.impl.xs.util.SimpleLocator;
import com.sun.org.apache.xerces.internal.parsers.XMLGrammarPreparser;
import com.sun.org.apache.xerces.internal.util.AugmentationsImpl; import com.sun.org.apache.xerces.internal.util.AugmentationsImpl;
import com.sun.org.apache.xerces.internal.util.NamespaceSupport; import com.sun.org.apache.xerces.internal.util.NamespaceSupport;
import com.sun.org.apache.xerces.internal.util.SymbolTable; import com.sun.org.apache.xerces.internal.util.SymbolTable;
import com.sun.org.apache.xerces.internal.util.XML11Char; import com.sun.org.apache.xerces.internal.util.XML11Char;
import com.sun.org.apache.xerces.internal.util.XMLChar; import com.sun.org.apache.xerces.internal.util.XMLChar;
import com.sun.org.apache.xerces.internal.util.XMLGrammarPoolImpl;
import com.sun.org.apache.xerces.internal.util.XMLSymbols; import com.sun.org.apache.xerces.internal.util.XMLSymbols;
import com.sun.org.apache.xerces.internal.xni.Augmentations; import com.sun.org.apache.xerces.internal.xni.Augmentations;
import com.sun.org.apache.xerces.internal.xni.NamespaceContext; import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
@ -48,15 +44,12 @@ import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
import com.sun.org.apache.xerces.internal.xni.XMLString; import com.sun.org.apache.xerces.internal.xni.XMLString;
import com.sun.org.apache.xerces.internal.xni.XNIException; import com.sun.org.apache.xerces.internal.xni.XNIException;
import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription; import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent; import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource; import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
import com.sun.org.apache.xerces.internal.xs.AttributePSVI; import com.sun.org.apache.xerces.internal.xs.AttributePSVI;
import com.sun.org.apache.xerces.internal.xs.ElementPSVI; import com.sun.org.apache.xerces.internal.xs.ElementPSVI;
import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition; import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
import java.io.IOException; import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Vector; import java.util.Vector;
@ -96,7 +89,7 @@ import org.w3c.dom.Text;
* *
* @author Elena Litani, IBM * @author Elena Litani, IBM
* @author Neeraj Bajaj, Sun Microsystems, inc. * @author Neeraj Bajaj, Sun Microsystems, inc.
* @LastModified: Nov 2017 * @LastModified: Apr 2019
*/ */
public class DOMNormalizer implements XMLDocumentHandler { public class DOMNormalizer implements XMLDocumentHandler {
@ -155,7 +148,7 @@ public class DOMNormalizer implements XMLDocumentHandler {
/** for setting the PSVI */ /** for setting the PSVI */
protected Node fCurrentNode = null; protected Node fCurrentNode = null;
private QName fAttrQName = new QName(); private final QName fAttrQName = new QName();
// attribute value normalization // attribute value normalization
final XMLString fNormalizedValue = new XMLString(new char[16], 0, 0); final XMLString fNormalizedValue = new XMLString(new char[16], 0, 0);
@ -163,8 +156,11 @@ public class DOMNormalizer implements XMLDocumentHandler {
//DTD validator //DTD validator
private XMLDTDValidator fDTDValidator; private XMLDTDValidator fDTDValidator;
/** Empty string to pass to the validator. **/
public static final XMLString EMPTY_STRING = new XMLString();
// Check if element content is all "ignorable whitespace" // Check if element content is all "ignorable whitespace"
private boolean allWhitespace = false; private boolean fAllWhitespace = false;
// Constructor // Constructor
// //
@ -181,20 +177,26 @@ public class DOMNormalizer implements XMLDocumentHandler {
fDocument = document; fDocument = document;
fConfiguration = config; fConfiguration = config;
fAllWhitespace = false;
fNamespaceValidation = false;
String xmlVersion = fDocument.getXmlVersion();
String schemaType = null;
String [] schemaLocations = null;
// intialize and reset DOMNormalizer component // intialize and reset DOMNormalizer component
// //
fSymbolTable = (SymbolTable) fConfiguration.getProperty(DOMConfigurationImpl.SYMBOL_TABLE); fSymbolTable = (SymbolTable) fConfiguration.getProperty(DOMConfigurationImpl.SYMBOL_TABLE);
// reset namespace context // reset namespace context
fNamespaceContext.reset(); fNamespaceContext.reset();
fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING); fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, null);
if ((fConfiguration.features & DOMConfigurationImpl.VALIDATE) != 0) { if ((fConfiguration.features & DOMConfigurationImpl.VALIDATE) != 0) {
String schemaLang = (String)fConfiguration.getProperty(DOMConfigurationImpl.JAXP_SCHEMA_LANGUAGE); String schemaLang = (String)fConfiguration.getProperty(DOMConfigurationImpl.JAXP_SCHEMA_LANGUAGE);
if (schemaLang != null && schemaLang.equals(Constants.NS_XMLSCHEMA)) { if (schemaLang != null && schemaLang.equals(Constants.NS_XMLSCHEMA)) {
fValidationHandler = schemaType = XMLGrammarDescription.XML_SCHEMA;
CoreDOMImplementationImpl.singleton.getValidator(XMLGrammarDescription.XML_SCHEMA); fValidationHandler = CoreDOMImplementationImpl.singleton.getValidator(schemaType, xmlVersion);
fConfiguration.setFeature(DOMConfigurationImpl.SCHEMA, true); fConfiguration.setFeature(DOMConfigurationImpl.SCHEMA, true);
fConfiguration.setFeature(DOMConfigurationImpl.SCHEMA_FULL_CHECKING, true); fConfiguration.setFeature(DOMConfigurationImpl.SCHEMA_FULL_CHECKING, true);
// report fatal error on DOM Level 1 nodes // report fatal error on DOM Level 1 nodes
@ -203,16 +205,28 @@ public class DOMNormalizer implements XMLDocumentHandler {
// check if we need to fill in PSVI // check if we need to fill in PSVI
fPSVI = ((fConfiguration.features & DOMConfigurationImpl.PSVI) !=0)?true:false; fPSVI = ((fConfiguration.features & DOMConfigurationImpl.PSVI) !=0)?true:false;
} }
else {
schemaType = XMLGrammarDescription.XML_DTD;
if (schemaLang != null) {
schemaLocations = (String []) fConfiguration.getProperty(DOMConfigurationImpl.JAXP_SCHEMA_SOURCE);
}
fConfiguration.setDTDValidatorFactory(xmlVersion);
fValidationHandler = CoreDOMImplementationImpl.singleton.getValidator(schemaType, xmlVersion);
fPSVI = false;
}
fConfiguration.setFeature(DOMConfigurationImpl.XERCES_VALIDATION, true); fConfiguration.setFeature(DOMConfigurationImpl.XERCES_VALIDATION, true);
// reset ID table // reset ID table
fDocument.clearIdentifiers(); fDocument.clearIdentifiers();
if(fValidationHandler != null) if (fValidationHandler != null) {
// reset schema validator // reset the validation handler
((XMLComponent) fValidationHandler).reset(fConfiguration); ((XMLComponent) fValidationHandler).reset(fConfiguration);
}
}
else {
fValidationHandler = null;
} }
fErrorHandler = (DOMErrorHandler) fConfiguration.getParameter(Constants.DOM_ERROR_HANDLER); fErrorHandler = (DOMErrorHandler) fConfiguration.getParameter(Constants.DOM_ERROR_HANDLER);
@ -221,9 +235,14 @@ public class DOMNormalizer implements XMLDocumentHandler {
fValidationHandler.startDocument( fValidationHandler.startDocument(
new SimpleLocator(fDocument.fDocumentURI, fDocument.fDocumentURI, new SimpleLocator(fDocument.fDocumentURI, fDocument.fDocumentURI,
-1, -1 ), fDocument.encoding, fNamespaceContext, null); -1, -1 ), fDocument.encoding, fNamespaceContext, null);
fValidationHandler.xmlDecl(fDocument.getXmlVersion(),
fDocument.getXmlEncoding(), fDocument.getXmlStandalone() ? "yes" : "no", null);
} }
try { try {
if (schemaType == XMLGrammarDescription.XML_DTD) {
processDTD(xmlVersion, schemaLocations != null ? schemaLocations[0] : null);
}
Node kid, next; Node kid, next;
for (kid = fDocument.getFirstChild(); kid != null; kid = next) { for (kid = fDocument.getFirstChild(); kid != null; kid = next) {
next = kid.getNextSibling(); next = kid.getNextSibling();
@ -236,16 +255,24 @@ public class DOMNormalizer implements XMLDocumentHandler {
// release resources // release resources
if (fValidationHandler != null) { if (fValidationHandler != null) {
fValidationHandler.endDocument(null); fValidationHandler.endDocument(null);
CoreDOMImplementationImpl.singleton.releaseValidator( fValidationHandler.setDocumentHandler(null);
XMLGrammarDescription.XML_SCHEMA, fValidationHandler); CoreDOMImplementationImpl.singleton.releaseValidator(schemaType, xmlVersion, fValidationHandler);
fValidationHandler = null; fValidationHandler = null;
} }
} catch (AbortException e) {
return;
} }
catch (RuntimeException e) {
// release resources
if (fValidationHandler != null) {
fValidationHandler.setDocumentHandler(null);
CoreDOMImplementationImpl.singleton.releaseValidator(schemaType, xmlVersion, fValidationHandler);
fValidationHandler = null;
}
if (e instanceof AbortException) {
return; // processing aborted by the user
}
throw e; // otherwise re-throw.
}
} }
/** /**
* *
@ -273,16 +300,7 @@ public class DOMNormalizer implements XMLDocumentHandler {
if (DEBUG_ND) { if (DEBUG_ND) {
System.out.println("==>normalizeNode:{doctype}"); System.out.println("==>normalizeNode:{doctype}");
} }
DocumentTypeImpl docType = (DocumentTypeImpl)node; // REVISIT: well-formedness encoding info
fDTDValidator = (XMLDTDValidator)CoreDOMImplementationImpl.singleton.getValidator(XMLGrammarDescription.XML_DTD);
fDTDValidator.setDocumentHandler(this);
fConfiguration.setProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY, createGrammarPool(docType));
fDTDValidator.reset(fConfiguration);
fDTDValidator.startDocument(
new SimpleLocator(fDocument.fDocumentURI, fDocument.fDocumentURI,
-1, -1 ), fDocument.encoding, fNamespaceContext, null);
fDTDValidator.doctypeDecl(docType.getName(), docType.getPublicId(), docType.getSystemId(), null);
//REVISIT: well-formness encoding info
break; break;
} }
@ -329,7 +347,14 @@ public class DOMNormalizer implements XMLDocumentHandler {
// remove default attributes // remove default attributes
namespaceFixUp(elem, attributes); namespaceFixUp(elem, attributes);
if ((fConfiguration.features & DOMConfigurationImpl.NSDECL) == 0 && attributes != null ) { if ((fConfiguration.features & DOMConfigurationImpl.NSDECL) == 0) {
// Namespace declarations may have been added by namespace fix-up. Need
// to fetch the AttributeMap again if it contained no attributes prior
// to namespace fix-up.
if (attributes == null) {
attributes = (elem.hasAttributes()) ? (AttributeMap) elem.getAttributes() : null;
}
if (attributes != null) {
for (int i = 0; i < attributes.getLength(); ++i) { for (int i = 0; i < attributes.getLength(); ++i) {
Attr att = (Attr)attributes.getItem(i); Attr att = (Attr)attributes.getItem(i);
if (XMLSymbols.PREFIX_XMLNS.equals(att.getPrefix()) || if (XMLSymbols.PREFIX_XMLNS.equals(att.getPrefix()) ||
@ -339,6 +364,7 @@ public class DOMNormalizer implements XMLDocumentHandler {
} }
} }
} }
}
} else { } else {
if ( attributes!=null ) { if ( attributes!=null ) {
@ -347,9 +373,14 @@ public class DOMNormalizer implements XMLDocumentHandler {
//removeDefault(attr, attributes); //removeDefault(attr, attributes);
attr.normalize(); attr.normalize();
if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)){ if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)){
isAttrValueWF(fErrorHandler, fError, fLocator, attributes, (AttrImpl)attr, attr.getValue(), fDocument.isXML11Version()); isAttrValueWF(fErrorHandler, fError, fLocator, attributes, attr, attr.getValue(), fDocument.isXML11Version());
if (fDocument.isXMLVersionChanged()) { if (fDocument.isXMLVersionChanged()) {
if (fNamespaceValidation){
wellformed = CoreDocumentImpl.isValidQName(node.getPrefix(), node.getLocalName(), fDocument.isXML11Version());
}
else {
wellformed = CoreDocumentImpl.isXMLName(node.getNodeName(), fDocument.isXML11Version()); wellformed = CoreDocumentImpl.isXMLName(node.getNodeName(), fDocument.isXML11Version());
}
if (!wellformed) { if (!wellformed) {
String msg = DOMMessageFormatter.formatMessage( String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN, DOMMessageFormatter.DOM_DOMAIN,
@ -379,20 +410,6 @@ public class DOMNormalizer implements XMLDocumentHandler {
fValidationHandler.startElement(fQName, fAttrProxy, null); fValidationHandler.startElement(fQName, fAttrProxy, null);
} }
if (fDTDValidator != null) {
// REVISIT: possible solutions to discard default content are:
// either we pass some flag to XML Schema validator
// or rely on the PSVI information.
fAttrProxy.setAttributes(attributes, fDocument, elem);
updateQName(elem, fQName); // updates global qname
// set error node in the dom error wrapper
// so if error occurs we can report an error node
fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
fCurrentNode = node;
// call re-validation handler
fDTDValidator.startElement(fQName, fAttrProxy, null);
}
// normalize children // normalize children
Node kid, next; Node kid, next;
for (kid = elem.getFirstChild(); kid != null; kid = next) { for (kid = elem.getFirstChild(); kid != null; kid = next) {
@ -412,7 +429,6 @@ public class DOMNormalizer implements XMLDocumentHandler {
} }
if (fValidationHandler != null) { if (fValidationHandler != null) {
updateQName(elem, fQName); // updates global qname updateQName(elem, fQName); // updates global qname
// //
@ -423,16 +439,6 @@ public class DOMNormalizer implements XMLDocumentHandler {
fValidationHandler.endElement(fQName, null); fValidationHandler.endElement(fQName, null);
} }
if (fDTDValidator != null) {
updateQName(elem, fQName); // updates global qname
//
// set error node in the dom error wrapper
// so if error occurs we can report an error node
fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
fCurrentNode = node;
fDTDValidator.endElement(fQName, null);
}
// pop namespace context // pop namespace context
fNamespaceContext.popContext(); fNamespaceContext.popContext();
@ -465,6 +471,13 @@ public class DOMNormalizer implements XMLDocumentHandler {
// of the document // of the document
isCommentWF(fErrorHandler, fError, fLocator, commentdata, fDocument.isXML11Version()); isCommentWF(fErrorHandler, fError, fLocator, commentdata, fDocument.isXML11Version());
} }
if (fValidationHandler != null) {
// Don't bother filling an XMLString with the text of the comment.
// We only send the comment event to the validator handler so that
// when the schema-type is DTD an error will be reported for a
// comment appearing in EMPTY content.
fValidationHandler.comment(EMPTY_STRING, null);
}
}//end-else if comment node is not to be removed. }//end-else if comment node is not to be removed.
break; break;
} }
@ -531,16 +544,6 @@ public class DOMNormalizer implements XMLDocumentHandler {
fValidationHandler.characterData(node.getNodeValue(), null); fValidationHandler.characterData(node.getNodeValue(), null);
fValidationHandler.endCDATA(null); fValidationHandler.endCDATA(null);
} }
if (fDTDValidator != null) {
// set error node in the dom error wrapper
// so if error occurs we can report an error node
fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
fCurrentNode = node;
fDTDValidator.startCDATA(null);
fDTDValidator.characterData(node.getNodeValue(), null);
fDTDValidator.endCDATA(null);
}
String value = node.getNodeValue(); String value = node.getNodeValue();
if ((fConfiguration.features & DOMConfigurationImpl.SPLITCDATA) != 0) { if ((fConfiguration.features & DOMConfigurationImpl.SPLITCDATA) != 0) {
@ -617,23 +620,18 @@ public class DOMNormalizer implements XMLDocumentHandler {
fConfiguration.fErrorHandlerWrapper.fCurrentNode = node; fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
fCurrentNode = node; fCurrentNode = node;
fValidationHandler.characterData(node.getNodeValue(), null); fValidationHandler.characterData(node.getNodeValue(), null);
if (DEBUG_ND) { if (!fNamespaceValidation) {
System.out.println("=====>characterData(),"+nextType); if (fAllWhitespace) {
fAllWhitespace = false;
}
}
if (fDTDValidator != null) {
fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
fCurrentNode = node;
fDTDValidator.characterData(node.getNodeValue(), null);
if (DEBUG_ND) {
System.out.println("=====>characterData(),"+nextType);
}
if(allWhitespace) {
allWhitespace = false;
((TextImpl)node).setIgnorableWhitespace(true); ((TextImpl)node).setIgnorableWhitespace(true);
} }
else {
((TextImpl)node).setIgnorableWhitespace(false);
}
}
if (DEBUG_ND) {
System.out.println("=====>characterData(),"+nextType);
}
} }
} }
else { else {
@ -674,42 +672,66 @@ public class DOMNormalizer implements XMLDocumentHandler {
//which may not be valid XML character //which may not be valid XML character
isXMLCharWF(fErrorHandler, fError, fLocator, pinode.getData(), fDocument.isXML11Version()); isXMLCharWF(fErrorHandler, fError, fLocator, pinode.getData(), fDocument.isXML11Version());
} }
if (fValidationHandler != null) {
// Don't bother filling an XMLString with the data section of the
// processing instruction. We only send the processing instruction
// event to the validator handler so that when the schema-type is
// DTD an error will be reported for a processing instruction
// appearing in EMPTY content.
fValidationHandler.processingInstruction(((ProcessingInstruction) node).getTarget(), EMPTY_STRING, null);
}
}//end case Node.PROCESSING_INSTRUCTION_NODE }//end case Node.PROCESSING_INSTRUCTION_NODE
}//end of switch }//end of switch
return null; return null;
}//normalizeNode }//normalizeNode
private XMLGrammarPool createGrammarPool(DocumentTypeImpl docType) { private void processDTD(String xmlVersion, String schemaLocation) {
XMLGrammarPoolImpl pool = new XMLGrammarPoolImpl(); String rootName = null;
String publicId = null;
String systemId = schemaLocation;
String baseSystemId = fDocument.getDocumentURI();
String internalSubset = null;
XMLGrammarPreparser preParser = new XMLGrammarPreparser(fSymbolTable); DocumentType docType = fDocument.getDoctype();
preParser.registerPreparser(XMLGrammarDescription.XML_DTD, null); if (docType != null) {
preParser.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE, true); rootName = docType.getName();
preParser.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATION_FEATURE, true); publicId = docType.getPublicId();
preParser.setProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY, pool); if (systemId == null || systemId.length() == 0) {
systemId = docType.getSystemId();
}
internalSubset = docType.getInternalSubset();
}
// If the DOM doesn't have a DocumentType node we may still
// be able to fetch a DTD if the application provided a URI
else {
Element elem = fDocument.getDocumentElement();
if (elem == null) return;
rootName = elem.getNodeName();
if (systemId == null || systemId.length() == 0) return;
}
String internalSubset = docType.getInternalSubset(); XMLDTDLoader loader = null;
XMLInputSource is = new XMLInputSource(docType.getPublicId(), docType.getSystemId(), null, false);
if(internalSubset != null)
is.setCharacterStream(new StringReader(internalSubset));
try { try {
DTDGrammar g = (DTDGrammar)preParser.preparseGrammar(XMLGrammarDescription.XML_DTD, is); fValidationHandler.doctypeDecl(rootName, publicId, systemId, null);
((XMLDTDDescription)g.getGrammarDescription()).setRootName(docType.getName()); loader = CoreDOMImplementationImpl.singleton.getDTDLoader(xmlVersion);
is.setCharacterStream(null); loader.setFeature(DOMConfigurationImpl.XERCES_VALIDATION, true);
g = (DTDGrammar)preParser.preparseGrammar(XMLGrammarDescription.XML_DTD, is); loader.setEntityResolver(fConfiguration.getEntityResolver());
((XMLDTDDescription)g.getGrammarDescription()).setRootName(docType.getName()); loader.setErrorHandler(fConfiguration.getErrorHandler());
loader.loadGrammarWithContext((XMLDTDValidator) fValidationHandler, rootName,
} catch (XNIException e) { publicId, systemId, baseSystemId, internalSubset);
} catch (IOException e) {
} }
// REVISIT: Should probably report this exception to the error handler.
return pool; catch (IOException e) {
} }
finally {
if (loader != null) {
CoreDOMImplementationImpl.singleton.releaseDTDLoader(xmlVersion, loader);
}
}
} // processDTD(String, String)
protected final void expandEntityRef (Node parent, Node reference){ protected final void expandEntityRef (Node parent, Node reference){
Node kid, next; Node kid, next;
@ -740,30 +762,15 @@ public class DOMNormalizer implements XMLDocumentHandler {
// //
// ------------------------------------ // ------------------------------------
String value, name, uri, prefix; String value, uri, prefix;
if (attributes != null) { if (attributes != null) {
// Record all valid local declarations // Record all valid local declarations
for (int k = 0; k < attributes.getLength(); ++k) { for (int k = 0; k < attributes.getLength(); ++k) {
Attr attr = (Attr)attributes.getItem(k); Attr attr = (Attr)attributes.getItem(k);
//do the name check only when version of the document was changed &
//application has set the value of well-formed features to true
if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) &&
fDocument.isXMLVersionChanged()) {
//checkQName does checking based on the version of the document
fDocument.checkQName(attr.getPrefix() , attr.getLocalName()) ;
}
uri = attr.getNamespaceURI(); uri = attr.getNamespaceURI();
if (uri != null && uri.equals(NamespaceContext.XMLNS_URI)) { if (uri != null && uri.equals(NamespaceContext.XMLNS_URI)) {
// namespace attribute // namespace attribute
// "namespace-declarations" == false; Discard all namespace declaration attributes
if ((fConfiguration.features & DOMConfigurationImpl.NSDECL) == 0) {
continue;
}
value = attr.getNodeValue(); value = attr.getNodeValue();
if (value == null) { if (value == null) {
value=XMLSymbols.EMPTY_STRING; value=XMLSymbols.EMPTY_STRING;
@ -798,7 +805,7 @@ public class DOMNormalizer implements XMLDocumentHandler {
} else { // (localpart == fXmlnsSymbol && prefix == fEmptySymbol) -- xmlns } else { // (localpart == fXmlnsSymbol && prefix == fEmptySymbol) -- xmlns
// empty prefix is always bound ("" or some string) // empty prefix is always bound ("" or some string)
value = fSymbolTable.addSymbol(value); value = fSymbolTable.addSymbol(value);
fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, value); fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, value.length() != 0 ? value : null);
//removeDefault (attr, attributes); //removeDefault (attr, attributes);
continue; continue;
} }
@ -826,12 +833,7 @@ public class DOMNormalizer implements XMLDocumentHandler {
uri = element.getNamespaceURI(); uri = element.getNamespaceURI();
prefix = element.getPrefix(); prefix = element.getPrefix();
if (uri != null) { // Element has a namespace
// "namespace-declarations" == false? Discard all namespace declaration attributes
if ((fConfiguration.features & DOMConfigurationImpl.NSDECL) == 0) {
// no namespace declaration == no namespace URI, semantics are to keep prefix
uri = null;
} else if (uri != null) { // Element has a namespace
uri = fSymbolTable.addSymbol(uri); uri = fSymbolTable.addSymbol(uri);
prefix = (prefix == null || prefix = (prefix == null ||
prefix.length() == 0) ? XMLSymbols.EMPTY_STRING :fSymbolTable.addSymbol(prefix); prefix.length() == 0) ? XMLSymbols.EMPTY_STRING :fSymbolTable.addSymbol(prefix);
@ -870,8 +872,8 @@ public class DOMNormalizer implements XMLDocumentHandler {
// undeclare default namespace declaration (before that element // undeclare default namespace declaration (before that element
// bound to non-zero length uir), but adding xmlns="" decl // bound to non-zero length uir), but adding xmlns="" decl
addNamespaceDecl (XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING, element); addNamespaceDecl (XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING, element);
fLocalNSBinder.declarePrefix(XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING); fLocalNSBinder.declarePrefix(XMLSymbols.EMPTY_STRING, null);
fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING); fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, null);
} }
} }
} }
@ -894,7 +896,6 @@ public class DOMNormalizer implements XMLDocumentHandler {
// normalize attribute value // normalize attribute value
attr.normalize(); attr.normalize();
value = attr.getValue(); value = attr.getValue();
name = attr.getNodeName();
uri = attr.getNamespaceURI(); uri = attr.getNamespaceURI();
// make sure that value is never null. // make sure that value is never null.
@ -902,6 +903,30 @@ public class DOMNormalizer implements XMLDocumentHandler {
value = XMLSymbols.EMPTY_STRING; value = XMLSymbols.EMPTY_STRING;
} }
//---------------------------------------
// check if value of the attribute is namespace well-formed
//---------------------------------------
if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)) {
isAttrValueWF(fErrorHandler, fError, fLocator, attributes, attr, value, fDocument.isXML11Version());
if (fDocument.isXMLVersionChanged()) {
boolean wellformed;
if (fNamespaceValidation){
wellformed = CoreDocumentImpl.isValidQName(attr.getPrefix(), attr.getLocalName(), fDocument.isXML11Version());
}
else {
wellformed = CoreDocumentImpl.isXMLName(attr.getNodeName(), fDocument.isXML11Version());
}
if (!wellformed) {
String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"wf-invalid-character-in-node-name",
new Object[]{"Attr", attr.getNodeName()});
reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR,
"wf-invalid-character-in-node-name");
}
}
}
if (uri != null) { // attribute has namespace !=null if (uri != null) { // attribute has namespace !=null
prefix = attr.getPrefix(); prefix = attr.getPrefix();
prefix = (prefix == null || prefix = (prefix == null ||
@ -916,23 +941,6 @@ public class DOMNormalizer implements XMLDocumentHandler {
if (uri != null && uri.equals(NamespaceContext.XMLNS_URI)) { if (uri != null && uri.equals(NamespaceContext.XMLNS_URI)) {
continue; continue;
} }
//---------------------------------------
// check if value of the attribute is namespace well-formed
//---------------------------------------
if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)) {
isAttrValueWF(fErrorHandler, fError, fLocator, attributes, (AttrImpl)attr, attr.getValue(), fDocument.isXML11Version());
if (fDocument.isXMLVersionChanged()){
boolean wellformed=CoreDocumentImpl.isXMLName(attr.getNodeName() , fDocument.isXML11Version());
if (!wellformed){
String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"wf-invalid-character-in-node-name",
new Object[]{"Attribute", attr.getNodeName()});
reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR,
"wf-invalid-character-in-node-name");
}
}
}
// --------------------------------------- // ---------------------------------------
// remove default attributes // remove default attributes
@ -948,7 +956,6 @@ public class DOMNormalizer implements XMLDocumentHandler {
// reset id-attributes // reset id-attributes
((AttrImpl)attr).setIdAttribute(false); ((AttrImpl)attr).setIdAttribute(false);
uri = fSymbolTable.addSymbol(uri); uri = fSymbolTable.addSymbol(uri);
// find if for this prefix a URI was already declared // find if for this prefix a URI was already declared
@ -962,7 +969,6 @@ public class DOMNormalizer implements XMLDocumentHandler {
// conflict: attribute has a prefix that conficlicts with a binding // conflict: attribute has a prefix that conficlicts with a binding
// already active in scope // already active in scope
name = attr.getNodeName();
// Find if any prefix for attributes namespace URI is available // Find if any prefix for attributes namespace URI is available
// in the scope // in the scope
String declaredPrefix = fNamespaceContext.getPrefix(uri); String declaredPrefix = fNamespaceContext.getPrefix(uri);
@ -1447,8 +1453,8 @@ public class DOMNormalizer implements XMLDocumentHandler {
protected CoreDocumentImpl fDocument; protected CoreDocumentImpl fDocument;
protected ElementImpl fElement; protected ElementImpl fElement;
protected final Vector<Augmentations> fAugmentations = new Vector<>(5); protected Vector<String> fDTDTypes = new Vector<>(5);
protected Vector<Augmentations> fAugmentations = new Vector<>(5);
public void setAttributes(AttributeMap attributes, CoreDocumentImpl doc, ElementImpl elem) { public void setAttributes(AttributeMap attributes, CoreDocumentImpl doc, ElementImpl elem) {
fDocument = doc; fDocument = doc;
@ -1456,7 +1462,7 @@ public class DOMNormalizer implements XMLDocumentHandler {
fElement = elem; fElement = elem;
if (attributes != null) { if (attributes != null) {
int length = attributes.getLength(); int length = attributes.getLength();
fDTDTypes.setSize(length);
fAugmentations.setSize(length); fAugmentations.setSize(length);
// REVISIT: this implementation does not store any value in augmentations // REVISIT: this implementation does not store any value in augmentations
// and basically not keeping augs in parallel to attributes map // and basically not keeping augs in parallel to attributes map
@ -1464,7 +1470,9 @@ public class DOMNormalizer implements XMLDocumentHandler {
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
fAugmentations.setElementAt(new AugmentationsImpl(), i); fAugmentations.setElementAt(new AugmentationsImpl(), i);
} }
} else { }
else {
fDTDTypes.setSize(0);
fAugmentations.setSize(0); fAugmentations.setSize(0);
} }
} }
@ -1488,6 +1496,7 @@ public class DOMNormalizer implements XMLDocumentHandler {
// REVISIT: the following should also update ID table // REVISIT: the following should also update ID table
attr.setNodeValue(attrValue); attr.setNodeValue(attrValue);
index = fElement.setXercesAttributeNode(attr); index = fElement.setXercesAttributeNode(attr);
fDTDTypes.insertElementAt(attrType, index);
fAugmentations.insertElementAt(new AugmentationsImpl(), index); fAugmentations.insertElementAt(new AugmentationsImpl(), index);
attr.setSpecified(false); attr.setSpecified(false);
} }
@ -1539,25 +1548,42 @@ public class DOMNormalizer implements XMLDocumentHandler {
} }
public String getPrefix(int index) { public String getPrefix(int index) {
// REVISIT: implement if (fAttributes != null) {
Node node = (Node) fAttributes.getItem(index);
String prefix = node.getPrefix();
prefix = (prefix != null && prefix.length() != 0) ? fSymbolTable.addSymbol(prefix) : null;
return prefix;
}
return null; return null;
} }
public String getURI(int index) { public String getURI(int index) {
// REVISIT: implement if (fAttributes != null) {
Node node = (Node) fAttributes.getItem(index);
String namespace = node.getNamespaceURI();
namespace = (namespace != null) ? fSymbolTable.addSymbol(namespace) : null;
return namespace;
}
return null; return null;
} }
public String getLocalName(int index) { public String getLocalName(int index) {
// REVISIT: implement if (fAttributes != null) {
Node node = (Node) fAttributes.getItem(index);
String localName = node.getLocalName();
localName = (localName != null) ? fSymbolTable.addSymbol(localName) : null;
return localName;
}
return null; return null;
} }
public String getQName(int index) { public String getQName(int index) {
// REVISIT: implement if (fAttributes != null) {
Node node = (Node) fAttributes.getItem(index);
String rawname = fSymbolTable.addSymbol(node.getNodeName());
return rawname;
}
return null; return null;
} }
@ -1567,24 +1593,28 @@ public class DOMNormalizer implements XMLDocumentHandler {
} }
public void setType(int attrIndex, String attrType) { public void setType(int attrIndex, String attrType) {
// REVISIT: implement fDTDTypes.setElementAt(attrType, attrIndex);
} }
public String getType(int index) { public String getType(int index) {
return "CDATA"; String type = fDTDTypes.elementAt(index);
return (type != null) ? getReportableType(type) : "CDATA";
} }
public String getType(String qName) { public String getType(String qName) {
return "CDATA"; return "CDATA";
} }
public String getType(String uri, String localName) { public String getType(String uri, String localName) {
return "CDATA"; return "CDATA";
} }
private String getReportableType(String type) {
if (type.charAt(0) == '(') {
return "NMTOKEN";
}
return type;
}
public void setValue(int attrIndex, String attrValue) { public void setValue(int attrIndex, String attrValue) {
// REVISIT: is this desired behaviour? // REVISIT: is this desired behaviour?
@ -1609,13 +1639,11 @@ public class DOMNormalizer implements XMLDocumentHandler {
} }
public String getValue(String qName){ public String getValue(String qName){
// REVISIT: implement // REVISIT: implement
return null; return null;
} }
public String getValue(String uri, String localName){ public String getValue(String uri, String localName){
if (fAttributes != null) { if (fAttributes != null) {
Node node = fAttributes.getNamedItemNS(uri, localName); Node node = fAttributes.getNamedItemNS(uri, localName);
@ -1624,19 +1652,16 @@ public class DOMNormalizer implements XMLDocumentHandler {
return null; return null;
} }
public void setNonNormalizedValue(int attrIndex, String attrValue){ public void setNonNormalizedValue(int attrIndex, String attrValue){
// REVISIT: implement // REVISIT: implement
} }
public String getNonNormalizedValue(int attrIndex){ public String getNonNormalizedValue(int attrIndex){
// REVISIT: implement // REVISIT: implement
return null; return null;
} }
public void setSpecified(int attrIndex, boolean specified){ public void setSpecified(int attrIndex, boolean specified){
AttrImpl attr = (AttrImpl)fAttributes.getItem(attrIndex); AttrImpl attr = (AttrImpl)fAttributes.getItem(attrIndex);
attr.setSpecified(specified); attr.setSpecified(specified);
@ -1802,6 +1827,10 @@ public class DOMNormalizer implements XMLDocumentHandler {
Attr attr = null; Attr attr = null;
attr = currentElement.getAttributeNodeNS(fAttrQName.uri, fAttrQName.localpart); attr = currentElement.getAttributeNodeNS(fAttrQName.uri, fAttrQName.localpart);
if (attr == null) {
// Must be a non-namespace aware DOM Level 1 node.
attr = currentElement.getAttributeNode(fAttrQName.rawname);
}
AttributePSVI attrPSVI = AttributePSVI attrPSVI =
(AttributePSVI) attributes.getAugmentations(i).getItem(Constants.ATTRIBUTE_PSVI); (AttributePSVI) attributes.getAugmentations(i).getItem(Constants.ATTRIBUTE_PSVI);
@ -1812,7 +1841,8 @@ public class DOMNormalizer implements XMLDocumentHandler {
boolean id = false; boolean id = false;
if (decl != null) { if (decl != null) {
id = ((XSSimpleType)decl).isIDType(); id = ((XSSimpleType)decl).isIDType();
} else{ }
else {
decl = attrPSVI.getTypeDefinition(); decl = attrPSVI.getTypeDefinition();
if (decl != null) { if (decl != null) {
id = ((XSSimpleType)decl).isIDType(); id = ((XSSimpleType)decl).isIDType();
@ -1825,20 +1855,42 @@ public class DOMNormalizer implements XMLDocumentHandler {
if (fPSVI) { if (fPSVI) {
((PSVIAttrNSImpl) attr).setPSVI(attrPSVI); ((PSVIAttrNSImpl) attr).setPSVI(attrPSVI);
} }
// Updating the TypeInfo for this attribute.
((AttrImpl) attr).setType(decl);
if ((fConfiguration.features & DOMConfigurationImpl.DTNORMALIZATION) != 0) { if ((fConfiguration.features & DOMConfigurationImpl.DTNORMALIZATION) != 0) {
// datatype-normalization // datatype-normalization
// NOTE: The specified value MUST be set after we set // NOTE: The specified value MUST be set after we set
// the node value because that turns the "specified" // the node value because that turns the "specified"
// flag to "true" which may overwrite a "false" // flag to "true" which may overwrite a "false"
// value from the attribute list. // value from the attribute list.
final String normalizedValue = attrPSVI.getSchemaValue().getNormalizedValue();
if (normalizedValue != null) {
boolean specified = attr.getSpecified(); boolean specified = attr.getSpecified();
attr.setValue(attrPSVI.getSchemaValue().getNormalizedValue()); attr.setValue(normalizedValue);
if (!specified) { if (!specified) {
((AttrImpl) attr).setSpecified(specified); ((AttrImpl) attr).setSpecified(specified);
} }
} }
} }
} }
else { // DTD
String type = null;
boolean isDeclared = Boolean.TRUE.equals(attributes.getAugmentations(i).getItem (Constants.ATTRIBUTE_DECLARED));
// For DOM Level 3 TypeInfo, the type name must
// be null if this attribute has not been declared
// in the DTD.
if (isDeclared) {
type = attributes.getType(i);
if ("ID".equals (type)) {
((ElementImpl) currentElement).setIdAttributeNode(attr, true);
}
}
// Updating the TypeInfo for this attribute.
((AttrImpl) attr).setType(type);
}
}
} }
@ -1948,7 +2000,7 @@ public class DOMNormalizer implements XMLDocumentHandler {
* Thrown by handler to signal an error. * Thrown by handler to signal an error.
*/ */
public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException{ public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException{
allWhitespace = true; fAllWhitespace = true;
} }
/** /**
@ -1972,6 +2024,14 @@ public class DOMNormalizer implements XMLDocumentHandler {
if (fPSVI) { if (fPSVI) {
((PSVIElementNSImpl) fCurrentNode).setPSVI(elementPSVI); ((PSVIElementNSImpl) fCurrentNode).setPSVI(elementPSVI);
} }
// Updating the TypeInfo for this element.
if (elementNode instanceof ElementNSImpl) {
XSTypeDefinition type = elementPSVI.getMemberTypeDefinition();
if (type == null) {
type = elementPSVI.getTypeDefinition();
}
((ElementNSImpl) elementNode).setType(type);
}
// include element default content (if one is available) // include element default content (if one is available)
String normalizedValue = elementPSVI.getSchemaValue().getNormalizedValue(); String normalizedValue = elementPSVI.getSchemaValue().getNormalizedValue();
if ((fConfiguration.features & DOMConfigurationImpl.DTNORMALIZATION) != 0) { if ((fConfiguration.features & DOMConfigurationImpl.DTNORMALIZATION) != 0) {
@ -1989,8 +2049,13 @@ public class DOMNormalizer implements XMLDocumentHandler {
elementNode.setTextContent(normalizedValue); elementNode.setTextContent(normalizedValue);
} }
} }
return;
} }
} }
// DTD; elements have no type.
if (fCurrentNode instanceof ElementNSImpl) {
((ElementNSImpl) fCurrentNode).setType(null);
}
} }

View File

@ -69,7 +69,7 @@ public class DeferredDocumentImpl
// protected // protected
/** Chunk shift. */ /** Chunk shift. */
protected static final int CHUNK_SHIFT = 8; // 2^8 = 256 protected static final int CHUNK_SHIFT = 11; // 2^11 = 2k
/** Chunk size. */ /** Chunk size. */
protected static final int CHUNK_SIZE = (1 << CHUNK_SHIFT); protected static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
@ -78,7 +78,7 @@ public class DeferredDocumentImpl
protected static final int CHUNK_MASK = CHUNK_SIZE - 1; protected static final int CHUNK_MASK = CHUNK_SIZE - 1;
/** Initial chunk size. */ /** Initial chunk size. */
protected static final int INITIAL_CHUNK_COUNT = (1 << (13 - CHUNK_SHIFT)); // 32 protected static final int INITIAL_CHUNK_COUNT = (1 << (16 - CHUNK_SHIFT)); // 2^16 = 64k
// //
// Data // Data

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2019 Oracle and/or its affiliates. All rights reserved.
*/ */
/* /*
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
@ -56,6 +56,7 @@ import org.w3c.dom.UserDataHandler;
* @author Joe Kesselman, IBM * @author Joe Kesselman, IBM
* @author Andy Clark, IBM * @author Andy Clark, IBM
* @since PR-DOM-Level-1-19980818. * @since PR-DOM-Level-1-19980818.
* @LastModified: Apr 2019
*/ */
public class DocumentTypeImpl public class DocumentTypeImpl
extends ParentNode extends ParentNode
@ -324,7 +325,7 @@ public class DocumentTypeImpl
Node entNode2 = Node entNode2 =
argEntities.getNamedItem(entNode1.getNodeName()); argEntities.getNamedItem(entNode1.getNodeName());
if (!((NodeImpl) entNode1).isEqualNode((NodeImpl) entNode2)) if (!((NodeImpl) entNode1).isEqualNode(entNode2))
return false; return false;
} }
} }
@ -344,7 +345,7 @@ public class DocumentTypeImpl
Node noteNode2 = Node noteNode2 =
argNotations.getNamedItem(noteNode1.getNodeName()); argNotations.getNamedItem(noteNode1.getNodeName());
if (!((NodeImpl) noteNode1).isEqualNode((NodeImpl) noteNode2)) if (!((NodeImpl) noteNode1).isEqualNode(noteNode2))
return false; return false;
} }
} }
@ -357,7 +358,7 @@ public class DocumentTypeImpl
* NON-DOM * NON-DOM
* set the ownerDocument of this node and its children * set the ownerDocument of this node and its children
*/ */
void setOwnerDocument(CoreDocumentImpl doc) { protected void setOwnerDocument(CoreDocumentImpl doc) {
super.setOwnerDocument(doc); super.setOwnerDocument(doc);
entities.setOwnerDocument(doc); entities.setOwnerDocument(doc);
notations.setOwnerDocument(doc); notations.setOwnerDocument(doc);

View File

@ -1,6 +1,5 @@
/* /*
* reserved comment block * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT REMOVE OR ALTER!
*/ */
/* /*
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
@ -55,6 +54,7 @@ import com.sun.org.apache.xerces.internal.util.URI;
* @author Andy Clark, IBM * @author Andy Clark, IBM
* @author Ralf Pfeiffer, IBM * @author Ralf Pfeiffer, IBM
* @since PR-DOM-Level-1-19980818. * @since PR-DOM-Level-1-19980818.
* @LastModified: Apr 2019
*/ */
public class ElementImpl public class ElementImpl
extends ParentNode extends ParentNode
@ -63,30 +63,24 @@ public class ElementImpl
// //
// Constants // Constants
// //
/**
* Serialization version. /** Serialization version. */
*/
static final long serialVersionUID = 3717253516652722278L; static final long serialVersionUID = 3717253516652722278L;
// //
// Data // Data
// //
/** /** Element name. */
* Element name.
*/
protected String name; protected String name;
/** /** Attributes. */
* Attributes.
*/
protected AttributeMap attributes; protected AttributeMap attributes;
// //
// Constructors // Constructors
// //
/**
* Factory constructor. /** Factory constructor. */
*/
public ElementImpl(CoreDocumentImpl ownerDoc, String name) { public ElementImpl(CoreDocumentImpl ownerDoc, String name) {
super(ownerDoc); super(ownerDoc);
this.name = name; this.name = name;
@ -94,8 +88,7 @@ public class ElementImpl
} }
// for ElementNSImpl // for ElementNSImpl
protected ElementImpl() { protected ElementImpl() {}
}
// Support for DOM Level 3 renameNode method. // Support for DOM Level 3 renameNode method.
// Note: This only deals with part of the pb. CoreDocumentImpl // Note: This only deals with part of the pb. CoreDocumentImpl
@ -494,8 +487,7 @@ public class ElementImpl
public void setAttribute(String name, String value) { public void setAttribute(String name, String value) {
if (ownerDocument.errorChecking && isReadOnly()) { if (ownerDocument.errorChecking && isReadOnly()) {
String msg String msg = DOMMessageFormatter.formatMessage(
= DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN, DOMMessageFormatter.DOM_DOMAIN,
"NO_MODIFICATION_ALLOWED_ERR", "NO_MODIFICATION_ALLOWED_ERR",
null); null);
@ -635,14 +627,11 @@ public class ElementImpl
public void setAttributeNS(String namespaceURI, String qualifiedName, public void setAttributeNS(String namespaceURI, String qualifiedName,
String value) { String value) {
if (ownerDocument.errorChecking && isReadOnly()) { if (ownerDocument.errorChecking && isReadOnly()) {
String msg String msg = DOMMessageFormatter.formatMessage(
= DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN, DOMMessageFormatter.DOM_DOMAIN,
"NO_MODIFICATION_ALLOWED_ERR", "NO_MODIFICATION_ALLOWED_ERR",
null); null);
throw new DOMException( throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
DOMException.NO_MODIFICATION_ALLOWED_ERR,
msg);
} }
if (needsSyncData()) { if (needsSyncData()) {
synchronizeData(); synchronizeData();
@ -693,7 +682,7 @@ public class ElementImpl
// This case is not defined by the DOM spec, we choose // This case is not defined by the DOM spec, we choose
// to create a new attribute in this case and remove an old one from the tree // to create a new attribute in this case and remove an old one from the tree
// note this might cause events to be propagated or user data to be lost // note this might cause events to be propagated or user data to be lost
newAttr = new AttrNSImpl((CoreDocumentImpl)getOwnerDocument(), namespaceURI, qualifiedName, localName); newAttr = ((CoreDocumentImpl)getOwnerDocument()).createAttributeNS(namespaceURI, qualifiedName, localName);
attributes.setNamedItemNS(newAttr); attributes.setNamedItemNS(newAttr);
} }
@ -930,14 +919,15 @@ public class ElementImpl
} }
if (ownerDocument.errorChecking) { if (ownerDocument.errorChecking) {
if (isReadOnly()) { if (isReadOnly()) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null); String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
throw new DOMException( throw new DOMException(
DOMException.NO_MODIFICATION_ALLOWED_ERR, DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
msg);
} }
if (at.getOwnerElement() != this) { if (at.getOwnerElement() != this) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null); String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
throw new DOMException(DOMException.NOT_FOUND_ERR, msg); throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
} }
} }
@ -960,21 +950,20 @@ public class ElementImpl
if (at == null) { if (at == null) {
String msg = DOMMessageFormatter.formatMessage( String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN, DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
"NOT_FOUND_ERR", null);
throw new DOMException(DOMException.NOT_FOUND_ERR, msg); throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
} }
if (ownerDocument.errorChecking) { if (ownerDocument.errorChecking) {
if (isReadOnly()) { if (isReadOnly()) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null); String msg = DOMMessageFormatter.formatMessage(
throw new DOMException( DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
DOMException.NO_MODIFICATION_ALLOWED_ERR, throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
msg);
} }
if (at.getOwnerElement() != this) { if (at.getOwnerElement() != this) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null); String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
throw new DOMException(DOMException.NOT_FOUND_ERR, msg); throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
} }
} }
@ -1003,8 +992,7 @@ public class ElementImpl
if (at == null) { if (at == null) {
String msg = DOMMessageFormatter.formatMessage( String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN, DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
"NOT_FOUND_ERR", null);
throw new DOMException(DOMException.NOT_FOUND_ERR, msg); throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
} }
@ -1067,7 +1055,6 @@ public class ElementImpl
/** /**
* Method getSchemaTypeInfo. * Method getSchemaTypeInfo.
*
* @return TypeInfo * @return TypeInfo
*/ */
public TypeInfo getSchemaTypeInfo() { public TypeInfo getSchemaTypeInfo() {
@ -1159,8 +1146,7 @@ public class ElementImpl
if (doctype == null) { if (doctype == null) {
return null; return null;
} }
ElementDefinitionImpl eldef ElementDefinitionImpl eldef = (ElementDefinitionImpl)doctype.getElements()
= (ElementDefinitionImpl) doctype.getElements()
.getNamedItem(getNodeName()); .getNamedItem(getNodeName());
if (eldef == null) { if (eldef == null) {
return null; return null;

View File

@ -190,37 +190,6 @@ public class ElementNSImpl
reconcileDefaultAttributes(); reconcileDefaultAttributes();
} }
/**
* NON-DOM: resets this node and sets specified values for the node
*
* @param ownerDocument
* @param namespaceURI
* @param qualifiedName
* @param localName
*/
protected void setValues (CoreDocumentImpl ownerDocument,
String namespaceURI, String qualifiedName,
String localName){
// remove children first
firstChild = null;
previousSibling = null;
nextSibling = null;
fNodeListCache = null;
// set owner document
attributes = null;
super.flags = 0;
setOwnerDocument(ownerDocument);
// synchronizeData will initialize attributes
needsSyncData(true);
super.name = qualifiedName;
this.localName = localName;
this.namespaceURI = namespaceURI;
}
// //
// Node methods // Node methods
// //
@ -340,88 +309,13 @@ public class ElementNSImpl
return localName; return localName;
} }
/** /**
* DOM Level 3 WD - Experimental. * NON-DOM
* Retrieve baseURI * Returns the xml:base attribute.
*/ */
public String getBaseURI() { protected Attr getXMLBaseAttribute() {
return (Attr) attributes.getNamedItemNS("http://www.w3.org/XML/1998/namespace", "base");
if (needsSyncData()) { } // getXMLBaseAttribute():Attr
synchronizeData();
}
// Absolute base URI is computed according to XML Base (http://www.w3.org/TR/xmlbase/#granularity)
// 1. the base URI specified by an xml:base attribute on the element, if one exists
if (attributes != null) {
Attr attrNode = (Attr)attributes.getNamedItemNS("http://www.w3.org/XML/1998/namespace", "base");
if (attrNode != null) {
String uri = attrNode.getNodeValue();
if (uri.length() != 0 ) {// attribute value is always empty string
try {
uri = new URI(uri).toString();
}
catch (com.sun.org.apache.xerces.internal.util.URI.MalformedURIException e) {
// This may be a relative URI.
// Start from the base URI of the parent, or if this node has no parent, the owner node.
NodeImpl parentOrOwner = (parentNode() != null) ? parentNode() : ownerNode;
// Make any parentURI into a URI object to use with the URI(URI, String) constructor.
String parentBaseURI = (parentOrOwner != null) ? parentOrOwner.getBaseURI() : null;
if (parentBaseURI != null) {
try {
uri = new URI(new URI(parentBaseURI), uri).toString();
}
catch (com.sun.org.apache.xerces.internal.util.URI.MalformedURIException ex){
// This should never happen: parent should have checked the URI and returned null if invalid.
return null;
}
return uri;
}
// REVISIT: what should happen in this case?
return null;
}
return uri;
}
}
}
//2.the base URI of the element's parent element within the document or external entity,
//if one exists
String parentElementBaseURI = (this.parentNode() != null) ? this.parentNode().getBaseURI() : null ;
//base URI of parent element is not null
if(parentElementBaseURI != null){
try {
//return valid absolute base URI
return new URI(parentElementBaseURI).toString();
}
catch (com.sun.org.apache.xerces.internal.util.URI.MalformedURIException e){
// REVISIT: what should happen in this case?
return null;
}
}
//3. the base URI of the document entity or external entity containing the element
String baseURI = (this.ownerNode != null) ? this.ownerNode.getBaseURI() : null ;
if(baseURI != null){
try {
//return valid absolute base URI
return new URI(baseURI).toString();
}
catch (com.sun.org.apache.xerces.internal.util.URI.MalformedURIException e){
// REVISIT: what should happen in this case?
return null;
}
}
return null;
}
/** /**
* @see org.w3c.dom.TypeInfo#getTypeName() * @see org.w3c.dom.TypeInfo#getTypeName()
@ -452,12 +346,12 @@ public class ElementNSImpl
* Checks if a type is derived from another by restriction. See: * Checks if a type is derived from another by restriction. See:
* http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom * http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom
* *
* @param ancestorNS * @param typeNamespaceArg
* The namspace of the ancestor type declaration * The namspace of the ancestor type declaration
* @param ancestorName * @param typeNameArg
* The name of the ancestor type declaration * The name of the ancestor type declaration
* @param type * @param derivationMethod
* The reference type definition * The derivation method
* *
* @return boolean True if the type is derived by restriciton for the * @return boolean True if the type is derived by restriciton for the
* reference type * reference type

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2017 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2019 Oracle and/or its affiliates. All rights reserved.
*/ */
/* /*
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
@ -27,6 +27,7 @@ import java.util.Map;
import org.w3c.dom.DOMException; import org.w3c.dom.DOMException;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.DocumentType; import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap; import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
@ -78,6 +79,7 @@ import org.w3c.dom.events.EventTarget;
* @author Arnaud Le Hors, IBM * @author Arnaud Le Hors, IBM
* @author Joe Kesselman, IBM * @author Joe Kesselman, IBM
* @since PR-DOM-Level-1-19980818. * @since PR-DOM-Level-1-19980818.
* @LastModified: Apr 2019
*/ */
public abstract class NodeImpl public abstract class NodeImpl
implements Node, NodeList, EventTarget, Cloneable, Serializable{ implements Node, NodeList, EventTarget, Cloneable, Serializable{
@ -122,15 +124,6 @@ public abstract class NodeImpl
*/ */
public static final short TREE_POSITION_DISCONNECTED = 0x00; public static final short TREE_POSITION_DISCONNECTED = 0x00;
// DocumentPosition
public static final short DOCUMENT_POSITION_DISCONNECTED = 0x01;
public static final short DOCUMENT_POSITION_PRECEDING = 0x02;
public static final short DOCUMENT_POSITION_FOLLOWING = 0x04;
public static final short DOCUMENT_POSITION_CONTAINS = 0x08;
public static final short DOCUMENT_POSITION_IS_CONTAINED = 0x10;
public static final short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
/** Serialization version. */ /** Serialization version. */
static final long serialVersionUID = -6316591992167219696L; static final long serialVersionUID = -6316591992167219696L;
@ -324,7 +317,7 @@ public abstract class NodeImpl
* NON-DOM * NON-DOM
* set the ownerDocument of this node * set the ownerDocument of this node
*/ */
void setOwnerDocument(CoreDocumentImpl doc) { protected void setOwnerDocument(CoreDocumentImpl doc) {
if (needsSyncData()) { if (needsSyncData()) {
synchronizeData(); synchronizeData();
} }
@ -559,7 +552,7 @@ public abstract class NodeImpl
* @see ParentNode * @see ParentNode
* *
* @return org.w3c.dom.Node * @return org.w3c.dom.Node
* @param Index int * @param index int
*/ */
public Node item(int index) { public Node item(int index) {
return null; return null;
@ -976,9 +969,7 @@ public abstract class NodeImpl
return 0; return 0;
// check if other is from a different implementation // check if other is from a different implementation
try { if (other != null && !(other instanceof NodeImpl)) {
NodeImpl node = (NodeImpl) other;
} catch (ClassCastException e) {
// other comes from a different implementation // other comes from a different implementation
String msg = DOMMessageFormatter.formatMessage( String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null); DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
@ -1041,7 +1032,7 @@ public abstract class NodeImpl
otherDepth +=1; otherDepth +=1;
if (node == this) if (node == this)
// The other node is a descendent of the reference node. // The other node is a descendent of the reference node.
return (DOCUMENT_POSITION_IS_CONTAINED | return (DOCUMENT_POSITION_CONTAINED_BY |
DOCUMENT_POSITION_FOLLOWING); DOCUMENT_POSITION_FOLLOWING);
otherAncestor = node; otherAncestor = node;
} }
@ -1131,7 +1122,7 @@ public abstract class NodeImpl
case Node.NOTATION_NODE: case Node.NOTATION_NODE:
case Node.ENTITY_NODE: { case Node.ENTITY_NODE: {
DocumentType container = thisOwnerDoc.getDoctype(); DocumentType container = thisOwnerDoc.getDoctype();
if (container == this) return (DOCUMENT_POSITION_IS_CONTAINED | if (container == this) return (DOCUMENT_POSITION_CONTAINED_BY |
DOCUMENT_POSITION_FOLLOWING); DOCUMENT_POSITION_FOLLOWING);
otherNode = otherAncestor = thisOwnerDoc; otherNode = otherAncestor = thisOwnerDoc;
break; break;
@ -1139,7 +1130,7 @@ public abstract class NodeImpl
case Node.DOCUMENT_TYPE_NODE: { case Node.DOCUMENT_TYPE_NODE: {
if (thisNode == otherOwnerDoc) if (thisNode == otherOwnerDoc)
return (DOCUMENT_POSITION_FOLLOWING | return (DOCUMENT_POSITION_FOLLOWING |
DOCUMENT_POSITION_IS_CONTAINED); DOCUMENT_POSITION_CONTAINED_BY);
else if (otherOwnerDoc!=null && thisOwnerDoc==otherOwnerDoc) else if (otherOwnerDoc!=null && thisOwnerDoc==otherOwnerDoc)
return (DOCUMENT_POSITION_PRECEDING); return (DOCUMENT_POSITION_PRECEDING);
break; break;
@ -1153,7 +1144,7 @@ public abstract class NodeImpl
// The other node is a descendent of the reference // The other node is a descendent of the reference
// node's element // node's element
return DOCUMENT_POSITION_FOLLOWING | return DOCUMENT_POSITION_FOLLOWING |
DOCUMENT_POSITION_IS_CONTAINED; DOCUMENT_POSITION_CONTAINED_BY;
otherAncestor = node; otherAncestor = node;
} }
@ -1302,8 +1293,8 @@ public abstract class NodeImpl
return getNodeValue(); // overriden in some subclasses return getNodeValue(); // overriden in some subclasses
} }
// internal method taking a StringBuffer in parameter // internal method taking a StringBuilder in parameter
void getTextContent(StringBuffer buf) throws DOMException { void getTextContent(StringBuilder buf) throws DOMException {
String content = getNodeValue(); String content = getNodeValue();
if (content != null) { if (content != null) {
buf.append(content); buf.append(content);
@ -1425,7 +1416,11 @@ public abstract class NodeImpl
return false; return false;
} }
case Node.DOCUMENT_NODE:{ case Node.DOCUMENT_NODE:{
return((NodeImpl)((Document)this).getDocumentElement()).isDefaultNamespace(namespaceURI); Element docElement = ((Document)this).getDocumentElement();
if (docElement != null) {
return docElement.isDefaultNamespace(namespaceURI);
}
return false;
} }
case Node.ENTITY_NODE : case Node.ENTITY_NODE :
@ -1475,12 +1470,15 @@ public abstract class NodeImpl
switch (type) { switch (type) {
case Node.ELEMENT_NODE: { case Node.ELEMENT_NODE: {
this.getNamespaceURI(); // to flip out children
String namespace = this.getNamespaceURI(); // to flip out children
return lookupNamespacePrefix(namespaceURI, (ElementImpl)this); return lookupNamespacePrefix(namespaceURI, (ElementImpl)this);
} }
case Node.DOCUMENT_NODE:{ case Node.DOCUMENT_NODE:{
return((NodeImpl)((Document)this).getDocumentElement()).lookupPrefix(namespaceURI); Element docElement = ((Document)this).getDocumentElement();
if (docElement != null) {
return docElement.lookupPrefix(namespaceURI);
}
return null;
} }
case Node.ENTITY_NODE : case Node.ENTITY_NODE :
@ -1511,8 +1509,8 @@ public abstract class NodeImpl
* Look up the namespace URI associated to the given prefix, starting from this node. * Look up the namespace URI associated to the given prefix, starting from this node.
* Use lookupNamespaceURI(null) to lookup the default namespace * Use lookupNamespaceURI(null) to lookup the default namespace
* *
* @param namespaceURI * @param specifiedPrefix
* @return th URI for the namespace * @return the URI for the namespace
* @since DOM Level 3 * @since DOM Level 3
*/ */
public String lookupNamespaceURI(String specifiedPrefix) { public String lookupNamespaceURI(String specifiedPrefix) {
@ -1537,20 +1535,20 @@ public abstract class NodeImpl
int length = map.getLength(); int length = map.getLength();
for (int i=0;i<length;i++) { for (int i=0;i<length;i++) {
Node attr = map.item(i); Node attr = map.item(i);
String attrPrefix = attr.getPrefix();
String value = attr.getNodeValue();
namespace = attr.getNamespaceURI(); namespace = attr.getNamespaceURI();
if (namespace !=null && namespace.equals("http://www.w3.org/2000/xmlns/")) { if (namespace !=null && namespace.equals("http://www.w3.org/2000/xmlns/")) {
String attrPrefix = attr.getPrefix();
String value = attr.getNodeValue();
// at this point we are dealing with DOM Level 2 nodes only // at this point we are dealing with DOM Level 2 nodes only
if (specifiedPrefix == null && if (specifiedPrefix == null &&
attr.getNodeName().equals("xmlns")) { attr.getNodeName().equals("xmlns")) {
// default namespace // default namespace
return value; return value.length() > 0 ? value : null;
} else if (attrPrefix !=null && } else if (attrPrefix !=null &&
attrPrefix.equals("xmlns") && attrPrefix.equals("xmlns") &&
attr.getLocalName().equals(specifiedPrefix)) { attr.getLocalName().equals(specifiedPrefix)) {
// non default namespace // non default namespace
return value; return value.length() > 0 ? value : null;
} }
} }
} }
@ -1565,7 +1563,11 @@ public abstract class NodeImpl
} }
case Node.DOCUMENT_NODE : { case Node.DOCUMENT_NODE : {
return((NodeImpl)((Document)this).getDocumentElement()).lookupNamespaceURI(specifiedPrefix); Element docElement = ((Document)this).getDocumentElement();
if (docElement != null) {
return docElement.lookupNamespaceURI(specifiedPrefix);
}
return null;
} }
case Node.ENTITY_NODE : case Node.ENTITY_NODE :
case Node.NOTATION_NODE: case Node.NOTATION_NODE:
@ -1591,15 +1593,14 @@ public abstract class NodeImpl
} }
} }
Node getElementAncestor(Node currentNode) { Node getElementAncestor(Node currentNode) {
Node parent = currentNode.getParentNode(); Node parent = currentNode.getParentNode();
if (parent != null) { while (parent != null) {
short type = parent.getNodeType(); short type = parent.getNodeType();
if (type == Node.ELEMENT_NODE) { if (type == Node.ELEMENT_NODE) {
return parent; return parent;
} }
return getElementAncestor(parent); parent = parent.getParentNode();
} }
return null; return null;
} }
@ -1624,10 +1625,10 @@ public abstract class NodeImpl
int length = map.getLength(); int length = map.getLength();
for (int i=0;i<length;i++) { for (int i=0;i<length;i++) {
Node attr = map.item(i); Node attr = map.item(i);
String attrPrefix = attr.getPrefix();
String value = attr.getNodeValue();
namespace = attr.getNamespaceURI(); namespace = attr.getNamespaceURI();
if (namespace !=null && namespace.equals("http://www.w3.org/2000/xmlns/")) { if (namespace !=null && namespace.equals("http://www.w3.org/2000/xmlns/")) {
String attrPrefix = attr.getPrefix();
String value = attr.getNodeValue();
// DOM Level 2 nodes // DOM Level 2 nodes
if (((attr.getNodeName().equals("xmlns")) || if (((attr.getNodeName().equals("xmlns")) ||
(attrPrefix !=null && attrPrefix.equals("xmlns")) && (attrPrefix !=null && attrPrefix.equals("xmlns")) &&
@ -1687,9 +1688,6 @@ public abstract class NodeImpl
* <code>Text</code> nodes, as well as any user data or event listeners * <code>Text</code> nodes, as well as any user data or event listeners
* registered on the nodes. * registered on the nodes.
* @param arg The node to compare equality with. * @param arg The node to compare equality with.
* @param deep If <code>true</code>, recursively compare the subtrees; if
* <code>false</code>, compare only the nodes themselves (and its
* attributes, if it is an <code>Element</code>).
* @return If the nodes, and possibly subtrees are equal, * @return If the nodes, and possibly subtrees are equal,
* <code>true</code> otherwise <code>false</code>. * <code>true</code> otherwise <code>false</code>.
* @since DOM Level 3 * @since DOM Level 3

View File

@ -21,11 +21,8 @@
package com.sun.org.apache.xerces.internal.dom; package com.sun.org.apache.xerces.internal.dom;
import org.w3c.dom.DOMException;
import org.w3c.dom.DOMImplementation; import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType; import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
/** /**
* The DOMImplementation class is description of a particular * The DOMImplementation class is description of a particular
@ -40,7 +37,7 @@ import org.w3c.dom.Element;
* *
* @since PR-DOM-Level-1-19980818. * @since PR-DOM-Level-1-19980818.
*/ */
public class PSVIDOMImplementationImpl extends CoreDOMImplementationImpl { public class PSVIDOMImplementationImpl extends DOMImplementationImpl {
// //
// Data // Data
@ -49,7 +46,7 @@ public class PSVIDOMImplementationImpl extends CoreDOMImplementationImpl {
// static // static
/** Dom implementation singleton. */ /** Dom implementation singleton. */
static PSVIDOMImplementationImpl singleton = new PSVIDOMImplementationImpl(); static final PSVIDOMImplementationImpl singleton = new PSVIDOMImplementationImpl();
// //
// Public methods // Public methods
@ -84,42 +81,12 @@ public class PSVIDOMImplementationImpl extends CoreDOMImplementationImpl {
feature.equalsIgnoreCase("psvi"); feature.equalsIgnoreCase("psvi");
} // hasFeature(String,String):boolean } // hasFeature(String,String):boolean
/** //
* Introduced in DOM Level 2. <p> // Protected methods
* //
* Creates an XML Document object of the specified type with its document
* element. protected CoreDocumentImpl createDocument(DocumentType doctype) {
* return new PSVIDocumentImpl(doctype);
* @param namespaceURI The namespace URI of the document
* element to create, or null.
* @param qualifiedName The qualified name of the document
* element to create.
* @param doctype The type of document to be created or null.<p>
*
* When doctype is not null, its
* Node.ownerDocument attribute is set to
* the document being created.
* @return Document A new Document object.
* @throws DOMException WRONG_DOCUMENT_ERR: Raised if doctype has
* already been used with a different document.
* @since WD-DOM-Level-2-19990923
*/
public Document createDocument(String namespaceURI,
String qualifiedName,
DocumentType doctype)
throws DOMException
{
if (doctype != null && doctype.getOwnerDocument() != null) {
throw new DOMException(DOMException.WRONG_DOCUMENT_ERR,
DOMMessageFormatter.formatMessage(
DOMMessageFormatter.XML_DOMAIN,
"WRONG_DOCUMENT_ERR", null));
}
DocumentImpl doc = new PSVIDocumentImpl(doctype);
Element e = doc.createElementNS( namespaceURI, qualifiedName);
doc.appendChild(e);
return doc;
} }
} // class PSVIDOMImplementationImpl
} // class DOMImplementationImpl

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
*/ */
/* /*
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
@ -68,6 +68,7 @@ import org.w3c.dom.UserDataHandler;
* @author Arnaud Le Hors, IBM * @author Arnaud Le Hors, IBM
* @author Joe Kesselman, IBM * @author Joe Kesselman, IBM
* @author Andy Clark, IBM * @author Andy Clark, IBM
* @LastModified: Apr 2019
*/ */
public abstract class ParentNode public abstract class ParentNode
extends ChildNode { extends ChildNode {
@ -174,18 +175,16 @@ public abstract class ParentNode
* NON-DOM * NON-DOM
* set the ownerDocument of this node and its children * set the ownerDocument of this node and its children
*/ */
void setOwnerDocument(CoreDocumentImpl doc) { protected void setOwnerDocument(CoreDocumentImpl doc) {
if (needsSyncChildren()) { if (needsSyncChildren()) {
synchronizeChildren(); synchronizeChildren();
} }
super.setOwnerDocument(doc);
ownerDocument = doc;
for (ChildNode child = firstChild; for (ChildNode child = firstChild;
child != null; child = child.nextSibling) { child != null; child = child.nextSibling) {
child.setOwnerDocument(doc); child.setOwnerDocument(doc);
} }
/* setting the owner document of self, after it's children makes the
data of children available to the new document. */
super.setOwnerDocument(doc);
ownerDocument = doc;
} }
/** /**
@ -368,7 +367,6 @@ public abstract class ParentNode
// Prevent cycles in the tree // Prevent cycles in the tree
// newChild cannot be ancestor of this Node, // newChild cannot be ancestor of this Node,
// and actually cannot be this // and actually cannot be this
if (ownerDocument.ancestorChecking) {
boolean treeSafe = true; boolean treeSafe = true;
for (NodeImpl a = this; treeSafe && a != null; a = a.parentNode()) for (NodeImpl a = this; treeSafe && a != null; a = a.parentNode())
{ {
@ -379,7 +377,6 @@ public abstract class ParentNode
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null)); DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null));
} }
} }
}
// notify document // notify document
ownerDocument.insertingNode(this, replace); ownerDocument.insertingNode(this, replace);
@ -509,6 +506,9 @@ public abstract class ParentNode
// notify document // notify document
ownerDocument.removingNode(this, oldInternal, replace); ownerDocument.removingNode(this, oldInternal, replace);
// Save previous sibling for normalization checking.
final ChildNode oldPreviousSibling = oldInternal.previousSibling();
// update cached length if we have any // update cached length if we have any
if (fNodeListCache != null) { if (fNodeListCache != null) {
if (fNodeListCache.fLength != -1) { if (fNodeListCache.fLength != -1) {
@ -519,7 +519,7 @@ public abstract class ParentNode
// move the cache to its (soon former) previous sibling // move the cache to its (soon former) previous sibling
if (fNodeListCache.fChild == oldInternal) { if (fNodeListCache.fChild == oldInternal) {
fNodeListCache.fChildIndex--; fNodeListCache.fChildIndex--;
fNodeListCache.fChild = oldInternal.previousSibling(); fNodeListCache.fChild = oldPreviousSibling;
} else { } else {
// otherwise just invalidate the cache // otherwise just invalidate the cache
fNodeListCache.fChildIndex = -1; fNodeListCache.fChildIndex = -1;
@ -550,9 +550,6 @@ public abstract class ParentNode
} }
} }
// Save previous sibling for normalization checking.
ChildNode oldPreviousSibling = oldInternal.previousSibling();
// Remove oldInternal's references to tree // Remove oldInternal's references to tree
oldInternal.ownerNode = ownerDocument; oldInternal.ownerNode = ownerDocument;
oldInternal.isOwned(false); oldInternal.isOwned(false);
@ -624,20 +621,15 @@ public abstract class ParentNode
if (next == null) { if (next == null) {
return hasTextContent(child) ? ((NodeImpl) child).getTextContent() : ""; return hasTextContent(child) ? ((NodeImpl) child).getTextContent() : "";
} }
if (fBufferStr == null){ StringBuilder buf = new StringBuilder();
fBufferStr = new StringBuffer(); getTextContent(buf);
} return buf.toString();
else {
fBufferStr.setLength(0);
}
getTextContent(fBufferStr);
return fBufferStr.toString();
} }
return ""; return "";
} }
// internal method taking a StringBuffer in parameter // internal method taking a StringBuilder in parameter
void getTextContent(StringBuffer buf) throws DOMException { void getTextContent(StringBuilder buf) throws DOMException {
Node child = getFirstChild(); Node child = getFirstChild();
while (child != null) { while (child != null) {
if (hasTextContent(child)) { if (hasTextContent(child)) {
@ -684,6 +676,9 @@ public abstract class ParentNode
private int nodeListGetLength() { private int nodeListGetLength() {
if (fNodeListCache == null) { if (fNodeListCache == null) {
if (needsSyncChildren()) {
synchronizeChildren();
}
// get rid of trivial cases // get rid of trivial cases
if (firstChild == null) { if (firstChild == null) {
return 0; return 0;
@ -733,6 +728,9 @@ public abstract class ParentNode
private Node nodeListItem(int index) { private Node nodeListItem(int index) {
if (fNodeListCache == null) { if (fNodeListCache == null) {
if (needsSyncChildren()) {
synchronizeChildren();
}
// get rid of trivial case // get rid of trivial case
if (firstChild == lastChild()) { if (firstChild == lastChild()) {
return index == 0 ? firstChild : null; return index == 0 ? firstChild : null;
@ -870,7 +868,7 @@ public abstract class ParentNode
Node child1 = getFirstChild(); Node child1 = getFirstChild();
Node child2 = arg.getFirstChild(); Node child2 = arg.getFirstChild();
while (child1 != null && child2 != null) { while (child1 != null && child2 != null) {
if (!((NodeImpl) child1).isEqualNode(child2)) { if (!child1.isEqualNode(child2)) {
return false; return false;
} }
child1 = child1.getNextSibling(); child1 = child1.getNextSibling();
@ -997,7 +995,7 @@ public abstract class ParentNode
/** Serialize object. */ /** Serialize object. */
private void writeObject(ObjectOutputStream out) throws IOException { private void writeObject(ObjectOutputStream out) throws IOException {
// synchronize chilren // synchronize children
if (needsSyncChildren()) { if (needsSyncChildren()) {
synchronizeChildren(); synchronizeChildren();
} }
@ -1022,7 +1020,7 @@ public abstract class ParentNode
/* /*
* a class to store some user data along with its handler * a class to store some user data along with its handler
*/ */
protected class UserDataRecord implements Serializable { class UserDataRecord implements Serializable {
/** Serialization version. */ /** Serialization version. */
private static final long serialVersionUID = 3258126977134310455L; private static final long serialVersionUID = 3258126977134310455L;

View File

@ -1,6 +1,5 @@
/* /*
* reserved comment block * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT REMOVE OR ALTER!
*/ */
/* /*
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
@ -42,6 +41,7 @@ import org.w3c.dom.Text;
* @xerces.internal * @xerces.internal
* *
* @since PR-DOM-Level-1-19980818. * @since PR-DOM-Level-1-19980818.
* @LastModified: Apr 2019
*/ */
public class TextImpl public class TextImpl
extends CharacterDataImpl extends CharacterDataImpl
@ -146,37 +146,32 @@ public class TextImpl
synchronizeData(); synchronizeData();
} }
if (fBufferStr == null){ StringBuilder buffer = new StringBuilder();
fBufferStr = new StringBuffer();
}
else {
fBufferStr.setLength(0);
}
if (data != null && data.length() != 0) { if (data != null && data.length() != 0) {
fBufferStr.append(data); buffer.append(data);
} }
// concatenate text of logically adjacent text nodes to the left of this node in the tree // concatenate text of logically adjacent text nodes to the left of this node in the tree
getWholeTextBackward(this.getPreviousSibling(), fBufferStr, this.getParentNode()); getWholeTextBackward(this.getPreviousSibling(), buffer, this.getParentNode());
String temp = fBufferStr.toString(); String temp = buffer.toString();
// clear buffer // clear buffer
fBufferStr.setLength(0); buffer.setLength(0);
// concatenate text of logically adjacent text nodes to the right of this node in the tree // concatenate text of logically adjacent text nodes to the right of this node in the tree
getWholeTextForward(this.getNextSibling(), fBufferStr, this.getParentNode()); getWholeTextForward(this.getNextSibling(), buffer, this.getParentNode());
return temp + fBufferStr.toString(); return temp + buffer.toString();
} }
/** /**
* internal method taking a StringBuffer in parameter and inserts the * internal method taking a StringBuilder in parameter and inserts the
* text content at the start of the buffer * text content at the start of the buffer
* *
* @param buf * @param buf
*/ */
protected void insertTextContent(StringBuffer buf) throws DOMException { protected void insertTextContent(StringBuilder buf) throws DOMException {
String content = getNodeValue(); String content = getNodeValue();
if (content != null) { if (content != null) {
buf.insert(0, content); buf.insert(0, content);
@ -193,7 +188,7 @@ public class TextImpl
* other than EntityRef, Text, CDATA is encountered, otherwise * other than EntityRef, Text, CDATA is encountered, otherwise
* return false * return false
*/ */
private boolean getWholeTextForward(Node node, StringBuffer buffer, Node parent){ private boolean getWholeTextForward(Node node, StringBuilder buffer, Node parent){
// boolean to indicate whether node is a child of an entity reference // boolean to indicate whether node is a child of an entity reference
boolean inEntRef = false; boolean inEntRef = false;
@ -240,7 +235,7 @@ public class TextImpl
* other than EntityRef, Text, CDATA is encountered, otherwise * other than EntityRef, Text, CDATA is encountered, otherwise
* return false * return false
*/ */
private boolean getWholeTextBackward(Node node, StringBuffer buffer, Node parent){ private boolean getWholeTextBackward(Node node, StringBuilder buffer, Node parent){
// boolean to indicate whether node is a child of an entity reference // boolean to indicate whether node is a child of an entity reference
boolean inEntRef = false; boolean inEntRef = false;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
*/ */
/* /*
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
@ -23,11 +23,11 @@ package com.sun.org.apache.xerces.internal.util;
import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.Constants;
import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* This class implements the basic operations for managing parser * This class implements the basic operations for managing parser
@ -42,6 +42,7 @@ import java.util.Set;
* *
* @author Andy Clark, IBM * @author Andy Clark, IBM
* *
* @LastModified: Apr 2019
*/ */
public class ParserConfigurationSettings public class ParserConfigurationSettings
implements XMLComponentManager { implements XMLComponentManager {
@ -56,13 +57,13 @@ public class ParserConfigurationSettings
// data // data
/** Recognized properties. */ /** Recognized properties. */
protected Set<String> fRecognizedProperties; protected List<String> fRecognizedProperties;
/** Properties. */ /** Properties. */
protected Map<String, Object> fProperties; protected Map<String, Object> fProperties;
/** Recognized features. */ /** Recognized features. */
protected Set<String> fRecognizedFeatures; protected List<String> fRecognizedFeatures;
/** Features. */ /** Features. */
protected Map<String, Boolean> fFeatures; protected Map<String, Boolean> fFeatures;
@ -86,8 +87,8 @@ public class ParserConfigurationSettings
public ParserConfigurationSettings(XMLComponentManager parent) { public ParserConfigurationSettings(XMLComponentManager parent) {
// create storage for recognized features and properties // create storage for recognized features and properties
fRecognizedFeatures = new HashSet<>(); fRecognizedFeatures = new ArrayList<>();
fRecognizedProperties = new HashSet<>(); fRecognizedProperties = new ArrayList<>();
// create table for features and properties // create table for features and properties
fFeatures = new HashMap<>(); fFeatures = new HashMap<>();
@ -195,7 +196,7 @@ public class ParserConfigurationSettings
* a critical error. * a critical error.
*/ */
@Override @Override
public final boolean getFeature(String featureId) public boolean getFeature(String featureId)
throws XMLConfigurationException { throws XMLConfigurationException {
FeatureState state = getFeatureState(featureId); FeatureState state = getFeatureState(featureId);
@ -241,7 +242,7 @@ public class ParserConfigurationSettings
* a critical error. * a critical error.
*/ */
@Override @Override
public final Object getProperty(String propertyId) public Object getProperty(String propertyId)
throws XMLConfigurationException { throws XMLConfigurationException {
PropertyState state = getPropertyState(propertyId); PropertyState state = getPropertyState(propertyId);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,8 +22,12 @@
*/ */
package dom; package dom;
import com.sun.org.apache.xerces.internal.dom.AttrImpl;
import com.sun.org.apache.xerces.internal.dom.DocumentImpl;
import com.sun.org.apache.xerces.internal.dom.ElementImpl;
import com.sun.org.apache.xerces.internal.dom.events.MutationEventImpl;
import com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
@ -33,20 +37,24 @@ import org.testng.annotations.Test;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.xml.sax.SAXException; import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;
/* /*
* @test * @test
* @bug 8213117 * @bug 8213117 8222743
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
* @modules java.xml
* @modules java.xml/com.sun.org.apache.xerces.internal.dom
* @modules java.xml/com.sun.org.apache.xerces.internal.dom.events
* @modules java.xml/com.sun.org.apache.xerces.internal.jaxp
* @run testng dom.DocumentTest * @run testng dom.DocumentTest
* @summary Tests functionalities for Document. * @summary Tests functionalities for Document.
*/ */
@Listeners({jaxp.library.BasePolicy.class}) @Listeners({jaxp.library.BasePolicy.class})
public class DocumentTest { public class DocumentTest {
static final int DOC1 = 1;
private static final String XML1 = "<root><oldNode oldAttrib1=\"old value 1\" oldAttrib2=\"old value 2\"></oldNode></root>"; static final int DOC2 = 2;
private static final String XML2 = "<root><newNode newAttrib=\"new value\"></newNode></root>";
/** /**
* Verifies the adoptNode method. Before a node from a deferred DOM can be * Verifies the adoptNode method. Before a node from a deferred DOM can be
@ -54,12 +62,11 @@ public class DocumentTest {
*/ */
@Test @Test
public void testAdoptNode() throws Exception { public void testAdoptNode() throws Exception {
String xml1 = "<root><oldNode oldAttrib1=\"old value 1\" oldAttrib2=\"old value 2\"></oldNode></root>";
String xml2 = "<root><newNode newAttrib=\"new value\"></newNode></root>";
DocumentBuilder builder = DocumentBuilderFactory.newInstance() Document doc1 = getDocument(xml1);
.newDocumentBuilder(); Document doc2 = getDocument(xml2);
Document doc1 = getDocument(builder, XML1);
Document doc2 = getDocument(builder, XML2);
Element newNode = (Element) doc2.getFirstChild().getFirstChild(); Element newNode = (Element) doc2.getFirstChild().getFirstChild();
Element replacementNode = (Element) doc1.adoptNode(newNode); Element replacementNode = (Element) doc1.adoptNode(newNode);
@ -72,10 +79,118 @@ public class DocumentTest {
Assert.assertEquals(attrValue, "new value"); Assert.assertEquals(attrValue, "new value");
} }
private static Document getDocument(DocumentBuilder builder, String xml) throws SAXException, IOException { /**
* Verifies that the lookupNamespaceURI method returns null (not empty string)
* for unbound prefix.
*
* Specification for lookupNamespaceURI:
* Returns the associated namespace URI or null if none is found.
*
* @throws Exception
*/
@Test
public void testUnboundNamespaceURI() throws Exception {
String xml = "<?xml version='1.1'?>"
+ "<root><e1 xmlns='' xmlns:p1='' xmlns:p2='uri2'><e2/></e1></root>";
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = getDocument(xml);
Element e1 = doc.getDocumentElement();
Element e2 = (Element)e1.getFirstChild().getFirstChild();
Assert.assertEquals(e1.lookupNamespaceURI(null), null);
Assert.assertEquals(e2.lookupNamespaceURI(null), null);
Assert.assertEquals(e1.lookupNamespaceURI("p1"), null);
Assert.assertEquals(e2.lookupNamespaceURI("p1"), null);
Assert.assertEquals(e1.lookupNamespaceURI("p2"), null);
Assert.assertEquals(e2.lookupNamespaceURI("p2"), "uri2");
}
/**
* Verifies that calling namespace methods on an empty document won't result
* in a NPE.
* @throws Exception
*/
@Test
public void testNamespaceNPE() throws Exception {
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
document.lookupNamespaceURI("prefix");
document.lookupPrefix("uri");
document.isDefaultNamespace("uri");
}
/**
* Verifies that manipulating an independent document from within a mutation
* listener does not modify the original event object.
*/
@Test
public void testMutation() throws Exception {
String xml1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<root><a a_attr=\"a_attr_value\"/></root>";
String xml2 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<root><b b_attr=\"b_attr_value\"/></root>";
DocumentBuilder db = DocumentBuilderFactoryImpl.newInstance().newDocumentBuilder();
DocumentImpl doc1 = (DocumentImpl)getDocument(xml1);
DocumentImpl doc2 = (DocumentImpl)getDocument(xml2);
ElementImpl a = (ElementImpl) doc1.getDocumentElement().getFirstChild();
AttrImpl attr = (AttrImpl) a.getAttributeNode("a_attr");
attr.addEventListener(MutationEventImpl.DOM_NODE_REMOVED, new MyEventListener(DOC1, doc2), false);
doc2.addEventListener(MutationEventImpl.DOM_ATTR_MODIFIED, new MyEventListener(DOC2), true);
// make a change to doc1 to trigger the event
Element a1 = (Element) doc1.getDocumentElement().getFirstChild();
a1.setAttribute("a_attr", "a_attr_newvalue");
}
private static Document getDocument(String xml) throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
InputStream a = new ByteArrayInputStream(xml.getBytes()); InputStream a = new ByteArrayInputStream(xml.getBytes());
Document out = builder.parse(a); Document out = db.parse(a);
return out; return out;
} }
// EventListener that mutates an unrelated document when an event is received.
static class MyEventListener implements EventListener {
private int docId;
private Document doc = null;
public MyEventListener(int docId) {
this.docId = docId;
}
public MyEventListener(int docId, Document doc) {
this.docId = docId;
this.doc = doc;
}
public void handleEvent(Event evt) {
if (docId == DOC1) {
//check the related node before making changes
checkRelatedNode(evt, "a_attr_value");
//make a change to doc2
Element ele = (Element)doc.getDocumentElement().getFirstChild();
ele.setAttribute("b_attr", "value for b_attr in doc2");
//check the related node again after the change
checkRelatedNode(evt, "a_attr_value");
} else { //DOC2
checkRelatedNode(evt, "value for b_attr in doc2");
}
}
}
// Utility method to display an event
public static void checkRelatedNode(Event evt, String expected) {
//System.out.println(" Event: " + evt + ", on " + evt.getTarget());
if (evt instanceof MutationEventImpl) {
MutationEventImpl mutation = (MutationEventImpl) evt;
//System.out.println(" + Related: " + mutation.getRelatedNode());
Assert.assertTrue(mutation.getRelatedNode().toString().contains(expected));
}
}
} }