blob: 4ed5becbc8a0e3d3afde553c25092072565539f1 [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999,2000 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 1999, International
* Business Machines, Inc., http://www.apache.org. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.xerces.framework;
import org.apache.xerces.readers.XMLEntityHandler;
import org.apache.xerces.readers.DefaultEntityHandler;
import org.apache.xerces.utils.QName;
import org.apache.xerces.utils.StringPool;
import org.apache.xerces.utils.XMLCharacterProperties;
import org.apache.xerces.utils.XMLMessages;
import org.apache.xerces.validators.common.Grammar;
import org.apache.xerces.validators.common.GrammarResolver;
import org.apache.xerces.validators.common.XMLAttributeDecl;
import org.apache.xerces.validators.common.XMLElementDecl;
import org.apache.xerces.validators.dtd.DTDGrammar;
import org.xml.sax.Locator;
import org.xml.sax.SAXParseException;
import java.util.StringTokenizer;
/**
* Default implementation of an XML DTD scanner.
* <p>
* Clients who wish to scan a DTD should implement
* XMLDTDScanner.EventHandler to provide the desired behavior
* when various DTD components are encountered.
* <p>
* To process the DTD, the client application should follow the
* following sequence:
* <ol>
* <li>call scanDocTypeDecl() to scan the DOCTYPE declaration
* <li>call getReadingExternalEntity() to determine if scanDocTypeDecl found an
* external subset
* <li>if scanning an external subset, call scanDecls(true) to process the external subset
* </ol>
*
* @see XMLDTDScanner.EventHandler
* @version $Id$
*/
public final class XMLDTDScanner {
//
// Constants
//
//
// [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
//
private static final char[] version_string = { 'v','e','r','s','i','o','n' };
//
// [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
//
private static final char[] element_string = { 'E','L','E','M','E','N','T' };
//
// [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
//
private static final char[] empty_string = { 'E','M','P','T','Y' };
private static final char[] any_string = { 'A','N','Y' };
//
// [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*'
// | '(' S? '#PCDATA' S? ')'
//
private static final char[] pcdata_string = { '#','P','C','D','A','T','A' };
//
// [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
//
private static final char[] attlist_string = { 'A','T','T','L','I','S','T' };
//
// [55] StringType ::= 'CDATA'
//
private static final char[] cdata_string = { 'C','D','A','T','A' };
//
// [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' | 'ENTITIES'
// | 'NMTOKEN' | 'NMTOKENS'
//
// Note: We search for common substrings always trying to move forward
//
// 'ID' - Common prefix of ID, IDREF and IDREFS
// 'REF' - Common substring of IDREF and IDREFS after matching ID prefix
// 'ENTIT' - Common prefix of ENTITY and ENTITIES
// 'IES' - Suffix of ENTITIES
// 'NMTOKEN' - Common prefix of NMTOKEN and NMTOKENS
//
private static final char[] id_string = { 'I','D' };
private static final char[] ref_string = { 'R','E','F' };
private static final char[] entit_string = { 'E','N','T','I','T' };
private static final char[] ies_string = { 'I','E','S' };
private static final char[] nmtoken_string = { 'N','M','T','O','K','E','N' };
//
// [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
// [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID | PublicID) S? '>'
//
private static final char[] notation_string = { 'N','O','T','A','T','I','O','N' };
//
// [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
//
private static final char[] required_string = { '#','R','E','Q','U','I','R','E','D' };
private static final char[] implied_string = { '#','I','M','P','L','I','E','D' };
private static final char[] fixed_string = { '#','F','I','X','E','D' };
//
// [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
//
private static final char[] include_string = { 'I','N','C','L','U','D','E' };
//
// [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
//
private static final char[] ignore_string = { 'I','G','N','O','R','E' };
//
// [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
// [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
//
private static final char[] entity_string = { 'E','N','T','I','T','Y' };
//
// [75] ExternalID ::= 'SYSTEM' S SystemLiteral
// | 'PUBLIC' S PubidLiteral S SystemLiteral
// [83] PublicID ::= 'PUBLIC' S PubidLiteral
//
private static final char[] system_string = { 'S','Y','S','T','E','M' };
private static final char[] public_string = { 'P','U','B','L','I','C' };
//
// [76] NDataDecl ::= S 'NDATA' S Name
//
private static final char[] ndata_string = { 'N','D','A','T','A' };
//
// [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" )
//
private static final char[] encoding_string = { 'e','n','c','o','d','i','n','g' };
//
// Instance Variables
//
private DTDGrammar fDTDGrammar = null;
private GrammarResolver fGrammarResolver = null;
private boolean fNamespacesEnabled = false;
private boolean fValidationEnabled = false;
private XMLElementDecl fTempElementDecl = new XMLElementDecl();
private XMLAttributeDecl fTempAttributeDecl = new XMLAttributeDecl();
private QName fElementQName = new QName();
private QName fAttributeQName = new QName();
private QName fElementRefQName = new QName();
private EventHandler fEventHandler = null;
private XMLDocumentHandler.DTDHandler fDTDHandler = null;
private StringPool fStringPool = null;
private XMLErrorReporter fErrorReporter = null;
private XMLEntityHandler fEntityHandler = null;
private XMLEntityHandler.EntityReader fEntityReader = null;
private XMLEntityHandler.CharBuffer fLiteralData = null;
private int fReaderId = -1;
private int fSystemLiteral = -1;
private int fPubidLiteral = -1;
private int[] fOpStack = null;
private int[] fNodeIndexStack = null;
private int[] fPrevNodeIndexStack = null;
private int fScannerState = SCANNER_STATE_INVALID;
private int fIncludeSectDepth = 0;
private int fDoctypeReader = -1;
private int fExternalSubsetReader = -1;
private int fDefaultAttValueReader = -1;
private int fDefaultAttValueElementType = -1;
private int fDefaultAttValueAttrName = -1;
private int fDefaultAttValueOffset = -1;
private int fDefaultAttValueMark = -1;
private int fEntityValueReader = -1;
private int fEntityValueMark = -1;
private int fXMLSymbol = -1;
private int fXMLNamespace = -1;
private int fXMLSpace = -1;
private int fDefault = -1;
private int fPreserve = -1;
private int fScannerMarkupDepth = 0;
private int fScannerParenDepth = 0;
//
// Constructors
//
public XMLDTDScanner(StringPool stringPool,
XMLErrorReporter errorReporter,
XMLEntityHandler entityHandler,
XMLEntityHandler.CharBuffer literalData) {
fStringPool = stringPool;
fErrorReporter = errorReporter;
fEntityHandler = entityHandler;
fLiteralData = literalData;
init();
}
/**
* Set the event handler
*
* @param eventHandler The place to send our callbacks.
*/
public void setEventHandler(XMLDTDScanner.EventHandler eventHandler) {
fEventHandler = eventHandler;
}
/** Set the DTD handler. */
public void setDTDHandler(XMLDocumentHandler.DTDHandler dtdHandler) {
fDTDHandler = dtdHandler;
}
/** Sets the grammar resolver. */
public void setGrammarResolver(GrammarResolver resolver) {
fGrammarResolver = resolver;
}
/** set fNamespacesEnabled **/
public void setNamespacesEnabled(boolean enabled) {
fNamespacesEnabled = enabled;
}
/** set fValidationEnabled **/
public void setValidationEnabled(boolean enabled) {
fValidationEnabled = enabled;
}
/**
* Is the XMLDTDScanner reading from an external entity?
*
* This will be true, in particular if there was an external subset
*
* @return true if the XMLDTDScanner is reading from an external entity.
*/
public boolean getReadingExternalEntity() {
return fReaderId != fDoctypeReader;
}
/**
* Is the scanner reading a ContentSpec?
*
* @return true if the scanner is reading a ContentSpec
*/
public boolean getReadingContentSpec() {
return getScannerState() == SCANNER_STATE_CONTENTSPEC;
}
/**
* Report the markup nesting depth. This allows a client to
* perform validation checks for correct markup nesting. This keeps
* scanning and validation separate.
*
* @return the markup nesting depth
*/
public int markupDepth() {
return fScannerMarkupDepth;
}
private int increaseMarkupDepth() {
return fScannerMarkupDepth++;
}
private int decreaseMarkupDepth() {
return fScannerMarkupDepth--;
}
/**
* Report the parenthesis nesting depth. This allows a client to
* perform validation checks for correct parenthesis balancing. This keeps
* scanning and validation separate.
*
* @return the parenthesis depth
*/
public int parenDepth() {
return fScannerParenDepth;
}
private void setParenDepth(int parenDepth) {
fScannerParenDepth = parenDepth;
}
private void increaseParenDepth() {
fScannerParenDepth++;
}
private void decreaseParenDepth() {
fScannerParenDepth--;
}
//
//
//
/**
* Allow XMLDTDScanner to be reused. This method is called from an
* XMLParser reset method, which passes the StringPool to be used
* by the reset DTD scanner instance.
*
* @param stringPool the string pool to be used by XMLDTDScanner.
*/
public void reset(StringPool stringPool, XMLEntityHandler.CharBuffer literalData) throws Exception {
fStringPool = stringPool;
fLiteralData = literalData;
fEntityReader = null;
fReaderId = -1;
fSystemLiteral = -1;
fPubidLiteral = -1;
fOpStack = null;
fNodeIndexStack = null;
fPrevNodeIndexStack = null;
fScannerState = SCANNER_STATE_INVALID;
fIncludeSectDepth = 0;
fDoctypeReader = -1;
fExternalSubsetReader = -1;
fDefaultAttValueReader = -1;
fDefaultAttValueElementType = -1;
fDefaultAttValueAttrName = -1;
fDefaultAttValueOffset = -1;
fDefaultAttValueMark = -1;
fEntityValueReader = -1;
fEntityValueMark = -1;
fScannerMarkupDepth = 0;
fScannerParenDepth = 0;
init();
}
private void init() {
fXMLSymbol = fStringPool.addSymbol("xml");
fXMLNamespace = fStringPool.addSymbol("http://www.w3.org/XML/1998/namespace");
fXMLSpace = fStringPool.addSymbol("xml:space");
fDefault = fStringPool.addSymbol("default");
fPreserve = fStringPool.addSymbol("preserve");
}
//
// Interfaces
//
/**
* This interface must be implemented by the users of the XMLDTDScanner class.
* These methods form the abstraction between the implementation semantics and the
* more generic task of scanning the DTD-specific XML grammar.
*/
public interface EventHandler {
/** Start of DTD. */
public void callStartDTD() throws Exception;
/** End of DTD. */
public void callEndDTD() throws Exception;
/**
* Signal the Text declaration of an external entity.
*
* @param version the handle in the string pool for the version number
* @param encoding the handle in the string pool for the encoding
* @exception java.lang.Exception
*/
public void callTextDecl(int version, int encoding) throws Exception;
/**
* Called when the doctype decl is scanned
*
* @param rootElementType handle of the rootElement
* @param publicId StringPool handle of the public id
* @param systemId StringPool handle of the system id
* @exception java.lang.Exception
*/
public void doctypeDecl(QName rootElement, int publicId, int systemId) throws Exception;
/**
* Called when the DTDScanner starts reading from the external subset
*
* @param publicId StringPool handle of the public id
* @param systemId StringPool handle of the system id
* @exception java.lang.Exception
*/
public void startReadingFromExternalSubset(int publicId, int systemId) throws Exception;
/**
* Called when the DTDScanner stop reading from the external subset
*
* @exception java.lang.Exception
*/
public void stopReadingFromExternalSubset() throws Exception;
/**
* Add an element declaration (forward reference)
*
* @param handle to the name of the element being declared
* @return handle to the element whose declaration was added
* @exception java.lang.Exception
*/
public int addElementDecl(QName elementDecl) throws Exception;
/**
* Add an element declaration
*
* @param handle to the name of the element being declared
* @param contentSpecType handle to the type name of the content spec
* @param ContentSpec handle to the content spec node for the contentSpecType
* @return handle to the element declaration that was added
* @exception java.lang.Exception
*/
public int addElementDecl(QName elementDecl, int contentSpecType, int contentSpec, boolean isExternal) throws Exception;
/**
* Add an attribute definition
*
* @param handle to the element whose attribute is being declared
* @param attName StringPool handle to the attribute name being declared
* @param attType type of the attribute
* @param enumeration StringPool handle of the attribute's enumeration list (if any)
* @param attDefaultType an integer value denoting the DefaultDecl value
* @param attDefaultValue StringPool handle of this attribute's default value
* @return handle to the attribute definition
* @exception java.lang.Exception
*/
public int addAttDef(QName elementDecl, QName attributeDecl,
int attType, boolean attList, int enumeration,
int attDefaultType, int attDefaultValue, boolean isExternal) throws Exception;
/**
* create an XMLContentSpec for a leaf
*
* @param nameIndex StringPool handle to the name (Element) for the node
* @return handle to the newly create XMLContentSpec
* @exception java.lang.Exception
*/
public int addUniqueLeafNode(int nameIndex) throws Exception;
/**
* Create an XMLContentSpec for a single non-leaf
*
* @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_*
* @param nodeValue handle to an XMLContentSpec
* @return handle to the newly create XMLContentSpec
* @exception java.lang.Exception
*/
public int addContentSpecNode(int nodeType, int nodeValue) throws Exception;
/**
* Create an XMLContentSpec for a two child leaf
*
* @param nodeType the type of XMLContentSpec to create - from XMLContentSpec.CONTENTSPECNODE_*
* @param leftNodeIndex handle to an XMLContentSpec
* @param rightNodeIndex handle to an XMLContentSpec
* @return handle to the newly create XMLContentSpec
* @exception java.lang.Exception
*/
public int addContentSpecNode(int nodeType, int leftNodeIndex, int rightNodeIndex) throws Exception;
/**
* Create a string representation of an XMLContentSpec tree
*
* @param handle to an XMLContentSpec
* @return String representation of the content spec tree
* @exception java.lang.Exception
*/
public String getContentSpecNodeAsString(int nodeIndex) throws Exception;
/**
* Start the scope of an entity declaration.
*
* @return <code>true</code> on success; otherwise
* <code>false</code> if the entity declaration is recursive.
* @exception java.lang.Exception
*/
public boolean startEntityDecl(boolean isPE, int entityName) throws Exception;
/**
* End the scope of an entity declaration.
* @exception java.lang.Exception
*/
public void endEntityDecl() throws Exception;
/**
* Add a declaration for an internal parameter entity
*
* @param name StringPool handle of the parameter entity name
* @param value StringPool handle of the parameter entity value
* @return handle to the parameter entity declaration
* @exception java.lang.Exception
*/
public int addInternalPEDecl(int name, int value) throws Exception;
/**
* Add a declaration for an external parameter entity
*
* @param name StringPool handle of the parameter entity name
* @param publicId StringPool handle of the publicId
* @param systemId StringPool handle of the systemId
* @return handle to the parameter entity declaration
* @exception java.lang.Exception
*/
public int addExternalPEDecl(int name, int publicId, int systemId) throws Exception;
/**
* Add a declaration for an internal entity
*
* @param name StringPool handle of the entity name
* @param value StringPool handle of the entity value
* @return handle to the entity declaration
* @exception java.lang.Exception
*/
public int addInternalEntityDecl(int name, int value) throws Exception;
/**
* Add a declaration for an entity
*
* @param name StringPool handle of the entity name
* @param publicId StringPool handle of the publicId
* @param systemId StringPool handle of the systemId
* @return handle to the entity declaration
* @exception java.lang.Exception
*/
public int addExternalEntityDecl(int name, int publicId, int systemId) throws Exception;
/**
* Add a declaration for an unparsed entity
*
* @param name StringPool handle of the entity name
* @param publicId StringPool handle of the publicId
* @param systemId StringPool handle of the systemId
* @param notationName StringPool handle of the notationName
* @return handle to the entity declaration
* @exception java.lang.Exception
*/
public int addUnparsedEntityDecl(int name, int publicId, int systemId, int notationName) throws Exception;
/**
* Called when the scanner start scanning an enumeration
* @return StringPool handle to a string list that will hold the enumeration names
* @exception java.lang.Exception
*/
public int startEnumeration() throws Exception;
/**
* Add a name to an enumeration
* @param enumIndex StringPool handle to the string list for the enumeration
* @param elementType handle to the element that owns the attribute with the enumeration
* @param attrName StringPool handle to the name of the attribut with the enumeration
* @param nameIndex StringPool handle to the name to be added to the enumeration
* @param isNotationType true if the enumeration is an enumeration of NOTATION names
* @exception java.lang.Exception
*/
public void addNameToEnumeration(int enumIndex, int elementType, int attrName, int nameIndex, boolean isNotationType) throws Exception;
/**
* Finish processing an enumeration
*
* @param enumIndex handle to the string list which holds the enumeration to be finshed.
* @exception java.lang.Exception
*/
public void endEnumeration(int enumIndex) throws Exception;
/**
* Add a declaration for a notation
*
* @param notationName
* @param publicId
* @param systemId
* @return handle to the notation declaration
* @exception java.lang.Exception
*/
public int addNotationDecl(int notationName, int publicId, int systemId) throws Exception;
/**
* Called when a comment has been scanned
*
* @param data StringPool handle of the comment text
* @exception java.lang.Exception
*/
public void callComment(int data) throws Exception;
/**
* Called when a processing instruction has been scanned
* @param piTarget StringPool handle of the PI target
* @param piData StringPool handle of the PI data
* @exception java.lang.Exception
*/
public void callProcessingInstruction(int piTarget, int piData) throws Exception;
/**
* Supports DOM Level 2 internalSubset additions.
* Called when the internal subset is completely scanned.
*/
public void internalSubset(int internalSubset) throws Exception;
}
//
//
//
/** Report a recoverable xml error. */
protected void reportRecoverableXMLError(int majorCode, int minorCode,
int stringIndex1)
throws Exception {
Object[] args = { fStringPool.toString(stringIndex1) };
fErrorReporter.reportError(fErrorReporter.getLocator(),
XMLMessages.XML_DOMAIN,
majorCode,
minorCode,
args,
XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
} // reportRecoverableXMLError(int,int,int)
/** Report a recoverable xml error. */
protected void reportRecoverableXMLError(int majorCode, int minorCode,
String string1) throws Exception {
Object[] args = { string1 };
fErrorReporter.reportError(fErrorReporter.getLocator(),
XMLMessages.XML_DOMAIN,
majorCode,
minorCode,
args,
XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
} // reportRecoverableXMLError(int,int,String)
/** Report a recoverable xml error. */
protected void reportRecoverableXMLError(int majorCode, int minorCode,
String string1, String string2)
throws Exception {
Object[] args = { string1, string2 };
fErrorReporter.reportError(fErrorReporter.getLocator(),
XMLMessages.XML_DOMAIN,
majorCode,
minorCode,
args,
XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
} // reportRecoverableXMLError(int,int,String,String)
private void reportFatalXMLError(int majorCode, int minorCode) throws Exception {
fErrorReporter.reportError(fErrorReporter.getLocator(),
XMLMessages.XML_DOMAIN,
majorCode,
minorCode,
null,
XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
}
private void reportFatalXMLError(int majorCode, int minorCode, int stringIndex1) throws Exception {
Object[] args = { fStringPool.toString(stringIndex1) };
fErrorReporter.reportError(fErrorReporter.getLocator(),
XMLMessages.XML_DOMAIN,
majorCode,
minorCode,
args,
XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
}
private void reportFatalXMLError(int majorCode, int minorCode, String string1) throws Exception {
Object[] args = { string1 };
fErrorReporter.reportError(fErrorReporter.getLocator(),
XMLMessages.XML_DOMAIN,
majorCode,
minorCode,
args,
XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
}
private void reportFatalXMLError(int majorCode, int minorCode, int stringIndex1, int stringIndex2) throws Exception {
Object[] args = { fStringPool.toString(stringIndex1),
fStringPool.toString(stringIndex2) };
fErrorReporter.reportError(fErrorReporter.getLocator(),
XMLMessages.XML_DOMAIN,
majorCode,
minorCode,
args,
XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
}
private void reportFatalXMLError(int majorCode, int minorCode, String string1, String string2) throws Exception {
Object[] args = { string1, string2 };
fErrorReporter.reportError(fErrorReporter.getLocator(),
XMLMessages.XML_DOMAIN,
majorCode,
minorCode,
args,
XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
}
private void reportFatalXMLError(int majorCode, int minorCode, String string1, String string2, String string3) throws Exception {
Object[] args = { string1, string2, string3 };
fErrorReporter.reportError(fErrorReporter.getLocator(),
XMLMessages.XML_DOMAIN,
majorCode,
minorCode,
args,
XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
}
private void abortMarkup(int majorCode, int minorCode) throws Exception {
reportFatalXMLError(majorCode, minorCode);
skipPastEndOfCurrentMarkup();
}
private void abortMarkup(int majorCode, int minorCode, int stringIndex1) throws Exception {
reportFatalXMLError(majorCode, minorCode, stringIndex1);
skipPastEndOfCurrentMarkup();
}
private void abortMarkup(int majorCode, int minorCode, String string1) throws Exception {
reportFatalXMLError(majorCode, minorCode, string1);
skipPastEndOfCurrentMarkup();
}
private void abortMarkup(int majorCode, int minorCode, int stringIndex1, int stringIndex2) throws Exception {
reportFatalXMLError(majorCode, minorCode, stringIndex1, stringIndex2);
skipPastEndOfCurrentMarkup();
}
private void skipPastEndOfCurrentMarkup() throws Exception {
fEntityReader.skipToChar('>');
if (fEntityReader.lookingAtChar('>', true))
decreaseMarkupDepth();
}
//
//
//
static private final int SCANNER_STATE_INVALID = -1;
static private final int SCANNER_STATE_END_OF_INPUT = 0;
static private final int SCANNER_STATE_DOCTYPEDECL = 50;
static private final int SCANNER_STATE_MARKUP_DECL = 51;
static private final int SCANNER_STATE_TEXTDECL = 53;
static private final int SCANNER_STATE_COMMENT = 54;
static private final int SCANNER_STATE_PI = 55;
static private final int SCANNER_STATE_DEFAULT_ATTRIBUTE_VALUE = 56;
static private final int SCANNER_STATE_CONTENTSPEC = 57;
static private final int SCANNER_STATE_ENTITY_VALUE = 58;
static private final int SCANNER_STATE_SYSTEMLITERAL = 59;
static private final int SCANNER_STATE_PUBIDLITERAL = 60;
private int setScannerState(int scannerState) {
int prevState = fScannerState;
fScannerState = scannerState;
return prevState;
}
private int getScannerState() {
return fScannerState;
}
private void restoreScannerState(int scannerState) {
if (fScannerState != SCANNER_STATE_END_OF_INPUT)
fScannerState = scannerState;
}
/**
* Change readers
*
* @param nextReader the new reader that the scanner will use
* @param nextReaderId id of the reader to change to
* @exception throws java.lang.Exception
*/
public void readerChange(XMLEntityHandler.EntityReader nextReader, int nextReaderId) throws Exception {
fEntityReader = nextReader;
fReaderId = nextReaderId;
if (fScannerState == SCANNER_STATE_DEFAULT_ATTRIBUTE_VALUE) {
fDefaultAttValueOffset = fEntityReader.currentOffset();
fDefaultAttValueMark = fDefaultAttValueOffset;
} else if (fScannerState == SCANNER_STATE_ENTITY_VALUE) {
fEntityValueMark = fEntityReader.currentOffset();
}
}
/**
* Handle the end of input
*
* @param entityName the handle in the string pool of the name of the entity which has reached end of input
* @param moreToFollow if true, there is still input left to process in other readers
* @exception java.lang.Exception
*/
public void endOfInput(int entityNameIndex, boolean moreToFollow) throws Exception {
if (fValidationEnabled ) {
int readerDepth = fEntityHandler.getReaderDepth();
if (getReadingContentSpec()) {
int parenDepth = parenDepth();
if (readerDepth != parenDepth) {
reportRecoverableXMLError(XMLMessages.MSG_IMPROPER_GROUP_NESTING,
XMLMessages.VC_PROPER_GROUP_PE_NESTING,
entityNameIndex);
}
} else {
int markupDepth = markupDepth();
if (readerDepth != markupDepth) {
reportRecoverableXMLError(XMLMessages.MSG_IMPROPER_DECLARATION_NESTING,
XMLMessages.VC_PROPER_DECLARATION_PE_NESTING,
entityNameIndex);
}
}
}
//REVISIT, why are we doing this?
moreToFollow = fReaderId != fExternalSubsetReader;
// System.out.println("current Scanner state " + getScannerState() +","+ fScannerState + moreToFollow);
switch (fScannerState) {
case SCANNER_STATE_INVALID:
throw new RuntimeException("FWK004 XMLDTDScanner.endOfInput: cannot happen: 2"+"\n2");
case SCANNER_STATE_END_OF_INPUT:
break;
case SCANNER_STATE_MARKUP_DECL:
if (!moreToFollow && fIncludeSectDepth > 0) {
reportFatalXMLError(XMLMessages.MSG_INCLUDESECT_UNTERMINATED,
XMLMessages.P62_UNTERMINATED);
}
break;
case SCANNER_STATE_DOCTYPEDECL:
throw new RuntimeException("FWK004 XMLDTDScanner.endOfInput: cannot happen: 2.5"+"\n2.5");
// break;
case SCANNER_STATE_TEXTDECL:
// REVISIT reportFatalXMLError(XMLMessages.MSG_ATTVAL0);
break;
case SCANNER_STATE_SYSTEMLITERAL:
if (!moreToFollow) {
reportFatalXMLError(XMLMessages.MSG_SYSTEMID_UNTERMINATED,
XMLMessages.P11_UNTERMINATED);
} else {
// REVISIT reportFatalXMLError(XMLMessages.MSG_ATTVAL0);
}
break;
case SCANNER_STATE_PUBIDLITERAL:
if (!moreToFollow) {
reportFatalXMLError(XMLMessages.MSG_PUBLICID_UNTERMINATED,
XMLMessages.P12_UNTERMINATED);
} else {
// REVISIT reportFatalXMLError(XMLMessages.MSG_ATTVAL0);
}
break;
case SCANNER_STATE_COMMENT:
if (!moreToFollow && !getReadingExternalEntity()) {
reportFatalXMLError(XMLMessages.MSG_COMMENT_UNTERMINATED,
XMLMessages.P15_UNTERMINATED);
} else {
//
// REVISIT - HACK !!! code changed to pass incorrect OASIS test 'invalid--001'
// Uncomment the next line to conform to the spec...
//
//reportFatalXMLError(XMLMessages.MSG_COMMENT_NOT_IN_ONE_ENTITY,
// XMLMessages.P78_NOT_WELLFORMED);
}
break;
case SCANNER_STATE_PI:
if (!moreToFollow) {
reportFatalXMLError(XMLMessages.MSG_PI_UNTERMINATED,
XMLMessages.P16_UNTERMINATED);
} else {
reportFatalXMLError(XMLMessages.MSG_PI_NOT_IN_ONE_ENTITY,
XMLMessages.P78_NOT_WELLFORMED);
}
break;
case SCANNER_STATE_DEFAULT_ATTRIBUTE_VALUE:
if (!moreToFollow) {
reportFatalXMLError(XMLMessages.MSG_ATTRIBUTE_VALUE_UNTERMINATED,
XMLMessages.P10_UNTERMINATED,
fDefaultAttValueElementType,
fDefaultAttValueAttrName);
} else if (fReaderId == fDefaultAttValueReader) {
// REVISIT reportFatalXMLError(XMLMessages.MSG_ATTVAL0);
} else {
fEntityReader.append(fLiteralData, fDefaultAttValueMark, fDefaultAttValueOffset - fDefaultAttValueMark);
}
break;
case SCANNER_STATE_CONTENTSPEC:
break;
case SCANNER_STATE_ENTITY_VALUE:
if (fReaderId == fEntityValueReader) {
// REVISIT reportFatalXMLError(XMLMessages.MSG_ATTVAL0);
} else {
fEntityReader.append(fLiteralData, fEntityValueMark, fEntityReader.currentOffset() - fEntityValueMark);
}
break;
default:
throw new RuntimeException("FWK004 XMLDTDScanner.endOfInput: cannot happen: 3"+"\n3");
}
if (!moreToFollow) {
setScannerState(SCANNER_STATE_END_OF_INPUT);
}
}
//
// [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'
//
private int scanCharRef() throws Exception {
int valueOffset = fEntityReader.currentOffset();
boolean hex = fEntityReader.lookingAtChar('x', true);
int num = fEntityReader.scanCharRef(hex);
if (num < 0) {
switch (num) {
case XMLEntityHandler.CHARREF_RESULT_SEMICOLON_REQUIRED:
reportFatalXMLError(XMLMessages.MSG_SEMICOLON_REQUIRED_IN_CHARREF,
XMLMessages.P66_SEMICOLON_REQUIRED);
return -1;
case XMLEntityHandler.CHARREF_RESULT_INVALID_CHAR:
int majorCode = hex ? XMLMessages.MSG_HEXDIGIT_REQUIRED_IN_CHARREF :
XMLMessages.MSG_DIGIT_REQUIRED_IN_CHARREF;
int minorCode = hex ? XMLMessages.P66_HEXDIGIT_REQUIRED :
XMLMessages.P66_DIGIT_REQUIRED;
reportFatalXMLError(majorCode, minorCode);
return -1;
case XMLEntityHandler.CHARREF_RESULT_OUT_OF_RANGE:
num = 0x110000; // this will cause the right error to be reported below...
break;
}
}
//
// [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] // any Unicode character, excluding the
// | [#xE000-#xFFFD] | [#x10000-#x10FFFF] // surrogate blocks, FFFE, and FFFF.
//
if (num < 0x20) {
if (num == 0x09 || num == 0x0A || num == 0x0D) {
return num;
}
} else if (num <= 0xD7FF || (num >= 0xE000 && (num <= 0xFFFD || (num >= 0x10000 && num <= 0x10FFFF)))) {
return num;
}
int valueLength = fEntityReader.currentOffset() - valueOffset;
reportFatalXMLError(XMLMessages.MSG_INVALID_CHARREF,
XMLMessages.WFC_LEGAL_CHARACTER,
fEntityReader.addString(valueOffset, valueLength));
return -1;
}
//
// From the standard:
//
// [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
//
// Called after scanning past '<!--'
//
private void scanComment() throws Exception
{
int commentOffset = fEntityReader.currentOffset();
boolean sawDashDash = false;
int previousState = setScannerState(SCANNER_STATE_COMMENT);
while (fScannerState == SCANNER_STATE_COMMENT) {
if (fEntityReader.lookingAtChar('-', false)) {
int nextEndOffset = fEntityReader.currentOffset();
int endOffset = 0;
fEntityReader.lookingAtChar('-', true);
int offset = fEntityReader.currentOffset();
int count = 1;
while (fEntityReader.lookingAtChar('-', true)) {
count++;
endOffset = nextEndOffset;
nextEndOffset = offset;
offset = fEntityReader.currentOffset();
}
if (count > 1) {
if (fEntityReader.lookingAtChar('>', true)) {
if (!sawDashDash && count > 2) {
reportFatalXMLError(XMLMessages.MSG_DASH_DASH_IN_COMMENT,
XMLMessages.P15_DASH_DASH);
sawDashDash = true;
}
decreaseMarkupDepth();
int comment = fEntityReader.addString(commentOffset, endOffset - commentOffset);
fDTDGrammar.callComment(comment);
if (fDTDHandler != null) {
fDTDHandler.comment(comment);
}
restoreScannerState(previousState);
return;
} else if (!sawDashDash) {
reportFatalXMLError(XMLMessages.MSG_DASH_DASH_IN_COMMENT,
XMLMessages.P15_DASH_DASH);
sawDashDash = true;
}
}
} else {
if (!fEntityReader.lookingAtValidChar(true)) {
int invChar = fEntityReader.scanInvalidChar();
if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
if (invChar >= 0) {
reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_COMMENT,
XMLMessages.P15_INVALID_CHARACTER,
Integer.toHexString(invChar));
}
}
}
}
}
restoreScannerState(previousState);
}
//
// From the standard:
//
// [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
// [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
//
private void scanPI(int piTarget) throws Exception
{
String piTargetString = fStringPool.toString(piTarget);
if (piTargetString.length() == 3 &&
(piTargetString.charAt(0) == 'X' || piTargetString.charAt(0) == 'x') &&
(piTargetString.charAt(1) == 'M' || piTargetString.charAt(1) == 'm') &&
(piTargetString.charAt(2) == 'L' || piTargetString.charAt(2) == 'l')) {
abortMarkup(XMLMessages.MSG_RESERVED_PITARGET,
XMLMessages.P17_RESERVED_PITARGET);
return;
}
int prevState = setScannerState(SCANNER_STATE_PI);
int piDataOffset = -1;
int piDataLength = 0;
if (!fEntityReader.lookingAtSpace(true)) {
if (!fEntityReader.lookingAtChar('?', true) || !fEntityReader.lookingAtChar('>', true)) {
if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_IN_PI,
XMLMessages.P16_WHITESPACE_REQUIRED);
restoreScannerState(prevState);
}
return;
}
decreaseMarkupDepth();
restoreScannerState(prevState);
} else {
fEntityReader.skipPastSpaces();
piDataOffset = fEntityReader.currentOffset();
while (fScannerState == SCANNER_STATE_PI) {
while (fEntityReader.lookingAtChar('?', false)) {
int offset = fEntityReader.currentOffset();
fEntityReader.lookingAtChar('?', true);
if (fEntityReader.lookingAtChar('>', true)) {
piDataLength = offset - piDataOffset;
decreaseMarkupDepth();
restoreScannerState(prevState);
break;
}
}
if (fScannerState != SCANNER_STATE_PI)
break;
if (!fEntityReader.lookingAtValidChar(true)) {
int invChar = fEntityReader.scanInvalidChar();
if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
if (invChar >= 0) {
reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_PI,
XMLMessages.P16_INVALID_CHARACTER,
Integer.toHexString(invChar));
}
skipPastEndOfCurrentMarkup();
restoreScannerState(prevState);
}
return;
}
}
}
int piData = piDataLength == 0 ?
StringPool.EMPTY_STRING : fEntityReader.addString(piDataOffset, piDataLength);
fDTDGrammar.callProcessingInstruction(piTarget, piData);
if (fDTDHandler != null) {
fDTDHandler.processingInstruction(piTarget, piData);
}
}
//
// From the standard:
//
// [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
// ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
// [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl
// | NotationDecl | PI | Comment
//
// Called after scanning '<!DOCTYPE'
//
/**
* This routine is called after the &lt;!DOCTYPE portion of a DOCTYPE
* line has been called. scanDocTypeDecl goes onto scan the rest of the DOCTYPE
* decl. If an internal DTD subset exists, it is scanned. If an external DTD
* subset exists, scanDocTypeDecl sets up the state necessary to process it.
*
* @return true if successful
* @exception java.lang.Exception
*/
public boolean scanDoctypeDecl() throws Exception
{
//System.out.println("XMLDTDScanner#scanDoctypeDecl()");
fDTDGrammar = new DTDGrammar(fStringPool);
fDTDGrammar.callStartDTD();
increaseMarkupDepth();
fEntityReader = fEntityHandler.getEntityReader();
fReaderId = fEntityHandler.getReaderId();
fDoctypeReader = fReaderId;
setScannerState(SCANNER_STATE_DOCTYPEDECL);
if (!fEntityReader.lookingAtSpace(true)) {
abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL,
XMLMessages.P28_SPACE_REQUIRED);
return false;
}
fEntityReader.skipPastSpaces();
scanElementType(fEntityReader, ' ', fElementQName);
if (fElementQName.rawname == -1) {
abortMarkup(XMLMessages.MSG_ROOT_ELEMENT_TYPE_REQUIRED,
XMLMessages.P28_ROOT_ELEMENT_TYPE_REQUIRED);
return false;
}
boolean lbrkt;
boolean scanExternalSubset = false;
int publicId = -1;
int systemId = -1;
if (fEntityReader.lookingAtSpace(true)) {
fEntityReader.skipPastSpaces();
if (!(lbrkt = fEntityReader.lookingAtChar('[', true)) && !fEntityReader.lookingAtChar('>', false)) {
if (!scanExternalID(false)) {
skipPastEndOfCurrentMarkup();
return false;
}
scanExternalSubset = true;
publicId = fPubidLiteral;
systemId = fSystemLiteral;
fEntityReader.skipPastSpaces();
lbrkt = fEntityReader.lookingAtChar('[', true);
}
} else
lbrkt = fEntityReader.lookingAtChar('[', true);
fDTDGrammar.doctypeDecl(fElementQName, publicId, systemId);
if (fDTDHandler != null) {
fDTDHandler.startDTD(fElementQName, publicId, systemId);
}
if (lbrkt) {
scanDecls(false);
fEntityReader.skipPastSpaces();
}
if (!fEntityReader.lookingAtChar('>', true)) {
if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
abortMarkup(XMLMessages.MSG_DOCTYPEDECL_UNTERMINATED,
XMLMessages.P28_UNTERMINATED,
fElementQName.rawname);
}
return false;
}
decreaseMarkupDepth();
//System.out.println(" scanExternalSubset: "+scanExternalSubset);
if (scanExternalSubset) {
((DefaultEntityHandler) fEntityHandler).startReadingFromExternalSubset( fStringPool.toString(publicId),
fStringPool.toString(systemId),
markupDepth());
fDTDGrammar.startReadingFromExternalSubset(publicId, systemId);
}
else {
fDTDGrammar.callEndDTD();
if (fDTDHandler != null) {
fDTDHandler.endDTD();
}
}
fGrammarResolver.putGrammar("", fDTDGrammar);
return true;
}
//
// [75] ExternalID ::= 'SYSTEM' S SystemLiteral
// | 'PUBLIC' S PubidLiteral S SystemLiteral
// [83] PublicID ::= 'PUBLIC' S PubidLiteral
//
private boolean scanExternalID(boolean scanPublicID) throws Exception
{
fSystemLiteral = -1;
fPubidLiteral = -1;
int offset = fEntityReader.currentOffset();
if (fEntityReader.skippedString(system_string)) {
if (!fEntityReader.lookingAtSpace(true)) {
reportFatalXMLError(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_SYSTEMLITERAL_IN_EXTERNALID,
XMLMessages.P75_SPACE_REQUIRED);
return false;
}
fEntityReader.skipPastSpaces();
if( getReadingExternalEntity() == true ) { //Are we in external subset?
checkForPEReference(false);//If so Check for PE Ref
}
return scanSystemLiteral();
}
if (fEntityReader.skippedString(public_string)) {
if (!fEntityReader.lookingAtSpace(true)) {
reportFatalXMLError(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID,
XMLMessages.P75_SPACE_REQUIRED);
return false;
}
fEntityReader.skipPastSpaces();
if (!scanPubidLiteral())
return false;
if (scanPublicID) {
//
// [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID | PublicID) S? '>'
//
if (!fEntityReader.lookingAtSpace(true))
return true; // no S, not an ExternalID
fEntityReader.skipPastSpaces();
if (fEntityReader.lookingAtChar('>', false)) // matches end of NotationDecl
return true;
} else {
if (!fEntityReader.lookingAtSpace(true)) {
reportFatalXMLError(XMLMessages.MSG_SPACE_REQUIRED_AFTER_PUBIDLITERAL_IN_EXTERNALID,
XMLMessages.P75_SPACE_REQUIRED);
return false;
}
fEntityReader.skipPastSpaces();
}
return scanSystemLiteral();
}
reportFatalXMLError(XMLMessages.MSG_EXTERNALID_REQUIRED,
XMLMessages.P75_INVALID);
return false;
}
//
// [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
//
// REVISIT - need to look into uri escape mechanism for non-ascii characters.
//
private boolean scanSystemLiteral() throws Exception
{
boolean single;
if (!(single = fEntityReader.lookingAtChar('\'', true)) && !fEntityReader.lookingAtChar('\"', true)) {
reportFatalXMLError(XMLMessages.MSG_QUOTE_REQUIRED_IN_SYSTEMID,
XMLMessages.P11_QUOTE_REQUIRED);
return false;
}
int prevState = setScannerState(SCANNER_STATE_SYSTEMLITERAL);
int offset = fEntityReader.currentOffset();
char qchar = single ? '\'' : '\"';
boolean dataok = true;
boolean fragment = false;
while (!fEntityReader.lookingAtChar(qchar, false)) {
//ericye
//System.out.println("XMLDTDScanner#scanDoctypeDecl() 3333333, "+fReaderId+", " + fScannerState+", " +fExternalSubsetReader);
if (fEntityReader.lookingAtChar('#', true)) {
fragment = true;
} else if (!fEntityReader.lookingAtValidChar(true)) {
//System.out.println("XMLDTDScanner#scanDoctypeDecl() 555555 scan state: " + fScannerState);
dataok = false;
int invChar = fEntityReader.scanInvalidChar();
if (fScannerState == SCANNER_STATE_END_OF_INPUT)
return false;
if (invChar >= 0) {
reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_SYSTEMID,
XMLMessages.P11_INVALID_CHARACTER,
Integer.toHexString(invChar));
}
}
}
if (dataok) {
fSystemLiteral = fEntityReader.addString(offset, fEntityReader.currentOffset() - offset);
if (fragment) {
// NOTE: RECOVERABLE ERROR
Object[] args = { fStringPool.toString(fSystemLiteral) };
fErrorReporter.reportError(fErrorReporter.getLocator(),
XMLMessages.XML_DOMAIN,
XMLMessages.MSG_URI_FRAGMENT_IN_SYSTEMID,
XMLMessages.P11_URI_FRAGMENT,
args,
XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
}
}
fEntityReader.lookingAtChar(qchar, true);
restoreScannerState(prevState);
return dataok;
}
//
// [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
// [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
//
private boolean scanPubidLiteral() throws Exception
{
boolean single;
if (!(single = fEntityReader.lookingAtChar('\'', true)) && !fEntityReader.lookingAtChar('\"', true)) {
reportFatalXMLError(XMLMessages.MSG_QUOTE_REQUIRED_IN_PUBLICID,
XMLMessages.P12_QUOTE_REQUIRED);
return false;
}
char qchar = single ? '\'' : '\"';
int prevState = setScannerState(SCANNER_STATE_PUBIDLITERAL);
boolean dataok = true;
while (true) {
if (fEntityReader.lookingAtChar((char)0x09, true)) {
dataok = false;
reportFatalXMLError(XMLMessages.MSG_PUBIDCHAR_ILLEGAL,
XMLMessages.P12_INVALID_CHARACTER, "9");
}
if (!fEntityReader.lookingAtSpace(true))
break;
}
int offset = fEntityReader.currentOffset();
int dataOffset = fLiteralData.length();
int toCopy = offset;
while (true) {
if (fEntityReader.lookingAtChar(qchar, true)) {
if (dataok && offset - toCopy > 0)
fEntityReader.append(fLiteralData, toCopy, offset - toCopy);
break;
}
if (fEntityReader.lookingAtChar((char)0x09, true)) {
dataok = false;
reportFatalXMLError(XMLMessages.MSG_PUBIDCHAR_ILLEGAL,
XMLMessages.P12_INVALID_CHARACTER, "9");
continue;
}
if (fEntityReader.lookingAtSpace(true)) {
if (dataok && offset - toCopy > 0)
fEntityReader.append(fLiteralData, toCopy, offset - toCopy);
while (true) {
if (fEntityReader.lookingAtChar((char)0x09, true)) {
dataok = false;
reportFatalXMLError(XMLMessages.MSG_PUBIDCHAR_ILLEGAL,
XMLMessages.P12_INVALID_CHARACTER, "9");
break;
} else if (!fEntityReader.lookingAtSpace(true)) {
break;
}
}
if (fEntityReader.lookingAtChar(qchar, true))
break;
if (dataok) {
fLiteralData.append(' ');
offset = fEntityReader.currentOffset();
toCopy = offset;
}
continue;
}
if (!fEntityReader.lookingAtValidChar(true)) {
int invChar = fEntityReader.scanInvalidChar();
if (fScannerState == SCANNER_STATE_END_OF_INPUT)
return false;
dataok = false;
if (invChar >= 0) {
reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_PUBLICID,
XMLMessages.P12_INVALID_CHARACTER,
Integer.toHexString(invChar));
}
}
if (dataok)
offset = fEntityReader.currentOffset();
}
if (dataok) {
int dataLength = fLiteralData.length() - dataOffset;
fPubidLiteral = fLiteralData.addString(dataOffset, dataLength);
String publicId = fStringPool.toString(fPubidLiteral);
int invCharIndex = validPublicId(publicId);
if (invCharIndex >= 0) {
reportFatalXMLError(XMLMessages.MSG_PUBIDCHAR_ILLEGAL,
XMLMessages.P12_INVALID_CHARACTER,
Integer.toHexString(publicId.charAt(invCharIndex)));
return false;
}
}
restoreScannerState(prevState);
return dataok;
}
//
// [??] intSubsetDecl = '[' (markupdecl | PEReference | S)* ']'
//
// [31] extSubsetDecl ::= ( markupdecl | conditionalSect | PEReference | S )*
// [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
//
// [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl
// | NotationDecl | PI | Comment
//
// [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
//
// [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
//
// [70] EntityDecl ::= GEDecl | PEDecl
// [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
// [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
//
// [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID | PublicID) S? '>'
//
// [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
//
// [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
//
// [61] conditionalSect ::= includeSect | ignoreSect
// [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
// [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
// [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
// [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
//
/**
* Scan markup declarations
*
* @param extSubset true if the scanner is scanning an external subset, false
* if it is scanning an internal subset
* @exception java.lang.Exception
*/
public void scanDecls(boolean extSubset) throws Exception
{
int subsetOffset = fEntityReader.currentOffset();
if (extSubset)
fExternalSubsetReader = fReaderId;
fIncludeSectDepth = 0;
boolean parseTextDecl = extSubset;
int prevState = setScannerState(SCANNER_STATE_MARKUP_DECL);
while (fScannerState == SCANNER_STATE_MARKUP_DECL) {
boolean newParseTextDecl = false;
if (!extSubset && fEntityReader.lookingAtChar(']', false)) {
int subsetLength = fEntityReader.currentOffset() - subsetOffset;
int internalSubset = fEntityReader.addString(subsetOffset, subsetLength);
fDTDGrammar.internalSubset(internalSubset);
if (fDTDHandler != null) {
fDTDHandler.internalSubset(internalSubset);
}
fEntityReader.lookingAtChar(']', true);
restoreScannerState(prevState);
return;
}
if (fEntityReader.lookingAtChar('<', true)) {
int olddepth = markupDepth();
increaseMarkupDepth();
if (fEntityReader.lookingAtChar('!', true)) {
if (fEntityReader.lookingAtChar('-', true)) {
if (fEntityReader.lookingAtChar('-', true)) {
scanComment();
} else {
abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_DTD,
XMLMessages.P29_NOT_RECOGNIZED);
}
} else if (fEntityReader.lookingAtChar('[', true) && getReadingExternalEntity()) {
checkForPEReference(false);
if (fEntityReader.skippedString(include_string)) {
checkForPEReference(false);
if (!fEntityReader.lookingAtChar('[', true)) {
abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_DTD,
XMLMessages.P29_NOT_RECOGNIZED);
} else {
fIncludeSectDepth++;
}
} else if (fEntityReader.skippedString(ignore_string)) {
checkForPEReference(false);
if (!fEntityReader.lookingAtChar('[', true)) {
abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_DTD,
XMLMessages.P29_NOT_RECOGNIZED);
} else
scanIgnoreSectContents();
} else {
abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_DTD,
XMLMessages.P29_NOT_RECOGNIZED);
}
} else if (fEntityReader.skippedString(element_string)) {
scanElementDecl();
}
else if (fEntityReader.skippedString(attlist_string))
scanAttlistDecl();
else if (fEntityReader.skippedString(entity_string))
scanEntityDecl();
else if (fEntityReader.skippedString(notation_string))
scanNotationDecl();
else {
abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_DTD,
XMLMessages.P29_NOT_RECOGNIZED);
}
} else if (fEntityReader.lookingAtChar('?', true)) {
int piTarget = fEntityReader.scanName(' ');
if (piTarget == -1) {
abortMarkup(XMLMessages.MSG_PITARGET_REQUIRED,
XMLMessages.P16_REQUIRED);
} else if ("xml".equals(fStringPool.toString(piTarget))) {
if (fEntityReader.lookingAtSpace(true)) {
if (parseTextDecl) { // a TextDecl looks like a PI with the target 'xml'
scanTextDecl();
} else {
abortMarkup(XMLMessages.MSG_TEXTDECL_MUST_BE_FIRST,
XMLMessages.P30_TEXTDECL_MUST_BE_FIRST);
}
} else { // a PI target matching 'xml'
abortMarkup(XMLMessages.MSG_RESERVED_PITARGET,
XMLMessages.P17_RESERVED_PITARGET);
}
} else // PI
scanPI(piTarget);
} else {
abortMarkup(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_DTD,
XMLMessages.P29_NOT_RECOGNIZED);
}
} else if (fEntityReader.lookingAtSpace(true)) {
fEntityReader.skipPastSpaces();
} else if (fEntityReader.lookingAtChar('%', true)) {
//
// [69] PEReference ::= '%' Name ';'
//
int nameOffset = fEntityReader.currentOffset();
fEntityReader.skipPastName(';');
int nameLength = fEntityReader.currentOffset() - nameOffset;
if (nameLength == 0) {
reportFatalXMLError(XMLMessages.MSG_NAME_REQUIRED_IN_PEREFERENCE,
XMLMessages.P69_NAME_REQUIRED);
} else if (!fEntityReader.lookingAtChar(';', true)) {
reportFatalXMLError(XMLMessages.MSG_SEMICOLON_REQUIRED_IN_PEREFERENCE,
XMLMessages.P69_SEMICOLON_REQUIRED,
fEntityReader.addString(nameOffset, nameLength));
} else {
int peNameIndex = fEntityReader.addSymbol(nameOffset, nameLength);
newParseTextDecl = fEntityHandler.startReadingFromEntity(peNameIndex, markupDepth(), XMLEntityHandler.ENTITYREF_IN_DTD_AS_MARKUP);
}
} else if (fIncludeSectDepth > 0 && fEntityReader.lookingAtChar(']', true)) {
if (!fEntityReader.lookingAtChar(']', true) || !fEntityReader.lookingAtChar('>', true)) {
abortMarkup(XMLMessages.MSG_INCLUDESECT_UNTERMINATED,
XMLMessages.P62_UNTERMINATED);
} else
decreaseMarkupDepth();
fIncludeSectDepth--;
} else {
if (!fEntityReader.lookingAtValidChar(false)) {
int invChar = fEntityReader.scanInvalidChar();
if (fScannerState == SCANNER_STATE_END_OF_INPUT)
break;
if (invChar >= 0) {
if (!extSubset) {
reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_INTERNAL_SUBSET,
XMLMessages.P28_INVALID_CHARACTER,
Integer.toHexString(invChar));
} else {
reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_EXTERNAL_SUBSET,
XMLMessages.P30_INVALID_CHARACTER,
Integer.toHexString(invChar));
}
}
} else {
reportFatalXMLError(XMLMessages.MSG_MARKUP_NOT_RECOGNIZED_IN_DTD,
XMLMessages.P29_NOT_RECOGNIZED);
fEntityReader.lookingAtValidChar(true);
}
}
parseTextDecl = newParseTextDecl;
}
if (extSubset) {
((DefaultEntityHandler) fEntityHandler).stopReadingFromExternalSubset();
fDTDGrammar.stopReadingFromExternalSubset();
fDTDGrammar.callEndDTD();
if (fDTDHandler != null) {
fDTDHandler.endDTD();
}
// REVISIT: What should the namspace URI of a DTD be?
fGrammarResolver.putGrammar("", fDTDGrammar);
}
}
//
// [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
// [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
//
private void scanIgnoreSectContents() throws Exception
{
int initialDepth = ++fIncludeSectDepth;
while (true) {
if (fEntityReader.lookingAtChar('<', true)) {
//
// These tests are split so that we handle cases like
// '<<![' and '<!<![' which we might otherwise miss.
//
if (fEntityReader.lookingAtChar('!', true) && fEntityReader.lookingAtChar('[', true))
fIncludeSectDepth++;
} else if (fEntityReader.lookingAtChar(']', true)) {
//
// The same thing goes for ']<![' and '<]]>', etc.
//
if (fEntityReader.lookingAtChar(']', true)) {
while (fEntityReader.lookingAtChar(']', true)) {
/* empty loop body */
}
if (fEntityReader.lookingAtChar('>', true)) {
if (fIncludeSectDepth-- == initialDepth) {
decreaseMarkupDepth();
return;
}
}
}
} else if (!fEntityReader.lookingAtValidChar(true)) {
int invChar = fEntityReader.scanInvalidChar();
if (fScannerState == SCANNER_STATE_END_OF_INPUT)
return;
if (invChar >= 0) {
reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_IGNORESECT,
XMLMessages.P65_INVALID_CHARACTER,
Integer.toHexString(invChar));
}
}
}
}
//
// From the standard:
//
// [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
// [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
// [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" )
// [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
//
private void scanTextDecl() throws Exception {
int version = -1;
int encoding = -1;
final int TEXTDECL_START = 0;
final int TEXTDECL_VERSION = 1;
final int TEXTDECL_ENCODING = 2;
final int TEXTDECL_FINISHED = 3;
int prevState = setScannerState(SCANNER_STATE_TEXTDECL);
int state = TEXTDECL_START;
do {
fEntityReader.skipPastSpaces();
int offset = fEntityReader.currentOffset();
if (state == TEXTDECL_START && fEntityReader.skippedString(version_string)) {
state = TEXTDECL_VERSION;
} else if (fEntityReader.skippedString(encoding_string)) {
state = TEXTDECL_ENCODING;
} else {
abortMarkup(XMLMessages.MSG_ENCODINGDECL_REQUIRED,
XMLMessages.P77_ENCODINGDECL_REQUIRED);
restoreScannerState(prevState);
return;
}
int length = fEntityReader.currentOffset() - offset;
fEntityReader.skipPastSpaces();
if (!fEntityReader.lookingAtChar('=', true)) {
int minorCode = state == TEXTDECL_VERSION ?
XMLMessages.P24_EQ_REQUIRED :
XMLMessages.P80_EQ_REQUIRED;
abortMarkup(XMLMessages.MSG_EQ_REQUIRED_IN_TEXTDECL, minorCode,
fEntityReader.addString(offset, length));
restoreScannerState(prevState);
return;
}
fEntityReader.skipPastSpaces();
int result = fEntityReader.scanStringLiteral();
switch (result) {
case XMLEntityHandler.STRINGLIT_RESULT_QUOTE_REQUIRED:
{
int minorCode = state == TEXTDECL_VERSION ?
XMLMessages.P24_QUOTE_REQUIRED :
XMLMessages.P80_QUOTE_REQUIRED;
abortMarkup(XMLMessages.MSG_QUOTE_REQUIRED_IN_TEXTDECL, minorCode,
fEntityReader.addString(offset, length));
restoreScannerState(prevState);
return;
}
case XMLEntityHandler.STRINGLIT_RESULT_INVALID_CHAR:
int invChar = fEntityReader.scanInvalidChar();
if (fScannerState != SCANNER_STATE_END_OF_INPUT) {
if (invChar >= 0) {
int minorCode = state == TEXTDECL_VERSION ?
XMLMessages.P26_INVALID_CHARACTER :
XMLMessages.P81_INVALID_CHARACTER;
reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_TEXTDECL, minorCode,
Integer.toHexString(invChar));
}
skipPastEndOfCurrentMarkup();
restoreScannerState(prevState);
}
return;
default:
break;
}
switch (state) {
case TEXTDECL_VERSION:
//
// version="..."
//
version = result;
String versionString = fStringPool.toString(version);
if (!"1.0".equals(versionString)) {
if (!validVersionNum(versionString)) {
abortMarkup(XMLMessages.MSG_VERSIONINFO_INVALID,
XMLMessages.P26_INVALID_VALUE,
versionString);
restoreScannerState(prevState);
return;
}
// NOTE: RECOVERABLE ERROR
Object[] args = { versionString };
fErrorReporter.reportError(fErrorReporter.getLocator(),
XMLMessages.XML_DOMAIN,
XMLMessages.MSG_VERSION_NOT_SUPPORTED,
XMLMessages.P26_NOT_SUPPORTED,
args,
XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
// REVISIT - hope it is a compatible version...
// skipPastEndOfCurrentMarkup();
// return;
}
if (!fEntityReader.lookingAtSpace(true)) {
abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_IN_TEXTDECL,
XMLMessages.P80_WHITESPACE_REQUIRED);
restoreScannerState(prevState);
return;
}
break;
case TEXTDECL_ENCODING:
//
// encoding = "..."
//
encoding = result;
String encodingString = fStringPool.toString(encoding);
if (!validEncName(encodingString)) {
abortMarkup(XMLMessages.MSG_ENCODINGDECL_INVALID,
XMLMessages.P81_INVALID_VALUE,
encodingString);
restoreScannerState(prevState);
return;
}
fEntityReader.skipPastSpaces();
state = TEXTDECL_FINISHED;
break;
}
} while (state != TEXTDECL_FINISHED);
if (!fEntityReader.lookingAtChar('?', true) || !fEntityReader.lookingAtChar('>', true)) {
abortMarkup(XMLMessages.MSG_TEXTDECL_UNTERMINATED,
XMLMessages.P77_UNTERMINATED);
restoreScannerState(prevState);
return;
}
decreaseMarkupDepth();
fDTDGrammar.callTextDecl(version, encoding);
if (fDTDHandler != null) {
fDTDHandler.textDecl(version, encoding);
}
restoreScannerState(prevState);
}
private QName fElementDeclQName = new QName();
/**
* Scans an element declaration.
* <pre>
* [45] elementdecl ::= '&lt;!ELEMENT' S Name S contentspec S? '&gt;'
* </pre>
*/
private void scanElementDecl() throws Exception {
if (!checkForPEReference(true)) {
abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_ELEMENT_TYPE_IN_ELEMENTDECL,
XMLMessages.P45_SPACE_REQUIRED);
return;
}
checkForElementTypeWithPEReference(fEntityReader, ' ', fElementQName);
if (fElementQName.rawname == -1) {
abortMarkup(XMLMessages.MSG_ELEMENT_TYPE_REQUIRED_IN_ELEMENTDECL,
XMLMessages.P45_ELEMENT_TYPE_REQUIRED);
return;
}
if (fDTDHandler != null) {
fElementDeclQName.setValues(fElementQName);
}
if (!checkForPEReference(true)) {
abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_CONTENTSPEC_IN_ELEMENTDECL,
XMLMessages.P45_SPACE_REQUIRED,
fElementQName.rawname);
return;
}
int contentSpecType = -1;
int contentSpec = -1;
if (fEntityReader.skippedString(empty_string)) {
contentSpecType = XMLElementDecl.TYPE_EMPTY;
} else if (fEntityReader.skippedString(any_string)) {
contentSpecType = XMLElementDecl.TYPE_ANY;
} else if (!fEntityReader.lookingAtChar('(', true)) {
abortMarkup(XMLMessages.MSG_CONTENTSPEC_REQUIRED_IN_ELEMENTDECL,
XMLMessages.P45_CONTENTSPEC_REQUIRED,
fElementQName.rawname);
return;
} else {
int contentSpecReader = fReaderId;
int contentSpecReaderDepth = fEntityHandler.getReaderDepth();
int prevState = setScannerState(SCANNER_STATE_CONTENTSPEC);
int oldDepth = parenDepth();
fEntityHandler.setReaderDepth(oldDepth);
increaseParenDepth();
checkForPEReference(false);
boolean skippedPCDATA = fEntityReader.skippedString(pcdata_string);
if (skippedPCDATA) {
contentSpecType = XMLElementDecl.TYPE_MIXED;
// REVISIT: Validation. Should we pass in QName?
contentSpec = scanMixed(fElementQName);
} else {
contentSpecType = XMLElementDecl.TYPE_CHILDREN;
// REVISIT: Validation. Should we pass in QName?
contentSpec = scanChildren(fElementQName);
}
boolean success = contentSpec != -1;
restoreScannerState(prevState);
fEntityHandler.setReaderDepth(contentSpecReaderDepth);
if (!success) {
setParenDepth(oldDepth);
skipPastEndOfCurrentMarkup();
return;
} else {
if (parenDepth() != oldDepth) // REVISIT - should not be needed
// System.out.println("nesting depth mismatch");
;
}
}
checkForPEReference(false);
if (!fEntityReader.lookingAtChar('>', true)) {
abortMarkup(XMLMessages.MSG_ELEMENTDECL_UNTERMINATED,
XMLMessages.P45_UNTERMINATED,
fElementQName.rawname);
return;
}
decreaseMarkupDepth();
int elementIndex = fDTDGrammar.getElementDeclIndex(fElementQName, -1);
boolean elementDeclIsExternal = getReadingExternalEntity();
if (elementIndex == -1) {
elementIndex = fDTDGrammar.addElementDecl(fElementQName, contentSpecType, contentSpec, elementDeclIsExternal);
//System.out.println("XMLDTDScanner#scanElementDecl->DTDGrammar#addElementDecl: "+elementIndex+" ("+fElementQName.localpart+","+fStringPool.toString(fElementQName.localpart)+')');
}
else {
//now check if we already add this element Decl by foward reference
fDTDGrammar.getElementDecl(elementIndex, fTempElementDecl);
if (fTempElementDecl.type == -1) {
fTempElementDecl.type = contentSpecType;
fTempElementDecl.contentSpecIndex = contentSpec;
fDTDGrammar.setElementDeclDTD(elementIndex, fTempElementDecl);
fDTDGrammar.setElementDeclIsExternal(elementIndex, elementDeclIsExternal);
}
else {
//REVISIT, valiate VC duplicate element type.
if ( fValidationEnabled )
//&&
// (elemenetDeclIsExternal==fDTDGrammar.getElementDeclIsExternal(elementIndex)
{
reportRecoverableXMLError(
XMLMessages.MSG_ELEMENT_ALREADY_DECLARED,
XMLMessages.VC_UNIQUE_ELEMENT_TYPE_DECLARATION,
fStringPool.toString(fElementQName.rawname)
);
}
}
}
if (fDTDHandler != null) {
fDTDGrammar.getElementDecl(elementIndex, fTempElementDecl);
fDTDHandler.elementDecl(fElementDeclQName, contentSpecType, contentSpec, fDTDGrammar);
}
} // scanElementDecl()
/**
* Scans mixed content model. Called after scanning past '(' S? '#PCDATA'
* <pre>
* [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' | '(' S? '#PCDATA' S? ')'
* </pre>
*/
private int scanMixed(QName element) throws Exception {
int valueIndex = -1; // -1 is special value for #PCDATA
int prevNodeIndex = -1;
boolean starRequired = false;
int[] valueSeen = new int[32];
int valueCount = 0;
boolean dupAttrType = false;
int nodeIndex = -1;
while (true) {
if (fValidationEnabled) {
for (int i=0; i<valueCount;i++) {
if ( valueSeen[i] == valueIndex) {
dupAttrType = true;
break;
}
}
}
if (dupAttrType && fValidationEnabled) {
reportRecoverableXMLError(XMLMessages.MSG_DUPLICATE_TYPE_IN_MIXED_CONTENT,
XMLMessages.VC_NO_DUPLICATE_TYPES,
valueIndex);
dupAttrType = false;
}
else {
try {
valueSeen[valueCount] = valueIndex;
}
catch (ArrayIndexOutOfBoundsException ae) {
int[] newArray = new int[valueSeen.length*2];
System.arraycopy(valueSeen,0,newArray,0,valueSeen.length);
valueSeen = newArray;
valueSeen[valueCount] = valueIndex;
}
valueCount++;
nodeIndex = fDTDGrammar.addUniqueLeafNode(valueIndex);
}
checkForPEReference(false);
if (!fEntityReader.lookingAtChar('|', true)) {
if (!fEntityReader.lookingAtChar(')', true)) {
reportFatalXMLError(XMLMessages.MSG_CLOSE_PAREN_REQUIRED_IN_MIXED,
XMLMessages.P51_CLOSE_PAREN_REQUIRED,
element.rawname);
return -1;
}
decreaseParenDepth();
if (nodeIndex == -1) {
nodeIndex = prevNodeIndex;
} else if (prevNodeIndex != -1) {
nodeIndex = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE, prevNodeIndex, nodeIndex);
}
if (fEntityReader.lookingAtChar('*', true)) {
nodeIndex = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, nodeIndex);
} else if (starRequired) {
reportFatalXMLError(XMLMessages.MSG_MIXED_CONTENT_UNTERMINATED,
XMLMessages.P51_UNTERMINATED,
fStringPool.toString(element.rawname),
fDTDGrammar.getContentSpecNodeAsString(nodeIndex));
return -1;
}
return nodeIndex;
}
if (nodeIndex != -1) {
if (prevNodeIndex != -1) {
nodeIndex = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE, prevNodeIndex, nodeIndex);
}
prevNodeIndex = nodeIndex;
}
starRequired = true;
checkForPEReference(false);
checkForElementTypeWithPEReference(fEntityReader, ')', fElementRefQName);
valueIndex = fElementRefQName.rawname;
if (valueIndex == -1) {
reportFatalXMLError(XMLMessages.MSG_ELEMENT_TYPE_REQUIRED_IN_MIXED_CONTENT,
XMLMessages.P51_ELEMENT_TYPE_REQUIRED,
element.rawname);
return -1;
}
}
} // scanMixed(QName):int
/**
* Scans a children content model.
* <pre>
* [47] children ::= (choice | seq) ('?' | '*' | '+')?
* [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
* [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
* [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
* </pre>
*/
private int scanChildren(QName element) throws Exception {
int depth = 1;
initializeContentModelStack(depth);
while (true) {
if (fEntityReader.lookingAtChar('(', true)) {
increaseParenDepth();
checkForPEReference(false);
depth++;
initializeContentModelStack(depth);
continue;
}
checkForElementTypeWithPEReference(fEntityReader, ')', fElementRefQName);
int valueIndex = fElementRefQName.rawname;
if (valueIndex == -1) {
reportFatalXMLError(XMLMessages.MSG_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED_IN_CHILDREN,
XMLMessages.P47_OPEN_PAREN_OR_ELEMENT_TYPE_REQUIRED,
element.rawname);
return -1;
}
fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF, valueIndex);
if (fEntityReader.lookingAtChar('?', true)) {
fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE, fNodeIndexStack[depth]);
} else if (fEntityReader.lookingAtChar('*', true)) {
fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, fNodeIndexStack[depth]);
} else if (fEntityReader.lookingAtChar('+', true)) {
fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, fNodeIndexStack[depth]);
}
while (true) {
checkForPEReference(false);
if (fOpStack[depth] != XMLContentSpec.CONTENTSPECNODE_SEQ && fEntityReader.lookingAtChar('|', true)) {
if (fPrevNodeIndexStack[depth] != -1) {
fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(fOpStack[depth], fPrevNodeIndexStack[depth], fNodeIndexStack[depth]);
}
fPrevNodeIndexStack[depth] = fNodeIndexStack[depth];
fOpStack[depth] = XMLContentSpec.CONTENTSPECNODE_CHOICE;
break;
} else if (fOpStack[depth] != XMLContentSpec.CONTENTSPECNODE_CHOICE && fEntityReader.lookingAtChar(',', true)) {
if (fPrevNodeIndexStack[depth] != -1) {
fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(fOpStack[depth], fPrevNodeIndexStack[depth], fNodeIndexStack[depth]);
}
fPrevNodeIndexStack[depth] = fNodeIndexStack[depth];
fOpStack[depth] = XMLContentSpec.CONTENTSPECNODE_SEQ;
break;
} else {
if (!fEntityReader.lookingAtChar(')', true)) {
reportFatalXMLError(XMLMessages.MSG_CLOSE_PAREN_REQUIRED_IN_CHILDREN,
XMLMessages.P47_CLOSE_PAREN_REQUIRED,
element.rawname);
}
decreaseParenDepth();
if (fPrevNodeIndexStack[depth] != -1) {
fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(fOpStack[depth], fPrevNodeIndexStack[depth], fNodeIndexStack[depth]);
}
int nodeIndex = fNodeIndexStack[depth--];
fNodeIndexStack[depth] = nodeIndex;
if (fEntityReader.lookingAtChar('?', true)) {
fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE, fNodeIndexStack[depth]);
} else if (fEntityReader.lookingAtChar('*', true)) {
fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE, fNodeIndexStack[depth]);
} else if (fEntityReader.lookingAtChar('+', true)) {
fNodeIndexStack[depth] = fDTDGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE, fNodeIndexStack[depth]);
}
if (depth == 0) {
return fNodeIndexStack[0];
}
}
}
checkForPEReference(false);
}
} // scanChildren(QName):int
//
// [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
// [53] AttDef ::= S Name S AttType S DefaultDecl
// [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
//
private void scanAttlistDecl() throws Exception
{
if (!checkForPEReference(true)) {
abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_ELEMENT_TYPE_IN_ATTLISTDECL,
XMLMessages.P52_SPACE_REQUIRED);
return;
}
checkForElementTypeWithPEReference(fEntityReader, ' ', fElementQName);
int elementTypeIndex = fElementQName.rawname;
if (elementTypeIndex == -1) {
abortMarkup(XMLMessages.MSG_ELEMENT_TYPE_REQUIRED_IN_ATTLISTDECL,
XMLMessages.P52_ELEMENT_TYPE_REQUIRED);
return;
}
int elementIndex = fDTDGrammar.getElementDeclIndex(fElementQName, -1);
if (elementIndex == -1) {
elementIndex = fDTDGrammar.addElementDecl(fElementQName);
//System.out.println("XMLDTDScanner#scanAttListDecl->DTDGrammar#addElementDecl: "+elementIndex+" ("+fElementQName.localpart+","+fStringPool.toString(fElementQName.localpart)+')');
}
boolean sawSpace = checkForPEReference(true);
if (fEntityReader.lookingAtChar('>', true)) {
decreaseMarkupDepth();
return;
}
// REVISIT - review this code...
if (!sawSpace) {
if (fEntityReader.lookingAtSpace(true)) {
fEntityReader.skipPastSpaces();
} else
reportFatalXMLError(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_ATTRIBUTE_NAME_IN_ATTDEF,
XMLMessages.P53_SPACE_REQUIRED);
} else {
if (fEntityReader.lookingAtSpace(true)) {
fEntityReader.skipPastSpaces();
}
}
if (fEntityReader.lookingAtChar('>', true)) {
decreaseMarkupDepth();
return;
}
while (true) {
checkForAttributeNameWithPEReference(fEntityReader, ' ', fAttributeQName);
int attDefName = fAttributeQName.rawname;
if (attDefName == -1) {
abortMarkup(XMLMessages.MSG_ATTRIBUTE_NAME_REQUIRED_IN_ATTDEF,
XMLMessages.P53_NAME_REQUIRED,
fElementQName.rawname);
return;
}
if (!checkForPEReference(true)) {
abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_ATTTYPE_IN_ATTDEF,
XMLMessages.P53_SPACE_REQUIRED);
return;
}
int attDefType = -1;
boolean attDefList = false;
int attDefEnumeration = -1;
if (fEntityReader.skippedString(cdata_string)) {
attDefType = XMLAttributeDecl.TYPE_CDATA;
} else if (fEntityReader.skippedString(id_string)) {
if (!fEntityReader.skippedString(ref_string)) {
attDefType = XMLAttributeDecl.TYPE_ID;
} else if (!fEntityReader.lookingAtChar('S', true)) {
attDefType = XMLAttributeDecl.TYPE_IDREF;
} else {
attDefType = XMLAttributeDecl.TYPE_IDREF;
attDefList = true;
}
} else if (fEntityReader.skippedString(entit_string)) {
if (fEntityReader.lookingAtChar('Y', true)) {
attDefType = XMLAttributeDecl.TYPE_ENTITY;
} else if (fEntityReader.skippedString(ies_string)) {
attDefType = XMLAttributeDecl.TYPE_ENTITY;
attDefList = true;
} else {
abortMarkup(XMLMessages.MSG_ATTTYPE_REQUIRED_IN_ATTDEF,
XMLMessages.P53_ATTTYPE_REQUIRED,
elementTypeIndex, attDefName);
return;
}
} else if (fEntityReader.skippedString(nmtoken_string)) {
if (fEntityReader.lookingAtChar('S', true)) {
attDefType = XMLAttributeDecl.TYPE_NMTOKEN;
attDefList = true;
} else {
attDefType = XMLAttributeDecl.TYPE_NMTOKEN;
}
} else if (fEntityReader.skippedString(notation_string)) {
if (!checkForPEReference(true)) {
abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_AFTER_NOTATION_IN_NOTATIONTYPE,
XMLMessages.P58_SPACE_REQUIRED,
elementTypeIndex, attDefName);
return;
}
if (!fEntityReader.lookingAtChar('(', true)) {
abortMarkup(XMLMessages.MSG_OPEN_PAREN_REQUIRED_IN_NOTATIONTYPE,
XMLMessages.P58_OPEN_PAREN_REQUIRED,
elementTypeIndex, attDefName);
return;
}
increaseParenDepth();
attDefType = XMLAttributeDecl.TYPE_NOTATION;
attDefEnumeration = scanEnumeration(elementTypeIndex, attDefName, true);
if (attDefEnumeration == -1) {
skipPastEndOfCurrentMarkup();
return;
}
} else if (fEntityReader.lookingAtChar('(', true)) {
increaseParenDepth();
attDefType = XMLAttributeDecl.TYPE_ENUMERATION;
attDefEnumeration = scanEnumeration(elementTypeIndex, attDefName, false);
if (attDefEnumeration == -1) {
skipPastEndOfCurrentMarkup();
return;
}
} else {
abortMarkup(XMLMessages.MSG_ATTTYPE_REQUIRED_IN_ATTDEF,
XMLMessages.P53_ATTTYPE_REQUIRED,
elementTypeIndex, attDefName);
return;
}
if (!checkForPEReference(true)) {
abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_DEFAULTDECL_IN_ATTDEF,
XMLMessages.P53_SPACE_REQUIRED,
elementTypeIndex, attDefName);
return;
}
int attDefDefaultType = -1;
int attDefDefaultValue = -1;
if (fEntityReader.skippedString(required_string)) {
attDefDefaultType = XMLAttributeDecl.DEFAULT_TYPE_REQUIRED;
} else if (fEntityReader.skippedString(implied_string)) {
attDefDefaultType = XMLAttributeDecl.DEFAULT_TYPE_IMPLIED;
} else {
if (fEntityReader.skippedString(fixed_string)) {
if (!fEntityReader.lookingAtSpace(true)) {
abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_AFTER_FIXED_IN_DEFAULTDECL,
XMLMessages.P60_SPACE_REQUIRED,
elementTypeIndex, attDefName);
return;
}
fEntityReader.skipPastSpaces();
attDefDefaultType = XMLAttributeDecl.DEFAULT_TYPE_FIXED;
} else
attDefDefaultType = XMLAttributeDecl.DEFAULT_TYPE_DEFAULT;
//fElementQName.setValues(-1, elementTypeIndex, elementTypeIndex);
// if attribute name has a prefix "xml", bind it to the XML Namespace.
// since this is the only pre-defined namespace.
/***
if (fAttributeQName.prefix == fXMLSymbol) {
fAttributeQName.uri = fXMLNamespace;
}
else
fAttributeQName.setValues(-1, attDefName, attDefName);
****/
attDefDefaultValue = scanDefaultAttValue(fElementQName, fAttributeQName,
attDefType,
attDefEnumeration);
//normalize and check VC: Attribute Default Legal
if (attDefDefaultValue != -1 && attDefType != XMLAttributeDecl.TYPE_CDATA ) {
attDefDefaultValue = normalizeDefaultAttValue( fAttributeQName, attDefDefaultValue,
attDefType, attDefEnumeration,
attDefList);
}
if (attDefDefaultValue == -1) {
skipPastEndOfCurrentMarkup();
return;
}
}
if (attDefName == fXMLSpace) {
boolean ok = false;
if (attDefType == XMLAttributeDecl.TYPE_ENUMERATION) {
int index = attDefEnumeration;
if (index != -1) {
ok = (fStringPool.stringListLength(index) == 1 &&
(fStringPool.stringInList(index, fDefault) ||
fStringPool.stringInList(index, fPreserve))) ||
(fStringPool.stringListLength(index) == 2 &&
fStringPool.stringInList(index, fDefault) &&
fStringPool.stringInList(index, fPreserve));
}
}
if (!ok) {
reportFatalXMLError(XMLMessages.MSG_XML_SPACE_DECLARATION_ILLEGAL,
XMLMessages.S2_10_DECLARATION_ILLEGAL,
elementTypeIndex);
}
}
sawSpace = checkForPEReference(true);
// if attribute name has a prefix "xml", bind it to the XML Namespace.
// since this is the only pre-defined namespace.
if (fAttributeQName.prefix == fXMLSymbol) {
fAttributeQName.uri = fXMLNamespace;
}
if (fEntityReader.lookingAtChar('>', true)) {
int attDefIndex = addAttDef(fElementQName, fAttributeQName,
attDefType, attDefList, attDefEnumeration,
attDefDefaultType, attDefDefaultValue,
getReadingExternalEntity());
//System.out.println("XMLDTDScanner#scanAttlistDecl->DTDGrammar#addAttDef: "+attDefIndex+
// " ("+fElementQName.localpart+","+fStringPool.toString(fElementQName.rawname)+')'+
// " ("+fAttributeQName.localpart+","+fStringPool.toString(fAttributeQName.rawname)+')');
decreaseMarkupDepth();
return;
}
// REVISIT - review this code...
if (!sawSpace) {
if (fEntityReader.lookingAtSpace(true)) {
fEntityReader.skipPastSpaces();
} else
reportFatalXMLError(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_ATTRIBUTE_NAME_IN_ATTDEF,
XMLMessages.P53_SPACE_REQUIRED);
} else {
if (fEntityReader.lookingAtSpace(true)) {
fEntityReader.skipPastSpaces();
}
}
if (fEntityReader.lookingAtChar('>', true)) {
int attDefIndex = addAttDef(fElementQName, fAttributeQName,
attDefType, attDefList, attDefEnumeration,
attDefDefaultType, attDefDefaultValue,
getReadingExternalEntity() );
//System.out.println("XMLDTDScanner#scanAttlistDecl->DTDGrammar#addAttDef: "+attDefIndex+
// " ("+fElementQName.localpart+","+fStringPool.toString(fElementQName.rawname)+')'+
// " ("+fAttributeQName.localpart+","+fStringPool.toString(fAttributeQName.rawname)+')');
decreaseMarkupDepth();
return;
}
int attDefIndex = addAttDef(fElementQName, fAttributeQName,
attDefType, attDefList, attDefEnumeration,
attDefDefaultType, attDefDefaultValue,
getReadingExternalEntity());
//System.out.println("XMLDTDScanner#scanAttlistDecl->DTDGrammar#addAttDef: "+attDefIndex+
// " ("+fElementQName.localpart+","+fStringPool.toString(fElementQName.rawname)+')'+
// " ("+fAttributeQName.localpart+","+fStringPool.toString(fAttributeQName.rawname)+')');
}
}
private int addAttDef(QName element, QName attribute,
int attDefType, boolean attDefList, int attDefEnumeration,
int attDefDefaultType, int attDefDefaultValue,
boolean isExternal ) throws Exception {
if (fDTDHandler != null) {
String enumString = attDefEnumeration != -1 ? fStringPool.stringListAsString(attDefEnumeration) : null;
fDTDHandler.attlistDecl(element, attribute,
attDefType, attDefList,
enumString,
attDefDefaultType, attDefDefaultValue);
}
int elementIndex = fDTDGrammar.getElementDeclIndex(element, -1);
if (elementIndex == -1) {
// REPORT Internal error here
}
else {
int attlistIndex = fDTDGrammar.getFirstAttributeDeclIndex(elementIndex);
int dupID = -1;
int dupNotation = -1;
while (attlistIndex != -1) {
fDTDGrammar.getAttributeDecl(attlistIndex, fTempAttributeDecl);
// REVISIT: Validation. Attributes are also tuples.
if (fStringPool.equalNames(fTempAttributeDecl.name.rawname, attribute.rawname)) {
/******
if (fWarningOnDuplicateAttDef) {
Object[] args = { fStringPool.toString(fElementType[elemChunk][elemIndex]),
fStringPool.toString(attributeDecl.rawname) };
fErrorReporter.reportError(fErrorReporter.getLocator(),
XMLMessages.XML_DOMAIN,
XMLMessages.MSG_DUPLICATE_ATTDEF,
XMLMessages.P53_DUPLICATE,
args,
XMLErrorReporter.ERRORTYPE_WARNING);
}
******/
return -1;
}
if (fValidationEnabled) {
if (attDefType == XMLAttributeDecl.TYPE_ID &&
fTempAttributeDecl.type == XMLAttributeDecl.TYPE_ID ) {
dupID = fTempAttributeDecl.name.rawname;
}
if (attDefType == XMLAttributeDecl.TYPE_NOTATION
&& fTempAttributeDecl.type == XMLAttributeDecl.TYPE_NOTATION) {
dupNotation = fTempAttributeDecl.name.rawname;
}
}
attlistIndex = fDTDGrammar.getNextAttributeDeclIndex(attlistIndex);
}
if (fValidationEnabled) {
if (dupID != -1) {
Object[] args = { fStringPool.toString(element.rawname),
fStringPool.toString(dupID),
fStringPool.toString(attribute.rawname) };
fErrorReporter.reportError(fErrorReporter.getLocator(),
XMLMessages.XML_DOMAIN,
XMLMessages.MSG_MORE_THAN_ONE_ID_ATTRIBUTE,
XMLMessages.VC_ONE_ID_PER_ELEMENT_TYPE,
args,
XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
return -1;
}
if (dupNotation != -1) {
Object[] args = { fStringPool.toString(element.rawname),
fStringPool.toString(dupNotation),
fStringPool.toString(attribute.rawname) };
fErrorReporter.reportError(fErrorReporter.getLocator(),
XMLMessages.XML_DOMAIN,
XMLMessages.MSG_MORE_THAN_ONE_NOTATION_ATTRIBUTE,
XMLMessages.VC_ONE_NOTATION_PER_ELEMENT_TYPE,
args,
XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
return -1;
}
}
}
return fDTDGrammar.addAttDef(element, attribute,
attDefType, attDefList, attDefEnumeration,
attDefDefaultType, attDefDefaultValue,
isExternal);
}
//
// [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
// [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
//
private int scanEnumeration(int elementType, int attrName, boolean isNotationType) throws Exception
{
int enumIndex = fDTDGrammar.startEnumeration();
while (true) {
checkForPEReference(false);
int nameIndex = isNotationType ?
checkForNameWithPEReference(fEntityReader, ')') :
checkForNmtokenWithPEReference(fEntityReader, ')');
if (nameIndex == -1) {
if (isNotationType) {
reportFatalXMLError(XMLMessages.MSG_NAME_REQUIRED_IN_NOTATIONTYPE,
XMLMessages.P58_NAME_REQUIRED,
elementType,
attrName);
} else {
reportFatalXMLError(XMLMessages.MSG_NMTOKEN_REQUIRED_IN_ENUMERATION,
XMLMessages.P59_NMTOKEN_REQUIRED,
elementType,
attrName);
}
fDTDGrammar.endEnumeration(enumIndex);
return -1;
}
fDTDGrammar.addNameToEnumeration(enumIndex, elementType, attrName, nameIndex, isNotationType);
/*****/
if (isNotationType && !((DefaultEntityHandler)fEntityHandler).isNotationDeclared(nameIndex)) {
Object[] args = { fStringPool.toString(elementType),
fStringPool.toString(attrName),
fStringPool.toString(nameIndex) };
((DefaultEntityHandler)fEntityHandler).addRequiredNotation(nameIndex,
fErrorReporter.getLocator(),
XMLMessages.MSG_NOTATION_NOT_DECLARED_FOR_NOTATIONTYPE_ATTRIBUTE,
XMLMessages.VC_NOTATION_DECLARED,
args);
}
/*****/
checkForPEReference(false);
if (!fEntityReader.lookingAtChar('|', true)) {
fDTDGrammar.endEnumeration(enumIndex);
if (!fEntityReader.lookingAtChar(')', true)) {
if (isNotationType) {
reportFatalXMLError(XMLMessages.MSG_NOTATIONTYPE_UNTERMINATED,
XMLMessages.P58_UNTERMINATED,
elementType,
attrName);
} else {
reportFatalXMLError(XMLMessages.MSG_ENUMERATION_UNTERMINATED,
XMLMessages.P59_UNTERMINATED,
elementType,
attrName);
}
return -1;
}
decreaseParenDepth();
return enumIndex;
}
}
}
//
// [10] AttValue ::= '"' ([^<&"] | Reference)* '"'
// | "'" ([^<&'] | Reference)* "'"
//
/**
* Scan the default value in an attribute declaration
*
* @param elementType handle to the element that owns the attribute
* @param attrName handle in the string pool for the attribute name
* @return handle in the string pool for the default attribute value
* @exception java.lang.Exception
*/
public int scanDefaultAttValue(QName element, QName attribute) throws Exception
{
boolean single;
if (!(single = fEntityReader.lookingAtChar('\'', true)) && !fEntityReader.lookingAtChar('\"', true)) {
reportFatalXMLError(XMLMessages.MSG_QUOTE_REQUIRED_IN_ATTVALUE,
XMLMessages.P10_QUOTE_REQUIRED,
element.rawname,
attribute.rawname);
return -1;
}
int previousState = setScannerState(SCANNER_STATE_DEFAULT_ATTRIBUTE_VALUE);
char qchar = single ? '\'' : '\"';
fDefaultAttValueReader = fReaderId;
fDefaultAttValueElementType = element.rawname;
fDefaultAttValueAttrName = attribute.rawname;
boolean setMark = true;
int dataOffset = fLiteralData.length();
while (true) {
fDefaultAttValueOffset = fEntityReader.currentOffset();
if (setMark) {
fDefaultAttValueMark = fDefaultAttValueOffset;
setMark = false;
}
if (fEntityReader.lookingAtChar(qchar, true)) {
if (fReaderId == fDefaultAttValueReader)
break;
continue;
}
if (fEntityReader.lookingAtChar(' ', true)) {
continue;
}
boolean skippedCR;
if ((skippedCR = fEntityReader.lookingAtChar((char)0x0D, true)) || fEntityReader.lookingAtSpace(true)) {
if (fDefaultAttValueOffset - fDefaultAttValueMark > 0)
fEntityReader.append(fLiteralData, fDefaultAttValueMark, fDefaultAttValueOffset - fDefaultAttValueMark);
setMark = true;
fLiteralData.append(' ');
if (skippedCR)
fEntityReader.lookingAtChar((char)0x0A, true);
continue;
}
if (fEntityReader.lookingAtChar('&', true)) {
if (fDefaultAttValueOffset - fDefaultAttValueMark > 0)
fEntityReader.append(fLiteralData, fDefaultAttValueMark, fDefaultAttValueOffset - fDefaultAttValueMark);
setMark = true;
//
// Check for character reference first.
//
if (fEntityReader.lookingAtChar('#', true)) {
int ch = scanCharRef();
if (ch != -1) {
if (ch < 0x10000)
fLiteralData.append((char)ch);
else {
fLiteralData.append((char)(((ch-0x00010000)>>10)+0xd800));
fLiteralData.append((char)(((ch-0x00010000)&0x3ff)+0xdc00));
}
}
} else {
//
// Entity reference
//
int nameOffset = fEntityReader.currentOffset();
fEntityReader.skipPastName(';');
int nameLength = fEntityReader.currentOffset() - nameOffset;
if (nameLength == 0) {
reportFatalXMLError(XMLMessages.MSG_NAME_REQUIRED_IN_REFERENCE,
XMLMessages.P68_NAME_REQUIRED);
} else if (!fEntityReader.lookingAtChar(';', true)) {
reportFatalXMLError(XMLMessages.MSG_SEMICOLON_REQUIRED_IN_REFERENCE,
XMLMessages.P68_SEMICOLON_REQUIRED,
fEntityReader.addString(nameOffset, nameLength));
} else {
int entityNameIndex = fEntityReader.addSymbol(nameOffset, nameLength);
fEntityHandler.startReadingFromEntity(entityNameIndex, markupDepth(), XMLEntityHandler.ENTITYREF_IN_DEFAULTATTVALUE);
}
}
continue;
}
if (fEntityReader.lookingAtChar('<', true)) {
if (fDefaultAttValueOffset - fDefaultAttValueMark > 0)
fEntityReader.append(fLiteralData, fDefaultAttValueMark, fDefaultAttValueOffset - fDefaultAttValueMark);
setMark = true;
reportFatalXMLError(XMLMessages.MSG_LESSTHAN_IN_ATTVALUE,
XMLMessages.WFC_NO_LESSTHAN_IN_ATTVALUE,
element.rawname,
attribute.rawname);
continue;
}
//
// REVISIT - HACK !!! code added to pass incorrect OASIS test 'valid-sa-094'
// Remove this next section to conform to the spec...
//
if (!getReadingExternalEntity() && fEntityReader.lookingAtChar('%', true)) {
int nameOffset = fEntityReader.currentOffset();
fEntityReader.skipPastName(';');
int nameLength = fEntityReader.currentOffset() - nameOffset;
if (nameLength != 0 && fEntityReader.lookingAtChar(';', true)) {
reportFatalXMLError(XMLMessages.MSG_PEREFERENCE_WITHIN_MARKUP,
XMLMessages.WFC_PES_IN_INTERNAL_SUBSET,
fEntityReader.addString(nameOffset, nameLength));
}
}
//
// END HACK !!!
//
if (!fEntityReader.lookingAtValidChar(true)) {
if (fDefaultAttValueOffset - fDefaultAttValueMark > 0)
fEntityReader.append(fLiteralData, fDefaultAttValueMark, fDefaultAttValueOffset - fDefaultAttValueMark);
setMark = true;
int invChar = fEntityReader.scanInvalidChar();
if (fScannerState == SCANNER_STATE_END_OF_INPUT)
return -1;
if (invChar >= 0) {
reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_ATTVALUE,
XMLMessages.P10_INVALID_CHARACTER,
fStringPool.toString(element.rawname),
fStringPool.toString(attribute.rawname),
Integer.toHexString(invChar));
}
continue;
}
}
restoreScannerState(previousState);
int dataLength = fLiteralData.length() - dataOffset;
if (dataLength == 0) {
return fEntityReader.addString(fDefaultAttValueMark, fDefaultAttValueOffset - fDefaultAttValueMark);
}
if (fDefaultAttValueOffset - fDefaultAttValueMark > 0) {
fEntityReader.append(fLiteralData, fDefaultAttValueMark, fDefaultAttValueOffset - fDefaultAttValueMark);
dataLength = fLiteralData.length() - dataOffset;
}
return fLiteralData.addString(dataOffset, dataLength);
}
//
// [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID | PublicID) S? '>'
//
private void scanNotationDecl() throws Exception
{
if (!checkForPEReference(true)) {
abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_NOTATION_NAME_IN_NOTATIONDECL,
XMLMessages.P82_SPACE_REQUIRED);
return;
}
int notationName = checkForNameWithPEReference(fEntityReader, ' ');
if (notationName == -1) {
abortMarkup(XMLMessages.MSG_NOTATION_NAME_REQUIRED_IN_NOTATIONDECL,
XMLMessages.P82_NAME_REQUIRED);
return;
}
if (!checkForPEReference(true)) {
abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_AFTER_NOTATION_NAME_IN_NOTATIONDECL,
XMLMessages.P82_SPACE_REQUIRED,
notationName);
return;
}
if (!scanExternalID(true)) {
skipPastEndOfCurrentMarkup();
return;
}
checkForPEReference(false);
if (!fEntityReader.lookingAtChar('>', true)) {
abortMarkup(XMLMessages.MSG_NOTATIONDECL_UNTERMINATED,
XMLMessages.P82_UNTERMINATED,
notationName);
return;
}
decreaseMarkupDepth();
/****
System.out.println(fStringPool.toString(notationName)+","
+fStringPool.toString(fPubidLiteral) + ","
+fStringPool.toString(fSystemLiteral) + ","
+getReadingExternalEntity());
/****/
int notationIndex = ((DefaultEntityHandler) fEntityHandler).addNotationDecl( notationName,
fPubidLiteral,
fSystemLiteral,
getReadingExternalEntity());
fDTDGrammar.addNotationDecl(notationName, fPubidLiteral, fSystemLiteral);
if (fDTDHandler != null) {
fDTDHandler.notationDecl(notationName, fPubidLiteral, fSystemLiteral);
}
}
//
// [70] EntityDecl ::= GEDecl | PEDecl
// [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
// [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
// [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
// [74] PEDef ::= EntityValue | ExternalID
// [75] ExternalID ::= 'SYSTEM' S SystemLiteral
// | 'PUBLIC' S PubidLiteral S SystemLiteral
// [76] NDataDecl ::= S 'NDATA' S Name
// [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"'
// | "'" ([^%&'] | PEReference | Reference)* "'"
//
// Called after scanning 'ENTITY'
//
private void scanEntityDecl() throws Exception
{
boolean isPEDecl = false;
boolean sawPERef = false;
if (fEntityReader.lookingAtSpace(true)) {
fEntityReader.skipPastSpaces();
if (!fEntityReader.lookingAtChar('%', true)) {
isPEDecl = false; // <!ENTITY x "x">
} else if (fEntityReader.lookingAtSpace(true)) {
checkForPEReference(false); // <!ENTITY % x "x">
isPEDecl = true;
} else if (!getReadingExternalEntity()) {
reportFatalXMLError(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_ENTITY_NAME_IN_PEDECL,
XMLMessages.P72_SPACE);
isPEDecl = true;
} else if (fEntityReader.lookingAtChar('%', false)) {
checkForPEReference(false); // <!ENTITY %%x; "x"> is legal
isPEDecl = true;
} else {
sawPERef = true;
}
} else if (!getReadingExternalEntity() || !fEntityReader.lookingAtChar('%', true)) {
// <!ENTITY[^ ]...> or <!ENTITY[^ %]...>
reportFatalXMLError(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_ENTITY_NAME_IN_ENTITYDECL,
XMLMessages.P70_SPACE);
isPEDecl = false;
} else if (fEntityReader.lookingAtSpace(false)) {
// <!ENTITY% ...>
reportFatalXMLError(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_PERCENT_IN_PEDECL,
XMLMessages.P72_SPACE);
isPEDecl = false;
} else {
sawPERef = true;
}
if (sawPERef) {
while (true) {
int nameOffset = fEntityReader.currentOffset();
fEntityReader.skipPastName(';');
int nameLength = fEntityReader.currentOffset() - nameOffset;
if (nameLength == 0) {
reportFatalXMLError(XMLMessages.MSG_NAME_REQUIRED_IN_PEREFERENCE,
XMLMessages.P69_NAME_REQUIRED);
} else if (!fEntityReader.lookingAtChar(';', true)) {
reportFatalXMLError(XMLMessages.MSG_SEMICOLON_REQUIRED_IN_PEREFERENCE,
XMLMessages.P69_SEMICOLON_REQUIRED,
fEntityReader.addString(nameOffset, nameLength));
} else {
int peNameIndex = fEntityReader.addSymbol(nameOffset, nameLength);
int readerDepth = (fScannerState == SCANNER_STATE_CONTENTSPEC) ? parenDepth() : markupDepth();
fEntityHandler.startReadingFromEntity(peNameIndex, readerDepth, XMLEntityHandler.ENTITYREF_IN_DTD_WITHIN_MARKUP);
}
fEntityReader.skipPastSpaces();
if (!fEntityReader.lookingAtChar('%', true))
break;
if (!isPEDecl) {
if (fEntityReader.lookingAtSpace(true)) {
checkForPEReference(false);
isPEDecl = true;
break;
}
isPEDecl = fEntityReader.lookingAtChar('%', true);
}
}
}
int entityName = checkForNameWithPEReference(fEntityReader, ' ');
if (entityName == -1) {
abortMarkup(XMLMessages.MSG_ENTITY_NAME_REQUIRED_IN_ENTITYDECL,
XMLMessages.P70_REQUIRED_NAME);
return;
}
if (!fDTDGrammar.startEntityDecl(isPEDecl, entityName)) {
skipPastEndOfCurrentMarkup();
return;
}
if (!checkForPEReference(true)) {
abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_AFTER_ENTITY_NAME_IN_ENTITYDECL,
XMLMessages.P70_REQUIRED_SPACE,
entityName);
fDTDGrammar.endEntityDecl();
return;
}
if (isPEDecl) {
boolean single;
if ((single = fEntityReader.lookingAtChar('\'', true)) || fEntityReader.lookingAtChar('\"', true)) {
int value = scanEntityValue(single);
if (value == -1) {
skipPastEndOfCurrentMarkup();
fDTDGrammar.endEntityDecl();
return;
}
checkForPEReference(false);
if (!fEntityReader.lookingAtChar('>', true)) {
abortMarkup(XMLMessages.MSG_ENTITYDECL_UNTERMINATED,
XMLMessages.P72_UNTERMINATED,
entityName);
fDTDGrammar.endEntityDecl();
return;
}
decreaseMarkupDepth();
fDTDGrammar.endEntityDecl();
// a hack by Eric
//REVISIT
fDTDGrammar.addInternalPEDecl(entityName, value);
if (fDTDHandler != null) {
fDTDHandler.internalPEDecl(entityName, value);
}
int entityIndex = ((DefaultEntityHandler) fEntityHandler).addInternalPEDecl(entityName,
value,
getReadingExternalEntity());
} else {
if (!scanExternalID(false)) {
skipPastEndOfCurrentMarkup();
fDTDGrammar.endEntityDecl();
return;
}
checkForPEReference(false);
if (!fEntityReader.lookingAtChar('>', true)) {
abortMarkup(XMLMessages.MSG_ENTITYDECL_UNTERMINATED,
XMLMessages.P72_UNTERMINATED,
entityName);
fDTDGrammar.endEntityDecl();
return;
}
decreaseMarkupDepth();
fDTDGrammar.endEntityDecl();
//a hack by Eric
//REVISIT
fDTDGrammar.addExternalPEDecl(entityName, fPubidLiteral, fSystemLiteral);
if (fDTDHandler != null) {
fDTDHandler.externalPEDecl(entityName, fPubidLiteral, fSystemLiteral);
}
int entityIndex = ((DefaultEntityHandler) fEntityHandler).addExternalPEDecl(entityName,
fPubidLiteral,
fSystemLiteral, getReadingExternalEntity());
}
} else {
boolean single;
if ((single = fEntityReader.lookingAtChar('\'', true)) || fEntityReader.lookingAtChar('\"', true)) {
int value = scanEntityValue(single);
if (value == -1) {
skipPastEndOfCurrentMarkup();
fDTDGrammar.endEntityDecl();
return;
}
checkForPEReference(false);
if (!fEntityReader.lookingAtChar('>', true)) {
abortMarkup(XMLMessages.MSG_ENTITYDECL_UNTERMINATED,
XMLMessages.P71_UNTERMINATED,
entityName);
fDTDGrammar.endEntityDecl();
return;
}
decreaseMarkupDepth();
fDTDGrammar.endEntityDecl();
//a hack by Eric
//REVISIT
fDTDGrammar.addInternalEntityDecl(entityName, value);
if (fDTDHandler != null) {
fDTDHandler.internalEntityDecl(entityName, value);
}
int entityIndex = ((DefaultEntityHandler) fEntityHandler).addInternalEntityDecl(entityName,
value,
getReadingExternalEntity());
} else {
if (!scanExternalID(false)) {
skipPastEndOfCurrentMarkup();
fDTDGrammar.endEntityDecl();
return;
}
boolean unparsed = false;
if (fEntityReader.lookingAtSpace(true)) {
fEntityReader.skipPastSpaces();
unparsed = fEntityReader.skippedString(ndata_string);
}
if (!unparsed) {
checkForPEReference(false);
if (!fEntityReader.lookingAtChar('>', true)) {
abortMarkup(XMLMessages.MSG_ENTITYDECL_UNTERMINATED,
XMLMessages.P72_UNTERMINATED,
entityName);
fDTDGrammar.endEntityDecl();
return;
}
decreaseMarkupDepth();
fDTDGrammar.endEntityDecl();
//a hack by Eric
//REVISIT
fDTDGrammar.addExternalEntityDecl(entityName, fPubidLiteral, fSystemLiteral);
if (fDTDHandler != null) {
fDTDHandler.externalEntityDecl(entityName, fPubidLiteral, fSystemLiteral);
}
int entityIndex = ((DefaultEntityHandler) fEntityHandler).addExternalEntityDecl(entityName,
fPubidLiteral,
fSystemLiteral,
getReadingExternalEntity());
} else {
if (!fEntityReader.lookingAtSpace(true)) {
abortMarkup(XMLMessages.MSG_SPACE_REQUIRED_BEFORE_NOTATION_NAME_IN_UNPARSED_ENTITYDECL,
XMLMessages.P76_SPACE_REQUIRED,
entityName);
fDTDGrammar.endEntityDecl();
return;
}
fEntityReader.skipPastSpaces();
int ndataOffset = fEntityReader.currentOffset();
fEntityReader.skipPastName('>');
int ndataLength = fEntityReader.currentOffset() - ndataOffset;
if (ndataLength == 0) {
abortMarkup(XMLMessages.MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL,
XMLMessages.P76_REQUIRED,
entityName);
fDTDGrammar.endEntityDecl();
return;
}
int notationName = fEntityReader.addSymbol(ndataOffset, ndataLength);
checkForPEReference(false);
if (!fEntityReader.lookingAtChar('>', true)) {
abortMarkup(XMLMessages.MSG_ENTITYDECL_UNTERMINATED,
XMLMessages.P72_UNTERMINATED,
entityName);
fDTDGrammar.endEntityDecl();
return;
}
decreaseMarkupDepth();
fDTDGrammar.endEntityDecl();
//a hack by Eric
//REVISIT
fDTDGrammar.addUnparsedEntityDecl(entityName, fPubidLiteral, fSystemLiteral, notationName);
if (fDTDHandler != null) {
fDTDHandler.unparsedEntityDecl(entityName, fPubidLiteral, fSystemLiteral, notationName);
}
/****
System.out.println("----addUnparsedEntity--- "+ fStringPool.toString(entityName)+","
+fStringPool.toString(notationName)+","
+fStringPool.toString(fPubidLiteral) + ","
+fStringPool.toString(fSystemLiteral) + ","
+getReadingExternalEntity());
/****/
int entityIndex = ((DefaultEntityHandler) fEntityHandler).addUnparsedEntityDecl(entityName,
fPubidLiteral,
fSystemLiteral,
notationName,
getReadingExternalEntity());
}
}
}
}
//
// [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"'
// | "'" ([^%&'] | PEReference | Reference)* "'"
//
private int scanEntityValue(boolean single) throws Exception
{
char qchar = single ? '\'' : '\"';
fEntityValueMark = fEntityReader.currentOffset();
int entityValue = fEntityReader.scanEntityValue(qchar, true);
if (entityValue < 0)
entityValue = scanComplexEntityValue(qchar, entityValue);
return entityValue;
}
private int scanComplexEntityValue(char qchar, int result) throws Exception
{
int previousState = setScannerState(SCANNER_STATE_ENTITY_VALUE);
fEntityValueReader = fReaderId;
int dataOffset = fLiteralData.length();
while (true) {
switch (result) {
case XMLEntityHandler.ENTITYVALUE_RESULT_FINISHED:
{
int offset = fEntityReader.currentOffset();
fEntityReader.lookingAtChar(qchar, true);
restoreScannerState(previousState);
int dataLength = fLiteralData.length() - dataOffset;
if (dataLength == 0) {
return fEntityReader.addString(fEntityValueMark, offset - fEntityValueMark);
}
if (offset - fEntityValueMark > 0) {
fEntityReader.append(fLiteralData, fEntityValueMark, offset - fEntityValueMark);
dataLength = fLiteralData.length() - dataOffset;
}
return fLiteralData.addString(dataOffset, dataLength);
}
case XMLEntityHandler.ENTITYVALUE_RESULT_REFERENCE:
{
int offset = fEntityReader.currentOffset();
if (offset - fEntityValueMark > 0)
fEntityReader.append(fLiteralData, fEntityValueMark, offset - fEntityValueMark);
fEntityReader.lookingAtChar('&', true);
//
// Check for character reference first.
//
if (fEntityReader.lookingAtChar('#', true)) {
int ch = scanCharRef();
if (ch != -1) {
if (ch < 0x10000)
fLiteralData.append((char)ch);
else {
fLiteralData.append((char)(((ch-0x00010000)>>10)+0xd800));
fLiteralData.append((char)(((ch-0x00010000)&0x3ff)+0xdc00));
}
}
fEntityValueMark = fEntityReader.currentOffset();
} else {
//
// Entity reference
//
int nameOffset = fEntityReader.currentOffset();
fEntityReader.skipPastName(';');
int nameLength = fEntityReader.currentOffset() - nameOffset;
if (nameLength == 0) {
reportFatalXMLError(XMLMessages.MSG_NAME_REQUIRED_IN_REFERENCE,
XMLMessages.P68_NAME_REQUIRED);
fEntityValueMark = fEntityReader.currentOffset();
} else if (!fEntityReader.lookingAtChar(';', true)) {
reportFatalXMLError(XMLMessages.MSG_SEMICOLON_REQUIRED_IN_REFERENCE,
XMLMessages.P68_SEMICOLON_REQUIRED,
fEntityReader.addString(nameOffset, nameLength));
fEntityValueMark = fEntityReader.currentOffset();
} else {
//
// 4.4.7 Bypassed
//
// When a general entity reference appears in the EntityValue in an
// entity declaration, it is bypassed and left as is.
//
fEntityValueMark = offset;
}
}
break;
}
case XMLEntityHandler.ENTITYVALUE_RESULT_PEREF:
{
int offset = fEntityReader.currentOffset();
if (offset - fEntityValueMark > 0)
fEntityReader.append(fLiteralData, fEntityValueMark, offset - fEntityValueMark);
fEntityReader.lookingAtChar('%', true);
int nameOffset = fEntityReader.currentOffset();
fEntityReader.skipPastName(';');
int nameLength = fEntityReader.currentOffset() - nameOffset;
if (nameLength == 0) {
reportFatalXMLError(XMLMessages.MSG_NAME_REQUIRED_IN_PEREFERENCE,
XMLMessages.P69_NAME_REQUIRED);
} else if (!fEntityReader.lookingAtChar(';', true)) {
reportFatalXMLError(XMLMessages.MSG_SEMICOLON_REQUIRED_IN_PEREFERENCE,
XMLMessages.P69_SEMICOLON_REQUIRED,
fEntityReader.addString(nameOffset, nameLength));
} else if (!getReadingExternalEntity()) {
reportFatalXMLError(XMLMessages.MSG_PEREFERENCE_WITHIN_MARKUP,
XMLMessages.WFC_PES_IN_INTERNAL_SUBSET,
fEntityReader.addString(nameOffset, nameLength));
} else {
int peNameIndex = fEntityReader.addSymbol(nameOffset, nameLength);
fEntityHandler.startReadingFromEntity(peNameIndex, markupDepth(), XMLEntityHandler.ENTITYREF_IN_ENTITYVALUE);
}
fEntityValueMark = fEntityReader.currentOffset();
break;
}
case XMLEntityHandler.ENTITYVALUE_RESULT_INVALID_CHAR:
{
int offset = fEntityReader.currentOffset();
if (offset - fEntityValueMark > 0)
fEntityReader.append(fLiteralData, fEntityValueMark, offset - fEntityValueMark);
int invChar = fEntityReader.scanInvalidChar();
if (fScannerState == SCANNER_STATE_END_OF_INPUT)
return -1;
if (invChar >= 0) {
reportFatalXMLError(XMLMessages.MSG_INVALID_CHAR_IN_ENTITYVALUE,
XMLMessages.P9_INVALID_CHARACTER,
Integer.toHexString(invChar));
}
fEntityValueMark = fEntityReader.currentOffset();
break;
}
case XMLEntityHandler.ENTITYVALUE_RESULT_END_OF_INPUT:
// all the work is done by the previous reader, just invoke the next one now.
break;
default:
break;
}
result = fEntityReader.scanEntityValue(fReaderId == fEntityValueReader ? qchar : -1, false);
}
}
//
//
//
private boolean checkForPEReference(boolean spaceRequired) throws Exception
{
boolean sawSpace = true;
if (spaceRequired)
sawSpace = fEntityReader.lookingAtSpace(true);
fEntityReader.skipPastSpaces();
if (!getReadingExternalEntity())
return sawSpace;
if (!fEntityReader.lookingAtChar('%', true))
return sawSpace;
while (true) {
int nameOffset = fEntityReader.currentOffset();
fEntityReader.skipPastName(';');
int nameLength = fEntityReader.currentOffset() - nameOffset;
if (nameLength == 0) {
reportFatalXMLError(XMLMessages.MSG_NAME_REQUIRED_IN_PEREFERENCE,
XMLMessages.P69_NAME_REQUIRED);
} else if (!fEntityReader.lookingAtChar(';', true)) {
reportFatalXMLError(XMLMessages.MSG_SEMICOLON_REQUIRED_IN_PEREFERENCE,
XMLMessages.P69_SEMICOLON_REQUIRED,
fEntityReader.addString(nameOffset, nameLength));
} else {
int peNameIndex = fEntityReader.addSymbol(nameOffset, nameLength);
int readerDepth = (fScannerState == SCANNER_STATE_CONTENTSPEC) ? parenDepth() : markupDepth();
fEntityHandler.startReadingFromEntity(peNameIndex, readerDepth, XMLEntityHandler.ENTITYREF_IN_DTD_WITHIN_MARKUP);
}
fEntityReader.skipPastSpaces();
if (!fEntityReader.lookingAtChar('%', true))
return true;
}
}
//
// content model stack
//
private void initializeContentModelStack(int depth) {
if (fOpStack == null) {
fOpStack = new int[8];
fNodeIndexStack = new int[8];
fPrevNodeIndexStack = new int[8];
} else if (depth == fOpStack.length) {
int[] newStack = new int[depth * 2];
System.arraycopy(fOpStack, 0, newStack, 0, depth);
fOpStack = newStack;
newStack = new int[depth * 2];
System.arraycopy(fNodeIndexStack, 0, newStack, 0, depth);
fNodeIndexStack = newStack;
newStack = new int[depth * 2];
System.arraycopy(fPrevNodeIndexStack, 0, newStack, 0, depth);
fPrevNodeIndexStack = newStack;
}
fOpStack[depth] = -1;
fNodeIndexStack[depth] = -1;
fPrevNodeIndexStack[depth] = -1;
}
private boolean validVersionNum(String version) {
return XMLCharacterProperties.validVersionNum(version);
}
private boolean validEncName(String encoding) {
return XMLCharacterProperties.validEncName(encoding);
}
private int validPublicId(String publicId) {
return XMLCharacterProperties.validPublicId(publicId);
}
private void scanElementType(XMLEntityHandler.EntityReader entityReader,
char fastchar, QName element) throws Exception {
if (!fNamespacesEnabled) {
element.clear();
element.localpart = entityReader.scanName(fastchar);
element.rawname = element.localpart;
return;
}
entityReader.scanQName(fastchar, element);
if (entityReader.lookingAtChar(':', false)) {
fErrorReporter.reportError(fErrorReporter.getLocator(),
XMLMessages.XML_DOMAIN,
XMLMessages.MSG_TWO_COLONS_IN_QNAME,
XMLMessages.P5_INVALID_CHARACTER,
null,
XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
entityReader.skipPastNmtoken(' ');
}
} // scanElementType(XMLEntityHandler.EntityReader,char,QName)
public void checkForElementTypeWithPEReference(XMLEntityHandler.EntityReader entityReader,
char fastchar, QName element) throws Exception {
if (!fNamespacesEnabled) {
element.clear();
element.localpart = entityReader.scanName(fastchar);
element.rawname = element.localpart;
return;
}
entityReader.scanQName(fastchar, element);
if (entityReader.lookingAtChar(':', false)) {
fErrorReporter.reportError(fErrorReporter.getLocator(),
XMLMessages.XML_DOMAIN,
XMLMessages.MSG_TWO_COLONS_IN_QNAME,
XMLMessages.P5_INVALID_CHARACTER,
null,
XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
entityReader.skipPastNmtoken(' ');
}
} // checkForElementTypeWithPEReference(XMLEntityHandler.EntityReader,char,QName)
public void checkForAttributeNameWithPEReference(XMLEntityHandler.EntityReader entityReader,
char fastchar, QName attribute) throws Exception {
if (!fNamespacesEnabled) {
attribute.clear();
attribute.localpart = entityReader.scanName(fastchar);
attribute.rawname = attribute.localpart;
return;
}
entityReader.scanQName(fastchar, attribute);
if (entityReader.lookingAtChar(':', false)) {
fErrorReporter.reportError(fErrorReporter.getLocator(),
XMLMessages.XML_DOMAIN,
XMLMessages.MSG_TWO_COLONS_IN_QNAME,
XMLMessages.P5_INVALID_CHARACTER,
null,
XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
entityReader.skipPastNmtoken(' ');
}
} // checkForAttributeNameWithPEReference(XMLEntityHandler.EntityReader,char,QName)
public int checkForNameWithPEReference(XMLEntityHandler.EntityReader entityReader, char fastcheck) throws Exception {
//
// REVISIT - what does this have to do with PE references?
//
int valueIndex = entityReader.scanName(fastcheck);
return valueIndex;
}
public int checkForNmtokenWithPEReference(XMLEntityHandler.EntityReader entityReader, char fastcheck) throws Exception {
//
// REVISIT - what does this have to do with PE references?
//
int nameOffset = entityReader.currentOffset();
entityReader.skipPastNmtoken(fastcheck);
int nameLength = entityReader.currentOffset() - nameOffset;
if (nameLength == 0)
return -1;
int valueIndex = entityReader.addSymbol(nameOffset, nameLength);
return valueIndex;
}
public int scanDefaultAttValue(QName element, QName attribute,
int attType, int enumeration) throws Exception {
/***/
if (fValidationEnabled && attType == XMLAttributeDecl.TYPE_ID) {
reportRecoverableXMLError(XMLMessages.MSG_ID_DEFAULT_TYPE_INVALID,
XMLMessages.VC_ID_ATTRIBUTE_DEFAULT,
fStringPool.toString(attribute.rawname));
}
/***/
int defaultAttValue = scanDefaultAttValue(element, attribute);
if (defaultAttValue == -1)
return -1;
// REVISIT
/***
if (attType != fCDATASymbol) {
// REVISIT: Validation. Should we pass in the element or is this
// default attribute value normalization?
defaultAttValue = fValidator.normalizeAttValue(null, attribute, defaultAttValue, attType, enumeration);
}
/***/
return defaultAttValue;
}
public int normalizeDefaultAttValue( QName attribute, int defaultAttValue,
int attType, int enumeration,
boolean list) throws Exception {
//
// Normalize attribute based upon attribute type...
//
String attValue = fStringPool.toString(defaultAttValue);
if (list) {
StringTokenizer tokenizer = new StringTokenizer(attValue);
StringBuffer sb = new StringBuffer(attValue.length());
boolean ok = true;
if (tokenizer.hasMoreTokens()) {
while (true) {
String nmtoken = tokenizer.nextToken();
if (attType == XMLAttributeDecl.TYPE_NMTOKEN) {
if (fValidationEnabled && !XMLCharacterProperties.validNmtoken(nmtoken)) {
ok = false;
}
}
else if (attType == XMLAttributeDecl.TYPE_IDREF || attType == XMLAttributeDecl.TYPE_ENTITY) {
if (fValidationEnabled && !XMLCharacterProperties.validName(nmtoken)) {
ok = false;
}
// REVISIT: a Hack!!! THis is to pass SUN test /invalid/attr11.xml and attr12.xml
// not consistent with XML1.0 spec VC: Attribute Default Legal
if (fValidationEnabled && attType == XMLAttributeDecl.TYPE_ENTITY)
if (! ((DefaultEntityHandler) fEntityHandler).isUnparsedEntity(defaultAttValue)) {
reportRecoverableXMLError(XMLMessages.MSG_ENTITY_INVALID,
XMLMessages.VC_ENTITY_NAME,
fStringPool.toString(attribute.rawname), nmtoken);
}
}
sb.append(nmtoken);
if (!tokenizer.hasMoreTokens()) {
break;
}
sb.append(' ');
}
}
String newAttValue = sb.toString();
if (fValidationEnabled && (!ok || newAttValue.length() == 0)) {
reportRecoverableXMLError(XMLMessages.MSG_ATT_DEFAULT_INVALID,
XMLMessages.VC_ATTRIBUTE_DEFAULT_LEGAL,
fStringPool.toString(attribute.rawname), newAttValue);
}
if (!newAttValue.equals(attValue)) {
defaultAttValue = fStringPool.addString(newAttValue);
}
return defaultAttValue;
}
else {
String newAttValue = attValue.trim();
if (fValidationEnabled) {
// REVISIT - can we release the old string?
if (newAttValue != attValue) {
defaultAttValue = fStringPool.addSymbol(newAttValue);
}
else {
defaultAttValue = fStringPool.addSymbol(defaultAttValue);
}
if (attType == XMLAttributeDecl.TYPE_ENTITY ||
attType == XMLAttributeDecl.TYPE_ID ||
attType == XMLAttributeDecl.TYPE_IDREF ||
attType == XMLAttributeDecl.TYPE_NOTATION) {
// REVISIT: A Hack!!! THis is to pass SUN test /invalid/attr11.xml and attr12.xml
// not consistent with XML1.0 spec VC: Attribute Default Legal
if (attType == XMLAttributeDecl.TYPE_ENTITY)
if (! ((DefaultEntityHandler) fEntityHandler).isUnparsedEntity(defaultAttValue)) {
reportRecoverableXMLError(XMLMessages.MSG_ENTITY_INVALID,
XMLMessages.VC_ENTITY_NAME,
fStringPool.toString(attribute.rawname), newAttValue);
}
if (!XMLCharacterProperties.validName(newAttValue)) {
reportRecoverableXMLError(XMLMessages.MSG_ATT_DEFAULT_INVALID,
XMLMessages.VC_ATTRIBUTE_DEFAULT_LEGAL,
fStringPool.toString(attribute.rawname), newAttValue);
}
}
else if (attType == XMLAttributeDecl.TYPE_NMTOKEN ||
attType == XMLAttributeDecl.TYPE_ENUMERATION ) {
if (!XMLCharacterProperties.validNmtoken(newAttValue)) {
reportRecoverableXMLError(XMLMessages.MSG_ATT_DEFAULT_INVALID,
XMLMessages.VC_ATTRIBUTE_DEFAULT_LEGAL,
fStringPool.toString(attribute.rawname), newAttValue);
}
}
if (attType == XMLAttributeDecl.TYPE_NOTATION ||
attType == XMLAttributeDecl.TYPE_ENUMERATION ) {
if ( !fStringPool.stringInList(enumeration, defaultAttValue) ) {
reportRecoverableXMLError(XMLMessages.MSG_ATT_DEFAULT_INVALID,
XMLMessages.VC_ATTRIBUTE_DEFAULT_LEGAL,
fStringPool.toString(attribute.rawname), newAttValue);
}
}
}
else if (newAttValue != attValue) {
// REVISIT - can we release the old string?
defaultAttValue = fStringPool.addSymbol(newAttValue);
}
}
return defaultAttValue;
}
/***
public boolean scanDoctypeDecl(boolean standalone) throws Exception {
fStandaloneReader = standalone ? fEntityHandler.getReaderId() : -1;
fDeclsAreExternal = false;
if (!fDTDScanner.scanDoctypeDecl()) {
return false;
}
if (fDTDScanner.getReadingExternalEntity()) {
fDTDScanner.scanDecls(true);
}
fDTDHandler.endDTD();
return true;
}
/***/
} // class XMLDTDScanner