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 [EMAIL PROTECTED] * * 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: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]