aboutsummaryrefslogtreecommitdiff
path: root/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java')
-rw-r--r--src/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java3292
1 files changed, 0 insertions, 3292 deletions
diff --git a/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java b/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java
deleted file mode 100644
index 6d197c5..0000000
--- a/src/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java
+++ /dev/null
@@ -1,3292 +0,0 @@
-/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
- */
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.sun.org.apache.xerces.internal.impl;
-
-import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
-import com.sun.org.apache.xerces.internal.util.AugmentationsImpl;
-import com.sun.org.apache.xerces.internal.util.XMLAttributesIteratorImpl;
-import com.sun.org.apache.xerces.internal.util.XMLChar;
-import com.sun.org.apache.xerces.internal.util.XMLStringBuffer;
-import com.sun.org.apache.xerces.internal.util.XMLSymbols;
-import com.sun.org.apache.xerces.internal.utils.SecuritySupport;
-import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
-import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.Limit;
-import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
-import com.sun.org.apache.xerces.internal.xni.Augmentations;
-import com.sun.org.apache.xerces.internal.xni.QName;
-import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
-import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
-import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
-import com.sun.org.apache.xerces.internal.xni.XMLString;
-import com.sun.org.apache.xerces.internal.xni.XNIException;
-import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
-import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
-import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
-import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentScanner;
-import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
-import com.sun.xml.internal.stream.XMLBufferListener;
-import com.sun.xml.internal.stream.XMLEntityStorage;
-import com.sun.xml.internal.stream.dtd.DTDGrammarUtil;
-import java.io.EOFException;
-import java.io.IOException;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLStreamConstants;
-import javax.xml.stream.events.XMLEvent;
-
-
-/**
- *
- * This class is responsible for scanning the structure and content
- * of document fragments.
- *
- * This class has been modified as per the new design which is more suited to
- * efficiently build pull parser. Lot of improvements have been done and
- * the code has been added to support stax functionality/features.
- *
- * @author Neeraj Bajaj SUN Microsystems
- * @author K.Venugopal SUN Microsystems
- * @author Glenn Marcy, IBM
- * @author Andy Clark, IBM
- * @author Arnaud Le Hors, IBM
- * @author Eric Ye, IBM
- * @author Sunitha Reddy, SUN Microsystems
- * @version $Id: XMLDocumentFragmentScannerImpl.java,v 1.19 2010-11-02 19:54:55 joehw Exp $
- *
- */
-public class XMLDocumentFragmentScannerImpl
- extends XMLScanner
- implements XMLDocumentScanner, XMLComponent, XMLEntityHandler, XMLBufferListener {
-
- //
- // Constants
- //
-
- protected int fElementAttributeLimit, fXMLNameLimit;
-
- /** External subset resolver. **/
- protected ExternalSubsetResolver fExternalSubsetResolver;
-
- // scanner states
-
- //XXX this should be divided into more states.
- /** Scanner state: start of markup. */
- protected static final int SCANNER_STATE_START_OF_MARKUP = 21;
-
- /** Scanner state: content. */
- protected static final int SCANNER_STATE_CONTENT = 22;
-
- /** Scanner state: processing instruction. */
- protected static final int SCANNER_STATE_PI = 23;
-
- /** Scanner state: DOCTYPE. */
- protected static final int SCANNER_STATE_DOCTYPE = 24;
-
- /** Scanner state: XML Declaration */
- protected static final int SCANNER_STATE_XML_DECL = 25;
-
- /** Scanner state: root element. */
- protected static final int SCANNER_STATE_ROOT_ELEMENT = 26;
-
- /** Scanner state: comment. */
- protected static final int SCANNER_STATE_COMMENT = 27;
-
- /** Scanner state: reference. */
- protected static final int SCANNER_STATE_REFERENCE = 28;
-
- // <book type="hard"> reading attribute name 'type'
- protected static final int SCANNER_STATE_ATTRIBUTE = 29;
-
- // <book type="hard"> //reading attribute value.
- protected static final int SCANNER_STATE_ATTRIBUTE_VALUE = 30;
-
- /** Scanner state: trailing misc. USED BY DOCUMENT_SCANNER_IMPL*/
- //protected static final int SCANNER_STATE_TRAILING_MISC = 32;
-
- /** Scanner state: end of input. */
- protected static final int SCANNER_STATE_END_OF_INPUT = 33;
-
- /** Scanner state: terminated. */
- protected static final int SCANNER_STATE_TERMINATED = 34;
-
- /** Scanner state: CDATA section. */
- protected static final int SCANNER_STATE_CDATA = 35;
-
- /** Scanner state: Text declaration. */
- protected static final int SCANNER_STATE_TEXT_DECL = 36;
-
- /** Scanner state: Text declaration. */
- protected static final int SCANNER_STATE_CHARACTER_DATA = 37;
-
- //<book type="hard">foo</book>
- protected static final int SCANNER_STATE_START_ELEMENT_TAG = 38;
-
- //<book type="hard">foo</book> reading </book>
- protected static final int SCANNER_STATE_END_ELEMENT_TAG = 39;
-
- protected static final int SCANNER_STATE_CHAR_REFERENCE = 40;
- protected static final int SCANNER_STATE_BUILT_IN_REFS = 41;
-
- // feature identifiers
-
-
- /** Feature identifier: notify built-in refereces. */
- protected static final String NOTIFY_BUILTIN_REFS =
- Constants.XERCES_FEATURE_PREFIX + Constants.NOTIFY_BUILTIN_REFS_FEATURE;
-
- /** Property identifier: entity resolver. */
- protected static final String ENTITY_RESOLVER =
- Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
-
- /** Feature identifier: standard uri conformant */
- protected static final String STANDARD_URI_CONFORMANT =
- Constants.XERCES_FEATURE_PREFIX +Constants.STANDARD_URI_CONFORMANT_FEATURE;
-
- /** Property identifier: Security property manager. */
- private static final String XML_SECURITY_PROPERTY_MANAGER =
- Constants.XML_SECURITY_PROPERTY_MANAGER;
-
- /** access external dtd: file protocol
- * For DOM/SAX, the secure feature is set to true by default
- */
- final static String EXTERNAL_ACCESS_DEFAULT = Constants.EXTERNAL_ACCESS_DEFAULT;
-
- // recognized features and properties
-
- /** Recognized features. */
- private static final String[] RECOGNIZED_FEATURES = {
- NAMESPACES,
- VALIDATION,
- NOTIFY_BUILTIN_REFS,
- NOTIFY_CHAR_REFS,
- Constants.STAX_REPORT_CDATA_EVENT
- };
-
- /** Feature defaults. */
- private static final Boolean[] FEATURE_DEFAULTS = {
- Boolean.TRUE,
- null,
- Boolean.FALSE,
- Boolean.FALSE,
- Boolean.TRUE
- };
-
- /** Recognized properties. */
- private static final String[] RECOGNIZED_PROPERTIES = {
- SYMBOL_TABLE,
- ERROR_REPORTER,
- ENTITY_MANAGER,
- XML_SECURITY_PROPERTY_MANAGER
- };
-
- /** Property defaults. */
- private static final Object[] PROPERTY_DEFAULTS = {
- null,
- null,
- null,
- null
- };
-
- private static final char [] cdata = {'[','C','D','A','T','A','['};
- static final char [] xmlDecl = {'<','?','x','m','l'};
- // private static final char [] endTag = {'<','/'};
- // debugging
-
- /** Debug scanner state. */
- private static final boolean DEBUG_SCANNER_STATE = false;
-
- /** Debug driver. */
- private static final boolean DEBUG_DISPATCHER = false;
-
- /** Debug content driver scanning. */
- protected static final boolean DEBUG_START_END_ELEMENT = false;
-
-
- /** Debug driver next */
- protected static final boolean DEBUG_NEXT = false ;
-
- /** Debug driver next */
- protected static final boolean DEBUG = false;
- protected static final boolean DEBUG_COALESCE = false;
- //
- // Data
- //
-
- // protected data
-
- /** Document handler. */
- protected XMLDocumentHandler fDocumentHandler;
- protected int fScannerLastState ;
-
- /** Entity Storage */
- protected XMLEntityStorage fEntityStore;
-
- /** Entity stack. */
- protected int[] fEntityStack = new int[4];
-
- /** Markup depth. */
- protected int fMarkupDepth;
-
- //is the element empty
- protected boolean fEmptyElement ;
-
- //track if we are reading attributes, this is usefule while
- //there is a callback
- protected boolean fReadingAttributes = false;
-
- /** Scanner state. */
- protected int fScannerState;
-
- /** SubScanner state: inside scanContent method. */
- protected boolean fInScanContent = false;
- protected boolean fLastSectionWasCData = false;
- protected boolean fLastSectionWasEntityReference = false;
- protected boolean fLastSectionWasCharacterData = false;
-
- /** has external dtd */
- protected boolean fHasExternalDTD;
-
- /** Standalone. */
- protected boolean fStandaloneSet;
- protected boolean fStandalone;
- protected String fVersion;
-
- // element information
-
- /** Current element. */
- protected QName fCurrentElement;
-
- /** Element stack. */
- protected ElementStack fElementStack = new ElementStack();
- protected ElementStack2 fElementStack2 = new ElementStack2();
-
- // other info
-
- /** Document system identifier.
- * REVISIT: So what's this used for? - NG
- * protected String fDocumentSystemId;
- ******/
-
- protected String fPITarget ;
-
- //xxx do we need to create an extra XMLString object... look for using fTempString for collecting all the data values
- protected XMLString fPIData = new XMLString();
-
- // features
-
-
- /** Notify built-in references. */
- protected boolean fNotifyBuiltInRefs = false;
-
- //STAX related properties
- //defaultValues.
- protected boolean fSupportDTD = true;
- protected boolean fReplaceEntityReferences = true;
- protected boolean fSupportExternalEntities = false;
- protected boolean fReportCdataEvent = false ;
- protected boolean fIsCoalesce = false ;
- protected String fDeclaredEncoding = null;
- /** Xerces Feature: Disallow doctype declaration. */
- protected boolean fDisallowDoctype = false;
-
- /**
- * comma-delimited list of protocols that are allowed for the purpose
- * of accessing external dtd or entity references
- */
- protected String fAccessExternalDTD = EXTERNAL_ACCESS_DEFAULT;
-
- /**
- * standard uri conformant (strict uri).
- * http://apache.org/xml/features/standard-uri-conformant
- */
- protected boolean fStrictURI;
-
- // drivers
-
- /** Active driver. */
- protected Driver fDriver;
-
- /** Content driver. */
- protected Driver fContentDriver = createContentDriver();
-
- // temporary variables
-
- /** Element QName. */
- protected QName fElementQName = new QName();
-
- /** Attribute QName. */
- protected QName fAttributeQName = new QName();
-
- /**
- * CHANGED: Using XMLAttributesIteratorImpl instead of XMLAttributesImpl. This class
- * implements Iterator interface so we can directly give Attributes in the form of
- * iterator.
- */
- protected XMLAttributesIteratorImpl fAttributes = new XMLAttributesIteratorImpl();
-
-
- /** String. */
- protected XMLString fTempString = new XMLString();
-
- /** String. */
- protected XMLString fTempString2 = new XMLString();
-
- /** Array of 3 strings. */
- private String[] fStrings = new String[3];
-
- /** Making the buffer accesible to derived class -- String buffer. */
- protected XMLStringBuffer fStringBuffer = new XMLStringBuffer();
-
- /** Making the buffer accesible to derived class -- String buffer. */
- protected XMLStringBuffer fStringBuffer2 = new XMLStringBuffer();
-
- /** stores character data. */
- /** Making the buffer accesible to derived class -- stores PI data */
- protected XMLStringBuffer fContentBuffer = new XMLStringBuffer();
-
- /** Single character array. */
- private final char[] fSingleChar = new char[1];
- private String fCurrentEntityName = null;
-
- // New members
- protected boolean fScanToEnd = false;
-
- protected DTDGrammarUtil dtdGrammarUtil= null;
-
- protected boolean fAddDefaultAttr = false;
-
- protected boolean foundBuiltInRefs = false;
-
-
- //skip element algorithm
- static final short MAX_DEPTH_LIMIT = 5 ;
- static final short ELEMENT_ARRAY_LENGTH = 200 ;
- static final short MAX_POINTER_AT_A_DEPTH = 4 ;
- static final boolean DEBUG_SKIP_ALGORITHM = false;
- //create a elemnet array of length equal to ELEMENT_ARRAY_LENGTH
- String [] fElementArray = new String[ELEMENT_ARRAY_LENGTH] ;
- //pointer location where last element was skipped
- short fLastPointerLocation = 0 ;
- short fElementPointer = 0 ;
- //2D array to store pointer info
- short [] [] fPointerInfo = new short[MAX_DEPTH_LIMIT] [MAX_POINTER_AT_A_DEPTH] ;
- protected String fElementRawname ;
- protected boolean fShouldSkip = false;
- protected boolean fAdd = false ;
- protected boolean fSkip = false;
-
- /** Reusable Augmentations. */
- private Augmentations fTempAugmentations = null;
- //
- // Constructors
- //
-
- /** Default constructor. */
- public XMLDocumentFragmentScannerImpl() {
- } // <init>()
-
- //
- // XMLDocumentScanner methods
- //
-
- /**
- * Sets the input source.
- *
- * @param inputSource The input source.
- *
- * @throws IOException Thrown on i/o error.
- */
- public void setInputSource(XMLInputSource inputSource) throws IOException {
- fEntityManager.setEntityHandler(this);
- fEntityManager.startEntity(false, "$fragment$", inputSource, false, true);
- // fDocumentSystemId = fEntityManager.expandSystemId(inputSource.getSystemId());
- } // setInputSource(XMLInputSource)
-
- /**
- * Scans a document.
- *
- * @param complete True if the scanner should scan the document
- * completely, pushing all events to the registered
- * document handler. A value of false indicates that
- * that the scanner should only scan the next portion
- * of the document and return. A scanner instance is
- * permitted to completely scan a document if it does
- * not support this "pull" scanning model.
- *
- * @return True if there is more to scan, false otherwise.
- */
- public boolean scanDocument(boolean complete)
- throws IOException, XNIException {
-
- // keep dispatching "events"
- fEntityManager.setEntityHandler(this);
- //System.out.println(" get Document Handler in NSDocumentHandler " + fDocumentHandler );
-
- int event = next();
- do {
- switch (event) {
- case XMLStreamConstants.START_DOCUMENT :
- //fDocumentHandler.startDocument(fEntityManager.getEntityScanner(),fEntityManager.getEntityScanner().getVersion(),fNamespaceContext,null);// not able to get
- break;
- case XMLStreamConstants.START_ELEMENT :
- //System.out.println(" in scann element");
- //fDocumentHandler.startElement(getElementQName(),fAttributes,null);
- break;
- case XMLStreamConstants.CHARACTERS :
- fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
- fDocumentHandler.characters(getCharacterData(),null);
- break;
- case XMLStreamConstants.SPACE:
- //check if getCharacterData() is the right function to retrieve ignorableWhitespace information.
- //System.out.println("in the space");
- //fDocumentHandler.ignorableWhitespace(getCharacterData(), null);
- break;
- case XMLStreamConstants.ENTITY_REFERENCE :
- fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
- //entity reference callback are given in startEntity
- break;
- case XMLStreamConstants.PROCESSING_INSTRUCTION :
- fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
- fDocumentHandler.processingInstruction(getPITarget(),getPIData(),null);
- break;
- case XMLStreamConstants.COMMENT :
- fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
- fDocumentHandler.comment(getCharacterData(),null);
- break;
- case XMLStreamConstants.DTD :
- //all DTD related callbacks are handled in DTDScanner.
- //1. Stax doesn't define DTD states as it does for XML Document.
- //therefore we don't need to take care of anything here. So Just break;
- break;
- case XMLStreamConstants.CDATA:
- fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
- fDocumentHandler.startCDATA(null);
- //xxx: check if CDATA values comes from getCharacterData() function
- fDocumentHandler.characters(getCharacterData(),null);
- fDocumentHandler.endCDATA(null);
- //System.out.println(" in CDATA of the XMLNSDocumentScannerImpl");
- break;
- case XMLStreamConstants.NOTATION_DECLARATION :
- break;
- case XMLStreamConstants.ENTITY_DECLARATION :
- break;
- case XMLStreamConstants.NAMESPACE :
- break;
- case XMLStreamConstants.ATTRIBUTE :
- break;
- case XMLStreamConstants.END_ELEMENT :
- //do not give callback here.
- //this callback is given in scanEndElement function.
- //fDocumentHandler.endElement(getElementQName(),null);
- break;
- default :
- throw new InternalError("processing event: " + event);
-
- }
- //System.out.println("here in before calling next");
- event = next();
- //System.out.println("here in after calling next");
- } while (event!=XMLStreamConstants.END_DOCUMENT && complete);
-
- if(event == XMLStreamConstants.END_DOCUMENT) {
- fDocumentHandler.endDocument(null);
- return false;
- }
-
- return true;
-
- } // scanDocument(boolean):boolean
-
-
-
- public com.sun.org.apache.xerces.internal.xni.QName getElementQName(){
- if(fScannerLastState == XMLEvent.END_ELEMENT){
- fElementQName.setValues(fElementStack.getLastPoppedElement());
- }
- return fElementQName ;
- }
-
- /** return the next state on the input
- * @return int
- */
-
- public int next() throws IOException, XNIException {
- return fDriver.next();
- }
-
- //
- // XMLComponent methods
- //
-
- /**
- * Resets the component. The component can query the component manager
- * about any features and properties that affect the operation of the
- * component.
- *
- * @param componentManager The component manager.
- *
- * @throws SAXException Thrown by component on initialization error.
- * For example, if a feature or property is
- * required for the operation of the component, the
- * component manager may throw a
- * SAXNotRecognizedException or a
- * SAXNotSupportedException.
- */
-
- public void reset(XMLComponentManager componentManager)
- throws XMLConfigurationException {
-
- super.reset(componentManager);
-
- // other settings
- // fDocumentSystemId = null;
-
- // sax features
- //fAttributes.setNamespaces(fNamespaces);
-
- // xerces features
- fReportCdataEvent = componentManager.getFeature(Constants.STAX_REPORT_CDATA_EVENT, true);
- fSecurityManager = (XMLSecurityManager)componentManager.getProperty(Constants.SECURITY_MANAGER, null);
- fNotifyBuiltInRefs = componentManager.getFeature(NOTIFY_BUILTIN_REFS, false);
-
- Object resolver = componentManager.getProperty(ENTITY_RESOLVER, null);
- fExternalSubsetResolver = (resolver instanceof ExternalSubsetResolver) ?
- (ExternalSubsetResolver) resolver : null;
-
- //attribute
- fReadingAttributes = false;
- //xxx: external entities are supported in Xerces
- // it would be good to define feature for this case
- fSupportExternalEntities = true;
- fReplaceEntityReferences = true;
- fIsCoalesce = false;
-
- // setup Driver
- setScannerState(SCANNER_STATE_CONTENT);
- setDriver(fContentDriver);
-
- // JAXP 1.5 features and properties
- XMLSecurityPropertyManager spm = (XMLSecurityPropertyManager)
- componentManager.getProperty(XML_SECURITY_PROPERTY_MANAGER, null);
- fAccessExternalDTD = spm.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD);
-
- fStrictURI = componentManager.getFeature(STANDARD_URI_CONFORMANT, false);
-
- resetCommon();
- //fEntityManager.test();
- } // reset(XMLComponentManager)
-
-
- public void reset(PropertyManager propertyManager){
-
- super.reset(propertyManager);
-
- // other settings
- // fDocumentSystemId = null;
- fNamespaces = ((Boolean)propertyManager.getProperty(XMLInputFactory.IS_NAMESPACE_AWARE)).booleanValue();
- fNotifyBuiltInRefs = false ;
-
- //fElementStack2.clear();
- //fReplaceEntityReferences = true;
- //fSupportExternalEntities = true;
- Boolean bo = (Boolean)propertyManager.getProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES);
- fReplaceEntityReferences = bo.booleanValue();
- bo = (Boolean)propertyManager.getProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES);
- fSupportExternalEntities = bo.booleanValue();
- Boolean cdata = (Boolean)propertyManager.getProperty(Constants.ZEPHYR_PROPERTY_PREFIX + Constants.STAX_REPORT_CDATA_EVENT) ;
- if(cdata != null)
- fReportCdataEvent = cdata.booleanValue() ;
- Boolean coalesce = (Boolean)propertyManager.getProperty(XMLInputFactory.IS_COALESCING) ;
- if(coalesce != null)
- fIsCoalesce = coalesce.booleanValue();
- fReportCdataEvent = fIsCoalesce ? false : (fReportCdataEvent && true) ;
- //if fIsCoalesce is set to true, set the value of fReplaceEntityReferences to true,
- //if fIsCoalesce is set to false, take the value of fReplaceEntityReferences as set by application
- fReplaceEntityReferences = fIsCoalesce ? true : fReplaceEntityReferences;
- // setup Driver
- //we dont need to do this -- nb.
- //setScannerState(SCANNER_STATE_CONTENT);
- //setDriver(fContentDriver);
- //fEntityManager.test();
-
- // JAXP 1.5 features and properties
- XMLSecurityPropertyManager spm = (XMLSecurityPropertyManager)
- propertyManager.getProperty(XML_SECURITY_PROPERTY_MANAGER);
- fAccessExternalDTD = spm.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD);
-
- fSecurityManager = (XMLSecurityManager)propertyManager.getProperty(Constants.SECURITY_MANAGER);
- resetCommon();
- } // reset(XMLComponentManager)
-
- void resetCommon() {
- // initialize vars
- fMarkupDepth = 0;
- fCurrentElement = null;
- fElementStack.clear();
- fHasExternalDTD = false;
- fStandaloneSet = false;
- fStandalone = false;
- fInScanContent = false;
- //skipping algorithm
- fShouldSkip = false;
- fAdd = false;
- fSkip = false;
-
- fEntityStore = fEntityManager.getEntityStore();
- dtdGrammarUtil = null;
-
- if (fSecurityManager != null) {
- fElementAttributeLimit = fSecurityManager.getLimit(XMLSecurityManager.Limit.ELEMENT_ATTRIBUTE_LIMIT);
- fXMLNameLimit = fSecurityManager.getLimit(XMLSecurityManager.Limit.MAX_NAME_LIMIT);
- } else {
- fElementAttributeLimit = 0;
- fXMLNameLimit = XMLSecurityManager.Limit.MAX_NAME_LIMIT.defaultValue();
- }
- fLimitAnalyzer = fEntityManager.fLimitAnalyzer;
- }
-
- /**
- * Returns a list of feature identifiers that are recognized by
- * this component. This method may return null if no features
- * are recognized by this component.
- */
- public String[] getRecognizedFeatures() {
- return (String[])(RECOGNIZED_FEATURES.clone());
- } // getRecognizedFeatures():String[]
-
- /**
- * Sets the state of a feature. This method is called by the component
- * manager any time after reset when a feature changes state.
- * <p>
- * <strong>Note:</strong> Components should silently ignore features
- * that do not affect the operation of the component.
- *
- * @param featureId The feature identifier.
- * @param state The state of the feature.
- *
- * @throws SAXNotRecognizedException The component should not throw
- * this exception.
- * @throws SAXNotSupportedException The component should not throw
- * this exception.
- */
- public void setFeature(String featureId, boolean state)
- throws XMLConfigurationException {
-
- super.setFeature(featureId, state);
-
- // Xerces properties
- if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
- String feature = featureId.substring(Constants.XERCES_FEATURE_PREFIX.length());
- if (feature.equals(Constants.NOTIFY_BUILTIN_REFS_FEATURE)) {
- fNotifyBuiltInRefs = state;
- }
- }
-
- } // setFeature(String,boolean)
-
- /**
- * Returns a list of property identifiers that are recognized by
- * this component. This method may return null if no properties
- * are recognized by this component.
- */
- public String[] getRecognizedProperties() {
- return (String[])(RECOGNIZED_PROPERTIES.clone());
- } // getRecognizedProperties():String[]
-
- /**
- * Sets the value of a property. This method is called by the component
- * manager any time after reset when a property changes value.
- * <p>
- * <strong>Note:</strong> Components should silently ignore properties
- * that do not affect the operation of the component.
- *
- * @param propertyId The property identifier.
- * @param value The value of the property.
- *
- * @throws SAXNotRecognizedException The component should not throw
- * this exception.
- * @throws SAXNotSupportedException The component should not throw
- * this exception.
- */
- public void setProperty(String propertyId, Object value)
- throws XMLConfigurationException {
-
- super.setProperty(propertyId, value);
-
- // Xerces properties
- if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
- final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
- if (suffixLength == Constants.ENTITY_MANAGER_PROPERTY.length() &&
- propertyId.endsWith(Constants.ENTITY_MANAGER_PROPERTY)) {
- fEntityManager = (XMLEntityManager)value;
- return;
- }
- if (suffixLength == Constants.ENTITY_RESOLVER_PROPERTY.length() &&
- propertyId.endsWith(Constants.ENTITY_RESOLVER_PROPERTY)) {
- fExternalSubsetResolver = (value instanceof ExternalSubsetResolver) ?
- (ExternalSubsetResolver) value : null;
- return;
- }
- }
-
-
- // Xerces properties
- if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
- String property = propertyId.substring(Constants.XERCES_PROPERTY_PREFIX.length());
- if (property.equals(Constants.ENTITY_MANAGER_PROPERTY)) {
- fEntityManager = (XMLEntityManager)value;
- }
- return;
- }
-
- //JAXP 1.5 properties
- if (propertyId.equals(XML_SECURITY_PROPERTY_MANAGER))
- {
- XMLSecurityPropertyManager spm = (XMLSecurityPropertyManager)value;
- fAccessExternalDTD = spm.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD);
- }
-
- } // setProperty(String,Object)
-
- /**
- * Returns the default state for a feature, or null if this
- * component does not want to report a default value for this
- * feature.
- *
- * @param featureId The feature identifier.
- *
- * @since Xerces 2.2.0
- */
- public Boolean getFeatureDefault(String featureId) {
- for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
- if (RECOGNIZED_FEATURES[i].equals(featureId)) {
- return FEATURE_DEFAULTS[i];
- }
- }
- return null;
- } // getFeatureDefault(String):Boolean
-
- /**
- * Returns the default state for a property, or null if this
- * component does not want to report a default value for this
- * property.
- *
- * @param propertyId The property identifier.
- *
- * @since Xerces 2.2.0
- */
- public Object getPropertyDefault(String propertyId) {
- for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
- if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
- return PROPERTY_DEFAULTS[i];
- }
- }
- return null;
- } // getPropertyDefault(String):Object
-
- //
- // XMLDocumentSource methods
- //
-
- /**
- * setDocumentHandler
- *
- * @param documentHandler
- */
- public void setDocumentHandler(XMLDocumentHandler documentHandler) {
- fDocumentHandler = documentHandler;
- //System.out.println(" In Set DOCUMENT HANDLER" + fDocumentHandler + " scanner =" + this);
- } // setDocumentHandler(XMLDocumentHandler)
-
-
- /** Returns the document handler */
- public XMLDocumentHandler getDocumentHandler(){
- return fDocumentHandler;
- }
-
- //
- // XMLEntityHandler methods
- //
-
- /**
- * This method notifies of the start of an entity. The DTD has the
- * pseudo-name of "[dtd]" parameter entity names start with '%'; and
- * general entities are just specified by their name.
- *
- * @param name The name of the entity.
- * @param identifier The resource identifier.
- * @param encoding The auto-detected IANA encoding name of the entity
- * stream. This value will be null in those situations
- * where the entity encoding is not auto-detected (e.g.
- * internal entities or a document entity that is
- * parsed from a java.io.Reader).
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void startEntity(String name,
- XMLResourceIdentifier identifier,
- String encoding, Augmentations augs) throws XNIException {
-
- // keep track of this entity before fEntityDepth is increased
- if (fEntityDepth == fEntityStack.length) {
- int[] entityarray = new int[fEntityStack.length * 2];
- System.arraycopy(fEntityStack, 0, entityarray, 0, fEntityStack.length);
- fEntityStack = entityarray;
- }
- fEntityStack[fEntityDepth] = fMarkupDepth;
-
- super.startEntity(name, identifier, encoding, augs);
-
- // WFC: entity declared in external subset in standalone doc
- if(fStandalone && fEntityStore.isEntityDeclInExternalSubset(name)) {
- reportFatalError("MSG_REFERENCE_TO_EXTERNALLY_DECLARED_ENTITY_WHEN_STANDALONE",
- new Object[]{name});
- }
-
- /** we are not calling the handlers yet.. */
- // call handler
- if (fDocumentHandler != null && !fScanningAttribute) {
- if (!name.equals("[xml]")) {
- fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
- }
- }
-
- } // startEntity(String,XMLResourceIdentifier,String)
-
- /**
- * This method notifies the end of an entity. The DTD has the pseudo-name
- * of "[dtd]" parameter entity names start with '%'; and general entities
- * are just specified by their name.
- *
- * @param name The name of the entity.
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void endEntity(String name, Augmentations augs) throws IOException, XNIException {
-
- /**
- * // flush possible pending output buffer - see scanContent
- * if (fInScanContent && fStringBuffer.length != 0
- * && fDocumentHandler != null) {
- * fDocumentHandler.characters(fStringBuffer, null);
- * fStringBuffer.length = 0; // make sure we know it's been flushed
- * }
- */
- super.endEntity(name, augs);
-
- // make sure markup is properly balanced
- if (fMarkupDepth != fEntityStack[fEntityDepth]) {
- reportFatalError("MarkupEntityMismatch", null);
- }
-
- /**/
- // call handler
- if (fDocumentHandler != null && !fScanningAttribute) {
- if (!name.equals("[xml]")) {
- fDocumentHandler.endGeneralEntity(name, augs);
- }
- }
-
-
- } // endEntity(String)
-
- //
- // Protected methods
- //
-
- // Driver factory methods
-
- /** Creates a content Driver. */
- protected Driver createContentDriver() {
- return new FragmentContentDriver();
- } // createContentDriver():Driver
-
- // scanning methods
-
- /**
- * Scans an XML or text declaration.
- * <p>
- * <pre>
- * [23] XMLDecl ::= '&lt;?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
- * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
- * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" )
- * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
- * [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'")
- * | ('"' ('yes' | 'no') '"'))
- *
- * [77] TextDecl ::= '&lt;?xml' VersionInfo? EncodingDecl S? '?>'
- * </pre>
- *
- * @param scanningTextDecl True if a text declaration is to
- * be scanned instead of an XML
- * declaration.
- */
- protected void scanXMLDeclOrTextDecl(boolean scanningTextDecl)
- throws IOException, XNIException {
-
- // scan decl
- super.scanXMLDeclOrTextDecl(scanningTextDecl, fStrings);
- fMarkupDepth--;
-
- // pseudo-attribute values
- String version = fStrings[0];
- String encoding = fStrings[1];
- String standalone = fStrings[2];
- fDeclaredEncoding = encoding;
- // set standalone
- fStandaloneSet = standalone != null;
- fStandalone = fStandaloneSet && standalone.equals("yes");
- ///xxx see where its used.. this is not used anywhere. it may be useful for entity to store this information
- //but this information is only related with Document Entity.
- fEntityManager.setStandalone(fStandalone);
-
-
- // call handler
- if (fDocumentHandler != null) {
- if (scanningTextDecl) {
- fDocumentHandler.textDecl(version, encoding, null);
- } else {
- fDocumentHandler.xmlDecl(version, encoding, standalone, null);
- }
- }
-
- if(version != null){
- fEntityScanner.setVersion(version);
- fEntityScanner.setXMLVersion(version);
- }
- // set encoding on reader, only if encoding was not specified by the application explicitly
- if (encoding != null && !fEntityScanner.getCurrentEntity().isEncodingExternallySpecified()) {
- fEntityScanner.setEncoding(encoding);
- }
-
- } // scanXMLDeclOrTextDecl(boolean)
-
- public String getPITarget(){
- return fPITarget ;
- }
-
- public XMLStringBuffer getPIData(){
- return fContentBuffer ;
- }
-
- //XXX: why not this function behave as per the state of the parser?
- public XMLString getCharacterData(){
- if(fUsebuffer){
- return fContentBuffer ;
- }else{
- return fTempString;
- }
-
- }
-
-
- /**
- * Scans a processing data. This is needed to handle the situation
- * where a document starts with a processing instruction whose
- * target name <em>starts with</em> "xml". (e.g. xmlfoo)
- *
- * @param target The PI target
- * @param data The XMLStringBuffer to fill in with the data
- */
- protected void scanPIData(String target, XMLStringBuffer data)
- throws IOException, XNIException {
-
- super.scanPIData(target, data);
-
- //set the PI target and values
- fPITarget = target ;
-
- fMarkupDepth--;
-
- } // scanPIData(String)
-
- /**
- * Scans a comment.
- * <p>
- * <pre>
- * [15] Comment ::= '&lt!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
- * </pre>
- * <p>
- * <strong>Note:</strong> Called after scanning past '&lt;!--'
- */
- protected void scanComment() throws IOException, XNIException {
- fContentBuffer.clear();
- scanComment(fContentBuffer);
- //getTextCharacters can also be called for reading comments
- fUsebuffer = true;
- fMarkupDepth--;
-
- } // scanComment()
-
- //xxx value returned by this function may not remain valid if another event is scanned.
- public String getComment(){
- return fContentBuffer.toString();
- }
-
- void addElement(String rawname){
- if(fElementPointer < ELEMENT_ARRAY_LENGTH){
- //storing element raw name in a linear list of array
- fElementArray[fElementPointer] = rawname ;
- //storing elemnetPointer for particular element depth
-
- if(DEBUG_SKIP_ALGORITHM){
- StringBuffer sb = new StringBuffer() ;
- sb.append(" Storing element information ") ;
- sb.append(" fElementPointer = " + fElementPointer) ;
- sb.append(" fElementRawname = " + fElementQName.rawname) ;
- sb.append(" fElementStack.fDepth = " + fElementStack.fDepth);
- System.out.println(sb.toString()) ;
- }
-
- //store pointer information only when element depth is less MAX_DEPTH_LIMIT
- if(fElementStack.fDepth < MAX_DEPTH_LIMIT){
- short column = storePointerForADepth(fElementPointer);
- if(column > 0){
- short pointer = getElementPointer((short)fElementStack.fDepth, (short)(column - 1) );
- //identity comparison shouldn't take much time and we can rely on this
- //since its guaranteed to have same object id for same string.
- if(rawname == fElementArray[pointer]){
- fShouldSkip = true ;
- fLastPointerLocation = pointer ;
- //reset the things and return.
- resetPointer((short)fElementStack.fDepth , column) ;
- fElementArray[fElementPointer] = null ;
- return ;
- }else{
- fShouldSkip = false ;
- }
- }
- }
- fElementPointer++ ;
- }
- }
-
-
- void resetPointer(short depth, short column){
- fPointerInfo[depth] [column] = (short)0;
- }
-
- //returns column information at which pointer was stored.
- short storePointerForADepth(short elementPointer){
- short depth = (short) fElementStack.fDepth ;
-
- //Stores element pointer locations at particular depth , only 4 pointer locations
- //are stored at particular depth for now.
- for(short i = 0 ; i < MAX_POINTER_AT_A_DEPTH ; i++){
-
- if(canStore(depth, i)){
- fPointerInfo[depth][i] = elementPointer ;
- if(DEBUG_SKIP_ALGORITHM){
- StringBuffer sb = new StringBuffer() ;
- sb.append(" Pointer information ") ;
- sb.append(" fElementPointer = " + fElementPointer) ;
- sb.append(" fElementStack.fDepth = " + fElementStack.fDepth);
- sb.append(" column = " + i ) ;
- System.out.println(sb.toString()) ;
- }
- return i;
- }
- //else
- //pointer was not stored because we reached the limit
- }
- return -1 ;
- }
-
- boolean canStore(short depth, short column){
- //colum = 0 , means first element at particular depth
- //column = 1, means second element at particular depth
- // calle should make sure that it doesn't call for value outside allowed co-ordinates
- return fPointerInfo[depth][column] == 0 ? true : false ;
- }
-
-
- short getElementPointer(short depth, short column){
- //colum = 0 , means first element at particular depth
- //column = 1, means second element at particular depth
- // calle should make sure that it doesn't call for value outside allowed co-ordinates
- return fPointerInfo[depth][column] ;
- }
-
- //this function assumes that string passed is not null and skips
- //the following string from the buffer this makes sure
- boolean skipFromTheBuffer(String rawname) throws IOException{
- if(fEntityScanner.skipString(rawname)){
- char c = (char)fEntityScanner.peekChar() ;
- //If the start element was completely skipped we should encounter either ' '(space),
- //or '/' (in case of empty element) or '>'
- if( c == ' ' || c == '/' || c == '>'){
- fElementRawname = rawname ;
- return true ;
- } else{
- return false;
- }
- } else
- return false ;
- }
-
- boolean skipQElement(String rawname) throws IOException{
-
- final int c = fEntityScanner.getChar(rawname.length());
- //if this character is still valid element name -- this means string can't match
- if(XMLChar.isName(c)){
- return false;
- }else{
- return fEntityScanner.skipString(rawname);
- }
- }
-
- protected boolean skipElement() throws IOException {
-
- if(!fShouldSkip) return false ;
-
- if(fLastPointerLocation != 0){
- //Look at the next element stored in the array list.. we might just get a match.
- String rawname = fElementArray[fLastPointerLocation + 1] ;
- if(rawname != null && skipFromTheBuffer(rawname)){
- fLastPointerLocation++ ;
- if(DEBUG_SKIP_ALGORITHM){
- System.out.println("Element " + fElementRawname + " was SKIPPED at pointer location = " + fLastPointerLocation);
- }
- return true ;
- } else{
- //reset it back to zero... we haven't got the correct subset yet.
- fLastPointerLocation = 0 ;
-
- }
- }
- //xxx: we can put some logic here as from what column it should start looking
- //for now we always start at 0
- //fallback to tolerant algorithm, it would look for differnt element stored at different
- //depth and get us the pointer location.
- return fShouldSkip && skipElement((short)0);
-
- }
-
- //start of the column at which it should try searching
- boolean skipElement(short column) throws IOException {
- short depth = (short)fElementStack.fDepth ;
-
- if(depth > MAX_DEPTH_LIMIT){
- return fShouldSkip = false ;
- }
- for(short i = column ; i < MAX_POINTER_AT_A_DEPTH ; i++){
- short pointer = getElementPointer(depth , i ) ;
-
- if(pointer == 0){
- return fShouldSkip = false ;
- }
-
- if(fElementArray[pointer] != null && skipFromTheBuffer(fElementArray[pointer])){
- if(DEBUG_SKIP_ALGORITHM){
- System.out.println();
- System.out.println("Element " + fElementRawname + " was SKIPPED at depth = " + fElementStack.fDepth + " column = " + column );
- System.out.println();
- }
- fLastPointerLocation = pointer ;
- return fShouldSkip = true ;
- }
- }
- return fShouldSkip = false ;
- }
-
- /**
- * Scans a start element. This method will handle the binding of
- * namespace information and notifying the handler of the start
- * of the element.
- * <p>
- * <pre>
- * [44] EmptyElemTag ::= '&lt;' Name (S Attribute)* S? '/>'
- * [40] STag ::= '&lt;' Name (S Attribute)* S? '>'
- * </pre>
- * <p>
- * <strong>Note:</strong> This method assumes that the leading
- * '&lt;' character has been consumed.
- * <p>
- * <strong>Note:</strong> This method uses the fElementQName and
- * fAttributes variables. The contents of these variables will be
- * destroyed. The caller should copy important information out of
- * these variables before calling this method.
- * NB: Content in fAttributes is valid only till the state of the parser is XMLEvent.START_ELEMENT
- *
- * @return True if element is empty. (i.e. It matches
- * production [44].
- */
- // fElementQName will have the details of element just read..
- // fAttributes will have the details of all the attributes.
- protected boolean scanStartElement()
- throws IOException, XNIException {
-
- if (DEBUG_START_END_ELEMENT) System.out.println( this.getClass().toString() + ">>> scanStartElement()");
- //when skipping is true and no more elements should be added
- if(fSkip && !fAdd){
- //get the stored element -- if everything goes right this should match the
- //token in the buffer
-
- QName name = fElementStack.getNext();
-
- if(DEBUG_SKIP_ALGORITHM){
- System.out.println("Trying to skip String = " + name.rawname);
- }
-
- //Be conservative -- if skipping fails -- stop.
- fSkip = fEntityScanner.skipString(name.rawname);
-
- if(fSkip){
- if(DEBUG_SKIP_ALGORITHM){
- System.out.println("Element SUCESSFULLY skipped = " + name.rawname);
- }
- fElementStack.push();
- fElementQName = name;
- }else{
- //if skipping fails reposition the stack or fallback to normal way of processing
- fElementStack.reposition();
- if(DEBUG_SKIP_ALGORITHM){
- System.out.println("Element was NOT skipped, REPOSITIONING stack" );
- }
- }
- }
-
- //we are still at the stage of adding elements
- //the elements were not matched or
- //fSkip is not set to true
- if(!fSkip || fAdd){
- //get the next element from the stack
- fElementQName = fElementStack.nextElement();
- // name
- if (fNamespaces) {
- fEntityScanner.scanQName(fElementQName, NameType.ELEMENTSTART);
- } else {
- String name = fEntityScanner.scanName(NameType.ELEMENTSTART);
- fElementQName.setValues(null, name, name, null);
- }
-
- if(DEBUG)System.out.println("Element scanned in start element is " + fElementQName.toString());
- if(DEBUG_SKIP_ALGORITHM){
- if(fAdd){
- System.out.println("Elements are being ADDED -- elemet added is = " + fElementQName.rawname + " at count = " + fElementStack.fCount);
- }
- }
-
- }
-
- //when the elements are being added , we need to check if we are set for skipping the elements
- if(fAdd){
- //this sets the value of fAdd variable
- fElementStack.matchElement(fElementQName);
- }
-
-
- //xxx: We dont need another pointer, fCurrentElement, we can use fElementQName
- fCurrentElement = fElementQName;
-
- String rawname = fElementQName.rawname;
-
- fEmptyElement = false;
-
- fAttributes.removeAllAttributes();
-
- checkDepth(rawname);
- if(!seekCloseOfStartTag()){
- fReadingAttributes = true;
- fAttributeCacheUsedCount =0;
- fStringBufferIndex =0;
- fAddDefaultAttr = true;
- do {
- scanAttribute(fAttributes);
- if (fSecurityManager != null && !fSecurityManager.isNoLimit(fElementAttributeLimit) &&
- fAttributes.getLength() > fElementAttributeLimit){
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- "ElementAttributeLimit",
- new Object[]{rawname, fElementAttributeLimit },
- XMLErrorReporter.SEVERITY_FATAL_ERROR );
- }
-
- } while (!seekCloseOfStartTag());
- fReadingAttributes=false;
- }
-
- if (fEmptyElement) {
- //decrease the markup depth..
- fMarkupDepth--;
-
- // check that this element was opened in the same entity
- if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) {
- reportFatalError("ElementEntityMismatch",
- new Object[]{fCurrentElement.rawname});
- }
- // call handler
- if (fDocumentHandler != null) {
- fDocumentHandler.emptyElement(fElementQName, fAttributes, null);
- }
-
- //We should not be popping out the context here in endELement becaause the namespace context is still
- //valid when parser is at the endElement state.
- //if (fNamespaces) {
- // fNamespaceContext.popContext();
- //}
-
- //pop the element off the stack..
- fElementStack.popElement();
-
- } else {
-
- if(dtdGrammarUtil != null)
- dtdGrammarUtil.startElement(fElementQName, fAttributes);
- if(fDocumentHandler != null){
- //complete element and attributes are traversed in this function so we can send a callback
- //here.
- //<strong>we shouldn't be sending callback in scanDocument()</strong>
- fDocumentHandler.startElement(fElementQName, fAttributes, null);
- }
- }
-
-
- if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() + "<<< scanStartElement(): "+fEmptyElement);
- return fEmptyElement;
-
- } // scanStartElement():boolean
-
- /**
- * Looks for the close of start tag, i.e. if it finds '>' or '/>'
- * Characters are consumed.
- */
- protected boolean seekCloseOfStartTag() throws IOException, XNIException {
- // spaces
- boolean sawSpace = fEntityScanner.skipSpaces();
-
- // end tag?
- final int c = fEntityScanner.peekChar();
- if (c == '>') {
- fEntityScanner.scanChar(null);
- return true;
- } else if (c == '/') {
- fEntityScanner.scanChar(null);
- if (!fEntityScanner.skipChar('>', NameType.ELEMENTEND)) {
- reportFatalError("ElementUnterminated",
- new Object[]{fElementQName.rawname});
- }
- fEmptyElement = true;
- return true;
- } else if (!isValidNameStartChar(c) || !sawSpace) {
- // Second chance. Check if this character is a high
- // surrogate of a valid name start character.
- if (!isValidNameStartHighSurrogate(c) || !sawSpace) {
- reportFatalError("ElementUnterminated",
- new Object[]{fElementQName.rawname});
- }
- }
-
- return false;
- }
-
- public boolean hasAttributes(){
- return fAttributes.getLength() > 0 ? true : false ;
- }
-
-
- /**
- * Scans an attribute.
- * <p>
- * <pre>
- * [41] Attribute ::= Name Eq AttValue
- * </pre>
- * <p>
- * <strong>Note:</strong> This method assumes that the next
- * character on the stream is the first character of the attribute
- * name.
- * <p>
- * <strong>Note:</strong> This method uses the fAttributeQName and
- * fQName variables. The contents of these variables will be
- * destroyed.
- *
- * @param attributes The attributes list for the scanned attribute.
- */
-
- /**
- * protected void scanAttribute(AttributeIteratorImpl attributes)
- * throws IOException, XNIException {
- * if (DEBUG_START_END_ELEMENT) System.out.println(">>> scanAttribute()");
- *
- *
- * // name
- * if (fNamespaces) {
- * fEntityScanner.scanQName(fAttributeQName);
- * }
- * else {
- * String name = fEntityScanner.scanName();
- * fAttributeQName.setValues(null, name, name, null);
- * }
- *
- * // equals
- * fEntityScanner.skipSpaces();
- * if (!fEntityScanner.skipChar('=')) {
- * reportFatalError("EqRequiredInAttribute",
- * new Object[]{fAttributeQName.rawname});
- * }
- * fEntityScanner.skipSpaces();
- *
- *
- * // content
- * int oldLen = attributes.getLength();
- */
- /**xxx there is one check of duplicate attribute that has been removed.
- * attributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol, null);
- *
- * // WFC: Unique Att Spec
- * if (oldLen == attributes.getLength()) {
- * reportFatalError("AttributeNotUnique",
- * new Object[]{fCurrentElement.rawname,
- * fAttributeQName.rawname});
- * }
- */
-
- /*
- //REVISIT: one more case needs to be included: external PE and standalone is no
- boolean isVC = fHasExternalDTD && !fStandalone;
- scanAttributeValue(fTempString, fTempString2,
- fAttributeQName.rawname, attributes,
- oldLen, isVC);
-
- //attributes.setValue(oldLen, fTempString.toString());
- //attributes.setNonNormalizedValue(oldLen, fTempString2.toString());
- //attributes.setSpecified(oldLen, true);
-
- AttributeImpl attribute = new AttributeImpl(fAttributeQName.prefix,fAttributeQName.localpart,fAttributeQName.uri,fTempString.toString(),fTempString2.toString(),XMLSymbols.fCDATASymbol,true);
- fAttributes.addAttribute(attribute);
- if (DEBUG_START_END_ELEMENT) System.out.println("<<< scanAttribute()");
- } // scanAttribute(XMLAttributes)
-
- */
-
- /** return the attribute iterator implementation */
- public XMLAttributesIteratorImpl getAttributeIterator(){
- if(dtdGrammarUtil != null && fAddDefaultAttr){
- dtdGrammarUtil.addDTDDefaultAttrs(fElementQName,fAttributes);
- fAddDefaultAttr = false;
- }
- return fAttributes;
- }
-
- /** return if standalone is set */
- public boolean standaloneSet(){
- return fStandaloneSet;
- }
- /** return if the doucment is standalone */
- public boolean isStandAlone(){
- return fStandalone ;
- }
- /**
- * Scans an attribute name value pair.
- * <p>
- * <pre>
- * [41] Attribute ::= Name Eq AttValue
- * </pre>
- * <p>
- * <strong>Note:</strong> This method assumes that the next
- * character on the stream is the first character of the attribute
- * name.
- * <p>
- * <strong>Note:</strong> This method uses the fAttributeQName and
- * fQName variables. The contents of these variables will be
- * destroyed.
- *
- * @param attributes The attributes list for the scanned attribute.
- */
-
- protected void scanAttribute(XMLAttributes attributes)
- throws IOException, XNIException {
- if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +">>> scanAttribute()");
-
- // name
- if (fNamespaces) {
- fEntityScanner.scanQName(fAttributeQName, NameType.ATTRIBUTENAME);
- } else {
- String name = fEntityScanner.scanName(NameType.ATTRIBUTENAME);
- fAttributeQName.setValues(null, name, name, null);
- }
-
- // equals
- fEntityScanner.skipSpaces();
- if (!fEntityScanner.skipChar('=', NameType.ATTRIBUTE)) {
- reportFatalError("EqRequiredInAttribute",
- new Object[] {fCurrentElement.rawname, fAttributeQName.rawname});
- }
- fEntityScanner.skipSpaces();
-
- int attIndex = 0 ;
- //REVISIT: one more case needs to be included: external PE and standalone is no
- boolean isVC = fHasExternalDTD && !fStandalone;
- //fTempString would store attribute value
- ///fTempString2 would store attribute non-normalized value
-
- //this function doesn't use 'attIndex'. We are adding the attribute later
- //after we have figured out that current attribute is not namespace declaration
- //since scanAttributeValue doesn't use attIndex parameter therefore we
- //can safely add the attribute later..
- XMLString tmpStr = getString();
-
- scanAttributeValue(tmpStr, fTempString2, fAttributeQName.rawname, attributes,
- attIndex, isVC, fCurrentElement.rawname, false);
-
- // content
- int oldLen = attributes.getLength();
- //if the attribute name already exists.. new value is replaced with old value
- attIndex = attributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol, null);
-
- // WFC: Unique Att Spec
- //attributes count will be same if the current attribute name already exists for this element name.
- //this means there are two duplicate attributes.
- if (oldLen == attributes.getLength()) {
- reportFatalError("AttributeNotUnique",
- new Object[]{fCurrentElement.rawname,
- fAttributeQName.rawname});
- }
-
- //tmpString contains attribute value
- //we are passing null as the attribute value
- attributes.setValue(attIndex, null, tmpStr);
-
- ///xxx: nonNormalizedValue is not being set as it is not required by SAX & DOM
- //attributes.setNonNormalizedValue(oldLen, fTempString2.toString());
- attributes.setSpecified(attIndex, true);
-
- if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +"<<< scanAttribute()");
-
- } // scanAttribute(XMLAttributes)
-
- /**
- * Scans element content.
- *
- * @return Returns the next character on the stream.
- */
- //CHANGED:
- //EARLIER: scanContent()
- //NOW: scanContent(XMLStringBuffer)
- //It makes things easy if this functions takes XMLStringBuffer as parameter..
- //this function appends the data to the buffer.
- protected int scanContent(XMLStringBuffer content) throws IOException, XNIException {
- //set the fTempString length to 0 before passing it on to scanContent
- //scanContent sets the correct co-ordinates as per the content read
- fTempString.length = 0;
- int c = fEntityScanner.scanContent(fTempString);
- content.append(fTempString);
- fTempString.length = 0;
- if (c == '\r') {
- // happens when there is the character reference &#13;
- //xxx: We know the next chracter.. we should just skip it and add ']' directlry
- fEntityScanner.scanChar(null);
- content.append((char)c);
- c = -1;
- } else if (c == ']') {
- //fStringBuffer.clear();
- //xxx: We know the next chracter.. we should just skip it and add ']' directlry
- content.append((char)fEntityScanner.scanChar(null));
- // remember where we are in case we get an endEntity before we
- // could flush the buffer out - this happens when we're parsing an
- // entity which ends with a ]
- fInScanContent = true;
- //
- // We work on a single character basis to handle cases such as:
- // ']]]>' which we might otherwise miss.
- //
- if (fEntityScanner.skipChar(']', null)) {
- content.append(']');
- while (fEntityScanner.skipChar(']', null)) {
- content.append(']');
- }
- if (fEntityScanner.skipChar('>', null)) {
- reportFatalError("CDEndInContent", null);
- }
- }
- fInScanContent = false;
- c = -1;
- }
- if (fDocumentHandler != null && content.length > 0) {
- //fDocumentHandler.characters(content, null);
- }
- return c;
-
- } // scanContent():int
-
-
- /**
- * Scans a CDATA section.
- * <p>
- * <strong>Note:</strong> This method uses the fTempString and
- * fStringBuffer variables.
- *
- * @param complete True if the CDATA section is to be scanned
- * completely.
- *
- * @return True if CDATA is completely scanned.
- */
- //CHANGED:
- protected boolean scanCDATASection(XMLStringBuffer contentBuffer, boolean complete)
- throws IOException, XNIException {
-
- // call handler
- if (fDocumentHandler != null) {
- //fDocumentHandler.startCDATA(null);
- }
-
- while (true) {
- //scanData will fill the contentBuffer
- if (!fEntityScanner.scanData("]]>", contentBuffer)) {
- break ;
- /** We dont need all this code if we pass ']]>' as delimeter..
- * int brackets = 2;
- * while (fEntityScanner.skipChar(']')) {
- * brackets++;
- * }
- *
- * //When we find more than 2 square brackets
- * if (fDocumentHandler != null && brackets > 2) {
- * //we dont need to clear the buffer..
- * //contentBuffer.clear();
- * for (int i = 2; i < brackets; i++) {
- * contentBuffer.append(']');
- * }
- * fDocumentHandler.characters(contentBuffer, null);
- * }
- *
- * if (fEntityScanner.skipChar('>')) {
- * break;
- * }
- * if (fDocumentHandler != null) {
- * //we dont need to clear the buffer now..
- * //contentBuffer.clear();
- * contentBuffer.append("]]");
- * fDocumentHandler.characters(contentBuffer, null);
- * }
- **/
- } else {
- int c = fEntityScanner.peekChar();
- if (c != -1 && isInvalidLiteral(c)) {
- if (XMLChar.isHighSurrogate(c)) {
- //contentBuffer.clear();
- //scan surrogates if any....
- scanSurrogates(contentBuffer);
- } else {
- reportFatalError("InvalidCharInCDSect",
- new Object[]{Integer.toString(c,16)});
- fEntityScanner.scanChar(null);
- }
- }
- //by this time we have also read surrogate contents if any...
- if (fDocumentHandler != null) {
- //fDocumentHandler.characters(contentBuffer, null);
- }
- }
- }
- fMarkupDepth--;
-
- if (fDocumentHandler != null && contentBuffer.length > 0) {
- //fDocumentHandler.characters(contentBuffer, null);
- }
-
- // call handler
- if (fDocumentHandler != null) {
- //fDocumentHandler.endCDATA(null);
- }
-
- return true;
-
- } // scanCDATASection(XMLStringBuffer, boolean):boolean
-
- /**
- * Scans an end element.
- * <p>
- * <pre>
- * [42] ETag ::= '&lt;/' Name S? '>'
- * </pre>
- * <p>
- * <strong>Note:</strong> This method uses the fElementQName variable.
- * The contents of this variable will be destroyed. The caller should
- * copy the needed information out of this variable before calling
- * this method.
- *
- * @return The element depth.
- */
- protected int scanEndElement() throws IOException, XNIException {
- if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +">>> scanEndElement()");
-
- // pop context
- QName endElementName = fElementStack.popElement();
-
- String rawname = endElementName.rawname;
- if(DEBUG)System.out.println("endElementName = " + endElementName.toString());
- // Take advantage of the fact that next string _should_ be "fElementQName.rawName",
- //In scanners most of the time is consumed on checks done for XML characters, we can
- // optimize on it and avoid the checks done for endElement,
- //we will also avoid symbol table lookup - neeraj.bajaj@sun.com
-
- // this should work both for namespace processing true or false...
-
- //REVISIT: if the string is not the same as expected.. we need to do better error handling..
- //We can skip this for now... In any case if the string doesn't match -- document is not well formed.
-
- if (!fEntityScanner.skipString(endElementName.rawname)) {
- reportFatalError("ETagRequired", new Object[]{rawname});
- }
-
- // end
- fEntityScanner.skipSpaces();
- if (!fEntityScanner.skipChar('>', NameType.ELEMENTEND)) {
- reportFatalError("ETagUnterminated",
- new Object[]{rawname});
- }
- fMarkupDepth--;
-
- //we have increased the depth for two markup "<" characters
- fMarkupDepth--;
-
- // check that this element was opened in the same entity
- if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) {
- reportFatalError("ElementEntityMismatch",
- new Object[]{rawname});
- }
-
- //We should not be popping out the context here in endELement becaause the namespace context is still
- //valid when parser is at the endElement state.
-
- //if (fNamespaces) {
- // fNamespaceContext.popContext();
- //}
-
- // call handler
- if (fDocumentHandler != null ) {
- //end element is scanned in this function so we can send a callback
- //here.
- //<strong>we shouldn't be sending callback in scanDocument()</strong>
-
- fDocumentHandler.endElement(endElementName, null);
- }
- if(dtdGrammarUtil != null)
- dtdGrammarUtil.endElement(endElementName);
-
- return fMarkupDepth;
-
- } // scanEndElement():int
-
- /**
- * Scans a character reference.
- * <p>
- * <pre>
- * [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'
- * </pre>
- */
- protected void scanCharReference()
- throws IOException, XNIException {
-
- fStringBuffer2.clear();
- int ch = scanCharReferenceValue(fStringBuffer2, null);
- fMarkupDepth--;
- if (ch != -1) {
- // call handler
-
- if (fDocumentHandler != null) {
- if (fNotifyCharRefs) {
- fDocumentHandler.startGeneralEntity(fCharRefLiteral, null, null, null);
- }
- Augmentations augs = null;
- if (fValidation && ch <= 0x20) {
- if (fTempAugmentations != null) {
- fTempAugmentations.removeAllItems();
- }
- else {
- fTempAugmentations = new AugmentationsImpl();
- }
- augs = fTempAugmentations;
- augs.putItem(Constants.CHAR_REF_PROBABLE_WS, Boolean.TRUE);
- }
- //xxx: How do we deal with this - how to return charReferenceValues
- //now this is being commented because this is taken care in scanDocument()
- //fDocumentHandler.characters(fStringBuffer2, null);
- if (fNotifyCharRefs) {
- fDocumentHandler.endGeneralEntity(fCharRefLiteral, null);
- }
- }
- }
-
- } // scanCharReference()
-
-
- /**
- * Scans an entity reference.
- *
- * @return returns true if the new entity is started. If it was built-in entity
- * 'false' is returned.
- * @throws IOException Thrown if i/o error occurs.
- * @throws XNIException Thrown if handler throws exception upon
- * notification.
- */
- protected void scanEntityReference(XMLStringBuffer content) throws IOException, XNIException {
- String name = fEntityScanner.scanName(NameType.REFERENCE);
- if (name == null) {
- reportFatalError("NameRequiredInReference", null);
- return;
- }
- if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) {
- reportFatalError("SemicolonRequiredInReference", new Object []{name});
- }
- if (fEntityStore.isUnparsedEntity(name)) {
- reportFatalError("ReferenceToUnparsedEntity", new Object[]{name});
- }
- fMarkupDepth--;
- fCurrentEntityName = name;
-
- // handle built-in entities
- if (name == fAmpSymbol) {
- handleCharacter('&', fAmpSymbol, content);
- fScannerState = SCANNER_STATE_BUILT_IN_REFS;
- return ;
- } else if (name == fLtSymbol) {
- handleCharacter('<', fLtSymbol, content);
- fScannerState = SCANNER_STATE_BUILT_IN_REFS;
- return ;
- } else if (name == fGtSymbol) {
- handleCharacter('>', fGtSymbol, content);
- fScannerState = SCANNER_STATE_BUILT_IN_REFS;
- return ;
- } else if (name == fQuotSymbol) {
- handleCharacter('"', fQuotSymbol, content);
- fScannerState = SCANNER_STATE_BUILT_IN_REFS;
- return ;
- } else if (name == fAposSymbol) {
- handleCharacter('\'', fAposSymbol, content);
- fScannerState = SCANNER_STATE_BUILT_IN_REFS;
- return ;
- }
-
- //1. if the entity is external and support to external entities is not required
- // 2. or entities should not be replaced
- //3. or if it is built in entity reference.
- boolean isEE = fEntityStore.isExternalEntity(name);
- if((isEE && !fSupportExternalEntities) || (!isEE && !fReplaceEntityReferences) || foundBuiltInRefs){
- fScannerState = SCANNER_STATE_REFERENCE;
- return ;
- }
- // start general entity
- if (!fEntityStore.isDeclaredEntity(name)) {
- //SUPPORT_DTD=false && ReplaceEntityReferences should throw exception
- if (!fSupportDTD && fReplaceEntityReferences) {
- reportFatalError("EntityNotDeclared", new Object[]{name});
- return;
- }
- //REVISIT: one more case needs to be included: external PE and standalone is no
- if ( fHasExternalDTD && !fStandalone) {
- if (fValidation)
- fErrorReporter.reportError(fEntityScanner, XMLMessageFormatter.XML_DOMAIN,"EntityNotDeclared",
- new Object[]{name}, XMLErrorReporter.SEVERITY_ERROR);
- } else
- reportFatalError("EntityNotDeclared", new Object[]{name});
- }
- //we are starting the entity even if the entity was not declared
- //if that was the case it its taken care in XMLEntityManager.startEntity()
- //we immediately call the endEntity. Application gets to know if there was
- //any entity that was not declared.
- fEntityManager.startEntity(true, name, false);
- //set the scaner state to content.. parser will automatically revive itself at any point of time.
- //setScannerState(SCANNER_STATE_CONTENT);
- //return true ;
- } // scanEntityReference()
-
- // utility methods
-
- /**
- * Check if the depth exceeds the maxElementDepth limit
- * @param elementName name of the current element
- */
- void checkDepth(String elementName) {
- fLimitAnalyzer.addValue(Limit.MAX_ELEMENT_DEPTH_LIMIT, elementName, fElementStack.fDepth);
- if (fSecurityManager.isOverLimit(Limit.MAX_ELEMENT_DEPTH_LIMIT,fLimitAnalyzer)) {
- fSecurityManager.debugPrint(fLimitAnalyzer);
- reportFatalError("MaxElementDepthLimit", new Object[]{elementName,
- fLimitAnalyzer.getTotalValue(Limit.MAX_ELEMENT_DEPTH_LIMIT),
- fSecurityManager.getLimit(Limit.MAX_ELEMENT_DEPTH_LIMIT),
- "maxElementDepth"});
- }
- }
-
- /**
- * Calls document handler with a single character resulting from
- * built-in entity resolution.
- *
- * @param c
- * @param entity built-in name
- * @param XMLStringBuffer append the character to buffer
- *
- * we really dont need to call this function -- this function is only required when
- * we integrate with rest of Xerces2. SO maintaining the current behavior and still
- * calling this function to hanlde built-in entity reference.
- *
- */
- private void handleCharacter(char c, String entity, XMLStringBuffer content) throws XNIException {
- foundBuiltInRefs = true;
- checkEntityLimit(false, fEntityScanner.fCurrentEntity.name, 1);
- content.append(c);
- if (fDocumentHandler != null) {
- fSingleChar[0] = c;
- if (fNotifyBuiltInRefs) {
- fDocumentHandler.startGeneralEntity(entity, null, null, null);
- }
- fTempString.setValues(fSingleChar, 0, 1);
- //fDocumentHandler.characters(fTempString, null);
-
- if (fNotifyBuiltInRefs) {
- fDocumentHandler.endGeneralEntity(entity, null);
- }
- }
- } // handleCharacter(char)
-
- // helper methods
-
- /**
- * Sets the scanner state.
- *
- * @param state The new scanner state.
- */
- protected final void setScannerState(int state) {
-
- fScannerState = state;
- if (DEBUG_SCANNER_STATE) {
- System.out.print("### setScannerState: ");
- //System.out.print(fScannerState);
- System.out.print(getScannerStateName(state));
- System.out.println();
- }
-
- } // setScannerState(int)
-
-
- /**
- * Sets the Driver.
- *
- * @param Driver The new Driver.
- */
- protected final void setDriver(Driver driver) {
- fDriver = driver;
- if (DEBUG_DISPATCHER) {
- System.out.print("%%% setDriver: ");
- System.out.print(getDriverName(driver));
- System.out.println();
- }
- }
-
- //
- // Private methods
- //
-
- /** Returns the scanner state name. */
- protected String getScannerStateName(int state) {
-
- switch (state) {
- case SCANNER_STATE_DOCTYPE: return "SCANNER_STATE_DOCTYPE";
- case SCANNER_STATE_ROOT_ELEMENT: return "SCANNER_STATE_ROOT_ELEMENT";
- case SCANNER_STATE_START_OF_MARKUP: return "SCANNER_STATE_START_OF_MARKUP";
- case SCANNER_STATE_COMMENT: return "SCANNER_STATE_COMMENT";
- case SCANNER_STATE_PI: return "SCANNER_STATE_PI";
- case SCANNER_STATE_CONTENT: return "SCANNER_STATE_CONTENT";
- case SCANNER_STATE_REFERENCE: return "SCANNER_STATE_REFERENCE";
- case SCANNER_STATE_END_OF_INPUT: return "SCANNER_STATE_END_OF_INPUT";
- case SCANNER_STATE_TERMINATED: return "SCANNER_STATE_TERMINATED";
- case SCANNER_STATE_CDATA: return "SCANNER_STATE_CDATA";
- case SCANNER_STATE_TEXT_DECL: return "SCANNER_STATE_TEXT_DECL";
- case SCANNER_STATE_ATTRIBUTE: return "SCANNER_STATE_ATTRIBUTE";
- case SCANNER_STATE_ATTRIBUTE_VALUE: return "SCANNER_STATE_ATTRIBUTE_VALUE";
- case SCANNER_STATE_START_ELEMENT_TAG: return "SCANNER_STATE_START_ELEMENT_TAG";
- case SCANNER_STATE_END_ELEMENT_TAG: return "SCANNER_STATE_END_ELEMENT_TAG";
- case SCANNER_STATE_CHARACTER_DATA: return "SCANNER_STATE_CHARACTER_DATA" ;
- }
-
- return "??? ("+state+')';
-
- } // getScannerStateName(int):String
- public String getEntityName(){
- //return the cached name
- return fCurrentEntityName;
- }
-
- /** Returns the driver name. */
- public String getDriverName(Driver driver) {
-
- if (DEBUG_DISPATCHER) {
- if (driver != null) {
- String name = driver.getClass().getName();
- int index = name.lastIndexOf('.');
- if (index != -1) {
- name = name.substring(index + 1);
- index = name.lastIndexOf('$');
- if (index != -1) {
- name = name.substring(index + 1);
- }
- }
- return name;
- }
- }
- return "null";
-
- } // getDriverName():String
-
- /**
- * Check the protocol used in the systemId against allowed protocols
- *
- * @param systemId the Id of the URI
- * @param allowedProtocols a list of allowed protocols separated by comma
- * @return the name of the protocol if rejected, null otherwise
- */
- String checkAccess(String systemId, String allowedProtocols) throws IOException {
- String baseSystemId = fEntityScanner.getBaseSystemId();
- String expandedSystemId = XMLEntityManager.expandSystemId(systemId, baseSystemId, fStrictURI);
- return SecuritySupport.checkAccess(expandedSystemId, allowedProtocols, Constants.ACCESS_EXTERNAL_ALL);
- }
-
- //
- // Classes
- //
-
- /**
- * @author Neeraj Bajaj, Sun Microsystems.
- */
- protected static final class Element {
-
- //
- // Data
- //
-
- /** Symbol. */
- public QName qname;
-
- //raw name stored as characters
- public char[] fRawname;
-
- /** The next Element entry. */
- public Element next;
-
- //
- // Constructors
- //
-
- /**
- * Constructs a new Element from the given QName and next Element
- * reference.
- */
- public Element(QName qname, Element next) {
- this.qname.setValues(qname);
- this.fRawname = qname.rawname.toCharArray();
- this.next = next;
- }
-
- } // class Element
-
- /**
- * Element stack.
- *
- * @author Neeraj Bajaj, Sun Microsystems.
- */
- protected class ElementStack2 {
-
- //
- // Data
- //
-
- /** The stack data. */
- protected QName [] fQName = new QName[20];
-
- //Element depth
- protected int fDepth;
- //total number of elements
- protected int fCount;
- //current position
- protected int fPosition;
- //Mark refers to the position
- protected int fMark;
-
- protected int fLastDepth ;
-
- //
- // Constructors
- //
-
- /** Default constructor. */
- public ElementStack2() {
- for (int i = 0; i < fQName.length; i++) {
- fQName[i] = new QName();
- }
- fMark = fPosition = 1;
- } // <init>()
-
- public void resize(){
- /**
- * int length = fElements.length;
- * Element [] temp = new Element[length * 2];
- * System.arraycopy(fElements, 0, temp, 0, length);
- * fElements = temp;
- */
- //resize QNames
- int oldLength = fQName.length;
- QName [] tmp = new QName[oldLength * 2];
- System.arraycopy(fQName, 0, tmp, 0, oldLength);
- fQName = tmp;
-
- for (int i = oldLength; i < fQName.length; i++) {
- fQName[i] = new QName();
- }
-
- }
-
-
- //
- // Public methods
- //
-
- /** Check if the element scanned during the start element
- *matches the stored element.
- *
- *@return true if the match suceeds.
- */
- public boolean matchElement(QName element) {
- //last depth is the depth when last elemnt was pushed
- //if last depth is greater than current depth
- if(DEBUG_SKIP_ALGORITHM){
- System.out.println("fLastDepth = " + fLastDepth);
- System.out.println("fDepth = " + fDepth);
- }
- boolean match = false;
- if(fLastDepth > fDepth && fDepth <= 2){
- if(DEBUG_SKIP_ALGORITHM){
- System.out.println("Checking if the elements match " + element.rawname + " , " + fQName[fDepth].rawname);
- }
- if(element.rawname == fQName[fDepth].rawname){
- fAdd = false;
- //mark this position
- //decrease the depth by 1 as arrays are 0 based
- fMark = fDepth - 1;
- //we found the match and from next element skipping will start, add 1
- fPosition = fMark + 1 ;
- match = true;
- //Once we get match decrease the count -- this was increased by nextElement()
- --fCount;
- if(DEBUG_SKIP_ALGORITHM){
- System.out.println("fAdd FALSE -- NOW ELEMENT SHOULD NOT BE ADDED");
- System.out.println("fMark = " + fMark);
- System.out.println("fPosition = " + fPosition);
- System.out.println("fDepth = " + fDepth);
- System.out.println("fCount = " + fCount);
- }
- }else{
- fAdd = true;
- if(DEBUG_SKIP_ALGORITHM)System.out.println("fAdd is " + fAdd);
- }
- }
- //store the last depth
- fLastDepth = fDepth++;
- return match;
- } // pushElement(QName):QName
-
- /**
- * This function doesn't increase depth. The function in this function is
- *broken down into two functions for efficiency. <@see>matchElement</see>.
- * This function just returns the pointer to the object and its values are set.
- *
- *@return QName reference to the next element in the list
- */
- public QName nextElement() {
-
- //if number of elements becomes equal to the length of array -- stop the skipping
- if (fCount == fQName.length) {
- fShouldSkip = false;
- fAdd = false;
- if(DEBUG_SKIP_ALGORITHM)System.out.println("SKIPPING STOPPED, fShouldSkip = " + fShouldSkip);
- //xxx: this is not correct, we are returning the last element
- //this wont make any difference since flag has been set to 'false'
- return fQName[--fCount];
- }
- if(DEBUG_SKIP_ALGORITHM){
- System.out.println("fCount = " + fCount);
- }
- return fQName[fCount++];
-
- }
-
- /** Note that this function is considerably different than nextElement()
- * This function just returns the previously stored elements
- */
- public QName getNext(){
- //when position reaches number of elements in the list..
- //set the position back to mark, making it a circular linked list.
- if(fPosition == fCount){
- fPosition = fMark;
- }
- return fQName[fPosition++];
- }
-
- /** returns the current depth
- */
- public int popElement(){
- return fDepth--;
- }
-
-
- /** Clears the stack without throwing away existing QName objects. */
- public void clear() {
- fLastDepth = 0;
- fDepth = 0;
- fCount = 0 ;
- fPosition = fMark = 1;
- } // clear()
-
- } // class ElementStack
-
- /**
- * Element stack. This stack operates without synchronization, error
- * checking, and it re-uses objects instead of throwing popped items
- * away.
- *
- * @author Andy Clark, IBM
- */
- protected class ElementStack {
-
- //
- // Data
- //
-
- /** The stack data. */
- protected QName[] fElements;
- protected int [] fInt = new int[20];
-
-
- //Element depth
- protected int fDepth;
- //total number of elements
- protected int fCount;
- //current position
- protected int fPosition;
- //Mark refers to the position
- protected int fMark;
-
- protected int fLastDepth ;
-
- //
- // Constructors
- //
-
- /** Default constructor. */
- public ElementStack() {
- fElements = new QName[20];
- for (int i = 0; i < fElements.length; i++) {
- fElements[i] = new QName();
- }
- } // <init>()
-
- //
- // Public methods
- //
-
- /**
- * Pushes an element on the stack.
- * <p>
- * <strong>Note:</strong> The QName values are copied into the
- * stack. In other words, the caller does <em>not</em> orphan
- * the element to the stack. Also, the QName object returned
- * is <em>not</em> orphaned to the caller. It should be
- * considered read-only.
- *
- * @param element The element to push onto the stack.
- *
- * @return Returns the actual QName object that stores the
- */
- //XXX: THIS FUNCTION IS NOT USED
- public QName pushElement(QName element) {
- if (fDepth == fElements.length) {
- QName[] array = new QName[fElements.length * 2];
- System.arraycopy(fElements, 0, array, 0, fDepth);
- fElements = array;
- for (int i = fDepth; i < fElements.length; i++) {
- fElements[i] = new QName();
- }
- }
- fElements[fDepth].setValues(element);
- return fElements[fDepth++];
- } // pushElement(QName):QName
-
-
- /** Note that this function is considerably different than nextElement()
- * This function just returns the previously stored elements
- */
- public QName getNext(){
- //when position reaches number of elements in the list..
- //set the position back to mark, making it a circular linked list.
- if(fPosition == fCount){
- fPosition = fMark;
- }
- //store the position of last opened tag at particular depth
- //fInt[++fDepth] = fPosition;
- if(DEBUG_SKIP_ALGORITHM){
- System.out.println("Element at fPosition = " + fPosition + " is " + fElements[fPosition].rawname);
- }
- //return fElements[fPosition++];
- return fElements[fPosition];
- }
-
- /** This function should be called only when element was skipped sucessfully.
- * 1. Increase the depth - because element was sucessfully skipped.
- *2. Store the position of the element token in array "last opened tag" at depth.
- *3. increase the position counter so as to point to the next element in the array
- */
- public void push(){
-
- fInt[++fDepth] = fPosition++;
- }
-
- /** Check if the element scanned during the start element
- *matches the stored element.
- *
- *@return true if the match suceeds.
- */
- public boolean matchElement(QName element) {
- //last depth is the depth when last elemnt was pushed
- //if last depth is greater than current depth
- //if(DEBUG_SKIP_ALGORITHM){
- // System.out.println("Check if the element " + element.rawname + " matches");
- // System.out.println("fLastDepth = " + fLastDepth);
- // System.out.println("fDepth = " + fDepth);
- //}
- boolean match = false;
- if(fLastDepth > fDepth && fDepth <= 3){
- if(DEBUG_SKIP_ALGORITHM){
- System.out.println("----------ENTERED THE LOOP WHERE WE CHECK FOR MATCHING OF ELMENT-----");
- System.out.println("Depth = " + fDepth + " Checking if INCOMING element " + element.rawname + " match STORED ELEMENT " + fElements[fDepth - 1].rawname);
- }
- if(element.rawname == fElements[fDepth - 1].rawname){
- fAdd = false;
- //mark this position
- //decrease the depth by 1 as arrays are 0 based
- fMark = fDepth - 1;
- //we found the match
- fPosition = fMark;
- match = true;
- //Once we get match decrease the count -- this was increased by nextElement()
- --fCount;
- if(DEBUG_SKIP_ALGORITHM){
- System.out.println("NOW ELEMENT SHOULD NOT BE ADDED, fAdd is set to false");
- System.out.println("fMark = " + fMark);
- System.out.println("fPosition = " + fPosition);
- System.out.println("fDepth = " + fDepth);
- System.out.println("fCount = " + fCount);
- System.out.println("---------MATCH SUCEEDED-----------------");
- System.out.println("");
- }
- }else{
- fAdd = true;
- if(DEBUG_SKIP_ALGORITHM)System.out.println("fAdd is " + fAdd);
- }
- }
- //store the position for the current depth
- //when we are adding the elements, when skipping
- //starts even then this should be tracked ie. when
- //calling getNext()
- if(match){
- //from next element skipping will start, add 1
- fInt[fDepth] = fPosition++;
- } else{
- if(DEBUG_SKIP_ALGORITHM){
- System.out.println("At depth = " + fDepth + "array position is = " + (fCount - 1));
- }
- //sicne fInt[fDepth] contains pointer to the element array which are 0 based.
- fInt[fDepth] = fCount - 1;
- }
-
- //if number of elements becomes equal to the length of array -- stop the skipping
- //xxx: should we do "fCount == fInt.length"
- if (fCount == fElements.length) {
- fSkip = false;
- fAdd = false;
- //reposition the stack -- it seems to be too complex document and there is no symmerty in structure
- reposition();
- if(DEBUG_SKIP_ALGORITHM){
- System.out.println("ALL THE ELMENTS IN ARRAY HAVE BEEN FILLED");
- System.out.println("REPOSITIONING THE STACK");
- System.out.println("-----------SKIPPING STOPPED----------");
- System.out.println("");
- }
- return false;
- }
- if(DEBUG_SKIP_ALGORITHM){
- if(match){
- System.out.println("Storing fPosition = " + fInt[fDepth] + " at fDepth = " + fDepth);
- }else{
- System.out.println("Storing fCount = " + fInt[fDepth] + " at fDepth = " + fDepth);
- }
- }
- //store the last depth
- fLastDepth = fDepth;
- return match;
- } // matchElement(QName):QName
-
-
- /**
- * Returns the next element on the stack.
- *
- * @return Returns the actual QName object. Callee should
- * use this object to store the details of next element encountered.
- */
- public QName nextElement() {
- if(fSkip){
- fDepth++;
- //boundary checks are done in matchElement()
- return fElements[fCount++];
- } else if (fDepth == fElements.length) {
- QName[] array = new QName[fElements.length * 2];
- System.arraycopy(fElements, 0, array, 0, fDepth);
- fElements = array;
- for (int i = fDepth; i < fElements.length; i++) {
- fElements[i] = new QName();
- }
- }
-
- return fElements[fDepth++];
-
- } // pushElement(QName):QName
-
-
- /**
- * Pops an element off of the stack by setting the values of
- * the specified QName.
- * <p>
- * <strong>Note:</strong> The object returned is <em>not</em>
- * orphaned to the caller. Therefore, the caller should consider
- * the object to be read-only.
- */
- public QName popElement() {
- //return the same object that was pushed -- this would avoid
- //setting the values for every end element.
- //STRONG: this object is read only -- this object reference shouldn't be stored.
- if(fSkip || fAdd ){
- if(DEBUG_SKIP_ALGORITHM){
- System.out.println("POPPING Element, at position " + fInt[fDepth] + " element at that count is = " + fElements[fInt[fDepth]].rawname);
- System.out.println("");
- }
- return fElements[fInt[fDepth--]];
- } else{
- if(DEBUG_SKIP_ALGORITHM){
- System.out.println("Retrieveing element at depth = " + fDepth + " is " + fElements[fDepth].rawname );
- }
- return fElements[--fDepth] ;
- }
- //element.setValues(fElements[--fDepth]);
- } // popElement(QName)
-
- /** Reposition the stack. fInt [] contains all the opened tags at particular depth.
- * Transfer all the opened tags starting from depth '2' to the current depth and reposition them
- *as per the depth.
- */
- public void reposition(){
- for( int i = 2 ; i <= fDepth ; i++){
- fElements[i-1] = fElements[fInt[i]];
- }
- if(DEBUG_SKIP_ALGORITHM){
- for( int i = 0 ; i < fDepth ; i++){
- System.out.println("fElements[" + i + "]" + " = " + fElements[i].rawname);
- }
- }
- }
-
- /** Clears the stack without throwing away existing QName objects. */
- public void clear() {
- fDepth = 0;
- fLastDepth = 0;
- fCount = 0 ;
- fPosition = fMark = 1;
-
- } // clear()
-
- /**
- * This function is as a result of optimization done for endElement --
- * we dont need to set the value for every end element encouterd.
- * For Well formedness checks we can have the same QName object that was pushed.
- * the values will be set only if application need to know about the endElement
- * -- neeraj.bajaj@sun.com
- */
-
- public QName getLastPoppedElement(){
- return fElements[fDepth];
- }
- } // class ElementStack
-
- /**
- * Drives the parser to the next state/event on the input. Parser is guaranteed
- * to stop at the next state/event.
- *
- * Internally XML document is divided into several states. Each state represents
- * a sections of XML document. When this functions returns normally, it has read
- * the section of XML document and returns the state corresponding to section of
- * document which has been read. For optimizations, a particular driver
- * can read ahead of the section of document (state returned) just read and
- * can maintain a different internal state.
- *
- *
- * @author Neeraj Bajaj, Sun Microsystems
- */
- protected interface Driver {
-
-
- /**
- * Drives the parser to the next state/event on the input. Parser is guaranteed
- * to stop at the next state/event.
- *
- * Internally XML document is divided into several states. Each state represents
- * a sections of XML document. When this functions returns normally, it has read
- * the section of XML document and returns the state corresponding to section of
- * document which has been read. For optimizations, a particular driver
- * can read ahead of the section of document (state returned) just read and
- * can maintain a different internal state.
- *
- * @return state representing the section of document just read.
- *
- * @throws IOException Thrown on i/o error.
- * @throws XNIException Thrown on parse error.
- */
-
- public int next() throws IOException, XNIException;
-
- } // interface Driver
-
- /**
- * Driver to handle content scanning. This driver is capable of reading
- * the fragment of XML document. When it has finished reading fragment
- * of XML documents, it can pass the job of reading to another driver.
- *
- * This class has been modified as per the new design which is more suited to
- * efficiently build pull parser. Lot of performance improvements have been done and
- * the code has been added to support stax functionality/features.
- *
- * @author Neeraj Bajaj, Sun Microsystems
- *
- *
- * @author Andy Clark, IBM
- * @author Eric Ye, IBM
- */
- protected class FragmentContentDriver
- implements Driver {
-
- //
- // Driver methods
- //
-
- /**
- * decides the appropriate state of the parser
- */
- private void startOfMarkup() throws IOException {
- fMarkupDepth++;
- final int ch = fEntityScanner.peekChar();
-
- if (isValidNameStartChar(ch) || isValidNameStartHighSurrogate(ch)) {
- setScannerState(SCANNER_STATE_START_ELEMENT_TAG);
- } else {
- switch(ch){
- case '?' :{
- setScannerState(SCANNER_STATE_PI);
- fEntityScanner.skipChar(ch, null);
- break;
- }
- case '!' :{
- fEntityScanner.skipChar(ch, null);
- if (fEntityScanner.skipChar('-', null)) {
- if (!fEntityScanner.skipChar('-', NameType.COMMENT)) {
- reportFatalError("InvalidCommentStart",
- null);
- }
- setScannerState(SCANNER_STATE_COMMENT);
- } else if (fEntityScanner.skipString(cdata)) {
- setScannerState(SCANNER_STATE_CDATA );
- } else if (!scanForDoctypeHook()) {
- reportFatalError("MarkupNotRecognizedInContent",
- null);
- }
- break;
- }
- case '/' :{
- setScannerState(SCANNER_STATE_END_ELEMENT_TAG);
- fEntityScanner.skipChar(ch, NameType.ELEMENTEND);
- break;
- }
- default :{
- reportFatalError("MarkupNotRecognizedInContent", null);
- }
- }
- }
-
- }//startOfMarkup
-
- private void startOfContent() throws IOException {
- if (fEntityScanner.skipChar('<', null)) {
- setScannerState(SCANNER_STATE_START_OF_MARKUP);
- } else if (fEntityScanner.skipChar('&', NameType.REFERENCE)) {
- setScannerState(SCANNER_STATE_REFERENCE) ; //XMLEvent.ENTITY_REFERENCE ); //SCANNER_STATE_REFERENCE
- } else {
- //element content is there..
- setScannerState(SCANNER_STATE_CHARACTER_DATA);
- }
- }//startOfContent
-
-
- /**
- *
- * SCANNER_STATE_CONTENT and SCANNER_STATE_START_OF_MARKUP are two super states of the parser.
- * At any point of time when in doubt over the current state of the parser, the state should be
- * set to SCANNER_STATE_CONTENT. Parser will automatically revive itself and will set state of
- * the parser to one of its sub state.
- * sub states are defined in the parser on the basis of different XML component like
- * SCANNER_STATE_ENTITY_REFERENCE , SCANNER_STATE_START_ELEMENT, SCANNER_STATE_CDATA etc..
- * These sub states help the parser to have fine control over the parsing. These are the
- * different milepost, parser stops at each sub state (milepost). Based on this state it is
- * decided if paresr needs to stop at next milepost ??
- *
- */
- public void decideSubState() throws IOException {
- while( fScannerState == SCANNER_STATE_CONTENT || fScannerState == SCANNER_STATE_START_OF_MARKUP){
-
- switch (fScannerState) {
-
- case SCANNER_STATE_CONTENT: {
- startOfContent() ;
- break;
- }
-
- case SCANNER_STATE_START_OF_MARKUP: {
- startOfMarkup() ;
- break;
- }
- }
- }
- }//decideSubState
-
- /**
- * Drives the parser to the next state/event on the input. Parser is guaranteed
- * to stop at the next state/event. Internally XML document
- * is divided into several states. Each state represents a sections of XML
- * document. When this functions returns normally, it has read the section
- * of XML document and returns the state corresponding to section of
- * document which has been read. For optimizations, a particular driver
- * can read ahead of the section of document (state returned) just read and
- * can maintain a different internal state.
- *
- * State returned corresponds to Stax states.
- *
- * @return state representing the section of document just read.
- *
- * @throws IOException Thrown on i/o error.
- * @throws XNIException Thrown on parse error.
- */
-
- public int next() throws IOException, XNIException {
- while (true) {
- try {
- if(DEBUG_NEXT){
- System.out.println("NOW IN FragmentContentDriver");
- System.out.println("Entering the FragmentContentDriver with = " + getScannerStateName(fScannerState));
- }
-
- //decide the actual sub state of the scanner.For more information refer to the javadoc of
- //decideSubState.
-
- switch (fScannerState) {
- case SCANNER_STATE_CONTENT: {
- final int ch = fEntityScanner.peekChar();
- if (ch == '<') {
- fEntityScanner.scanChar(null);
- setScannerState(SCANNER_STATE_START_OF_MARKUP);
- } else if (ch == '&') {
- fEntityScanner.scanChar(NameType.REFERENCE);
- setScannerState(SCANNER_STATE_REFERENCE) ; //XMLEvent.ENTITY_REFERENCE ); //SCANNER_STATE_REFERENCE
- break;
- } else {
- //element content is there..
- setScannerState(SCANNER_STATE_CHARACTER_DATA);
- break;
- }
- }
-
- case SCANNER_STATE_START_OF_MARKUP: {
- startOfMarkup();
- break;
- }//case: SCANNER_STATE_START_OF_MARKUP
-
- }//end of switch
- //decideSubState() ;
-
- //do some special handling if isCoalesce is set to true.
- if(fIsCoalesce){
- fUsebuffer = true ;
- //if the last section was character data
- if(fLastSectionWasCharacterData){
-
- //if we dont encounter any CDATA or ENITY REFERENCE and current state is also not SCANNER_STATE_CHARACTER_DATA
- //return the last scanned charactrer data.
- if((fScannerState != SCANNER_STATE_CDATA) && (fScannerState != SCANNER_STATE_REFERENCE)
- && (fScannerState != SCANNER_STATE_CHARACTER_DATA)){
- fLastSectionWasCharacterData = false;
- return XMLEvent.CHARACTERS;
- }
- }//if last section was CDATA or ENTITY REFERENCE
- //xxx: there might be another entity reference or CDATA after this
- //<foo>blah blah &amp;&lt;<![CDATA[[aa]]>blah blah</foo>
- else if((fLastSectionWasCData || fLastSectionWasEntityReference)){
- //and current state is not SCANNER_STATE_CHARACTER_DATA
- //or SCANNER_STATE_CDATA or SCANNER_STATE_REFERENCE
- //this means there is nothing more to be coalesced.
- //return the CHARACTERS event.
- if((fScannerState != SCANNER_STATE_CDATA) && (fScannerState != SCANNER_STATE_REFERENCE)
- && (fScannerState != SCANNER_STATE_CHARACTER_DATA)){
-
- fLastSectionWasCData = false;
- fLastSectionWasEntityReference = false;
- return XMLEvent.CHARACTERS;
- }
- }
- }
-
-
- if(DEBUG_NEXT){
- System.out.println("Actual scanner state set by decideSubState is = " + getScannerStateName(fScannerState));
- }
-
- switch(fScannerState){
-
- case XMLEvent.START_DOCUMENT :
- return XMLEvent.START_DOCUMENT;
-
- case SCANNER_STATE_START_ELEMENT_TAG :{
-
- //xxx this function returns true when element is empty.. can be linked to end element event.
- //returns true if the element is empty
- fEmptyElement = scanStartElement() ;
- //if the element is empty the next event is "end element"
- if(fEmptyElement){
- setScannerState(SCANNER_STATE_END_ELEMENT_TAG);
- }else{
- //set the next possible state
- setScannerState(SCANNER_STATE_CONTENT);
- }
- return XMLEvent.START_ELEMENT ;
- }
-
- case SCANNER_STATE_CHARACTER_DATA: {
- if(DEBUG_COALESCE){
- System.out.println("fLastSectionWasCData = " + fLastSectionWasCData);
- System.out.println("fIsCoalesce = " + fIsCoalesce);
- }
- //if last section was either entity reference or cdata or character data we should be using buffer
- fUsebuffer = fLastSectionWasEntityReference || fLastSectionWasCData || fLastSectionWasCharacterData ;
-
- //When coalesce is set to true and last state was REFERENCE or CDATA or CHARACTER_DATA, buffer should not be cleared.
- if( fIsCoalesce && (fLastSectionWasEntityReference || fLastSectionWasCData || fLastSectionWasCharacterData) ){
- fLastSectionWasEntityReference = false;
- fLastSectionWasCData = false;
- fLastSectionWasCharacterData = true ;
- fUsebuffer = true;
- }else{
- //clear the buffer
- fContentBuffer.clear();
- }
-
- //set the fTempString length to 0 before passing it on to scanContent
- //scanContent sets the correct co-ordinates as per the content read
- fTempString.length = 0;
- int c = fEntityScanner.scanContent(fTempString);
- if(DEBUG){
- System.out.println("fTempString = " + fTempString);
- }
- if(fEntityScanner.skipChar('<', null)){
- //check if we have reached end of element
- if(fEntityScanner.skipChar('/', NameType.ELEMENTEND)){
- //increase the mark up depth
- fMarkupDepth++;
- fLastSectionWasCharacterData = false;
- setScannerState(SCANNER_STATE_END_ELEMENT_TAG);
- //check if its start of new element
- }else if(XMLChar.isNameStart(fEntityScanner.peekChar())){
- fMarkupDepth++;
- fLastSectionWasCharacterData = false;
- setScannerState(SCANNER_STATE_START_ELEMENT_TAG);
- }else{
- setScannerState(SCANNER_STATE_START_OF_MARKUP);
- //there can be cdata ahead if coalesce is true we should call again
- if(fIsCoalesce){
- fUsebuffer = true;
- fLastSectionWasCharacterData = true;
- fContentBuffer.append(fTempString);
- fTempString.length = 0;
- continue;
- }
- }
- //in case last section was either entity reference or cdata or character data -- we should be using buffer
- if(fUsebuffer){
- fContentBuffer.append(fTempString);
- fTempString.length = 0;
- }
- if(DEBUG){
- System.out.println("NOT USING THE BUFFER, STRING = " + fTempString.toString());
- }
- if(dtdGrammarUtil!= null && dtdGrammarUtil.isIgnorableWhiteSpace(fContentBuffer)){
- if(DEBUG)System.out.println("Return SPACE EVENT");
- return XMLEvent.SPACE;
- }else
- return XMLEvent.CHARACTERS;
-
- } else{
- fUsebuffer = true ;
- if(DEBUG){
- System.out.println("fContentBuffer = " + fContentBuffer);
- System.out.println("fTempString = " + fTempString);
- }
- fContentBuffer.append(fTempString);
- fTempString.length = 0;
- }
- if (c == '\r') {
- if(DEBUG){
- System.out.println("'\r' character found");
- }
- // happens when there is the character reference &#13;
- //xxx: We know the next chracter.. we should just skip it and add ']' directlry
- fEntityScanner.scanChar(null);
- fUsebuffer = true;
- fContentBuffer.append((char)c);
- c = -1 ;
- } else if (c == ']') {
- //fStringBuffer.clear();
- //xxx: We know the next chracter.. we should just skip it and add ']' directlry
- fUsebuffer = true;
- fContentBuffer.append((char)fEntityScanner.scanChar(null));
- // remember where we are in case we get an endEntity before we
- // could flush the buffer out - this happens when we're parsing an
- // entity which ends with a ]
- fInScanContent = true;
-
- // We work on a single character basis to handle cases such as:
- // ']]]>' which we might otherwise miss.
- //
- if (fEntityScanner.skipChar(']', null)) {
- fContentBuffer.append(']');
- while (fEntityScanner.skipChar(']', null)) {
- fContentBuffer.append(']');
- }
- if (fEntityScanner.skipChar('>', null)) {
- reportFatalError("CDEndInContent", null);
- }
- }
- c = -1 ;
- fInScanContent = false;
- }
-
- do{
- //xxx: we should be using only one buffer..
- // we need not to grow the buffer only when isCoalesce() is not true;
-
- if (c == '<') {
- fEntityScanner.scanChar(null);
- setScannerState(SCANNER_STATE_START_OF_MARKUP);
- break;
- }//xxx what should be the behavior if entity reference is present in the content ?
- else if (c == '&') {
- fEntityScanner.scanChar(NameType.REFERENCE);
- setScannerState(SCANNER_STATE_REFERENCE);
- break;
- }///xxx since this part is also characters, it should be merged...
- else if (c != -1 && isInvalidLiteral(c)) {
- if (XMLChar.isHighSurrogate(c)) {
- // special case: surrogates
- scanSurrogates(fContentBuffer) ;
- setScannerState(SCANNER_STATE_CONTENT);
- } else {
- reportFatalError("InvalidCharInContent",
- new Object[] {
- Integer.toString(c, 16)});
- fEntityScanner.scanChar(null);
- }
- break;
- }
- //xxx: scanContent also gives character callback.
- c = scanContent(fContentBuffer) ;
- //we should not be iterating again if fIsCoalesce is not set to true
-
- if(!fIsCoalesce){
- setScannerState(SCANNER_STATE_CONTENT);
- break;
- }
-
- }while(true);
-
- //if (fDocumentHandler != null) {
- // fDocumentHandler.characters(fContentBuffer, null);
- //}
- if(DEBUG)System.out.println("USING THE BUFFER, STRING START=" + fContentBuffer.toString() +"=END");
- //if fIsCoalesce is true there might be more data so call fDriver.next()
- if(fIsCoalesce){
- fLastSectionWasCharacterData = true ;
- continue;
- }else{
- if(dtdGrammarUtil!= null && dtdGrammarUtil.isIgnorableWhiteSpace(fContentBuffer)){
- if(DEBUG)System.out.println("Return SPACE EVENT");
- return XMLEvent.SPACE;
- } else
- return XMLEvent.CHARACTERS ;
- }
- }
-
- case SCANNER_STATE_END_ELEMENT_TAG :{
- if(fEmptyElement){
- //set it back to false.
- fEmptyElement = false;
- setScannerState(SCANNER_STATE_CONTENT);
- //check the case when there is comment after single element document
- //<foo/> and some comment after this
- return (fMarkupDepth == 0 && elementDepthIsZeroHook() ) ? XMLEvent.END_ELEMENT : XMLEvent.END_ELEMENT ;
-
- } else if(scanEndElement() == 0) {
- //It is last element of the document
- if (elementDepthIsZeroHook()) {
- //if element depth is zero , it indicates the end of the document
- //the state shouldn't be set, because it is set by elementDepthIsZeroHook() function
- //xxx understand this point once again..
- return XMLEvent.END_ELEMENT ;
- }
-
- }
- setScannerState(SCANNER_STATE_CONTENT);
- return XMLEvent.END_ELEMENT ;
- }
-
- case SCANNER_STATE_COMMENT: { //SCANNER_STATE_COMMENT:
- scanComment();
- setScannerState(SCANNER_STATE_CONTENT);
- return XMLEvent.COMMENT;
- //break;
- }
- case SCANNER_STATE_PI:{ //SCANNER_STATE_PI: {
- //clear the buffer first
- fContentBuffer.clear() ;
- //xxx: which buffer should be passed. Ideally we shouldn't have
- //more than two buffers --
- //xxx: where should we add the switch for buffering.
- scanPI(fContentBuffer);
- setScannerState(SCANNER_STATE_CONTENT);
- return XMLEvent.PROCESSING_INSTRUCTION;
- //break;
- }
- case SCANNER_STATE_CDATA :{ //SCANNER_STATE_CDATA: {
- //xxx: What if CDATA is the first event
- //<foo><![CDATA[hello<><>]]>append</foo>
-
- //we should not clear the buffer only when the last state was either SCANNER_STATE_REFERENCE or
- //SCANNER_STATE_CHARACTER_DATA or SCANNER_STATE_REFERENCE
- if(fIsCoalesce && ( fLastSectionWasEntityReference || fLastSectionWasCData || fLastSectionWasCharacterData)){
- fLastSectionWasCData = true ;
- fLastSectionWasEntityReference = false;
- fLastSectionWasCharacterData = false;
- }//if we dont need to coalesce clear the buffer
- else{
- fContentBuffer.clear();
- }
- fUsebuffer = true;
- //CDATA section is completely read in all the case.
- scanCDATASection(fContentBuffer , true);
- setScannerState(SCANNER_STATE_CONTENT);
- //1. if fIsCoalesce is set to true we set the variable fLastSectionWasCData to true
- //and just call fDispatche.next(). Since we have set the scanner state to
- //SCANNER_STATE_CONTENT (super state) parser will automatically recover and
- //behave appropriately. When isCoalesce is set to true we dont need to reportCDATA event
- //2. Check if application has set for reporting CDATA event
- //3. if the application has neither set the fIsCoalesce to true nor fReportCdataEvent
- //return the cdata event as characters.
- if(fIsCoalesce){
- fLastSectionWasCData = true ;
- //there might be more data to coalesce.
- continue;
- }else if(fReportCdataEvent){
- return XMLEvent.CDATA;
- } else{
- return XMLEvent.CHARACTERS;
- }
- }
-
- case SCANNER_STATE_REFERENCE :{
- fMarkupDepth++;
- foundBuiltInRefs = false;
-
- //we should not clear the buffer only when the last state was either CDATA or
- //SCANNER_STATE_CHARACTER_DATA or SCANNER_STATE_REFERENCE
- if(fIsCoalesce && ( fLastSectionWasEntityReference || fLastSectionWasCData || fLastSectionWasCharacterData)){
- //fLastSectionWasEntityReference or fLastSectionWasCData are only
- //used when fIsCoalesce is set to true.
- fLastSectionWasEntityReference = true ;
- fLastSectionWasCData = false;
- fLastSectionWasCharacterData = false;
- }//if we dont need to coalesce clear the buffer
- else{
- fContentBuffer.clear();
- }
- fUsebuffer = true ;
- //take care of character reference
- if (fEntityScanner.skipChar('#', NameType.REFERENCE)) {
- scanCharReferenceValue(fContentBuffer, null);
- fMarkupDepth--;
- if(!fIsCoalesce){
- setScannerState(SCANNER_STATE_CONTENT);
- return XMLEvent.CHARACTERS;
- }
- } else {
- // this function also starts new entity
- scanEntityReference(fContentBuffer);
- //if there was built-in entity reference & coalesce is not true
- //return CHARACTERS
- if(fScannerState == SCANNER_STATE_BUILT_IN_REFS && !fIsCoalesce){
- setScannerState(SCANNER_STATE_CONTENT);
- return XMLEvent.CHARACTERS;
- }
-
- //if there was a text declaration, call next() it will be taken care.
- if(fScannerState == SCANNER_STATE_TEXT_DECL){
- fLastSectionWasEntityReference = true ;
- continue;
- }
-
- if(fScannerState == SCANNER_STATE_REFERENCE){
- setScannerState(SCANNER_STATE_CONTENT);
- if (fReplaceEntityReferences && fEntityStore.isDeclaredEntity(fCurrentEntityName)) {
- // Skip the entity reference, we don't care
- continue;
- }
- return XMLEvent.ENTITY_REFERENCE;
- }
- }
- //Wether it was character reference, entity reference or built-in entity
- //set the next possible state to SCANNER_STATE_CONTENT
- setScannerState(SCANNER_STATE_CONTENT);
- fLastSectionWasEntityReference = true ;
- continue;
- }
-
- case SCANNER_STATE_TEXT_DECL: {
- // scan text decl
- if (fEntityScanner.skipString("<?xml")) {
- fMarkupDepth++;
- // NOTE: special case where entity starts with a PI
- // whose name starts with "xml" (e.g. "xmlfoo")
- if (isValidNameChar(fEntityScanner.peekChar())) {
- fStringBuffer.clear();
- fStringBuffer.append("xml");
-
- if (fNamespaces) {
- while (isValidNCName(fEntityScanner.peekChar())) {
- fStringBuffer.append((char)fEntityScanner.scanChar(null));
- }
- } else {
- while (isValidNameChar(fEntityScanner.peekChar())) {
- fStringBuffer.append((char)fEntityScanner.scanChar(null));
- }
- }
- String target = fSymbolTable.addSymbol(fStringBuffer.ch, fStringBuffer.offset, fStringBuffer.length);
- fContentBuffer.clear();
- scanPIData(target, fContentBuffer);
- }
-
- // standard text declaration
- else {
- //xxx: this function gives callback
- scanXMLDeclOrTextDecl(true);
- }
- }
- // now that we've straightened out the readers, we can read in chunks:
- fEntityManager.fCurrentEntity.mayReadChunks = true;
- setScannerState(SCANNER_STATE_CONTENT);
- //xxx: we don't return any state, so how do we get to know about TEXT declarations.
- //it seems we have to careful when to allow function issue a callback
- //and when to allow adapter issue a callback.
- continue;
- }
-
-
- case SCANNER_STATE_ROOT_ELEMENT: {
- if (scanRootElementHook()) {
- fEmptyElement = true;
- //rest would be taken care by fTrailingMiscDriver set by scanRootElementHook
- return XMLEvent.START_ELEMENT;
- }
- setScannerState(SCANNER_STATE_CONTENT);
- return XMLEvent.START_ELEMENT ;
- }
- case SCANNER_STATE_CHAR_REFERENCE : {
- fContentBuffer.clear();
- scanCharReferenceValue(fContentBuffer, null);
- fMarkupDepth--;
- setScannerState(SCANNER_STATE_CONTENT);
- return XMLEvent.CHARACTERS;
- }
- default:
- throw new XNIException("Scanner State " + fScannerState + " not Recognized ");
-
- }//switch
- }
- // premature end of file
- catch (EOFException e) {
- endOfFileHook(e);
- return -1;
- }
- } //while loop
- }//next
-
- //
- // Protected methods
- //
-
- // hooks
-
- // NOTE: These hook methods are added so that the full document
- // scanner can share the majority of code with this class.
-
- /**
- * Scan for DOCTYPE hook. This method is a hook for subclasses
- * to add code to handle scanning for a the "DOCTYPE" string
- * after the string "<!" has been scanned.
- *
- * @return True if the "DOCTYPE" was scanned; false if "DOCTYPE"
- * was not scanned.
- */
- protected boolean scanForDoctypeHook()
- throws IOException, XNIException {
- return false;
- } // scanForDoctypeHook():boolean
-
- /**
- * Element depth iz zero. This methos is a hook for subclasses
- * to add code to handle when the element depth hits zero. When
- * scanning a document fragment, an element depth of zero is
- * normal. However, when scanning a full XML document, the
- * scanner must handle the trailing miscellanous section of
- * the document after the end of the document's root element.
- *
- * @return True if the caller should stop and return true which
- * allows the scanner to switch to a new scanning
- * driver. A return value of false indicates that
- * the content driver should continue as normal.
- */
- protected boolean elementDepthIsZeroHook()
- throws IOException, XNIException {
- return false;
- } // elementDepthIsZeroHook():boolean
-
- /**
- * Scan for root element hook. This method is a hook for
- * subclasses to add code that handles scanning for the root
- * element. When scanning a document fragment, there is no
- * "root" element. However, when scanning a full XML document,
- * the scanner must handle the root element specially.
- *
- * @return True if the caller should stop and return true which
- * allows the scanner to switch to a new scanning
- * driver. A return value of false indicates that
- * the content driver should continue as normal.
- */
- protected boolean scanRootElementHook()
- throws IOException, XNIException {
- return false;
- } // scanRootElementHook():boolean
-
- /**
- * End of file hook. This method is a hook for subclasses to
- * add code that handles the end of file. The end of file in
- * a document fragment is OK if the markup depth is zero.
- * However, when scanning a full XML document, an end of file
- * is always premature.
- */
- protected void endOfFileHook(EOFException e)
- throws IOException, XNIException {
-
- // NOTE: An end of file is only only an error if we were
- // in the middle of scanning some markup. -Ac
- if (fMarkupDepth != 0) {
- reportFatalError("PrematureEOF", null);
- }
-
- } // endOfFileHook()
-
- } // class FragmentContentDriver
-
- static void pr(String str) {
- System.out.println(str) ;
- }
-
- protected boolean fUsebuffer ;
-
- /** this function gets an XMLString (which is used to store the attribute value) from the special pool
- * maintained for attributes.
- * fAttributeCacheUsedCount tracks the number of attributes that has been consumed from the pool.
- * if all the attributes has been consumed, it adds a new XMLString inthe pool and returns the same
- * XMLString.
- *
- * @return XMLString XMLString used to store an attribute value.
- */
-
- protected XMLString getString(){
- if(fAttributeCacheUsedCount < initialCacheCount || fAttributeCacheUsedCount < attributeValueCache.size()){
- return attributeValueCache.get(fAttributeCacheUsedCount++);
- } else{
- XMLString str = new XMLString();
- fAttributeCacheUsedCount++;
- attributeValueCache.add(str);
- return str;
- }
- }
-
- /**
- * Implements XMLBufferListener interface.
- */
-
- public void refresh(){
- refresh(0);
- }
-
- /**
- * receives callbacks from {@link XMLEntityReader } when buffer
- * is being changed.
- * @param refreshPosition
- */
- public void refresh(int refreshPosition){
- //If you are reading attributes and you got a callback
- //cache available attributes.
- if(fReadingAttributes){
- fAttributes.refresh();
- }
- if(fScannerState == SCANNER_STATE_CHARACTER_DATA){
- //since fTempString directly matches to the underlying main buffer
- //store the data into buffer
- fContentBuffer.append(fTempString);
- //clear the XMLString so that data can't be added again.
- fTempString.length = 0;
- fUsebuffer = true;
- }
- }
-
-} // class XMLDocumentFragmentScannerImpl