mrglavas 2005/06/19 13:32:11
Modified: java/src/org/apache/xerces/jaxp SAXParserImpl.java
Log:
Completing the implementation of reset.
Created an extension of org.apache.xerces.parsers.SAXParser
which tracks changes to features and properties. This allows
us to reset the parser to its initial state without having to
dig deep into the parser configuration which in general isn't
possible. On reset we only restore the features and properties
which changed since the last reset.
Also added support for setting the secure processing
feature directly on the XMLReader.
Revision Changes Path
1.29 +260 -75
xml-xerces/java/src/org/apache/xerces/jaxp/SAXParserImpl.java
Index: SAXParserImpl.java
===================================================================
RCS file:
/home/cvs/xml-xerces/java/src/org/apache/xerces/jaxp/SAXParserImpl.java,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -r1.28 -r1.29
--- SAXParserImpl.java 19 Jun 2005 17:21:25 -0000 1.28
+++ SAXParserImpl.java 19 Jun 2005 20:32:10 -0000 1.29
@@ -17,13 +17,19 @@
package org.apache.xerces.jaxp;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import javax.xml.XMLConstants;
import javax.xml.validation.Schema;
import org.apache.xerces.impl.Constants;
+import org.apache.xerces.jaxp.validation.XSGrammarPoolContainer;
import org.apache.xerces.util.SAXMessageFormatter;
import org.apache.xerces.util.SecurityManager;
+import org.apache.xerces.xni.parser.XMLParserConfiguration;
import org.apache.xerces.xs.AttributePSVI;
import org.apache.xerces.xs.ElementPSVI;
import org.apache.xerces.xs.PSVIProvider;
@@ -71,7 +77,7 @@
private static final String SECURITY_MANAGER =
Constants.XERCES_PROPERTY_PREFIX +
Constants.SECURITY_MANAGER_PROPERTY;
- private XMLReader xmlReader;
+ private JAXPSAXParser xmlReader;
private String schemaLanguage = null; // null means DTD
private final Schema grammar;
@@ -97,49 +103,49 @@
SAXParserImpl(SAXParserFactoryImpl spf, Hashtable features, boolean
secureProcessing)
throws SAXException
{
- // Instantiate a SAXParser directly and not through SAX so that we
- // use the right ClassLoader
- xmlReader = new org.apache.xerces.parsers.SAXParser();
-
- // If validating, provide a default ErrorHandler that prints
- // validation errors with a warning telling the user to set an
- // ErrorHandler.
- if (spf.isValidating()) {
- fInitErrorHandler = new DefaultValidationErrorHandler();
- xmlReader.setErrorHandler(fInitErrorHandler);
- }
- else {
- fInitErrorHandler = xmlReader.getErrorHandler();
- }
-
- xmlReader.setFeature(VALIDATION_FEATURE, spf.isValidating());
+ // Instantiate a SAXParser directly and not through SAX so that we
use the right ClassLoader
+ xmlReader = new JAXPSAXParser(this);
// JAXP "namespaceAware" == SAX Namespaces feature
// Note: there is a compatibility problem here with default values:
// JAXP default is false while SAX 2 default is true!
- xmlReader.setFeature(NAMESPACES_FEATURE, spf.isNamespaceAware());
+ xmlReader.setFeature0(NAMESPACES_FEATURE, spf.isNamespaceAware());
// SAX "namespaces" and "namespace-prefixes" features should not
// both be false. We make them opposite for backward compatibility
// since JAXP 1.0 apps may want to receive xmlns* attributes.
- xmlReader.setFeature(NAMESPACE_PREFIXES_FEATURE,
!spf.isNamespaceAware());
+ xmlReader.setFeature0(NAMESPACE_PREFIXES_FEATURE,
!spf.isNamespaceAware());
// Avoid setting the XInclude processing feature if the value is
false.
// This will keep the configuration from throwing an exception if it
// does not support XInclude.
if (spf.isXIncludeAware()) {
- xmlReader.setFeature(XINCLUDE_FEATURE, true);
+ xmlReader.setFeature0(XINCLUDE_FEATURE, true);
}
// If the secure processing feature is on set a security manager.
if (secureProcessing) {
- xmlReader.setProperty(SECURITY_MANAGER, new SecurityManager());
+ xmlReader.setProperty0(SECURITY_MANAGER, new SecurityManager());
}
- this.grammar = spf.getSchema();
-
+ // Set application's features, followed by validation features.
setFeatures(features);
+ // If validating, provide a default ErrorHandler that prints
+ // validation errors with a warning telling the user to set an
+ // ErrorHandler.
+ if (spf.isValidating()) {
+ fInitErrorHandler = new DefaultValidationErrorHandler();
+ xmlReader.setErrorHandler(fInitErrorHandler);
+ }
+ else {
+ fInitErrorHandler = xmlReader.getErrorHandler();
+ }
+ xmlReader.setFeature0(VALIDATION_FEATURE, spf.isValidating());
+
+ // Get the Schema object from the factory
+ this.grammar = spf.getSchema();
+
// Initial EntityResolver
fInitEntityResolver = xmlReader.getEntityResolver();
}
@@ -152,13 +158,12 @@
* JAXP specific feature names, eg. SAXParserFactory.isValidating()
*/
private void setFeatures(Hashtable features)
- throws SAXNotSupportedException, SAXNotRecognizedException
- {
+ throws SAXNotSupportedException, SAXNotRecognizedException {
if (features != null) {
for (Enumeration e = features.keys(); e.hasMoreElements();) {
String feature = (String)e.nextElement();
boolean value =
((Boolean)features.get(feature)).booleanValue();
- xmlReader.setFeature(feature, value);
+ xmlReader.setFeature0(feature, value);
}
}
}
@@ -213,46 +218,8 @@
* org.xml.sax.XMLReader.
*/
public void setProperty(String name, Object value)
- throws SAXNotRecognizedException, SAXNotSupportedException
- {
- if (JAXP_SCHEMA_LANGUAGE.equals(name)) {
- // JAXP 1.2 support
- if ( W3C_XML_SCHEMA.equals(value) ) {
- //None of the properties will take effect till the
setValidating(true) has been called
- if( isValidating() ) {
- schemaLanguage = W3C_XML_SCHEMA;
- xmlReader.setFeature(XMLSCHEMA_VALIDATION_FEATURE, true);
- // this will allow the parser not to emit DTD-related
- // errors, as the spec demands
- xmlReader.setProperty(JAXP_SCHEMA_LANGUAGE,
W3C_XML_SCHEMA);
- }
-
- } else if (value == null) {
- schemaLanguage = null;
- xmlReader.setFeature(XMLSCHEMA_VALIDATION_FEATURE, false);
- } else {
- // REVISIT: It would be nice if we could format this message
- // using a user specified locale as we do in the underlying
- // XMLReader -- mrglavas
- throw new SAXNotSupportedException(
- SAXMessageFormatter.formatMessage(null,
"schema-not-supported", null));
- }
- }
- else if(JAXP_SCHEMA_SOURCE.equals(name)) {
- String val = (String)getProperty(JAXP_SCHEMA_LANGUAGE);
- if ( val != null && W3C_XML_SCHEMA.equals(val) ) {
- xmlReader.setProperty(name, value);
- }
- else {
- throw new SAXNotSupportedException(
- SAXMessageFormatter.formatMessage(null,
- "jaxp-order-not-supported",
- new Object[] {JAXP_SCHEMA_LANGUAGE,
JAXP_SCHEMA_SOURCE}));
- }
- }
- else {
- xmlReader.setProperty(name, value);
- }
+ throws SAXNotRecognizedException, SAXNotSupportedException {
+ xmlReader.setProperty(name, value);
}
/**
@@ -260,14 +227,8 @@
* implementation of org.xml.sax.XMLReader.
*/
public Object getProperty(String name)
- throws SAXNotRecognizedException, SAXNotSupportedException
- {
- if (JAXP_SCHEMA_LANGUAGE.equals(name)) {
- // JAXP 1.2 support
- return schemaLanguage;
- } else {
- return xmlReader.getProperty(name);
- }
+ throws SAXNotRecognizedException, SAXNotSupportedException {
+ return xmlReader.getProperty(name);
}
public Schema getSchema() {
@@ -275,6 +236,15 @@
}
public void reset() {
+ try {
+ /** Restore initial values of features and properties. **/
+ xmlReader.restoreInitState();
+ }
+ catch (SAXException exc) {
+ // This should never happen. We only store recognized
+ // features and properties in the hash maps. For now
+ // just ignore it.
+ }
/** Restore various handlers. **/
xmlReader.setContentHandler(null);
xmlReader.setDTDHandler(null);
@@ -301,4 +271,219 @@
public AttributePSVI getAttributePSVIByName(String uri, String
localname) {
return ((PSVIProvider)xmlReader).getAttributePSVIByName(uri,
localname);
}
+
+ /**
+ * Extension of SAXParser. This class tracks changes to
+ * features and properties to allow the parser to be reset to
+ * its initial state.
+ */
+ public static class JAXPSAXParser extends
org.apache.xerces.parsers.SAXParser {
+
+ private HashMap fInitFeatures = new HashMap();
+ private HashMap fInitProperties = new HashMap();
+ private SAXParserImpl fSAXParser;
+
+ public JAXPSAXParser() {
+ super();
+ }
+
+ private JAXPSAXParser(SAXParserImpl saxParser) {
+ super();
+ fSAXParser = saxParser;
+ }
+
+ /**
+ * Override SAXParser's setFeature method to track the initial state
+ * of features. This keeps us from affecting the performance of the
+ * SAXParser when it is created with XMLReaderFactory.
+ */
+ public synchronized void setFeature(String name, boolean value)
+ throws SAXNotRecognizedException, SAXNotSupportedException {
+ if (name == null) {
+ // TODO: Add localized error message.
+ throw new NullPointerException();
+ }
+ if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
+ try {
+ setProperty(SECURITY_MANAGER, value ? new
SecurityManager() : null);
+ }
+ catch (SAXNotRecognizedException exc) {
+ // If the property is not supported
+ // re-throw the exception if the value is true.
+ if (value) {
+ throw exc;
+ }
+ }
+ catch (SAXNotSupportedException exc) {
+ // If the property is not supported
+ // re-throw the exception if the value is true.
+ if (value) {
+ throw exc;
+ }
+ }
+ return;
+ }
+ if (!fInitFeatures.containsKey(name)) {
+ boolean current = super.getFeature(name);
+ fInitFeatures.put(name, current ? Boolean.TRUE :
Boolean.FALSE);
+ }
+ super.setFeature(name, value);
+ }
+
+ public synchronized boolean getFeature(String name)
+ throws SAXNotRecognizedException, SAXNotSupportedException {
+ if (name == null) {
+ // TODO: Add localized error message.
+ throw new NullPointerException();
+ }
+ if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
+ try {
+ return (super.getProperty(SECURITY_MANAGER) != null);
+ }
+ // If the property is not supported the value must be false.
+ catch (SAXException exc) {
+ return false;
+ }
+ }
+ return super.getFeature(name);
+ }
+
+ /**
+ * Override SAXParser's setProperty method to track the initial state
+ * of properties. This keeps us from affecting the performance of the
+ * SAXParser when it is created with XMLReaderFactory.
+ */
+ public synchronized void setProperty(String name, Object value)
+ throws SAXNotRecognizedException, SAXNotSupportedException {
+ if (name == null) {
+ // TODO: Add localized error message.
+ throw new NullPointerException();
+ }
+ if (fSAXParser != null) {
+ // JAXP 1.2 support
+ if (JAXP_SCHEMA_LANGUAGE.equals(name)) {
+ // The spec says if a schema is given via
SAXParserFactory
+ // the JAXP 1.2 properties shouldn't be allowed.
+ if (fSAXParser.grammar != null) {
+ throw new SAXNotSupportedException(
+
SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
"schema-already-specified", new Object[] {name}));
+ }
+ if ( W3C_XML_SCHEMA.equals(value) ) {
+ //None of the properties will take effect till the
setValidating(true) has been called
+ if( fSAXParser.isValidating() ) {
+ fSAXParser.schemaLanguage = W3C_XML_SCHEMA;
+ setFeature(XMLSCHEMA_VALIDATION_FEATURE, true);
+ // this will allow the parser not to emit
DTD-related
+ // errors, as the spec demands
+ if
(!fInitProperties.containsKey(JAXP_SCHEMA_LANGUAGE)) {
+ fInitProperties.put(JAXP_SCHEMA_LANGUAGE,
super.getProperty(JAXP_SCHEMA_LANGUAGE));
+ }
+ super.setProperty(JAXP_SCHEMA_LANGUAGE,
W3C_XML_SCHEMA);
+ }
+
+ }
+ else if (value == null) {
+ fSAXParser.schemaLanguage = null;
+ setFeature(XMLSCHEMA_VALIDATION_FEATURE, false);
+ }
+ else {
+ // REVISIT: It would be nice if we could format this
message
+ // using a user specified locale as we do in the
underlying
+ // XMLReader -- mrglavas
+ throw new SAXNotSupportedException(
+
SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
"schema-not-supported", null));
+ }
+ return;
+ }
+ else if (JAXP_SCHEMA_SOURCE.equals(name)) {
+ // The spec says if a schema is given via
SAXParserFactory
+ // the JAXP 1.2 properties shouldn't be allowed.
+ if (fSAXParser.grammar != null) {
+ throw new SAXNotSupportedException(
+
SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
"schema-already-specified", new Object[] {name}));
+ }
+ String val = (String)getProperty(JAXP_SCHEMA_LANGUAGE);
+ if ( val != null && W3C_XML_SCHEMA.equals(val) ) {
+ if
(!fInitProperties.containsKey(JAXP_SCHEMA_SOURCE)) {
+ fInitProperties.put(JAXP_SCHEMA_SOURCE,
super.getProperty(JAXP_SCHEMA_SOURCE));
+ }
+ super.setProperty(name, value);
+ }
+ else {
+ throw new SAXNotSupportedException(
+
SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
+ "jaxp-order-not-supported",
+ new Object[] {JAXP_SCHEMA_LANGUAGE,
JAXP_SCHEMA_SOURCE}));
+ }
+ return;
+ }
+ }
+ if (!fInitProperties.containsKey(name)) {
+ fInitProperties.put(name, super.getProperty(name));
+ }
+ super.setProperty(name, value);
+ }
+
+ public synchronized Object getProperty(String name)
+ throws SAXNotRecognizedException, SAXNotSupportedException {
+ if (name == null) {
+ // TODO: Add localized error message.
+ throw new NullPointerException();
+ }
+ if (fSAXParser != null && JAXP_SCHEMA_LANGUAGE.equals(name)) {
+ // JAXP 1.2 support
+ return fSAXParser.schemaLanguage;
+ }
+ return super.getProperty(name);
+ }
+
+ synchronized void restoreInitState()
+ throws SAXNotRecognizedException, SAXNotSupportedException {
+ Iterator iter;
+ if (!fInitFeatures.isEmpty()) {
+ iter = fInitFeatures.entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry entry = (Map.Entry) iter.next();
+ String name = (String) entry.getKey();
+ boolean value = ((Boolean)
entry.getValue()).booleanValue();
+ super.setFeature(name, value);
+ }
+ fInitFeatures.clear();
+ }
+ if (!fInitProperties.isEmpty()) {
+ iter = fInitProperties.entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry entry = (Map.Entry) iter.next();
+ String name = (String) entry.getKey();
+ Object value = entry.getValue();
+ super.setProperty(name, value);
+ }
+ fInitProperties.clear();
+ }
+ }
+
+ XMLParserConfiguration getXMLParserConfiguration() {
+ return fConfiguration;
+ }
+
+ void setFeature0(String name, boolean value)
+ throws SAXNotRecognizedException, SAXNotSupportedException {
+ super.setFeature(name, value);
+ }
+
+ boolean getFeature0(String name)
+ throws SAXNotRecognizedException, SAXNotSupportedException {
+ return super.getFeature(name);
+ }
+
+ void setProperty0(String name, Object value)
+ throws SAXNotRecognizedException, SAXNotSupportedException {
+ super.setProperty(name, value);
+ }
+
+ Object getProperty0(String name)
+ throws SAXNotRecognizedException, SAXNotSupportedException {
+ return super.getProperty(name);
+ }
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]