You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by el...@apache.org on 2003/07/18 19:34:39 UTC
cvs commit: xml-xerces/java/src/org/apache/xerces/xinclude XIncludeTextReader.java MultipleScopeNamespaceSupport.java XIncludeFatalError.java XIncludeHandler.java XIncludeMessageFormatter.java XIncludeNamespaceSupport.java XIncludeResourceError.java
elena 2003/07/18 10:34:39
Modified: java/src/org/apache/xerces/impl Constants.java
java/src/org/apache/xerces/impl/msg
XIncludeMessages.properties
java/src/org/apache/xerces/parsers AbstractSAXParser.java
XIncludeParserConfiguration.java
java/src/org/apache/xerces/xinclude
MultipleScopeNamespaceSupport.java
XIncludeFatalError.java XIncludeHandler.java
XIncludeMessageFormatter.java
XIncludeNamespaceSupport.java
XIncludeResourceError.java
Added: java/src/org/apache/xerces/xinclude XIncludeTextReader.java
Log:
XInclude implementation update:
* Couple of bugs fixes, copyright date updates (Peter McCracken)
* XIncludeHandler is now using EntityResover and structure of text inclusions has changed. (Peter McCracken)
* Implementation for determining the encoding of included documents
when parse="text". Encoding is determined as per section 4.3 of XInclude
spec (Arun Yadav)
* Support for unparsed entities and notations (Peter McCracken)
* Introduce a new features "allow-dtd-events-after-endDTD" that controls sending unparsed entity declaration and notation declaration
events outside of start/end DTD events. (Peter McCracken)
There is still no support for XPointer fragments.
Revision Changes Path
1.31 +5 -2 xml-xerces/java/src/org/apache/xerces/impl/Constants.java
Index: Constants.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/Constants.java,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -r1.30 -r1.31
--- Constants.java 24 Jun 2003 21:56:58 -0000 1.30
+++ Constants.java 18 Jul 2003 17:34:37 -0000 1.31
@@ -99,6 +99,9 @@
/** External parameter entities feature ("external-parameter-entities "). */
public static final String EXTERNAL_PARAMETER_ENTITIES_FEATURE = "external-parameter-entities";
+ /** Allow unparsed entity and notation declaration events to be sent after the end DTD event ("allow-dtd-events-after-endDTD") */
+ public static final String ALLOW_DTD_EVENTS_AFTER_ENDDTD_FEATURE = "allow-dtd-events-after-endDTD";
+
// sax properties
/** SAX property prefix ("http://xml.org/sax/properties/"). */
@@ -268,7 +271,7 @@
/** Standard URI conformant feature ("standard-uri-conformant"). */
public static final String STANDARD_URI_CONFORMANT_FEATURE = "standard-uri-conformant";
-
+
// xerces properties
/** Xerces properties prefix ("http://apache.org/xml/properties/"). */
1.2 +3 -1 xml-xerces/java/src/org/apache/xerces/impl/msg/XIncludeMessages.properties
Index: XIncludeMessages.properties
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/msg/XIncludeMessages.properties,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- XIncludeMessages.properties 24 Jun 2003 21:56:58 -0000 1.1
+++ XIncludeMessages.properties 18 Jul 2003 17:34:38 -0000 1.2
@@ -6,13 +6,15 @@
NoFallback = An 'include' failed, and no 'fallback' element was found.
MultipleFallbacks = The [children] of an 'include' element cannot contain more than one 'fallback' element.
FallbackParent = An 'include' element is not parent of 'fallback' element.
-IncludeParent = The parent of an 'include' element cannot be another 'include' element.
+IncludeChild = A ''{0}'' element cannot be a child of an 'include' element.
HrefMissing = The 'href' attribute of an 'include' element is missing.
RecursiveInclude = Recursive include detected.
InvalidParseValue = Invalid value for ''parse'' attribute on ''include'' element: ''{0}''.
XMLParseError = Error parsing invalid XML file.
XMLResourceError = Resource error reading XML file. Reason: {0}
TextResourceError = Resource error reading text file. Reason: {0}
+NonDuplicateNotation = Multiple notations were used which had the name ''{0}'', but which were not determined to be duplicates.
+NonDuplicateUnparsedEntity = Multiple unparsed entities were used which had the name ''{0}'', but which were not determined to be duplicates.
# Messages from erroneous set-up
IncompatibleNamespaceContext = The type of the NamespaceContext is incompatible with using XInclude; it must be an instance of XIncludeNamespaceSupport
1.42 +13 -1 xml-xerces/java/src/org/apache/xerces/parsers/AbstractSAXParser.java
Index: AbstractSAXParser.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/parsers/AbstractSAXParser.java,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -r1.41 -r1.42
--- AbstractSAXParser.java 8 May 2003 20:11:58 -0000 1.41
+++ AbstractSAXParser.java 18 Jul 2003 17:34:38 -0000 1.42
@@ -134,6 +134,12 @@
protected static final String STRING_INTERNING =
Constants.SAX_FEATURE_PREFIX + Constants.STRING_INTERNING_FEATURE;
+ /** Feature identifier: allow notation and unparsed entity events to be sent out of order. */
+ // this is not meant to be a recognized feature, but we need it here to use
+ // if it is already a recognized feature for the pipeline
+ protected static final String ALLOW_UE_AND_NOTATION_EVENTS =
+ Constants.SAX_FEATURE_PREFIX + Constants.ALLOW_DTD_EVENTS_AFTER_ENDDTD_FEATURE;
+
/** Recognized features. */
private static final String[] RECOGNIZED_FEATURES = {
NAMESPACES,
@@ -234,6 +240,12 @@
config.addRecognizedFeatures(RECOGNIZED_FEATURES);
config.addRecognizedProperties(RECOGNIZED_PROPERTIES);
+ try {
+ config.setFeature(ALLOW_UE_AND_NOTATION_EVENTS, false);
+ }
+ catch (XMLConfigurationException e) {
+ // it wasn't a recognized feature, so we don't worry about it
+ }
} // <init>(XMLParserConfiguration)
//
1.2 +66 -39 xml-xerces/java/src/org/apache/xerces/parsers/XIncludeParserConfiguration.java
Index: XIncludeParserConfiguration.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/parsers/XIncludeParserConfiguration.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- XIncludeParserConfiguration.java 24 Jun 2003 21:56:58 -0000 1.1
+++ XIncludeParserConfiguration.java 18 Jul 2003 17:34:38 -0000 1.2
@@ -60,9 +60,12 @@
import org.apache.xerces.util.SymbolTable;
import org.apache.xerces.xinclude.XIncludeHandler;
import org.apache.xerces.xinclude.XIncludeNamespaceSupport;
+import org.apache.xerces.xni.XMLDTDHandler;
import org.apache.xerces.xni.XMLDocumentHandler;
import org.apache.xerces.xni.grammars.XMLGrammarPool;
import org.apache.xerces.xni.parser.XMLComponentManager;
+import org.apache.xerces.xni.parser.XMLConfigurationException;
+import org.apache.xerces.xni.parser.XMLDTDSource;
import org.apache.xerces.xni.parser.XMLDocumentSource;
/**
@@ -70,7 +73,11 @@
*/
public class XIncludeParserConfiguration extends XML11Configuration {
- private XIncludeHandler fXIncludeComponent;
+ private XIncludeHandler fXIncludeHandler;
+
+ /** Feature identifier: allow notation and unparsed entity events to be sent out of order. */
+ protected static final String ALLOW_UE_AND_NOTATION_EVENTS =
+ Constants.SAX_FEATURE_PREFIX + Constants.ALLOW_DTD_EVENTS_AFTER_ENDDTD_FEATURE;
/** Property identifier: error reporter. */
protected static final String XINCLUDE_HANDLER =
@@ -83,7 +90,6 @@
/** Default constructor. */
public XIncludeParserConfiguration() {
this(null, null, null);
- //this(null, new XMLGrammarPoolImpl(), null);
} // <init>()
/**
@@ -93,7 +99,6 @@
*/
public XIncludeParserConfiguration(SymbolTable symbolTable) {
this(symbolTable, null, null);
- //this(symbolTable, new XMLGrammarPoolImpl(), null);
} // <init>(SymbolTable)
/**
@@ -131,8 +136,11 @@
XMLComponentManager parentSettings) {
super(symbolTable, grammarPool, parentSettings);
+ fXIncludeHandler = new XIncludeHandler();
+ addComponent(fXIncludeHandler);
+
final String[] recognizedFeatures = {
- // XINCLUDE_PROCESSING TODO: should this be a feature?
+ ALLOW_UE_AND_NOTATION_EVENTS
};
addRecognizedFeatures(recognizedFeatures);
@@ -140,51 +148,70 @@
final String[] recognizedProperties =
{ XINCLUDE_HANDLER, NAMESPACE_CONTEXT };
addRecognizedProperties(recognizedProperties);
-
+
+ setFeature(ALLOW_UE_AND_NOTATION_EVENTS, true);
+
+ setProperty(XINCLUDE_HANDLER, fXIncludeHandler);
setProperty(NAMESPACE_CONTEXT, new XIncludeNamespaceSupport());
-
- fXIncludeComponent = new XIncludeHandler();
- setProperty(XINCLUDE_HANDLER, fXIncludeComponent);
- addComponent(fXIncludeComponent);
} // <init>(SymbolTable,XMLGrammarPool)}
/** Configures the pipeline. */
protected void configurePipeline() {
+ // setup document pipeline
super.configurePipeline();
- // setup document pipeline
- // TODO: actually use XINCLUDE_PROCESSING feature, if we decide to implement it
- if (true /*fFeatures.get(XINCLUDE_PROCESSING) == Boolean.TRUE*/
- ) {
- if (fXIncludeComponent == null) {
- fXIncludeComponent = new XIncludeHandler();
- addComponent(fXIncludeComponent);
- }
+ // insert before fSchemaValidator, if one exists.
+ XMLDocumentSource prev = null;
+ if (fFeatures.get(XMLSCHEMA_VALIDATION) == Boolean.TRUE) {
+ // we don't have to worry about fSchemaValidator being null, since
+ // super.configurePipeline() instantiated it if the feature was set
+ prev = fSchemaValidator.getDocumentSource();
+ }
+ // Otherwise, insert after the last component in the pipeline
+ else {
+ prev = fLastComponent;
+ }
- // insert before fSchemaValidator, if one exists.
- XMLDocumentSource prev = null;
- if (fFeatures.get(XMLSCHEMA_VALIDATION) == Boolean.TRUE) {
- // we don't have to worry about fSchemaValidator being null, since
- // super.configurePipeline() instantiated it if the feature was set
- prev = fSchemaValidator.getDocumentSource();
+ if (prev != null) {
+ XMLDocumentHandler next = prev.getDocumentHandler();
+ if (next != null) {
+ fXIncludeHandler.setDocumentHandler(next);
+ next.setDocumentSource(fXIncludeHandler);
}
- // Otherwise, insert after the last component in the pipeline
- else {
- prev = fLastComponent;
+ prev.setDocumentHandler(fXIncludeHandler);
+ fXIncludeHandler.setDocumentSource(prev);
+ }
+ else {
+ setDocumentHandler(fXIncludeHandler);
+ }
+ } // configurePipeline()
+
+ protected void configureDTDPipeline() {
+ super.configureDTDPipeline();
+
+ // It doesn't really matter where we stick the XIncludeHandler in the
+ // DTD pipeline, since it doesn't ever modify anything.
+ // We'll put it right after the scanner
+ if (fDTDScanner != null) {
+ XMLDTDHandler next = fDTDScanner.getDTDHandler();
+ if (next != null) {
+ fXIncludeHandler.setDTDHandler(next);
+ next.setDTDSource(fXIncludeHandler);
}
+ fDTDScanner.setDTDHandler(fXIncludeHandler);
+ fXIncludeHandler.setDTDSource(fDTDScanner);
+ }
+ else {
+ setDTDHandler(fXIncludeHandler);
+ }
+ }
+
+ public void setProperty(String propertyId, Object value)
+ throws XMLConfigurationException {
- if (prev != null) {
- XMLDocumentHandler next = prev.getDocumentHandler();
- if (next != null) {
- fXIncludeComponent.setDocumentHandler(next);
- next.setDocumentSource(fXIncludeComponent);
- }
- prev.setDocumentHandler(fXIncludeComponent);
- fXIncludeComponent.setDocumentSource(prev);
- }
- else {
- setDocumentHandler(fXIncludeComponent);
- }
+ if (propertyId.equals(XINCLUDE_HANDLER)) {
}
- } // configurePipeline()
+
+ super.setProperty(propertyId, value);
+ } // setProperty(String,Object)
}
1.2 +1 -1 xml-xerces/java/src/org/apache/xerces/xinclude/MultipleScopeNamespaceSupport.java
Index: MultipleScopeNamespaceSupport.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/xinclude/MultipleScopeNamespaceSupport.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- MultipleScopeNamespaceSupport.java 25 Jun 2003 00:48:32 -0000 1.1
+++ MultipleScopeNamespaceSupport.java 18 Jul 2003 17:34:38 -0000 1.2
@@ -49,7 +49,7 @@
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
- * originally based on software copyright (c) 1999, International
+ * originally based on software copyright (c) 2003, International
* Business Machines, Inc., http://www.apache.org. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
1.2 +1 -3 xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeFatalError.java
Index: XIncludeFatalError.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeFatalError.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- XIncludeFatalError.java 25 Jun 2003 00:48:58 -0000 1.1
+++ XIncludeFatalError.java 18 Jul 2003 17:34:38 -0000 1.2
@@ -49,14 +49,12 @@
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
- * originally based on software copyright (c) 1999, International
+ * originally based on software copyright (c) 2003, International
* Business Machines, Inc., http://www.apache.org. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.xerces.xinclude;
-
-import org.apache.xerces.xni.XNIException;
/**
* @author Peter McCracken, IBM
1.2 +928 -328 xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeHandler.java
Index: XIncludeHandler.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeHandler.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- XIncludeHandler.java 25 Jun 2003 00:49:21 -0000 1.1
+++ XIncludeHandler.java 18 Jul 2003 17:34:38 -0000 1.2
@@ -49,7 +49,7 @@
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
- * originally based on software copyright (c) 1999, International
+ * originally based on software copyright (c) 2003, International
* Business Machines, Inc., http://www.apache.org. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
@@ -58,46 +58,48 @@
import java.io.File;
import java.io.IOException;
-import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
+import java.util.StringTokenizer;
import java.util.Vector;
import org.apache.xerces.impl.Constants;
import org.apache.xerces.impl.XMLEntityManager;
import org.apache.xerces.impl.XMLErrorReporter;
-import org.apache.xerces.impl.dtd.DTDGrammar;
-import org.apache.xerces.impl.dtd.XMLDTDDescription;
import org.apache.xerces.util.AugmentationsImpl;
import org.apache.xerces.util.ObjectFactory;
+import org.apache.xerces.util.ParserConfigurationSettings;
import org.apache.xerces.util.XMLAttributesImpl;
-import org.apache.xerces.util.XMLStringBuffer;
+import org.apache.xerces.util.XMLResourceIdentifierImpl;
import org.apache.xerces.util.XMLSymbols;
import org.apache.xerces.util.URI.MalformedURIException;
import org.apache.xerces.xni.Augmentations;
import org.apache.xerces.xni.NamespaceContext;
import org.apache.xerces.xni.QName;
import org.apache.xerces.xni.XMLAttributes;
+import org.apache.xerces.xni.XMLDTDHandler;
import org.apache.xerces.xni.XMLDocumentHandler;
import org.apache.xerces.xni.XMLLocator;
import org.apache.xerces.xni.XMLResourceIdentifier;
import org.apache.xerces.xni.XMLString;
import org.apache.xerces.xni.XNIException;
-import org.apache.xerces.xni.grammars.XMLGrammarDescription;
-import org.apache.xerces.xni.grammars.XMLGrammarPool;
import org.apache.xerces.xni.parser.XMLComponent;
import org.apache.xerces.xni.parser.XMLComponentManager;
import org.apache.xerces.xni.parser.XMLConfigurationException;
+import org.apache.xerces.xni.parser.XMLDTDFilter;
+import org.apache.xerces.xni.parser.XMLDTDSource;
import org.apache.xerces.xni.parser.XMLDocumentFilter;
import org.apache.xerces.xni.parser.XMLDocumentSource;
+import org.apache.xerces.xni.parser.XMLEntityResolver;
import org.apache.xerces.xni.parser.XMLInputSource;
import org.apache.xerces.xni.parser.XMLParserConfiguration;
/**
* @author Peter McCracken, IBM
*/
-public class XIncludeHandler implements XMLComponent, XMLDocumentFilter {
+public class XIncludeHandler
+ implements XMLComponent, XMLDocumentFilter, XMLDTDFilter {
public final static String XINCLUDE_DEFAULT_CONFIGURATION =
"org.apache.xerces.parsers.XIncludeParserConfiguration";
@@ -134,50 +136,63 @@
NamespaceContext.XMLNS_URI);
// Processing States
- private final static Integer STATE_NORMAL_PROCESSING = new Integer(1);
- private final static Integer STATE_IGNORE = new Integer(2);
- private final static Integer STATE_EXPECT_FALLBACK = new Integer(3);
+ private final static int STATE_NORMAL_PROCESSING = 1;
+ private final static int STATE_IGNORE = 2;
+ private final static int STATE_EXPECT_FALLBACK = 3;
// recognized features and properties
+ /** Feature identifier: allow notation and unparsed entity events to be sent out of order. */
+ protected static final String ALLOW_UE_AND_NOTATION_EVENTS =
+ Constants.SAX_FEATURE_PREFIX
+ + Constants.ALLOW_DTD_EVENTS_AFTER_ENDDTD_FEATURE;
+
/** Property identifier: error handler. */
protected static final String ERROR_REPORTER =
Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
/** Property identifier: grammar pool . */
- protected static final String GRAMMAR_POOL =
- Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
+ protected static final String ENTITY_RESOLVER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
/** Recognized features. */
- private static final String[] RECOGNIZED_FEATURES = {
- };
+ private static final String[] RECOGNIZED_FEATURES =
+ { ALLOW_UE_AND_NOTATION_EVENTS };
/** Feature defaults. */
- private static final Boolean[] FEATURE_DEFAULTS = {
- };
+ private static final Boolean[] FEATURE_DEFAULTS = { Boolean.TRUE };
/** Recognized properties. */
- // TODO: make DEFAULT_XINCLUDE_PIPELINE a property?
private static final String[] RECOGNIZED_PROPERTIES =
- { ERROR_REPORTER, GRAMMAR_POOL };
+ { ERROR_REPORTER, ENTITY_RESOLVER };
/** Property defaults. */
- private static final Object[] PROPERTY_DEFAULTS = { null, null, null, };
+ private static final Object[] PROPERTY_DEFAULTS = { null, null };
- // Data
+ // instance variables
+ // for XMLDocumentFilter
protected XMLDocumentHandler fDocumentHandler;
protected XMLDocumentSource fDocumentSource;
+ // for XMLDTDFilter
+ protected XMLDTDHandler fDTDHandler;
+ protected XMLDTDSource fDTDSource;
+
+ // for XIncludeHandler
protected XIncludeHandler fParentXIncludeHandler;
+ // for caching
+ protected XMLParserConfiguration fChildConfig;
+
protected XMLLocator fDocLocation;
protected XIncludeNamespaceSupport fNamespaceContext;
protected XMLErrorReporter fErrorReporter;
- protected XMLGrammarPool fGrammarPool;
- protected XMLGrammarDescription fGrammarDesc;
- protected DTDGrammar fDTDGrammar;
+ protected XMLEntityResolver fEntityResolver;
+
+ // used for passing features on to child XIncludeHandler objects
+ protected ParserConfigurationSettings fSettings;
// The current element depth.
// This is used to access the appropriate level of the following stacks.
@@ -188,40 +203,38 @@
// is an include, and processing goes to the fallback.
private int fRootDepth;
- // TODO: for performance, change these to expanding arrays
+ // this value must be at least 1
+ private static final int INITIAL_SIZE = 8;
// Used to ensure that fallbacks are always children of include elements,
// and that include elements are never children of other include elements.
// An index contains true if the ancestor of the current element which resides
// at that depth was an include element.
- private Vector fSawInclude;
+ private boolean[] fSawInclude = new boolean[INITIAL_SIZE];
// Ensures that only one fallback element can be at a single depth.
// An index contains true if we have seen any fallback elements at that depth,
// and it is only reset to false when the end tag of the parent is encountered.
- private Vector fSawFallback;
+ private boolean[] fSawFallback = new boolean[INITIAL_SIZE];
// The state of the processor at each given depth.
- private Vector fState;
+ private int[] fState = new int[INITIAL_SIZE];
- // Constructors
+ // buffering the necessary DTD events
+ private Vector fNotations = new Vector();
+ private Vector fUnparsedEntities = new Vector();
- public XIncludeHandler() {
- this(null);
- }
+ private boolean fSendUEAndNotationEvents;
- private XIncludeHandler(XIncludeHandler parent) {
- fParentXIncludeHandler = parent;
+ // Constructors
+ public XIncludeHandler() {
fDepth = 0;
fRootDepth = 0;
- fSawFallback = new Vector();
- fSawFallback.add(Boolean.FALSE);
- fSawInclude = new Vector();
- fSawInclude.add(Boolean.FALSE);
- fState = new Vector();
- fState.add(STATE_NORMAL_PROCESSING);
+ fSawFallback[fDepth] = false;
+ fSawInclude[fDepth] = false;
+ fState[fDepth] = STATE_NORMAL_PROCESSING;
}
// XMLComponent methods
@@ -233,19 +246,61 @@
fRootDepth = 0;
try {
- setErrorReporter(
- (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER));
+ fSendUEAndNotationEvents =
+ componentManager.getFeature(ALLOW_UE_AND_NOTATION_EVENTS);
+ if (fChildConfig != null) {
+ fChildConfig.setFeature(
+ ALLOW_UE_AND_NOTATION_EVENTS,
+ fSendUEAndNotationEvents);
+ }
+ }
+ catch (XMLConfigurationException e) {
+ }
+
+ try {
+ XMLErrorReporter value =
+ (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER);
+ setErrorReporter(value);
+ if (fChildConfig != null) {
+ fChildConfig.setProperty(ERROR_REPORTER, value);
+ }
}
catch (XMLConfigurationException e) {
fErrorReporter = null;
}
+
try {
- fGrammarPool =
- (XMLGrammarPool)componentManager.getProperty(GRAMMAR_POOL);
+ XMLEntityResolver value =
+ (XMLEntityResolver)componentManager.getProperty(
+ ENTITY_RESOLVER);
+ fEntityResolver = value;
+ if (fChildConfig != null) {
+ fChildConfig.setProperty(ENTITY_RESOLVER, value);
+ }
}
catch (XMLConfigurationException e) {
- fGrammarPool = null;
+ fEntityResolver = null;
}
+
+ fSettings = new ParserConfigurationSettings();
+
+ Enumeration xercesFeatures = Constants.getXercesFeatures();
+ while (xercesFeatures.hasMoreElements()) {
+ String featureId = (String)xercesFeatures.nextElement();
+ fSettings.addRecognizedFeatures(
+ new String[] { Constants.XERCES_FEATURE_PREFIX + featureId });
+ try {
+ fSettings.setFeature(
+ featureId,
+ componentManager.getFeature(featureId));
+ }
+ catch (XMLConfigurationException e) {
+ // componentManager doesn't support this feature,
+ // so we won't worry about it
+ }
+ }
+
+ // don't reset fChildConfig -- we don't want it to share the same components
} // reset(XMLComponentManager)
/**
@@ -274,6 +329,12 @@
*/
public void setFeature(String featureId, boolean state)
throws XMLConfigurationException {
+ if (featureId.equals(ALLOW_UE_AND_NOTATION_EVENTS)) {
+ fSendUEAndNotationEvents = state;
+ }
+ if (fSettings != null) {
+ fSettings.setFeature(featureId, state);
+ }
} // setFeature(String,boolean)
/**
@@ -304,9 +365,15 @@
throws XMLConfigurationException {
if (propertyId.equals(ERROR_REPORTER)) {
setErrorReporter((XMLErrorReporter)value);
+ if (fChildConfig != null) {
+ fChildConfig.setProperty(propertyId, value);
+ }
}
- if (propertyId.equals(GRAMMAR_POOL)) {
- fGrammarPool = (XMLGrammarPool)value;
+ if (propertyId.equals(ENTITY_RESOLVER)) {
+ fEntityResolver = (XMLEntityResolver)value;
+ if (fChildConfig != null) {
+ fChildConfig.setProperty(propertyId, value);
+ }
}
} // setProperty(String,Object)
@@ -346,15 +413,6 @@
return null;
} // getPropertyDefault(String):Object
- private void setErrorReporter(XMLErrorReporter reporter) {
- fErrorReporter = reporter;
- if (fErrorReporter != null) {
- fErrorReporter.putMessageFormatter(
- XIncludeMessageFormatter.XINCLUDE_DOMAIN,
- new XIncludeMessageFormatter());
- }
- }
-
public void setDocumentHandler(XMLDocumentHandler handler) {
fDocumentHandler = handler;
}
@@ -372,9 +430,14 @@
Augmentations augs)
throws XNIException {
- if (!isRootDocument()
- && fParentXIncludeHandler.searchForRecursiveIncludes(locator)) {
- throw new XIncludeFatalError("RecursiveInclude", null);
+ try {
+ if (!isRootDocument()
+ && fParentXIncludeHandler.searchForRecursiveIncludes(locator)) {
+ throw new XIncludeFatalError("RecursiveInclude", null);
+ }
+ }
+ catch (XIncludeFatalError e) {
+ reportFatalError(e.getKey(), e.getArgs());
}
if (!(namespaceContext instanceof XIncludeNamespaceSupport)) {
@@ -409,26 +472,6 @@
String systemId,
Augmentations augs)
throws XNIException {
-
- String eid = null;
- try {
- eid =
- XMLEntityManager.expandSystemId(
- systemId,
- fDocLocation.getExpandedSystemId(),
- false);
- }
- catch (java.io.IOException e) {
- }
-
- fGrammarDesc =
- new XMLDTDDescription(
- publicId,
- systemId,
- fDocLocation.getExpandedSystemId(),
- eid,
- rootElement);
-
if (isRootDocument() && fDocumentHandler != null) {
fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
}
@@ -512,6 +555,13 @@
else if (isFallbackElement(element)) {
this.handleFallbackElement();
}
+ else if (hasXIncludeNamespace(element)) {
+ if (getSawInclude(fDepth - 1)) {
+ reportFatalError(
+ "IncludeChild",
+ new Object[] { element.rawname });
+ }
+ }
else if (
fDocumentHandler != null
&& getState() == STATE_NORMAL_PROCESSING) {
@@ -528,157 +578,6 @@
fDepth--;
}
- protected void handleFallbackElement() {
- setSawInclude(fDepth, false);
- fNamespaceContext.setContextInvalid();
- if (!getSawInclude(fDepth - 1)) {
- reportFatalError("FallbackParent");
- }
-
- if (getSawFallback(fDepth)) {
- reportFatalError("MultipleFallbacks");
- }
- else {
- setSawFallback(fDepth, true);
- }
-
- // either the state is STATE_EXPECT_FALLBACK or it's STATE_IGNORE
- // if we're ignoring, we want to stay ignoring. But if we're expecting this fallback element,
- // we want to signal that we should process the children
- if (getState() == STATE_EXPECT_FALLBACK) {
- setState(STATE_NORMAL_PROCESSING);
- }
- }
-
- protected void handleIncludeElement(XMLAttributes attributes)
- throws XNIException {
- setSawInclude(fDepth, true);
- fNamespaceContext.setContextInvalid();
- if (getSawInclude(fDepth - 1)) {
- reportFatalError("IncludeParent");
- }
- if (getState() == STATE_IGNORE)
- return;
-
- String href = attributes.getValue(XINCLUDE_ATTR_HREF);
-
- XMLInputSource includedSource = null;
- if (href == null) {
- reportFatalError("HrefMissing");
- }
-
- includedSource =
- new XMLInputSource(null, href, fDocLocation.getBaseSystemId());
-
- String parse = attributes.getValue(XINCLUDE_ATTR_PARSE);
- if (parse == null) {
- parse = XINCLUDE_PARSE_XML;
- }
-
- if (parse.equals(XINCLUDE_PARSE_XML)) {
- // create pipeline with no schema validator
- // TODO: implement DEFAULT_XINCLUDE_PROPERTY?
- String parserName = XINCLUDE_DEFAULT_CONFIGURATION;
- XMLParserConfiguration parserConfig =
- (XMLParserConfiguration)ObjectFactory.newInstance(
- parserName,
- ObjectFactory.findClassLoader(),
- true);
-
- // TODO: set all features on parserConfig to match this parser configuration
-
- // we don't want a schema validator on the new pipeline
- parserConfig.setFeature(
- Constants.XERCES_FEATURE_PREFIX
- + Constants.SCHEMA_VALIDATION_FEATURE,
- false);
-
- // use the same error reporter
- parserConfig.setProperty(ERROR_REPORTER, fErrorReporter);
- // use the same namespace context
- parserConfig.setProperty(
- Constants.XERCES_PROPERTY_PREFIX
- + Constants.NAMESPACE_CONTEXT_PROPERTY,
- fNamespaceContext);
-
- XIncludeHandler newHandler =
- (XIncludeHandler)parserConfig.getProperty(
- Constants.XERCES_PROPERTY_PREFIX
- + Constants.XINCLUDE_HANDLER_PROPERTY);
- newHandler.setParent(this);
- newHandler.setDocumentHandler(this.getDocumentHandler());
-
- try {
- fNamespaceContext.pushScope();
-
- parserConfig.parse(includedSource);
- }
- catch (XIncludeFatalError e) {
- reportFatalError(e.getKey(), e.getArgs());
- }
- catch (XNIException e) {
- reportFatalError("XMLParseError");
- }
- catch (IOException e) {
- throw new XIncludeResourceError(
- "XMLResourceError",
- new Object[] { e.getMessage()});
- }
- finally {
- fNamespaceContext.popScope();
- }
- }
- // TODO: fix parsing as text.
- // Suggest writing a ParserConfiguration with an appropriate Scanner,
- // so that it will be parallel to how we treat parsing as XML
- else if (parse.equals(XINCLUDE_PARSE_TEXT)) {
- // TODO: This is what the spec says on encoding. Make sure it is being done.
- // The encoding of such a resource is determined by:
- // * external encoding information, if available, otherwise
- // * if the media type of the resource is text/xml, application/xml, or matches the conventions text/*+xml or application/*+xml as described in XML Media Types [IETF RFC 3023], the encoding is recognized as specified in XML 1.0, otherwise
- // * the value of the encoding attribute if one exists, otherwise
- // * UTF-8.
- // Byte sequences outside the range allowed by the encoding are a fatal error. Characters that are not permitted in XML documents also are a fatal error.
-
- // encoding only matters when parse="text"
- String encoding = attributes.getValue(XINCLUDE_ATTR_ENCODING);
- if (encoding != null) {
- includedSource.setEncoding(encoding);
- }
-
- String systemId = includedSource.getSystemId();
- InputStreamReader reader = null;
- try {
- URL url = this.createURL(includedSource);
- if (encoding != null) {
- reader = new InputStreamReader(url.openStream(), encoding);
- }
- else {
- reader = new InputStreamReader(url.openStream(), "UTF-8");
- }
-
- XMLStringBuffer buffer = new XMLStringBuffer();
- while (reader.ready()) {
- buffer.append((char)reader.read());
- }
- if (fDocumentHandler != null) {
- fDocumentHandler.characters(
- buffer,
- modifyAugmentations(null, true));
- }
- reader.close();
- }
- catch (IOException e) {
- throw new XIncludeResourceError(
- "TextResourceError",
- new Object[] { e.getMessage()});
- }
- }
- else {
- reportFatalError("InvalidParseValue", new Object[] { parse });
- }
- }
-
public void endElement(QName element, Augmentations augs)
throws XNIException {
@@ -789,14 +688,446 @@
return fDocumentSource;
}
+ // DTDHandler methods
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.XMLDTDHandler#attributeDecl(java.lang.String, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, org.apache.xerces.xni.XMLString, org.apache.xerces.xni.XMLString, org.apache.xerces.xni.Augmentations)
+ */
+ public void attributeDecl(
+ String elementName,
+ String attributeName,
+ String type,
+ String[] enumeration,
+ String defaultType,
+ XMLString defaultValue,
+ XMLString nonNormalizedDefaultValue,
+ Augmentations augmentations)
+ throws XNIException {
+ if (fDTDHandler != null) {
+ fDTDHandler.attributeDecl(
+ elementName,
+ attributeName,
+ type,
+ enumeration,
+ defaultType,
+ defaultValue,
+ nonNormalizedDefaultValue,
+ augmentations);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.XMLDTDHandler#elementDecl(java.lang.String, java.lang.String, org.apache.xerces.xni.Augmentations)
+ */
+ public void elementDecl(
+ String name,
+ String contentModel,
+ Augmentations augmentations)
+ throws XNIException {
+ if (fDTDHandler != null) {
+ fDTDHandler.elementDecl(name, contentModel, augmentations);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.XMLDTDHandler#endAttlist(org.apache.xerces.xni.Augmentations)
+ */
+ public void endAttlist(Augmentations augmentations) throws XNIException {
+ if (fDTDHandler != null) {
+ fDTDHandler.endAttlist(augmentations);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.XMLDTDHandler#endConditional(org.apache.xerces.xni.Augmentations)
+ */
+ public void endConditional(Augmentations augmentations)
+ throws XNIException {
+ if (fDTDHandler != null) {
+ fDTDHandler.endConditional(augmentations);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.XMLDTDHandler#endDTD(org.apache.xerces.xni.Augmentations)
+ */
+ public void endDTD(Augmentations augmentations) throws XNIException {
+ if (fDTDHandler != null) {
+ fDTDHandler.endDTD(augmentations);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.XMLDTDHandler#endExternalSubset(org.apache.xerces.xni.Augmentations)
+ */
+ public void endExternalSubset(Augmentations augmentations)
+ throws XNIException {
+ if (fDTDHandler != null) {
+ fDTDHandler.endExternalSubset(augmentations);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.XMLDTDHandler#endParameterEntity(java.lang.String, org.apache.xerces.xni.Augmentations)
+ */
+ public void endParameterEntity(String name, Augmentations augmentations)
+ throws XNIException {
+ if (fDTDHandler != null) {
+ fDTDHandler.endParameterEntity(name, augmentations);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.XMLDTDHandler#externalEntityDecl(java.lang.String, org.apache.xerces.xni.XMLResourceIdentifier, org.apache.xerces.xni.Augmentations)
+ */
+ public void externalEntityDecl(
+ String name,
+ XMLResourceIdentifier identifier,
+ Augmentations augmentations)
+ throws XNIException {
+ if (fDTDHandler != null) {
+ fDTDHandler.externalEntityDecl(name, identifier, augmentations);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.XMLDTDHandler#getDTDSource()
+ */
+ public XMLDTDSource getDTDSource() {
+ return fDTDSource;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.XMLDTDHandler#ignoredCharacters(org.apache.xerces.xni.XMLString, org.apache.xerces.xni.Augmentations)
+ */
+ public void ignoredCharacters(XMLString text, Augmentations augmentations)
+ throws XNIException {
+ if (fDTDHandler != null) {
+ fDTDHandler.ignoredCharacters(text, augmentations);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.XMLDTDHandler#internalEntityDecl(java.lang.String, org.apache.xerces.xni.XMLString, org.apache.xerces.xni.XMLString, org.apache.xerces.xni.Augmentations)
+ */
+ public void internalEntityDecl(
+ String name,
+ XMLString text,
+ XMLString nonNormalizedText,
+ Augmentations augmentations)
+ throws XNIException {
+ if (fDTDHandler != null) {
+ fDTDHandler.internalEntityDecl(
+ name,
+ text,
+ nonNormalizedText,
+ augmentations);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.XMLDTDHandler#notationDecl(java.lang.String, org.apache.xerces.xni.XMLResourceIdentifier, org.apache.xerces.xni.Augmentations)
+ */
+ public void notationDecl(
+ String name,
+ XMLResourceIdentifier identifier,
+ Augmentations augmentations)
+ throws XNIException {
+ this.addNotation(name, identifier, augmentations);
+ if (fDTDHandler != null) {
+ fDTDHandler.notationDecl(name, identifier, augmentations);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.XMLDTDHandler#setDTDSource(org.apache.xerces.xni.parser.XMLDTDSource)
+ */
+ public void setDTDSource(XMLDTDSource source) {
+ fDTDSource = source;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.XMLDTDHandler#startAttlist(java.lang.String, org.apache.xerces.xni.Augmentations)
+ */
+ public void startAttlist(String elementName, Augmentations augmentations)
+ throws XNIException {
+ if (fDTDHandler != null) {
+ fDTDHandler.startAttlist(elementName, augmentations);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.XMLDTDHandler#startConditional(short, org.apache.xerces.xni.Augmentations)
+ */
+ public void startConditional(short type, Augmentations augmentations)
+ throws XNIException {
+ if (fDTDHandler != null) {
+ fDTDHandler.startConditional(type, augmentations);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.XMLDTDHandler#startDTD(org.apache.xerces.xni.XMLLocator, org.apache.xerces.xni.Augmentations)
+ */
+ public void startDTD(XMLLocator locator, Augmentations augmentations)
+ throws XNIException {
+ if (fDTDHandler != null) {
+ fDTDHandler.startDTD(locator, augmentations);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.XMLDTDHandler#startExternalSubset(org.apache.xerces.xni.XMLResourceIdentifier, org.apache.xerces.xni.Augmentations)
+ */
+ public void startExternalSubset(
+ XMLResourceIdentifier identifier,
+ Augmentations augmentations)
+ throws XNIException {
+ if (fDTDHandler != null) {
+ fDTDHandler.startExternalSubset(identifier, augmentations);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.XMLDTDHandler#startParameterEntity(java.lang.String, org.apache.xerces.xni.XMLResourceIdentifier, java.lang.String, org.apache.xerces.xni.Augmentations)
+ */
+ public void startParameterEntity(
+ String name,
+ XMLResourceIdentifier identifier,
+ String encoding,
+ Augmentations augmentations)
+ throws XNIException {
+ if (fDTDHandler != null) {
+ fDTDHandler.startParameterEntity(
+ name,
+ identifier,
+ encoding,
+ augmentations);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.XMLDTDHandler#unparsedEntityDecl(java.lang.String, org.apache.xerces.xni.XMLResourceIdentifier, java.lang.String, org.apache.xerces.xni.Augmentations)
+ */
+ public void unparsedEntityDecl(
+ String name,
+ XMLResourceIdentifier identifier,
+ String notation,
+ Augmentations augmentations)
+ throws XNIException {
+ this.addUnparsedEntity(name, identifier, notation, augmentations);
+ if (fDTDHandler != null) {
+ fDTDHandler.unparsedEntityDecl(
+ name,
+ identifier,
+ notation,
+ augmentations);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.parser.XMLDTDSource#getDTDHandler()
+ */
+ public XMLDTDHandler getDTDHandler() {
+ return fDTDHandler;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.xerces.xni.parser.XMLDTDSource#setDTDHandler(org.apache.xerces.xni.XMLDTDHandler)
+ */
+ public void setDTDHandler(XMLDTDHandler handler) {
+ fDTDHandler = handler;
+ }
+
+ // XIncludeHandler methods
+
+ private void setErrorReporter(XMLErrorReporter reporter) {
+ fErrorReporter = reporter;
+ if (fErrorReporter != null) {
+ fErrorReporter.putMessageFormatter(
+ XIncludeMessageFormatter.XINCLUDE_DOMAIN,
+ new XIncludeMessageFormatter());
+ }
+ }
+
+ protected void handleFallbackElement() {
+ setSawInclude(fDepth, false);
+ fNamespaceContext.setContextInvalid();
+ if (!getSawInclude(fDepth - 1)) {
+ reportFatalError("FallbackParent");
+ }
+
+ if (getSawFallback(fDepth)) {
+ reportFatalError("MultipleFallbacks");
+ }
+ else {
+ setSawFallback(fDepth, true);
+ }
+
+ // either the state is STATE_EXPECT_FALLBACK or it's STATE_IGNORE
+ // if we're ignoring, we want to stay ignoring. But if we're expecting this fallback element,
+ // we want to signal that we should process the children
+ if (getState() == STATE_EXPECT_FALLBACK) {
+ setState(STATE_NORMAL_PROCESSING);
+ }
+ }
+
+ protected void handleIncludeElement(XMLAttributes attributes)
+ throws XNIException {
+ setSawInclude(fDepth, true);
+ fNamespaceContext.setContextInvalid();
+ if (getSawInclude(fDepth - 1)) {
+ reportFatalError("IncludeChild", new Object[] { XINCLUDE_INCLUDE });
+ }
+ if (getState() == STATE_IGNORE)
+ return;
+
+ String href = attributes.getValue(XINCLUDE_ATTR_HREF);
+ String parse = attributes.getValue(XINCLUDE_ATTR_PARSE);
+
+ if (href == null) {
+ reportFatalError("HrefMissing");
+ }
+ if (parse == null) {
+ parse = XINCLUDE_PARSE_XML;
+ }
+
+ XMLResourceIdentifier resourceIdentifier =
+ new XMLResourceIdentifierImpl(
+ null,
+ href,
+ fDocLocation.getBaseSystemId(),
+ null);
+
+ XMLInputSource includedSource = null;
+ if (fEntityResolver != null) {
+ try {
+ includedSource =
+ fEntityResolver.resolveEntity(resourceIdentifier);
+ }
+ catch (IOException e) {
+ throw new XIncludeResourceError(
+ "XMLResourceError",
+ new Object[] { e.getMessage()});
+ }
+ }
+
+ if (includedSource == null) {
+ includedSource =
+ new XMLInputSource(null, href, fDocLocation.getBaseSystemId());
+ }
+
+ if (parse.equals(XINCLUDE_PARSE_XML)) {
+ // Instead of always creating a new configuration, the first one can be reused
+ if (fChildConfig == null) {
+ String parserName = XINCLUDE_DEFAULT_CONFIGURATION;
+
+ fChildConfig =
+ (XMLParserConfiguration)ObjectFactory.newInstance(
+ parserName,
+ ObjectFactory.findClassLoader(),
+ true);
+
+ // use the same error reporter
+ fChildConfig.setProperty(ERROR_REPORTER, fErrorReporter);
+ // use the same namespace context
+ fChildConfig.setProperty(
+ Constants.XERCES_PROPERTY_PREFIX
+ + Constants.NAMESPACE_CONTEXT_PROPERTY,
+ fNamespaceContext);
+
+ XIncludeHandler newHandler = (XIncludeHandler)fChildConfig.getProperty(
+ Constants.XERCES_PROPERTY_PREFIX
+ + Constants.XINCLUDE_HANDLER_PROPERTY);
+ newHandler.setParent(this);
+ newHandler.setDocumentHandler(this.getDocumentHandler());
+ }
+
+ // set all features on parserConfig to match this parser configuration
+ Enumeration xercesFeatures = Constants.getXercesFeatures();
+ while (xercesFeatures.hasMoreElements()) {
+ String featureId = (String)xercesFeatures.nextElement();
+ try {
+ fChildConfig.setFeature(
+ featureId,
+ fSettings.getFeature(featureId));
+ }
+ catch (XMLConfigurationException e) {
+ // parserConfig doesn't support this feature,
+ // so we won't worry about it
+ }
+ }
+
+ // we don't want a schema validator on the new pipeline
+ fChildConfig.setFeature(
+ Constants.XERCES_FEATURE_PREFIX
+ + Constants.SCHEMA_VALIDATION_FEATURE,
+ false);
+
+ try {
+ fNamespaceContext.pushScope();
+ fChildConfig.parse(includedSource);
+ }
+ catch (XIncludeFatalError e) {
+ reportFatalError(e.getKey(), e.getArgs());
+ }
+ catch (XNIException e) {
+ reportFatalError("XMLParseError");
+ }
+ catch (IOException e) {
+ throw new XIncludeResourceError(
+ "XMLResourceError",
+ new Object[] { e.getMessage()});
+ }
+ finally {
+ fNamespaceContext.popScope();
+ }
+ }
+ else if (parse.equals(XINCLUDE_PARSE_TEXT)) {
+ String encoding = attributes.getValue(XINCLUDE_ATTR_ENCODING);
+ includedSource.setEncoding(encoding);
+
+ XIncludeTextReader reader = null;
+ try {
+ reader = new XIncludeTextReader(includedSource, this);
+ reader.parse();
+ }
+ catch (IOException e) {
+ throw new XIncludeResourceError(
+ "TextResourceError",
+ new Object[] { e.getMessage()});
+ }
+ finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ }
+ catch (IOException e) {
+ throw new XIncludeResourceError(
+ "TextResourceError",
+ new Object[] { e.getMessage()});
+ }
+ }
+ }
+ }
+ else {
+ reportFatalError("InvalidParseValue", new Object[] { parse });
+ }
+ }
+
+ protected boolean hasXIncludeNamespace(QName element) {
+ return element.uri == XINCLUDE_NS_URI
+ || fNamespaceContext.getURI(element.prefix) == XINCLUDE_NS_URI;
+ }
+
protected boolean isIncludeElement(QName element) {
return element.localpart.equals(XINCLUDE_INCLUDE)
- && fNamespaceContext.getURI(element.prefix).equals(XINCLUDE_NS_URI);
+ && hasXIncludeNamespace(element);
}
protected boolean isFallbackElement(QName element) {
return element.localpart.equals(XINCLUDE_FALLBACK)
- && fNamespaceContext.getURI(element.prefix).equals(XINCLUDE_NS_URI);
+ && hasXIncludeNamespace(element);
}
protected boolean sameBaseURISourceAsParent() {
@@ -805,8 +1136,17 @@
// We test if the included file is in the same directory as it's parent
// by creating a new URL, with the filename of the included file and the
// base of the parent, and checking if it is the same file as the included file
- URL input = createURL(fDocLocation);
- URL parent = createURL(fParentXIncludeHandler.fDocLocation);
+ // TODO: does Java use IURIs by default?
+ // [Definition: An internationalized URI reference, or IURI, is a URI reference that directly uses [Unicode] characters.]
+ // TODO: figure out what section 4.1.1 of the XInclude spec is talking about
+ // has to do with disallowed ASCII character escaping
+ // this ties in with the above IURI section, but I suspect Java already does it
+ URL input = new URL(fDocLocation.getExpandedSystemId());
+ URL parent =
+ new URL(
+ fParentXIncludeHandler
+ .fDocLocation
+ .getExpandedSystemId());
URL test = new URL(parent, new File(input.getFile()).getName());
return input.sameFile(test);
}
@@ -829,14 +1169,7 @@
false);
}
catch (MalformedURIException e) {
- reportFatalError("ExpandedSystemId");
- // returning false opens the possibility of attempting an infinite
- // recursive parse, in the case when:
- // we can't resolve the system id
- // AND continue-after-fatal-error is set
- // AND there is actually a recursive parse.
- // But that's probably a pretty slim chance.
- return false;
+ throw new XIncludeFatalError("ExpandedSystemId", null);
}
}
@@ -864,6 +1197,20 @@
return getSawFallback(fDepth - 1);
}
+ /**
+ * Processes the XMLAttributes object of startElement() calls. Performs the following tasks:
+ * <ul>
+ * <li> If the element is a top level included item whose [base URI] is different from the
+ * [base URI] of the include parent, then an xml:base attribute is added to specify the
+ * true [base URI]
+ * <li> For all namespace prefixes which are in-scope in an included item, but not in scope
+ * in the include parent, a xmlns:prefix attribute is added
+ * <li> For all attributes with a type of ENTITY, ENTITIES or NOTATIONS, the notations and
+ * unparsed entities are processed as described in the spec, sections 4.5.1 and 4.5.2
+ * </ul>
+ * @param attributes
+ * @return
+ */
protected XMLAttributes processAttributes(XMLAttributes attributes) {
if (isTopLevelIncludedItem()) {
// Modify attributes to fix the base URI (spec 4.5.5).
@@ -876,24 +1223,36 @@
// this causes errors with schema validation, since the schema doesn't specify that these elements can have an xml:base attribute
// TODO: add a user option to turn this off?
+ // TODO: make this a relative URL, when possible
+ // TODO: [base URI] is still an open issue with the working group.
+ // They're deciding if xml:base should be added if the [base URI] is different in terms
+ // of resolving relative references, or if it should be added if they are different at all.
+ // Revisit this after a final decision has been made.
+ // TODO: Output a relative URI instead of an absolute one.
int index =
attributes.addAttribute(
XML_BASE_QNAME,
XMLSymbols.fCDATASymbol,
- this.fDocLocation.getBaseSystemId());
+ fDocLocation.getBaseSystemId());
attributes.setSpecified(index, true);
}
// Modify attributes of included items to do namespace-fixup. (spec 4.5.4)
+ // TODO: worry about null namespace?
Enumeration inscopeNS = fNamespaceContext.getAllPrefixes();
while (inscopeNS.hasMoreElements()) {
String prefix = (String)inscopeNS.nextElement();
String parentURI =
fNamespaceContext.getURIFromIncludeParent(prefix);
String uri = fNamespaceContext.getURI(prefix);
- if (attributes.getValue(NamespaceContext.XMLNS_URI, prefix)
- == null
- && parentURI != uri) {
+ if (parentURI != uri
+ && (attributes != null
+ && attributes.getValue(NamespaceContext.XMLNS_URI, prefix)
+ == null)) {
+ if (attributes == null) {
+ attributes = new XMLAttributesImpl();
+ }
+
QName ns = (QName)NEW_NS_ATTR_QNAME.clone();
ns.localpart = prefix;
ns.rawname += prefix;
@@ -907,30 +1266,26 @@
for (int i = 0; i < length; i++) {
String type = attributes.getType(i);
String value = attributes.getValue(i);
- if (checkGrammar()) {
- // TODO: 4.5.1
- if (type == XMLSymbols.fENTITYSymbol) {
-
- }
- if (type == XMLSymbols.fENTITIESSymbol) {
-
- }
- else if (type == XMLSymbols.fNOTATIONSymbol) {
- // TODO: 4.5.2
- // Obtain [notations] property from DTD grammar
- // TODO: 4.5.2 -- don't forget about searching unparsed entities for notations, too
+ if (type == XMLSymbols.fENTITYSymbol) {
+ this.checkUnparsedEntity(value);
+ }
+ if (type == XMLSymbols.fENTITIESSymbol) {
+ // 4.5.1 - Unparsed Entities
+ StringTokenizer st = new StringTokenizer(value);
+ while (st.hasMoreTokens()) {
+ String entName = st.nextToken();
+ this.checkUnparsedEntity(entName);
}
}
+ else if (type == XMLSymbols.fNOTATIONSymbol) {
+ // 4.5.2 - Notations
+ this.checkNotation(value);
+ }
/* We actually don't need to do anything for 4.5.3, because at this stage the
* value of the attribute is just a string. It will be taken care of later
- * in the pipeline, when the IDREFs are actually resolved against elements.
- *
- * TODO: what about when XInclude processing comes after schema validation?
+ * in the pipeline, when the IDREFs are actually resolved against IDs.
*
- * if (type == XMLSymbols.fIDREFSymbol
- * || type == XMLSymbols.fIDREFSSymbol) {
- * // look at ValidationState for IDREFs (it should be a property)
- * }
+ * if (type == XMLSymbols.fIDREFSymbol || type == XMLSymbols.fIDREFSSymbol) { }
*/
}
}
@@ -954,72 +1309,67 @@
return augs;
}
- protected Integer getState(int val) {
- return (Integer)this.fState.elementAt(val);
+ protected int getState(int depth) {
+ return fState[depth];
}
- protected Integer getState() {
- return this.getState(fDepth);
+ protected int getState() {
+ return fState[fDepth];
}
- protected void setState(Integer state) {
- while (fDepth >= fState.size()) {
- this.fState.add(STATE_NORMAL_PROCESSING);
+ protected void setState(int state) {
+ if (fDepth >= fState.length) {
+ int[] newarray = new int[fDepth * 2];
+ System.arraycopy(fState, 0, newarray, 0, fState.length);
+ fState = newarray;
}
- this.fState.set(fDepth, state);
+ fState[fDepth] = state;
}
protected void setSawFallback(int depth, boolean val) {
- this.setSawFallback(depth, val ? Boolean.TRUE : Boolean.FALSE);
- }
-
- protected void setSawFallback(int depth, Boolean val) {
- while (depth >= fSawFallback.size()) {
- this.fSawFallback.add(Boolean.FALSE);
+ if (depth >= fSawFallback.length) {
+ boolean[] newarray = new boolean[depth * 2];
+ System.arraycopy(fSawFallback, 0, newarray, 0, fSawFallback.length);
+ fSawFallback = newarray;
}
- this.fSawFallback.set(depth, val);
+ fSawFallback[depth] = val;
}
protected boolean getSawFallback(int depth) {
- if (depth >= this.fSawFallback.size()) {
+ if (depth >= fSawFallback.length) {
return false;
}
- return ((Boolean)this.fSawFallback.elementAt(depth)).booleanValue();
+ return fSawFallback[depth];
}
+ /**
+ * Records that an <include> was encountered at the specified depth,
+ * as an ancestor of the current item.
+ *
+ * @param depth
+ * @param val
+ */
protected void setSawInclude(int depth, boolean val) {
- this.setSawInclude(depth, val ? Boolean.TRUE : Boolean.FALSE);
- }
-
- protected void setSawInclude(int depth, Boolean val) {
- while (depth >= fSawInclude.size()) {
- this.fSawInclude.add(Boolean.FALSE);
+ if (depth >= fSawInclude.length) {
+ boolean[] newarray = new boolean[depth * 2];
+ System.arraycopy(fSawInclude, 0, newarray, 0, fSawInclude.length);
+ fSawInclude = newarray;
}
- this.fSawInclude.set(depth, val);
+ fSawInclude[depth] = val;
}
+ /**
+ * Return whether an <include> was encountered at the specified depth,
+ * as an ancestor of the current item.
+ *
+ * @param depth
+ * @return
+ */
protected boolean getSawInclude(int depth) {
- if (depth >= this.fSawInclude.size()) {
+ if (depth >= fSawInclude.length) {
return false;
}
- return ((Boolean)this.fSawInclude.elementAt(depth)).booleanValue();
- }
-
- // TODO: this method really doesn't belong here; it's only temporary to make text include work
- // see comment about XINCLUDE_PARSE_TEXT
- // TODO: does Java use IURIs by default?
- // [Definition: An internationalized URI reference, or IURI, is a URI reference that directly uses [Unicode] characters.]
- // TODO: figure out what section 4.1.1 of the XInclude spec is talking about
- // has to do with disallowed ASCII character escaping
- // this ties in with the above IURI section, but I suspect Java already does it
- private URL createURL(XMLLocator source) throws MalformedURLException {
- return new URL(
- new URL(source.getBaseSystemId()),
- source.getExpandedSystemId());
- }
-
- private URL createURL(XMLInputSource source) throws MalformedURLException {
- return new URL(new URL(source.getBaseSystemId()), source.getSystemId());
+ return fSawInclude[depth];
}
protected void reportFatalError(String key) {
@@ -1039,33 +1389,283 @@
// at least the default error reporter
}
+ /**
+ * Set the parent of this XIncludeHandler in the tree
+ * @param parent
+ */
protected void setParent(XIncludeHandler parent) {
- this.fParentXIncludeHandler = parent;
+ fParentXIncludeHandler = parent;
}
// used to know whether to pass declarations to the document handler
protected boolean isRootDocument() {
- return this.fParentXIncludeHandler == null;
+ return fParentXIncludeHandler == null;
}
- private boolean checkGrammar() {
- /* System.err.println("checking grammar");
- if (fDTDGrammar == null) {
- System.err.println("grammar is null");
- if (fGrammarDesc == null || fGrammarPool == null) {
- System.err.println("bailed out");
- return false;
- }
- fDTDGrammar =
- (DTDGrammar)fGrammarPool.retrieveGrammar(fGrammarDesc);
- System.err.println(fDTDGrammar);
- return fDTDGrammar != null;
- }
- else {
- System.err.println("have grammar!");
- return true;
+ /**
+ * Caches an unparsed entity.
+ * @param name the name of the unparsed entity
+ * @param identifier the location of the unparsed entity
+ * @param augmentations any Augmentations that were on the original unparsed entity declaration
+ */
+ protected void addUnparsedEntity(
+ String name,
+ XMLResourceIdentifier identifier,
+ String notation,
+ Augmentations augmentations) {
+ UnparsedEntity ent = new UnparsedEntity();
+ ent.name = name;
+ ent.systemId = identifier.getLiteralSystemId();
+ ent.publicId = identifier.getPublicId();
+ ent.baseURI = identifier.getBaseSystemId();
+ ent.notation = notation;
+ ent.augmentations = augmentations;
+ fUnparsedEntities.add(ent);
+ }
+
+ /**
+ * Caches a notation.
+ * @param name the name of the notation
+ * @param identifier the location of the notation
+ * @param augmentations any Augmentations that were on the original notation declaration
+ */
+ protected void addNotation(
+ String name,
+ XMLResourceIdentifier identifier,
+ Augmentations augmentations) {
+ Notation not = new Notation();
+ not.name = name;
+ not.systemId = identifier.getLiteralSystemId();
+ not.publicId = identifier.getPublicId();
+ not.baseURI = identifier.getBaseSystemId();
+ not.augmentations = augmentations;
+ fNotations.add(not);
+ }
+
+ /**
+ * Checks if an UnparsedEntity with the given name was declared in the DTD of the document
+ * for the current pipeline. If so, then the notation for the UnparsedEntity is checked.
+ * If that turns out okay, then the UnparsedEntity is passed to the root pipeline to
+ * be checked for conflicts, and sent to the root DTDHandler.
+ *
+ * @param entName the name of the UnparsedEntity to check
+ */
+ protected void checkUnparsedEntity(String entName) {
+ UnparsedEntity ent = new UnparsedEntity();
+ ent.name = entName;
+ int index = fUnparsedEntities.indexOf(ent);
+ if (index != -1) {
+ ent = (UnparsedEntity)fUnparsedEntities.get(index);
+ // first check the notation of the unparsed entity
+ try {
+ checkNotation(ent.notation);
+ }
+ catch (XIncludeFatalError e) {
+ reportFatalError(e.getKey(), e.getArgs());
+ }
+
+ try {
+ checkAndSendUnparsedEntity(ent);
+ }
+ catch (XIncludeFatalError e) {
+ reportFatalError(e.getKey(), e.getArgs());
+ }
+ }
+ }
+
+ /**
+ * Checks if a Notation with the given name was declared in the DTD of the document
+ * for the current pipeline. If so, that Notation is passed to the root pipeline to
+ * be checked for conflicts, and sent to the root DTDHandler
+ *
+ * @param notName the name of the Notation to check
+ */
+ protected void checkNotation(String notName) {
+ Notation not = new Notation();
+ not.name = notName;
+ int index = fNotations.indexOf(not);
+ if (index != -1) {
+ not = (Notation)fNotations.get(index);
+ try {
+ checkAndSendNotation(not);
+ }
+ catch (XIncludeFatalError e) {
+ reportFatalError(e.getKey(), e.getArgs());
+ }
+ }
+ }
+
+ /**
+ * The purpose of this method is to check if an UnparsedEntity conflicts with a previously
+ * declared entity in the current pipeline stack. If there is no conflict, the
+ * UnparsedEntity is sent by the root pipeline.
+ *
+ * @param ent the UnparsedEntity to check for conflicts
+ * @throws XIncludeFatalError if there is an UnparsedEntity conflict as described in 4.5.1
+ */
+ protected void checkAndSendUnparsedEntity(UnparsedEntity ent)
+ throws XIncludeFatalError {
+ if (isRootDocument()) {
+ int index = fUnparsedEntities.indexOf(ent);
+ if (index == -1) {
+ // There is no unparsed entity with the same name that we have sent.
+ // Calling unparsedEntityDecl() will add the entity to our local store,
+ // and also send the unparsed entity to the DTDHandler
+ XMLResourceIdentifier id =
+ new XMLResourceIdentifierImpl(
+ ent.publicId,
+ ent.systemId,
+ ent.baseURI,
+ null);
+ this.addUnparsedEntity(
+ ent.name,
+ id,
+ ent.notation,
+ ent.augmentations);
+ if (fSendUEAndNotationEvents && fDTDHandler != null) {
+ fDTDHandler.unparsedEntityDecl(
+ ent.name,
+ id,
+ ent.notation,
+ ent.augmentations);
+ }
+ }
+ else {
+ UnparsedEntity localEntity =
+ (UnparsedEntity)fUnparsedEntities.get(index);
+ if (!ent.isDuplicate(localEntity)) {
+ throw new XIncludeFatalError(
+ "NonDuplicateUnparsedEntity",
+ new Object[] { ent.name });
}
- */
- return false;
+ }
+ }
+ else {
+ fParentXIncludeHandler.checkAndSendUnparsedEntity(ent);
+ }
+ }
+
+ /**
+ * The purpose of this method is to check if a Notation conflicts with a previously
+ * declared notation in the current pipeline stack. If there is no conflict, the
+ * Notation is sent by the root pipeline.
+ *
+ * @param not the Notation to check for conflicts
+ * @throws XIncludeFatalError if there is a Notation conflict as described in 4.5.2
+ */
+ protected void checkAndSendNotation(Notation not)
+ throws XIncludeFatalError {
+ if (isRootDocument()) {
+ int index = fNotations.indexOf(not);
+ if (index == -1) {
+ // There is no notation with the same name that we have sent.
+ XMLResourceIdentifier id =
+ new XMLResourceIdentifierImpl(
+ not.publicId,
+ not.systemId,
+ not.baseURI,
+ null);
+ this.addNotation(not.name, id, not.augmentations);
+ if (fSendUEAndNotationEvents && fDTDHandler != null) {
+ fDTDHandler.notationDecl(not.name, id, not.augmentations);
+ }
+ }
+ else {
+ Notation localNotation = (Notation)fNotations.get(index);
+ if (!not.isDuplicate(localNotation)) {
+ throw new XIncludeFatalError(
+ "NonDuplicateNotation",
+ new Object[] { not.name });
+ }
+ }
+ }
+ else {
+ fParentXIncludeHandler.checkAndSendNotation(not);
+ }
+ }
+
+ // This is a storage class to hold information about the notations.
+ // We're not using XMLNotationDecl because we don't want to lose the augmentations.
+ protected class Notation {
+ public String name;
+ public String systemId;
+ public String baseURI;
+ public String publicId;
+ public Augmentations augmentations;
+
+ // equals() returns true if two Notations have the same name.
+ // Useful for searching Vectors for notations with the same name
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj instanceof Notation) {
+ Notation other = (Notation)obj;
+ return name.equals(other.name);
+ }
+ return false;
+ }
+
+ // from 4.5.2
+ // Notation items with the same [name], [system identifier],
+ // [public identifier], and [declaration base URI] are considered
+ // to be duplicate
+ public boolean isDuplicate(Object obj) {
+ if (obj != null && obj instanceof Notation) {
+ Notation other = (Notation)obj;
+ return name.equals(other.name)
+ && (systemId == other.systemId
+ || (systemId != null && systemId.equals(other.systemId)))
+ && (publicId == other.publicId
+ || (publicId != null && publicId.equals(other.publicId)))
+ && (baseURI == other.baseURI
+ || (baseURI != null && baseURI.equals(other.baseURI)));
+ }
+ return false;
+ }
+ }
+
+ // This is a storage class to hold information about the unparsed entities.
+ // We're not using XMLEntityDecl because we don't want to lose the augmentations.
+ protected class UnparsedEntity {
+ public String name;
+ public String systemId;
+ public String baseURI;
+ public String publicId;
+ public String notation;
+ public Augmentations augmentations;
+
+ // equals() returns true if two UnparsedEntities have the same name.
+ // Useful for searching Vectors for entities with the same name
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj instanceof UnparsedEntity) {
+ UnparsedEntity other = (UnparsedEntity)obj;
+ return name.equals(other.name);
+ }
+ return false;
+ }
+
+ // from 4.5.1:
+ // Unparsed entity items with the same [name], [system identifier],
+ // [public identifier], [declaration base URI], [notation name], and
+ // [notation] are considered to be duplicate
+ public boolean isDuplicate(Object obj) {
+ if (obj != null && obj instanceof UnparsedEntity) {
+ UnparsedEntity other = (UnparsedEntity)obj;
+ return name.equals(other.name)
+ && (systemId == other.systemId
+ || (systemId != null && systemId.equals(other.systemId)))
+ && (publicId == other.publicId
+ || (publicId != null && publicId.equals(other.publicId)))
+ && (baseURI == other.baseURI
+ || (baseURI != null && baseURI.equals(other.baseURI)))
+ && (notation == other.notation
+ || (notation != null && notation.equals(other.notation)));
+ }
+ return false;
+ }
}
} // class XIncludeHandler
1.2 +1 -1 xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeMessageFormatter.java
Index: XIncludeMessageFormatter.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeMessageFormatter.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- XIncludeMessageFormatter.java 25 Jun 2003 00:50:29 -0000 1.1
+++ XIncludeMessageFormatter.java 18 Jul 2003 17:34:38 -0000 1.2
@@ -49,7 +49,7 @@
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
- * originally based on software copyright (c) 2001, International
+ * originally based on software copyright (c) 2003, International
* Business Machines, Inc., http://www.apache.org. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
1.2 +1 -1 xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeNamespaceSupport.java
Index: XIncludeNamespaceSupport.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeNamespaceSupport.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- XIncludeNamespaceSupport.java 25 Jun 2003 00:50:59 -0000 1.1
+++ XIncludeNamespaceSupport.java 18 Jul 2003 17:34:38 -0000 1.2
@@ -49,7 +49,7 @@
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
- * originally based on software copyright (c) 1999, International
+ * originally based on software copyright (c) 2003, International
* Business Machines, Inc., http://www.apache.org. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
1.2 +1 -3 xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeResourceError.java
Index: XIncludeResourceError.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeResourceError.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- XIncludeResourceError.java 25 Jun 2003 00:52:44 -0000 1.1
+++ XIncludeResourceError.java 18 Jul 2003 17:34:38 -0000 1.2
@@ -49,14 +49,12 @@
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
- * originally based on software copyright (c) 1999, International
+ * originally based on software copyright (c) 2003, International
* Business Machines, Inc., http://www.apache.org. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.xerces.xinclude;
-
-import org.apache.xerces.xni.XNIException;
/**
* @author Peter McCracken, IBM
1.1 xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeTextReader.java
Index: XIncludeTextReader.java
===================================================================
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2001-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 2003, International
* Business Machines, Inc., http://www.apache.org. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.xerces.xinclude;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
import org.apache.xerces.util.XMLStringBuffer;
import org.apache.xerces.xni.parser.XMLInputSource;
/**
* @author Peter McCracken, IBM
* @author Arun Yadav, Sun Microsystem
*/
public class XIncludeTextReader {
private Reader fReader;
private XIncludeHandler fHandler;
private XMLInputSource fSource;
private boolean fCheckBOM = false;
/**
* Construct the XIncludeReader using the XMLInputSource and XIncludeHandler.
*
* @param source The XMLInputSource to use.
* @param handler The XIncludeHandler to use.
*/
public XIncludeTextReader(XMLInputSource source, XIncludeHandler handler)
throws IOException {
fHandler = handler;
fSource = source;
}
/**
* Return the Reader for given XMLInputSource.
*
* @param source The XMLInputSource to use.
*/
protected Reader getReader(XMLInputSource source) throws IOException {
if (source.getCharacterStream() != null) {
return fReader = source.getCharacterStream();
}
else {
InputStream stream = null;
String encoding = source.getEncoding();
if (encoding == null) {
encoding = "UTF-8";
}
if (source.getByteStream() != null) {
stream = source.getByteStream();
}
else {
URL url =
new URL(
new URL(source.getBaseSystemId()),
source.getSystemId());
stream = url.openStream();
URLConnection urlCon = url.openConnection();
String charset = urlCon.getContentEncoding();
String contentType = urlCon.getContentType();
/** The encoding of such a resource is determined by:
1 external encoding information, if available, otherwise
-- the most common type of external information is the "charset" parameter of a MIME package
2 if the media type of the resource is text/xml, application/xml, or matches the conventions text/*+xml or application/*+xml as described in XML Media Types [IETF RFC 3023], the encoding is recognized as specified in XML 1.0, otherwise
3 the value of the encoding attribute if one exists, otherwise
4 UTF-8.
**/
if (charset != null) {
encoding = charset;
}
/* RFC2376 section 3.1: If text/xml entity is received with
charset parameter omitted, then MIME processors and XML processors
MUST use the default charset value of "us-ascii". */
else if (contentType.equals("text/xml")) {
encoding = "US-ASCII";
}
/* RFC2376 section 3.1: If text/xml entity is received with
charset parameter omitted, no information is provided about the
charset by the MIME Content-type header. Conforming XML processors
MUST follow the requirements in section 4.3.3 of [REC-XML].
*/
else if (contentType.equals("application/xml")) {
encoding = getEncodingName(stream);
}
else if (contentType.endsWith("+xml")) {
System.out.println("Not suppported");
// TODO: Error messages need to be defined.
}
//else 3 or 4.
}
return fReader = new InputStreamReader(stream, encoding);
}
}
protected String getEncodingName(InputStream stream) throws IOException {
final byte[] b4 = new byte[4];
int count = 0;
for (; count < 4; count++) {
b4[count] = (byte)stream.read();
}
Object[] encodinginfo = getEncodingName(b4, count);
// REVISIT: what to do if encodinginfo[1] == null
// Currently, this isn't a problem, since getEncodingName() will never
// return a null value, but the javadocs say it's possible.
if (encodinginfo[1] != null
&& !((Boolean)encodinginfo[1]).booleanValue()) {
stream.reset();
fCheckBOM = false;
}
else {
fCheckBOM = true;
}
return (String)encodinginfo[0];
}
/**
* REVISIT: This code is take from org.apache.xerces.impl.XMLEntityManager.
* Is there any way we can share the code, without having it implemented twice?
*
* Returns the IANA encoding name that is auto-detected from
* the bytes specified, with the endian-ness of that encoding where appropriate.
*
* @param b4 The first four bytes of the input.
* @param count The number of bytes actually read.
* @return a 2-element array: the first element, an IANA-encoding string,
* the second element a Boolean which is true iff the document is big endian, false
* if it's little-endian, and null if the distinction isn't relevant.
*/
protected Object[] getEncodingName(byte[] b4, int count) {
if (count < 2) {
return new Object[] { "UTF-8", new Boolean(false)};
}
// UTF-16, with BOM
int b0 = b4[0] & 0xFF;
int b1 = b4[1] & 0xFF;
if (b0 == 0xFE && b1 == 0xFF) {
// UTF-16, big-endian
return new Object[] { "UTF-16BE", new Boolean(true)};
}
if (b0 == 0xFF && b1 == 0xFE) {
// UTF-16, little-endian
return new Object[] { "UTF-16LE", new Boolean(true)};
}
// default to UTF-8 if we don't have enough bytes to make a
// good determination of the encoding
if (count < 3) {
return new Object[] { "UTF-8", new Boolean(false)};
}
// UTF-8 with a BOM
int b2 = b4[2] & 0xFF;
if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF) {
return new Object[] { "UTF-8", new Boolean(true)};
}
// default to UTF-8 if we don't have enough bytes to make a
// good determination of the encoding
if (count < 4) {
return new Object[] { "UTF-8", new Boolean(false)};
}
// other encodings
int b3 = b4[3] & 0xFF;
if (b0 == 0x00 && b1 == 0x00 && b2 == 0x00 && b3 == 0x3C) {
// UCS-4, big endian (1234), with BOM
return new Object[] { "ISO-10646-UCS-4", new Boolean(true)};
}
if (b0 == 0x3C && b1 == 0x00 && b2 == 0x00 && b3 == 0x00) {
// UCS-4, little endian (4321), with BOM
return new Object[] { "ISO-10646-UCS-4", new Boolean(true)};
}
if (b0 == 0x00 && b1 == 0x00 && b2 == 0x3C && b3 == 0x00) {
// UCS-4, unusual octet order (2143), with BOM
// REVISIT: What should this be?
return new Object[] { "ISO-10646-UCS-4", new Boolean(true)};
}
if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x00) {
// UCS-4, unusual octect order (3412), with BOM
// REVISIT: What should this be?
return new Object[] { "ISO-10646-UCS-4", new Boolean(true)};
}
if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F) {
// UTF-16, big-endian, no BOM
// (or could turn out to be UCS-2...
// REVISIT: What should this be?
return new Object[] { "UTF-16BE", new Boolean(false)};
}
if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00) {
// UTF-16, little-endian, no BOM
// (or could turn out to be UCS-2...
return new Object[] { "UTF-16LE", new Boolean(false)};
}
if (b0 == 0x4C && b1 == 0x6F && b2 == 0xA7 && b3 == 0x94) {
// EBCDIC, no BOM
// a la xerces1, return CP037 instead of EBCDIC here
return new Object[] { "CP037", new Boolean(false)};
}
if (b0 == 0x00 && b1 == 0x00 && b2 == 0x00 && b3 == 0x3C) {
// UCS-4, no BOM
//
return new Object[] { "UCS-4", new Boolean(false)};
}
// default encoding
return new Object[] { "UTF-8", new Boolean(false)};
} // getEncodingName(byte[],int):Object[]
public void parse() throws IOException {
XMLStringBuffer buffer = new XMLStringBuffer();
fReader = getReader(fSource);
if (fReader.ready()) {
// deal with byte order mark, see spec 4.3
if (!fCheckBOM) {
int bom = fReader.read();
// only include the character if it isn't the byte-order mark
if (bom != '\uFEFF') {
buffer.append((char)bom);
}
}
// REVISIT: We might want to consider sending the character events in chunks
// instead of reading them all. This would be a space hog for large
// text includes.
while (fReader.ready()) {
buffer.append((char)fReader.read());
}
if (fHandler != null) {
fHandler.characters(
buffer,
fHandler.modifyAugmentations(null, true));
}
}
}
public void close() throws IOException {
if (fReader != null) {
fReader.close();
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: xerces-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xerces-cvs-help@xml.apache.org