0001: /*
0002: * $Id: XMLDocumentScannerImpl.java,v 1.9 2007/03/16 14:48:44 spericas Exp $
0003: */
0004:
0005: /*
0006: * The contents of this file are subject to the terms
0007: * of the Common Development and Distribution License
0008: * (the License). You may not use this file except in
0009: * compliance with the License.
0010: *
0011: * You can obtain a copy of the license at
0012: * https://glassfish.dev.java.net/public/CDDLv1.0.html.
0013: * See the License for the specific language governing
0014: * permissions and limitations under the License.
0015: *
0016: * When distributing Covered Code, include this CDDL
0017: * Header Notice in each file and include the License file
0018: * at https://glassfish.dev.java.net/public/CDDLv1.0.html.
0019: * If applicable, add the following below the CDDL Header,
0020: * with the fields enclosed by brackets [] replaced by
0021: * you own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * [Name of File] [ver.__] [Date]
0025: *
0026: * Copyright 2006 Sun Microsystems Inc. All Rights Reserved
0027: */
0028:
0029: /*
0030: * The Apache Software License, Version 1.1
0031: *
0032: *
0033: * Copyright (c) 1999-2002 The Apache Software Foundation.
0034: * All rights reserved.
0035: *
0036: * Redistribution and use in source and binary forms, with or without
0037: * modification, are permitted provided that the following conditions
0038: * are met:
0039: *
0040: * 1. Redistributions of source code must retain the above copyright
0041: * notice, this list of conditions and the following disclaimer.
0042: *
0043: * 2. Redistributions in binary form must reproduce the above copyright
0044: * notice, this list of conditions and the following disclaimer in
0045: * the documentation and/or other materials provided with the
0046: * distribution.
0047: *
0048: * 3. The end-user documentation included with the redistribution,
0049: * if any, must include the following acknowledgment:
0050: * "This product includes software developed by the
0051: * Apache Software Foundation (http://www.apache.org/)."
0052: * Alternately, this acknowledgment may appear in the software itself,
0053: * if and wherever such third-party acknowledgments normally appear.
0054: *
0055: * 4. The names "Xerces" and "Apache Software Foundation" must
0056: * not be used to endorse or promote products derived from this
0057: * software without prior written permission. For written
0058: * permission, please contact apache@apache.org.
0059: *
0060: * 5. Products derived from this software may not be called "Apache",
0061: * nor may "Apache" appear in their name, without prior written
0062: * permission of the Apache Software Foundation.
0063: *
0064: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0065: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0066: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0067: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0068: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0069: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0070: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0071: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0072: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0073: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0074: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0075: * SUCH DAMAGE.
0076: * ====================================================================
0077: *
0078: * This software consists of voluntary contributions made by many
0079: * individuals on behalf of the Apache Software Foundation and was
0080: * originally based on software copyright (c) 1999, International
0081: * Business Machines, Inc., http://www.apache.org. For more
0082: * information on the Apache Software Foundation, please see
0083: * <http://www.apache.org/>.
0084: */
0085:
0086: package com.sun.xml.stream;
0087:
0088: import com.sun.xml.stream.dtd.DTDGrammarUtil;
0089: import java.io.EOFException;
0090: import java.io.IOException;
0091: import javax.xml.stream.XMLInputFactory;
0092: import javax.xml.stream.events.XMLEvent;
0093:
0094: import com.sun.xml.stream.xerces.util.NamespaceSupport;
0095: import com.sun.xml.stream.xerces.util.XMLChar;
0096: import com.sun.xml.stream.xerces.util.XMLResourceIdentifierImpl;
0097: import com.sun.xml.stream.xerces.util.XMLStringBuffer;
0098: import com.sun.xml.stream.xerces.xni.NamespaceContext;
0099: import com.sun.xml.stream.xerces.xni.XMLResourceIdentifier;
0100: import com.sun.xml.stream.xerces.xni.XMLString;
0101: import com.sun.xml.stream.xerces.xni.XNIException;
0102: import com.sun.xml.stream.xerces.xni.parser.XMLInputSource;
0103: import com.sun.xml.stream.xerces.xni.parser.XMLComponentManager;
0104: import com.sun.xml.stream.xerces.xni.parser.XMLConfigurationException;
0105: import com.sun.xml.stream.xerces.xni.parser.XMLDTDScanner;
0106:
0107: /**
0108: * This class is responsible for scanning XML document structure
0109: * and content.
0110: *
0111: * This class has been modified as per the new design which is more suited to
0112: * efficiently build pull parser. Lot of improvements have been done and
0113: * the code has been added to support stax functionality/features.
0114: *
0115: * @author Neeraj Bajaj, Sun Microsystems
0116: * @author K.Venugopal, Sun Microsystems
0117: * @author Glenn Marcy, IBM
0118: * @author Andy Clark, IBM
0119: * @author Arnaud Le Hors, IBM
0120: * @author Eric Ye, IBM
0121: * @author Sunitha Reddy, Sun Microsystems
0122: * @version $Id: XMLDocumentScannerImpl.java,v 1.9 2007/03/16 14:48:44 spericas Exp $
0123: */
0124: public class XMLDocumentScannerImpl extends
0125: XMLDocumentFragmentScannerImpl {
0126:
0127: //
0128: // Constants
0129: //
0130:
0131: // scanner states
0132:
0133: /** Scanner state: XML declaration. */
0134: protected static final int SCANNER_STATE_XML_DECL = 42;
0135:
0136: /** Scanner state: prolog. */
0137: protected static final int SCANNER_STATE_PROLOG = 43;
0138:
0139: /** Scanner state: trailing misc. */
0140: protected static final int SCANNER_STATE_TRAILING_MISC = 44;
0141:
0142: /** Scanner state: DTD internal declarations. */
0143: protected static final int SCANNER_STATE_DTD_INTERNAL_DECLS = 45;
0144:
0145: /** Scanner state: open DTD external subset. */
0146: protected static final int SCANNER_STATE_DTD_EXTERNAL = 46;
0147:
0148: /** Scanner state: DTD external declarations. */
0149: protected static final int SCANNER_STATE_DTD_EXTERNAL_DECLS = 47;
0150:
0151: /** Scanner state: NO MORE ELEMENTS. */
0152: protected static final int SCANNER_STATE_NO_SUCH_ELEMENT_EXCEPTION = 48;
0153:
0154: // feature identifiers
0155:
0156: /** Feature identifier: load external DTD. */
0157: protected static final String LOAD_EXTERNAL_DTD = Constants.XERCES_FEATURE_PREFIX
0158: + Constants.LOAD_EXTERNAL_DTD_FEATURE;
0159:
0160: /** Feature identifier: load external DTD. */
0161: protected static final String DISALLOW_DOCTYPE_DECL_FEATURE = Constants.XERCES_FEATURE_PREFIX
0162: + Constants.DISALLOW_DOCTYPE_DECL_FEATURE;
0163:
0164: // property identifiers
0165:
0166: /** Property identifier: DTD scanner. */
0167: protected static final String DTD_SCANNER = Constants.XERCES_PROPERTY_PREFIX
0168: + Constants.DTD_SCANNER_PROPERTY;
0169:
0170: // property identifier: ValidationManager
0171: protected static final String VALIDATION_MANAGER = Constants.XERCES_PROPERTY_PREFIX
0172: + Constants.VALIDATION_MANAGER_PROPERTY;
0173:
0174: // recognized features and properties
0175:
0176: /** Recognized features. */
0177: private static final String[] RECOGNIZED_FEATURES = {
0178: LOAD_EXTERNAL_DTD, DISALLOW_DOCTYPE_DECL_FEATURE, };
0179:
0180: /** Feature defaults. */
0181: private static final Boolean[] FEATURE_DEFAULTS = { Boolean.TRUE,
0182: Boolean.FALSE, };
0183:
0184: /** Recognized properties. */
0185: private static final String[] RECOGNIZED_PROPERTIES = {
0186: DTD_SCANNER, VALIDATION_MANAGER };
0187:
0188: /** Property defaults. */
0189: private static final Object[] PROPERTY_DEFAULTS = { null, null };
0190:
0191: //
0192: // Data
0193: //
0194:
0195: // properties
0196:
0197: /** DTD scanner. */
0198: protected XMLDTDScanner fDTDScanner = null;
0199: protected XMLStringBuffer fDTDDecl = null;
0200: protected boolean fReadingDTD = false;
0201: //tracks.. if end of document has reached ?
0202: protected boolean fEndOfDocument;
0203:
0204: // protected data
0205:
0206: // other info
0207:
0208: /** Doctype name. */
0209: protected String fDoctypeName;
0210:
0211: /** Doctype declaration public identifier. */
0212: protected String fDoctypePublicId;
0213:
0214: /** Doctype declaration system identifier. */
0215: protected String fDoctypeSystemId;
0216:
0217: /** Namespace support. */
0218: protected NamespaceContext fNamespaceContext = new NamespaceSupport();
0219:
0220: // features
0221:
0222: /** Load external DTD. */
0223: protected boolean fLoadExternalDTD = true;
0224:
0225: /** Disallow doctype declaration. */
0226: protected boolean fDisallowDoctype = false;
0227:
0228: // state
0229:
0230: /** Seen doctype declaration. */
0231: protected boolean fSeenDoctypeDecl;
0232:
0233: protected boolean fBindNamespaces;
0234: protected boolean fScanEndElement;
0235:
0236: protected int fScannerLastState;
0237:
0238: // drivers
0239:
0240: /** XML declaration driver. */
0241: protected Driver fXMLDeclDriver = new XMLDeclDriver();
0242:
0243: /** Prolog driver. */
0244: protected Driver fPrologDriver = new PrologDriver();
0245:
0246: /** DTD driver. */
0247: protected Driver fDTDDriver = null;
0248:
0249: /** Trailing miscellaneous section driver. */
0250: protected Driver fTrailingMiscDriver = new TrailingMiscDriver();
0251: protected int fStartPos = 0;
0252: protected int fEndPos = 0;
0253: protected boolean fSeenInternalSubset = false;
0254: // temporary variables
0255:
0256: /** Array of 3 strings. */
0257: private String[] fStrings = new String[3];
0258:
0259: /** String. */
0260: private XMLString fString = new XMLString();
0261:
0262: public static final char[] DOCTYPE = { 'D', 'O', 'C', 'T', 'Y',
0263: 'P', 'E' };
0264: public static final char[] COMMENTSTRING = { '-', '-' };
0265:
0266: protected boolean fReadingAttributes = false;
0267: protected XMLBufferListenerImpl fScannerBufferlistener = new XMLBufferListenerImpl();
0268:
0269: //
0270: // Constructors
0271: //
0272:
0273: /** Default constructor. */
0274: public XMLDocumentScannerImpl() {
0275: } // <init>()
0276:
0277: //
0278: // XMLDocumentScanner methods
0279: //
0280:
0281: /**
0282: * Sets the input source.
0283: *
0284: * @param inputSource The input source.
0285: *
0286: * @throws IOException Thrown on i/o error.
0287: */
0288: public void setInputSource(XMLInputSource inputSource)
0289: throws IOException {
0290: fEntityManager.setEntityHandler(this );
0291: //this starts a new entity and sets the current entity to the document entity.
0292: fEntityManager.startDocumentEntity(inputSource);
0293: // fDocumentSystemId = fEntityManager.expandSystemId(inputSource.getSystemId());
0294: setScannerState(XMLEvent.START_DOCUMENT);
0295: } // setInputSource(XMLInputSource)
0296:
0297: public void reset(PropertyManager propertyManager) {
0298: super .reset(propertyManager);
0299: // other settings
0300: fDoctypeName = null;
0301: fDoctypePublicId = null;
0302: fDoctypeSystemId = null;
0303: fSeenDoctypeDecl = false;
0304: fNamespaceContext.reset();
0305: fDisallowDoctype = !((Boolean) propertyManager
0306: .getProperty(XMLInputFactory.SUPPORT_DTD))
0307: .booleanValue();
0308: fBindNamespaces = ((Boolean) propertyManager
0309: .getProperty(XMLInputFactory.IS_NAMESPACE_AWARE))
0310: .booleanValue();
0311: // xerces features
0312: fLoadExternalDTD = true;
0313: //end of document false
0314: fEndOfDocument = false;
0315: setScannerState(XMLEvent.START_DOCUMENT);
0316: setDriver(fXMLDeclDriver);
0317: fSeenInternalSubset = false;
0318: if (fDTDScanner != null) {
0319: ((XMLDTDScannerImpl) fDTDScanner).reset(propertyManager);
0320: }
0321: fEndPos = 0;
0322: fStartPos = 0;
0323: if (fDTDDecl != null)
0324: fDTDDecl.clear();
0325: }
0326:
0327: /**return the state of the scanner */
0328: public int getScannetState() {
0329: return fScannerState;
0330: }
0331:
0332: /** return the next state on the input
0333: *
0334: * @return int
0335: */
0336:
0337: public int next() throws IOException, XNIException {
0338: //since namespace context should still be valid when the parser is at the end element state therefore
0339: //we pop the context only when next() has been called after the end element state was encountered. - nb.
0340:
0341: if ((fScannerLastState == XMLEvent.END_ELEMENT)
0342: && fBindNamespaces) {
0343: fScannerLastState = -1;
0344: fNamespaceContext.popContext();
0345: }
0346:
0347: return fScannerLastState = fDriver.next();
0348: }
0349:
0350: /**
0351: * Resets the component. The component can query the component manager
0352: * about any features and properties that affect the operation of the
0353: * component.
0354: *
0355: * @param componentManager The component manager.
0356: *
0357: * @throws SAXException Thrown by component on initialization error.
0358: * For example, if a feature or property is
0359: * required for the operation of the component, the
0360: * component manager may throw a
0361: * SAXNotRecognizedException or a
0362: * SAXNotSupportedException.
0363: */
0364: public void reset(XMLComponentManager componentManager)
0365: throws XMLConfigurationException {
0366:
0367: super .reset(componentManager);
0368:
0369: // other settings
0370: fDoctypeName = null;
0371: fDoctypePublicId = null;
0372: fDoctypeSystemId = null;
0373: fSeenDoctypeDecl = false;
0374: fNamespaceContext.reset();
0375:
0376: // xerces features
0377: try {
0378: fLoadExternalDTD = componentManager
0379: .getFeature(LOAD_EXTERNAL_DTD);
0380: } catch (XMLConfigurationException e) {
0381: fLoadExternalDTD = true;
0382: }
0383:
0384: try {
0385: fDisallowDoctype = componentManager
0386: .getFeature(DISALLOW_DOCTYPE_DECL_FEATURE);
0387: } catch (XMLConfigurationException e) {
0388: fDisallowDoctype = false;
0389: }
0390:
0391: // xerces properties
0392: fDTDScanner = (XMLDTDScanner) componentManager
0393: .getProperty(DTD_SCANNER);
0394: fEndPos = 0;
0395: fStartPos = 0;
0396: if (fDTDDecl != null)
0397: fDTDDecl.clear();
0398:
0399: // setup driver
0400: setScannerState(SCANNER_STATE_XML_DECL);
0401: setDriver(fXMLDeclDriver);
0402:
0403: } // reset(XMLComponentManager)
0404:
0405: /**
0406: * Returns a list of feature identifiers that are recognized by
0407: * this component. This method may return null if no features
0408: * are recognized by this component.
0409: */
0410: public String[] getRecognizedFeatures() {
0411: String[] featureIds = super .getRecognizedFeatures();
0412: int length = featureIds != null ? featureIds.length : 0;
0413: String[] combinedFeatureIds = new String[length
0414: + RECOGNIZED_FEATURES.length];
0415: if (featureIds != null) {
0416: System.arraycopy(featureIds, 0, combinedFeatureIds, 0,
0417: featureIds.length);
0418: }
0419: System.arraycopy(RECOGNIZED_FEATURES, 0, combinedFeatureIds,
0420: length, RECOGNIZED_FEATURES.length);
0421: return combinedFeatureIds;
0422: } // getRecognizedFeatures():String[]
0423:
0424: /**
0425: * Sets the state of a feature. This method is called by the component
0426: * manager any time after reset when a feature changes state.
0427: * <p>
0428: * <strong>Note:</strong> Components should silently ignore features
0429: * that do not affect the operation of the component.
0430: *
0431: * @param featureId The feature identifier.
0432: * @param state The state of the feature.
0433: *
0434: * @throws SAXNotRecognizedException The component should not throw
0435: * this exception.
0436: * @throws SAXNotSupportedException The component should not throw
0437: * this exception.
0438: */
0439: public void setFeature(String featureId, boolean state)
0440: throws XMLConfigurationException {
0441:
0442: super .setFeature(featureId, state);
0443:
0444: // Xerces properties
0445: if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
0446: String feature = featureId
0447: .substring(Constants.XERCES_FEATURE_PREFIX.length());
0448: if (feature.equals(Constants.LOAD_EXTERNAL_DTD_FEATURE)) {
0449: fLoadExternalDTD = state;
0450: return;
0451: }
0452: }
0453:
0454: } // setFeature(String,boolean)
0455:
0456: /**
0457: * Returns a list of property identifiers that are recognized by
0458: * this component. This method may return null if no properties
0459: * are recognized by this component.
0460: */
0461: public String[] getRecognizedProperties() {
0462: String[] propertyIds = super .getRecognizedProperties();
0463: int length = propertyIds != null ? propertyIds.length : 0;
0464: String[] combinedPropertyIds = new String[length
0465: + RECOGNIZED_PROPERTIES.length];
0466: if (propertyIds != null) {
0467: System.arraycopy(propertyIds, 0, combinedPropertyIds, 0,
0468: propertyIds.length);
0469: }
0470: System.arraycopy(RECOGNIZED_PROPERTIES, 0, combinedPropertyIds,
0471: length, RECOGNIZED_PROPERTIES.length);
0472: return combinedPropertyIds;
0473: } // getRecognizedProperties():String[]
0474:
0475: /**
0476: * Sets the value of a property. This method is called by the component
0477: * manager any time after reset when a property changes value.
0478: * <p>
0479: * <strong>Note:</strong> Components should silently ignore properties
0480: * that do not affect the operation of the component.
0481: *
0482: * @param propertyId The property identifier.
0483: * @param value The value of the property.
0484: *
0485: * @throws SAXNotRecognizedException The component should not throw
0486: * this exception.
0487: * @throws SAXNotSupportedException The component should not throw
0488: * this exception.
0489: */
0490: public void setProperty(String propertyId, Object value)
0491: throws XMLConfigurationException {
0492:
0493: super .setProperty(propertyId, value);
0494:
0495: // Xerces properties
0496: if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
0497: String property = propertyId
0498: .substring(Constants.XERCES_PROPERTY_PREFIX
0499: .length());
0500: if (property.equals(Constants.DTD_SCANNER_PROPERTY)) {
0501: fDTDScanner = (XMLDTDScanner) value;
0502: }
0503: return;
0504: }
0505:
0506: } // setProperty(String,Object)
0507:
0508: /**
0509: * Returns the default state for a feature, or null if this
0510: * component does not want to report a default value for this
0511: * feature.
0512: *
0513: * @param featureId The feature identifier.
0514: *
0515: * @since Xerces 2.2.0
0516: */
0517: public Boolean getFeatureDefault(String featureId) {
0518:
0519: for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
0520: if (RECOGNIZED_FEATURES[i].equals(featureId)) {
0521: return FEATURE_DEFAULTS[i];
0522: }
0523: }
0524: return super .getFeatureDefault(featureId);
0525: } // getFeatureDefault(String):Boolean
0526:
0527: /**
0528: * Returns the default state for a property, or null if this
0529: * component does not want to report a default value for this
0530: * property.
0531: *
0532: * @param propertyId The property identifier.
0533: *
0534: * @since Xerces 2.2.0
0535: */
0536: public Object getPropertyDefault(String propertyId) {
0537: for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
0538: if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
0539: return PROPERTY_DEFAULTS[i];
0540: }
0541: }
0542: return super .getPropertyDefault(propertyId);
0543: } // getPropertyDefault(String):Object
0544:
0545: //
0546: // XMLEntityHandler methods
0547: //
0548:
0549: /**
0550: * This method notifies of the start of an entity. The DTD has the
0551: * pseudo-name of "[dtd]" parameter entity names start with '%'; and
0552: * general entities are just specified by their name.
0553: *
0554: * @param name The name of the entity.
0555: * @param identifier The resource identifier.
0556: * @param encoding The auto-detected IANA encoding name of the entity
0557: * stream. This value will be null in those situations
0558: * where the entity encoding is not auto-detected (e.g.
0559: * internal entities or a document entity that is
0560: * parsed from a java.io.Reader).
0561: *
0562: * @throws XNIException Thrown by handler to signal an error.
0563: */
0564: public void startEntity(String name,
0565: XMLResourceIdentifier identifier, String encoding)
0566: throws XNIException {
0567:
0568: super .startEntity(name, identifier, encoding);
0569:
0570: // prepare to look for a TextDecl if external general entity
0571: if (!name.equals("[xml]") && fEntityScanner.isExternal()) {
0572: setScannerState(SCANNER_STATE_TEXT_DECL);
0573: }
0574:
0575: // call handler
0576: /** comment this part.. LOCATOR problem.. */
0577: if (fDocumentHandler != null && name.equals("[xml]")) {
0578: fDocumentHandler.startDocument(fEntityScanner, encoding,
0579: fNamespaceContext, null);
0580: }
0581:
0582: } // startEntity(String,identifier,String)
0583:
0584: /**
0585: * This method notifies the end of an entity. The DTD has the pseudo-name
0586: * of "[dtd]" parameter entity names start with '%'; and general entities
0587: * are just specified by their name.
0588: *
0589: * @param name The name of the entity.
0590: *
0591: * @throws XNIException Thrown by handler to signal an error.
0592: */
0593: public void endEntity(String name) throws IOException, XNIException {
0594:
0595: super .endEntity(name);
0596:
0597: if (name.equals("[xml]")) {
0598:
0599: //if fMarkupDepth has reached 0.
0600: //and driver is fTrailingMiscDriver (which
0601: //handles end of document in normal case)
0602: //set the scanner state of SCANNER_STATE_TERMINATED
0603: if (fMarkupDepth == 0 && fDriver == fTrailingMiscDriver) {
0604: //set the scanner set to SCANNER_STATE_TERMINATED
0605: setScannerState(SCANNER_STATE_TERMINATED);
0606: } else {
0607: //else we have reached the end of document prematurely
0608: //so throw EOFException.
0609: throw new java.io.EOFException();
0610: }
0611:
0612: //There are no next events
0613: // call handler
0614: if (fDocumentHandler != null) {
0615: fDocumentHandler.endDocument(null);
0616: }
0617: }
0618: } // endEntity(String)
0619:
0620: //
0621: // Protected methods
0622: //
0623:
0624: // driver factory methods
0625:
0626: /** Creates a content driver. */
0627: protected Driver createContentDriver() {
0628: return new ContentDriver();
0629: } // createContentDriver():Driver
0630:
0631: // scanning methods
0632:
0633: /**
0634: <!DOCTYPE root PUBLIC "..." SYSTEM "..." [
0635: <!ENTITY e "i am an entity"
0636: ]>
0637: */
0638:
0639: /** Scans a doctype declaration. */
0640: protected boolean scanDoctypeDecl(boolean ignore)
0641: throws IOException, XNIException {
0642:
0643: // spaces
0644: if (!fEntityScanner.skipSpaces()) {
0645: reportFatalError(
0646: "MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL",
0647: null);
0648: }
0649:
0650: // root element name
0651: fDoctypeName = fEntityScanner.scanName();
0652: if (fDoctypeName == null) {
0653: reportFatalError("MSG_ROOT_ELEMENT_TYPE_REQUIRED", null);
0654: }
0655:
0656: // external id
0657: if (fEntityScanner.skipSpaces()) {
0658: scanExternalID(fStrings, false);
0659: fDoctypeSystemId = fStrings[0];
0660: fDoctypePublicId = fStrings[1];
0661: fEntityScanner.skipSpaces();
0662: }
0663:
0664: fHasExternalDTD = fDoctypeSystemId != null;
0665:
0666: // call handler unless support for DTD is off
0667: if (fDocumentHandler != null && !ignore) {
0668: // NOTE: I don't like calling the doctypeDecl callback until
0669: // end of the *full* doctype line (including internal
0670: // subset) is parsed correctly but SAX2 requires that
0671: // it knows the root element name and public and system
0672: // identifier for the startDTD call. -Ac
0673: fDocumentHandler.doctypeDecl(fDoctypeName,
0674: fDoctypePublicId, fDoctypeSystemId, null);
0675: }
0676:
0677: // is there an internal subset?
0678: boolean internalSubset = true;
0679: if (!fEntityScanner.skipChar('[')) {
0680: internalSubset = false;
0681: fEntityScanner.skipSpaces();
0682: if (!fEntityScanner.skipChar('>')) {
0683: reportFatalError("DoctypedeclUnterminated",
0684: new Object[] { fDoctypeName });
0685: }
0686: fMarkupDepth--;
0687: }
0688: return internalSubset;
0689:
0690: } // scanDoctypeDecl():boolean
0691:
0692: //
0693: // Private methods
0694: //
0695:
0696: /** Returns the scanner state name. */
0697: protected String getScannerStateName(int state) {
0698:
0699: switch (state) {
0700: case SCANNER_STATE_XML_DECL:
0701: return "SCANNER_STATE_XML_DECL";
0702: case SCANNER_STATE_PROLOG:
0703: return "SCANNER_STATE_PROLOG";
0704: case SCANNER_STATE_TRAILING_MISC:
0705: return "SCANNER_STATE_TRAILING_MISC";
0706: case SCANNER_STATE_DTD_INTERNAL_DECLS:
0707: return "SCANNER_STATE_DTD_INTERNAL_DECLS";
0708: case SCANNER_STATE_DTD_EXTERNAL:
0709: return "SCANNER_STATE_DTD_EXTERNAL";
0710: case SCANNER_STATE_DTD_EXTERNAL_DECLS:
0711: return "SCANNER_STATE_DTD_EXTERNAL_DECLS";
0712: }
0713: return super .getScannerStateName(state);
0714:
0715: } // getScannerStateName(int):String
0716:
0717: //
0718: // Classes
0719: //
0720:
0721: /**
0722: * Driver to handle XMLDecl scanning.
0723: *
0724: * This class has been modified as per the new design which is more suited to
0725: * efficiently build pull parser. Lots of performance improvements have been done and
0726: * the code has been added to support stax functionality/features.
0727: *
0728: * @author Neeraj Bajaj, Sun Microsystems.
0729: *
0730: * @author Andy Clark, IBM
0731: */
0732: protected final class XMLDeclDriver implements Driver {
0733:
0734: //
0735: // Driver methods
0736: //
0737:
0738: public int next() throws IOException, XNIException {
0739: if (DEBUG_NEXT) {
0740: System.out.println("NOW IN XMLDeclDriver");
0741: }
0742:
0743: // next driver is prolog regardless of whether there
0744: // is an XMLDecl in this document
0745: setScannerState(SCANNER_STATE_PROLOG);
0746: setDriver(fPrologDriver);
0747:
0748: // scan XMLDecl
0749: try {
0750: if (fEntityScanner.skipString(xmlDecl)) {
0751: fMarkupDepth++;
0752: // NOTE: special case where document starts with a PI
0753: // whose name starts with "xml" (e.g. "xmlfoo")
0754: if (XMLChar.isName(fEntityScanner.peekChar())) {
0755: fStringBuffer.clear();
0756: fStringBuffer.append("xml");
0757: while (XMLChar
0758: .isName(fEntityScanner.peekChar())) {
0759: fStringBuffer.append((char) fEntityScanner
0760: .scanChar());
0761: }
0762: String target = fSymbolTable.addSymbol(
0763: fStringBuffer.ch, fStringBuffer.offset,
0764: fStringBuffer.length);
0765: //this function should fill the data.. and set the fEvent object to this event.
0766: fStringBuffer.clear();
0767: scanPIData(target, fStringBuffer);
0768: //REVISIT:where else we can set this value to 'true'
0769: fEntityManager.fCurrentEntity.mayReadChunks = true;
0770: //return PI event since PI was encountered
0771: return XMLEvent.PROCESSING_INSTRUCTION;
0772: }
0773: // standard XML declaration
0774: else {
0775: scanXMLDeclOrTextDecl(false);
0776: //REVISIT:where else we can set this value to 'true'
0777: fEntityManager.fCurrentEntity.mayReadChunks = true;
0778: return XMLEvent.START_DOCUMENT;
0779: }
0780: } else {
0781: //REVISIT:where else we can set this value to 'true'
0782: fEntityManager.fCurrentEntity.mayReadChunks = true;
0783: //In both case return the START_DOCUMENT. ony difference is that first block will
0784: //cosume the XML declaration if any.
0785: return XMLEvent.START_DOCUMENT;
0786: }
0787:
0788: //START_OF_THE_DOCUMENT
0789:
0790: }
0791:
0792: // premature end of file
0793: catch (EOFException e) {
0794: reportFatalError("PrematureEOF", null);
0795: return -1;
0796: //throw e;
0797: }
0798:
0799: }
0800: } // class XMLDeclDriver
0801:
0802: /**
0803: * Driver to handle prolog scanning.
0804: *
0805: * @author Andy Clark, IBM
0806: */
0807: protected final class PrologDriver implements Driver {
0808:
0809: /**
0810: * Drives the parser to the next state/event on the input. Parser is guaranteed
0811: * to stop at the next state/event.
0812: *
0813: * Internally XML document is divided into several states. Each state represents
0814: * a sections of XML document. When this functions returns normally, it has read
0815: * the section of XML document and returns the state corresponding to section of
0816: * document which has been read. For optimizations, a particular driver
0817: * can read ahead of the section of document (state returned) just read and
0818: * can maintain a different internal state.
0819: *
0820: * @return state representing the section of document just read.
0821: *
0822: * @throws IOException Thrown on i/o error.
0823: * @throws XNIException Thrown on parse error.
0824: */
0825:
0826: public int next() throws IOException, XNIException {
0827: if (DEBUG_NEXT) {
0828: System.out.println("NOW IN PrologDriver");
0829: }
0830: try {
0831: do {
0832: switch (fScannerState) {
0833: case SCANNER_STATE_PROLOG: {
0834: fEntityScanner.skipSpaces();
0835: if (fEntityScanner.skipChar('<')) {
0836: setScannerState(SCANNER_STATE_START_OF_MARKUP);
0837: } else if (fEntityScanner.skipChar('&')) {
0838: setScannerState(SCANNER_STATE_REFERENCE);
0839: } else {
0840: setScannerState(SCANNER_STATE_CONTENT);
0841: }
0842: break;
0843: }
0844:
0845: case SCANNER_STATE_START_OF_MARKUP: {
0846: fMarkupDepth++;
0847: if (fEntityScanner.skipChar('?')) {
0848: setScannerState(SCANNER_STATE_PI);
0849: } else if (fEntityScanner.skipChar('!')) {
0850: if (fEntityScanner.skipChar('-')) {
0851: if (!fEntityScanner.skipChar('-')) {
0852: reportFatalError(
0853: "InvalidCommentStart", null);
0854: }
0855: setScannerState(SCANNER_STATE_COMMENT);
0856: } else if (fEntityScanner
0857: .skipString(DOCTYPE)) {
0858: setScannerState(SCANNER_STATE_DOCTYPE);
0859: Entity entity = fEntityScanner
0860: .getCurrentEntity();
0861: if (entity instanceof Entity.ScannedEntity) {
0862: fStartPos = ((Entity.ScannedEntity) entity).position;
0863: }
0864: fReadingDTD = true;
0865: if (fDTDDecl == null)
0866: fDTDDecl = new XMLStringBuffer();
0867: fDTDDecl.append("<!DOCTYPE");
0868:
0869: } else {
0870: reportFatalError(
0871: "MarkupNotRecognizedInProlog",
0872: null);
0873: }
0874: } else if (XMLChar.isNameStart(fEntityScanner
0875: .peekChar())) {
0876: setScannerState(SCANNER_STATE_ROOT_ELEMENT);
0877: } else {
0878: reportFatalError(
0879: "MarkupNotRecognizedInProlog", null);
0880: }
0881: break;
0882: }
0883: }
0884: } while (fScannerState == SCANNER_STATE_PROLOG
0885: || fScannerState == SCANNER_STATE_START_OF_MARKUP);
0886:
0887: switch (fScannerState) {
0888: //this part is handled by FragmentContentHandler
0889: case SCANNER_STATE_ROOT_ELEMENT: {
0890: //we have read '<' and beginning of reading the start element tag
0891: setScannerState(SCANNER_STATE_START_ELEMENT_TAG);
0892: setDriver(fContentDriver);
0893: //from now onwards this would be handled by fContentDriver,in the same next() call
0894: return fContentDriver.next();
0895: }
0896: case SCANNER_STATE_COMMENT: {
0897: //this function fills the data..
0898: scanComment();
0899: setScannerState(SCANNER_STATE_PROLOG);
0900: return XMLEvent.COMMENT;
0901: //setScannerState(SCANNER_STATE_PROLOG);
0902: //break;
0903: }
0904: case SCANNER_STATE_PI: {
0905: //this function fills the data.. and also set the event to the current event..
0906: fContentBuffer.clear();
0907: scanPI(fContentBuffer);
0908: setScannerState(SCANNER_STATE_PROLOG);
0909: return XMLEvent.PROCESSING_INSTRUCTION;
0910: //setScannerState(SCANNER_STATE_PROLOG);
0911: //break;
0912: }
0913: case SCANNER_STATE_DOCTYPE: {
0914:
0915: if (fSeenDoctypeDecl) {
0916: reportFatalError("AlreadySeenDoctype", null);
0917: }
0918: fSeenDoctypeDecl = true;
0919:
0920: // scanDoctypeDecl() sends XNI doctypeDecl event that
0921: // in SAX is converted to startDTD() event.
0922: if (scanDoctypeDecl(fDisallowDoctype)) {
0923: setScannerState(SCANNER_STATE_DTD_INTERNAL_DECLS);
0924: fSeenInternalSubset = true;
0925: if (fDTDDriver == null) {
0926: fDTDDriver = new DTDDriver();
0927: }
0928: setDriver(fContentDriver);
0929: int dtdEvent = fDTDDriver.next();
0930: // If no DTD support, ignore and continue parsing
0931: return fDisallowDoctype ? next() : dtdEvent;
0932: }
0933:
0934: /**
0935: // handle external subset
0936: if (fDoctypeSystemId != null) {
0937: if (((fValidation || fLoadExternalDTD)
0938: && (fValidationManager == null || !fValidationManager.isCachedDTD()))) {
0939: setScannerState(SCANNER_STATE_DTD_EXTERNAL);
0940: setDispatcher(fDTDDispatcher);
0941: return true;
0942: }
0943: }
0944: */
0945:
0946: if (fSeenDoctypeDecl) {
0947: Entity entity = fEntityScanner
0948: .getCurrentEntity();
0949: if (entity instanceof Entity.ScannedEntity) {
0950: fEndPos = ((Entity.ScannedEntity) entity).position;
0951: }
0952: fReadingDTD = false;
0953: }
0954:
0955: if (fDisallowDoctype) {
0956: setScannerState(SCANNER_STATE_PROLOG);
0957: return next();
0958: }
0959:
0960: if (fDoctypeSystemId != null
0961: && (fValidation || fLoadExternalDTD)) {
0962: setScannerState(SCANNER_STATE_DTD_EXTERNAL);
0963: setDriver(fContentDriver);
0964: if (fDTDDriver == null)
0965: fDTDDriver = new DTDDriver();
0966: return fDTDDriver.next();
0967: } else {
0968: // Send endDTD() call if:
0969: // a) systemId is null
0970: // b) "load-external-dtd" and validation are false
0971: // c) DTD grammar is cached
0972:
0973: // in XNI this results in 3 events: doctypeDecl, startDTD, endDTD
0974: // in SAX this results in 2 events: startDTD, endDTD
0975: if (fDTDScanner != null) {
0976: fDTDScanner.setInputSource(null);
0977: }
0978: }
0979: setScannerState(SCANNER_STATE_PROLOG);
0980: return XMLEvent.DTD;
0981: }
0982:
0983: case SCANNER_STATE_CONTENT: {
0984: reportFatalError("ContentIllegalInProlog", null);
0985: fEntityScanner.scanChar();
0986: }
0987: case SCANNER_STATE_REFERENCE: {
0988: reportFatalError("ReferenceIllegalInProlog", null);
0989: }
0990:
0991: /**
0992: * if (complete) {
0993: * if (fEntityScanner.scanChar() != '<') {
0994: * reportFatalError("RootElementRequired", null);
0995: * }
0996: * setScannerState(SCANNER_STATE_ROOT_ELEMENT);
0997: * setDriver(fContentDriver);
0998: * }
0999: */
1000: }
1001: }
1002: // premature end of file
1003: catch (EOFException e) {
1004: reportFatalError("PrematureEOF", null);
1005: //xxx what should be returned here.... ???
1006: return -1;
1007: //throw e;
1008: }
1009: //xxx what should be returned here.... ???
1010: return -1;
1011:
1012: }
1013:
1014: } // class PrologDriver
1015:
1016: /**
1017: * Driver to handle the internal and external DTD subsets.
1018: *
1019: * @author Andy Clark, IBM
1020: */
1021: protected final class DTDDriver implements Driver {
1022:
1023: //
1024: // Driver methods
1025: //
1026:
1027: public int next() throws IOException, XNIException {
1028: // throw new XNIException("DTD Parsing is currently not supported");
1029: if (DEBUG_NEXT) {
1030: System.out.println("Now in DTD Driver");
1031: }
1032:
1033: dispatch(true);
1034:
1035: if (DEBUG_NEXT) {
1036: System.out
1037: .println("After calling dispatch(true) -- At this point whole DTD is read.");
1038: }
1039:
1040: dtdGrammarUtil = new DTDGrammarUtil(
1041: ((XMLDTDScannerImpl) fDTDScanner).getGrammar(),
1042: fSymbolTable, fNamespaceContext);
1043:
1044: return XMLEvent.DTD;
1045: }
1046:
1047: /**
1048: * Dispatch an XML "event".
1049: *
1050: * @param complete True if this driver is intended to scan
1051: * and dispatch as much as possible.
1052: *
1053: * @return True if there is more to dispatch either from this
1054: * or a another driver.
1055: *
1056: * @throws IOException Thrown on i/o error.
1057: * @throws XNIException Thrown on parse error.
1058: */
1059: public boolean dispatch(boolean complete) throws IOException,
1060: XNIException {
1061: fEntityManager.setEntityHandler(null);
1062: try {
1063: boolean again;
1064: XMLResourceIdentifierImpl resourceIdentifier = new XMLResourceIdentifierImpl();
1065: if (fDTDScanner == null) {
1066: fDTDScanner = new XMLDTDScannerImpl();
1067: if (fPropertyManager != null) {
1068: ((XMLDTDScannerImpl) fDTDScanner)
1069: .reset(fPropertyManager);
1070: }
1071: }
1072: do {
1073: again = false;
1074: switch (fScannerState) {
1075: case SCANNER_STATE_DTD_INTERNAL_DECLS: {
1076: // REVISIT: Should there be a feature for
1077: // the "complete" parameter?
1078: boolean completeDTD = true;
1079:
1080: boolean moreToScan = fDTDScanner
1081: .scanDTDInternalSubset(completeDTD,
1082: fStandalone, fHasExternalDTD
1083: && fLoadExternalDTD);
1084: Entity entity = fEntityScanner
1085: .getCurrentEntity();
1086: if (entity instanceof Entity.ScannedEntity) {
1087: fEndPos = ((Entity.ScannedEntity) entity).position;
1088: }
1089: fReadingDTD = false;
1090: if (!moreToScan) {
1091: // end doctype declaration
1092: if (!fEntityScanner.skipChar(']')) {
1093: reportFatalError(
1094: "EXPECTED_SQUARE_BRACKET_TO_CLOSE_INTERNAL_SUBSET",
1095: null);
1096: }
1097: fEntityScanner.skipSpaces();
1098: if (!fEntityScanner.skipChar('>')) {
1099: reportFatalError(
1100: "DoctypedeclUnterminated",
1101: new Object[] { fDoctypeName });
1102: }
1103: fMarkupDepth--;
1104:
1105: // scan external subset next unless we are ignoring DTDs
1106: if (!XMLDocumentScannerImpl.this .fDisallowDoctype
1107: && fDoctypeSystemId != null
1108: && (fValidation || fLoadExternalDTD)) {
1109: setScannerState(SCANNER_STATE_DTD_EXTERNAL);
1110: }
1111:
1112: // break out of here
1113: else {
1114: setScannerState(SCANNER_STATE_PROLOG);
1115: setDriver(fPrologDriver);
1116: fEntityManager
1117: .setEntityHandler(XMLDocumentScannerImpl.this );
1118: return true;
1119: }
1120: }
1121: break;
1122: }
1123: case SCANNER_STATE_DTD_EXTERNAL: {
1124: resourceIdentifier.setValues(fDoctypePublicId,
1125: fDoctypeSystemId, null, null);
1126: XMLInputSource xmlInputSource = null;
1127: // xmlInputSource = fEntityManager.resolveEntity(resourceIdentifier);
1128: StaxXMLInputSource staxInputSource = fEntityManager
1129: .resolveEntityAsPerStax(resourceIdentifier);
1130: xmlInputSource = staxInputSource
1131: .getXMLInputSource();
1132: fDTDScanner.setInputSource(xmlInputSource);
1133: setScannerState(SCANNER_STATE_DTD_EXTERNAL_DECLS);
1134: again = true;
1135: break;
1136: }
1137: case SCANNER_STATE_DTD_EXTERNAL_DECLS: {
1138: // REVISIT: Should there be a feature for
1139: // the "complete" parameter?
1140: boolean completeDTD = true;
1141: boolean moreToScan = fDTDScanner
1142: .scanDTDExternalSubset(completeDTD);
1143: if (!moreToScan) {
1144: setScannerState(SCANNER_STATE_PROLOG);
1145: setDriver(fPrologDriver);
1146: fEntityManager
1147: .setEntityHandler(XMLDocumentScannerImpl.this );
1148: return true;
1149: }
1150: break;
1151: }
1152: default: {
1153: throw new XNIException(
1154: "DTDDriver#dispatch: scanner state="
1155: + fScannerState
1156: + " ("
1157: + getScannerStateName(fScannerState)
1158: + ')');
1159: }
1160: }
1161: } while (complete || again);
1162: }
1163:
1164: // premature end of file
1165: catch (EOFException e) {
1166: e.printStackTrace();
1167: reportFatalError("PrematureEOF", null);
1168: return false;
1169: //throw e;
1170: }
1171:
1172: // cleanup
1173: finally {
1174: fEntityManager
1175: .setEntityHandler(XMLDocumentScannerImpl.this );
1176: }
1177:
1178: return true;
1179:
1180: }
1181:
1182: // dispatch(boolean):boolean
1183:
1184: } // class DTDDriver
1185:
1186: /**
1187: * Driver to handle content scanning.
1188: *
1189: * @author Andy Clark, IBM
1190: * @author Eric Ye, IBM
1191: */
1192: protected class ContentDriver extends FragmentContentDriver {
1193:
1194: //
1195: // Protected methods
1196: //
1197:
1198: // hooks
1199:
1200: // NOTE: These hook methods are added so that the full document
1201: // scanner can share the majority of code with this class.
1202:
1203: /**
1204: * Scan for DOCTYPE hook. This method is a hook for subclasses
1205: * to add code to handle scanning for a the "DOCTYPE" string
1206: * after the string "<!" has been scanned.
1207: *
1208: * @return True if the "DOCTYPE" was scanned; false if "DOCTYPE"
1209: * was not scanned.
1210: */
1211: protected boolean scanForDoctypeHook() throws IOException,
1212: XNIException {
1213:
1214: if (fEntityScanner.skipString(DOCTYPE)) {
1215: setScannerState(SCANNER_STATE_DOCTYPE);
1216: // fEntityScanner.markStartOfDTD();
1217: return true;
1218: }
1219: return false;
1220:
1221: } // scanForDoctypeHook():boolean
1222:
1223: /**
1224: * Element depth iz zero. This methos is a hook for subclasses
1225: * to add code to handle when the element depth hits zero. When
1226: * scanning a document fragment, an element depth of zero is
1227: * normal. However, when scanning a full XML document, the
1228: * scanner must handle the trailing miscellanous section of
1229: * the document after the end of the document's root element.
1230: *
1231: * @return True if the caller should stop and return true which
1232: * allows the scanner to switch to a new scanning
1233: * driver. A return value of false indicates that
1234: * the content driver should continue as normal.
1235: */
1236: protected boolean elementDepthIsZeroHook() throws IOException,
1237: XNIException {
1238:
1239: setScannerState(SCANNER_STATE_TRAILING_MISC);
1240: setDriver(fTrailingMiscDriver);
1241: return true;
1242:
1243: } // elementDepthIsZeroHook():boolean
1244:
1245: /**
1246: * Scan for root element hook. This method is a hook for
1247: * subclasses to add code that handles scanning for the root
1248: * element. When scanning a document fragment, there is no
1249: * "root" element. However, when scanning a full XML document,
1250: * the scanner must handle the root element specially.
1251: *
1252: * @return True if the caller should stop and return true which
1253: * allows the scanner to switch to a new scanning
1254: * driver. A return value of false indicates that
1255: * the content driver should continue as normal.
1256: */
1257: protected boolean scanRootElementHook() throws IOException,
1258: XNIException {
1259:
1260: if (scanStartElement()) {
1261: setScannerState(SCANNER_STATE_TRAILING_MISC);
1262: setDriver(fTrailingMiscDriver);
1263: return true;
1264: }
1265: return false;
1266:
1267: } // scanRootElementHook():boolean
1268:
1269: /**
1270: * End of file hook. This method is a hook for subclasses to
1271: * add code that handles the end of file. The end of file in
1272: * a document fragment is OK if the markup depth is zero.
1273: * However, when scanning a full XML document, an end of file
1274: * is always premature.
1275: */
1276: protected void endOfFileHook(EOFException e)
1277: throws IOException, XNIException {
1278:
1279: reportFatalError("PrematureEOF", null);
1280: // in case continue-after-fatal-error set, should not do this...
1281: //throw e;
1282:
1283: } // endOfFileHook()
1284:
1285: } // class ContentDriver
1286:
1287: /**
1288: * Driver to handle trailing miscellaneous section scanning.
1289: *
1290: * @author Andy Clark, IBM
1291: * @author Eric Ye, IBM
1292: */
1293: protected final class TrailingMiscDriver implements Driver {
1294:
1295: //
1296: // Driver methods
1297: //
1298: public int next() throws IOException, XNIException {
1299: try {
1300: if (fScannerState == SCANNER_STATE_TERMINATED) {
1301: return XMLEvent.END_DOCUMENT;
1302: }
1303: do {
1304: switch (fScannerState) {
1305: case SCANNER_STATE_TRAILING_MISC: {
1306:
1307: fEntityScanner.skipSpaces();
1308: //we should have reached the end of the document in
1309: //most cases.
1310: if (fScannerState == SCANNER_STATE_TERMINATED) {
1311: return XMLEvent.END_DOCUMENT;
1312: }
1313: if (fEntityScanner.skipChar('<')) {
1314: setScannerState(SCANNER_STATE_START_OF_MARKUP);
1315: } else {
1316: setScannerState(SCANNER_STATE_CONTENT);
1317: }
1318: break;
1319: }
1320: case SCANNER_STATE_START_OF_MARKUP: {
1321: fMarkupDepth++;
1322: if (fEntityScanner.skipChar('?')) {
1323: setScannerState(SCANNER_STATE_PI);
1324: } else if (fEntityScanner.skipChar('!')) {
1325: setScannerState(SCANNER_STATE_COMMENT);
1326: } else if (fEntityScanner.skipChar('/')) {
1327: reportFatalError(
1328: "MarkupNotRecognizedInMisc", null);
1329: } else if (XMLChar.isNameStart(fEntityScanner
1330: .peekChar())) {
1331: reportFatalError(
1332: "MarkupNotRecognizedInMisc", null);
1333: scanStartElement();
1334: setScannerState(SCANNER_STATE_CONTENT);
1335: } else {
1336: reportFatalError(
1337: "MarkupNotRecognizedInMisc", null);
1338: }
1339: break;
1340: }
1341: }
1342: } while (fScannerState == SCANNER_STATE_START_OF_MARKUP
1343: || fScannerState == SCANNER_STATE_TRAILING_MISC);
1344: if (DEBUG_NEXT) {
1345: System.out
1346: .println("State set by deciding while loop [TrailingMiscellaneous] is = "
1347: + getScannerStateName(fScannerState));
1348: }
1349: switch (fScannerState) {
1350: case SCANNER_STATE_PI: {
1351: //clear the buffer first.
1352: fContentBuffer.clear();
1353: scanPI(fContentBuffer);
1354: setScannerState(SCANNER_STATE_TRAILING_MISC);
1355: return XMLEvent.PROCESSING_INSTRUCTION;
1356: }
1357: case SCANNER_STATE_COMMENT: {
1358: if (!fEntityScanner.skipString(COMMENTSTRING)) {
1359: reportFatalError("InvalidCommentStart", null);
1360: }
1361: scanComment();
1362: setScannerState(SCANNER_STATE_TRAILING_MISC);
1363: return XMLEvent.COMMENT;
1364: }
1365: case SCANNER_STATE_CONTENT: {
1366: int ch = fEntityScanner.peekChar();
1367: if (ch == -1) {
1368: setScannerState(SCANNER_STATE_TERMINATED);
1369: return XMLEvent.END_DOCUMENT;
1370: } else {
1371: reportFatalError(
1372: "ContentIllegalInTrailingMisc", null);
1373: fEntityScanner.scanChar();
1374: setScannerState(SCANNER_STATE_TRAILING_MISC);
1375: return XMLEvent.CHARACTERS;
1376: }
1377:
1378: }
1379: case SCANNER_STATE_REFERENCE: {
1380: reportFatalError("ReferenceIllegalInTrailingMisc",
1381: null);
1382: setScannerState(SCANNER_STATE_TRAILING_MISC);
1383: return XMLEvent.ENTITY_REFERENCE;
1384: }
1385: case SCANNER_STATE_TERMINATED: {
1386: //there can't be any element after SCANNER_STATE_TERMINATED or when the parser
1387: //has reached the end of document
1388: setScannerState(SCANNER_STATE_NO_SUCH_ELEMENT_EXCEPTION);
1389: //xxx what to do when the scanner has reached the terminating state.
1390: return XMLEvent.END_DOCUMENT;
1391: }
1392: case SCANNER_STATE_NO_SUCH_ELEMENT_EXCEPTION: {
1393: throw new java.util.NoSuchElementException(
1394: "No more events to be parsed");
1395: }
1396: default:
1397: throw new XNIException("Scanner State "
1398: + fScannerState + " not Recognized ");
1399: }//switch
1400:
1401: } catch (EOFException e) {
1402: // NOTE: This is the only place we're allowed to reach
1403: // the real end of the document stream. Unless the
1404: // end of file was reached prematurely.
1405: if (fMarkupDepth != 0) {
1406: reportFatalError("PrematureEOF", null);
1407: return -1;
1408: //throw e;
1409: }
1410: System.out.println("EOFException thrown");
1411: setScannerState(SCANNER_STATE_TERMINATED);
1412: }
1413:
1414: return XMLEvent.END_DOCUMENT;
1415:
1416: }//next
1417:
1418: } // class TrailingMiscDriver
1419:
1420: /**
1421: * Implements XMLBufferListener interface.
1422: */
1423: protected class XMLBufferListenerImpl implements XMLBufferListener {
1424: public void refresh() {
1425: refresh(0);
1426: }
1427:
1428: /**
1429: * receives callbacks from {@link XMLEntityReader } when buffer
1430: * is being changed.
1431: * @param refreshPosition
1432: */
1433: public void refresh(int refreshPosition) {
1434: //If you are reading attributes and you got a callback
1435: //cache available attributes.
1436: if (fReadingAttributes)
1437: fAttributes.refresh();
1438: if (fReadingDTD) {
1439: Entity entity = fEntityScanner.getCurrentEntity();
1440: if (entity instanceof Entity.ScannedEntity) {
1441: fEndPos = ((Entity.ScannedEntity) entity).position;
1442: }
1443: fDTDDecl.append(((Entity.ScannedEntity) entity).ch,
1444: fStartPos, fEndPos - fStartPos);
1445: fStartPos = refreshPosition;
1446: }
1447: if (fScannerState == SCANNER_STATE_CHARACTER_DATA) {
1448: //since fTempString directly matches to the underlying main buffer
1449: //store the data into buffer
1450: fContentBuffer.append(fTempString);
1451: //clear the XMLString so that data can't be added again.
1452: fTempString.length = 0;
1453: fUsebuffer = true;
1454: }
1455: }
1456: }
1457: } // class XMLDocumentScannerImpl
|