FileDocCategorySizeDatePackage
XMLScanner.javaAPI DocJava SE 6 API57273Tue Jun 10 00:22:40 BST 2008com.sun.org.apache.xerces.internal.impl

XMLScanner

public abstract class XMLScanner extends Object implements XMLComponent
This class is responsible for holding scanning methods common to scanning the XML document structure and content as well as the DTD structure and content. Both XMLDocumentScanner and XMLDTDScanner inherit from this base class.

This component requires the following features and properties from the component manager that uses it:

  • http://xml.org/sax/features/validation
  • http://apache.org/xml/features/scanner/notify-char-refs
  • http://apache.org/xml/properties/internal/symbol-table
  • http://apache.org/xml/properties/internal/error-reporter
  • http://apache.org/xml/properties/internal/entity-manager
author
Andy Clark, IBM
author
Arnaud Le Hors, IBM
author
Eric Ye, IBM
author
K.Venugopal SUN Microsystems
author
Sunitha Reddy, SUN Microsystems
version
$Id: XMLScanner.java,v 1.6 2006/06/06 06:28:41 sunithareddy Exp $

Fields Summary
protected static final String
NAMESPACES
Feature identifier: namespaces.
protected static final String
VALIDATION
Feature identifier: validation.
protected static final String
NOTIFY_CHAR_REFS
Feature identifier: notify character references.
protected static final String
PARSER_SETTINGS
protected static final String
SYMBOL_TABLE
Property identifier: symbol table.
protected static final String
ERROR_REPORTER
Property identifier: error reporter.
protected static final String
ENTITY_MANAGER
Property identifier: entity manager.
protected static final boolean
DEBUG_ATTR_NORMALIZATION
Debug attribute normalization.
private boolean
fNeedNonNormalizedValue
protected ArrayList
attributeValueCache
protected ArrayList
stringBufferCache
protected int
fStringBufferIndex
protected boolean
fAttributeCacheInitDone
protected int
fAttributeCacheUsedCount
protected boolean
fValidation
Validation. This feature identifier is: http://xml.org/sax/features/validation
protected boolean
fNamespaces
Namespaces.
protected boolean
fNotifyCharRefs
Character references notification.
protected boolean
fParserSettings
Internal parser-settings feature
protected PropertyManager
fPropertyManager
protected SymbolTable
fSymbolTable
Symbol table.
protected XMLErrorReporter
fErrorReporter
Error reporter.
protected XMLEntityManager
fEntityManager
Entity manager.
protected XMLEntityStorage
fEntityStore
xxx this should be available from EntityManager Entity storage
protected XMLEvent
fEvent
event type
protected XMLEntityScanner
fEntityScanner
Entity scanner, this alwasy works on last entity that was opened.
protected int
fEntityDepth
Entity depth.
protected String
fCharRefLiteral
Literal value of the last character refence scanned.
protected boolean
fScanningAttribute
Scanning attribute.
protected boolean
fReportEntity
Report entity boundary.
protected static final String
fVersionSymbol
Symbol: "version".
protected static final String
fEncodingSymbol
Symbol: "encoding".
protected static final String
fStandaloneSymbol
Symbol: "standalone".
protected static final String
fAmpSymbol
Symbol: "amp".
protected static final String
fLtSymbol
Symbol: "lt".
protected static final String
fGtSymbol
Symbol: "gt".
protected static final String
fQuotSymbol
Symbol: "quot".
protected static final String
fAposSymbol
Symbol: "apos".
private XMLString
fString
String.
private XMLStringBuffer
fStringBuffer
String buffer.
private XMLStringBuffer
fStringBuffer2
String buffer.
private XMLStringBuffer
fStringBuffer3
String buffer.
protected XMLResourceIdentifierImpl
fResourceIdentifier
int
initialCacheCount
Constructors Summary
Methods Summary
public voidendEntity(java.lang.String name, com.sun.org.apache.xerces.internal.xni.Augmentations augs)
This method notifies the end of an entity. The document entity has the pseudo-name of "[xml]" the DTD has the pseudo-name of "[dtd]" parameter entity names start with '%'; and general entities are just specified by their name.

param
name The name of the entity.
throws
XNIException Thrown by handler to signal an error.

        
        // keep track of the entity depth
        fEntityDepth--;
        
    
public booleangetFeature(java.lang.String featureId)

        
        if (VALIDATION.equals(featureId)) {
            return fValidation;
        } else if (NOTIFY_CHAR_REFS.equals(featureId)) {
            return fNotifyCharRefs;
        }
        throw new XMLConfigurationException(XMLConfigurationException.NOT_RECOGNIZED, featureId);
    
com.sun.org.apache.xerces.internal.util.XMLStringBuffergetStringBuffer()

        if((fStringBufferIndex < initialCacheCount )|| (fStringBufferIndex < stringBufferCache.size())){
            return (XMLStringBuffer)stringBufferCache.get(fStringBufferIndex++);
        }else{
            XMLStringBuffer tmpObj = new XMLStringBuffer();
            stringBufferCache.add(fStringBufferIndex, tmpObj);
            return tmpObj;
        }
    
private voidinit()

        // initialize scanner
        fEntityScanner = null;        
        // initialize vars
        fEntityDepth = 0;
        fReportEntity = true;
        fResourceIdentifier.clear();

        if(!fAttributeCacheInitDone){
            for(int i = 0; i < initialCacheCount; i++){
                attributeValueCache.add(new XMLString());
                stringBufferCache.add(new XMLStringBuffer());
            }
            fAttributeCacheInitDone = true;
        }
        fStringBufferIndex = 0;
        fAttributeCacheUsedCount = 0;
        
    
protected booleanisInvalid(int value)

        return (XMLChar.isInvalid(value));
    
protected booleanisInvalidLiteral(int value)

        return (XMLChar.isInvalid(value));
    
protected booleanisValidNCName(int value)

        return (XMLChar.isNCName(value));
    
protected booleanisValidNameChar(int value)

        return (XMLChar.isName(value));
    
protected booleanisValidNameStartChar(int value)

        return (XMLChar.isNameStart(value));
    
protected voidnormalizeWhitespace(com.sun.org.apache.xerces.internal.xni.XMLString value)
Normalize whitespace in an XMLString converting all whitespace characters to space characters.

        int i=0;
        int j=0;
        int [] buff = fEntityScanner.whiteSpaceLookup;
        int buffLen = fEntityScanner.whiteSpaceLen;
        int end = value.offset + value.length;
        while(i < buffLen){
            j = buff[i];
            if(j < end ){
                value.ch[j] = ' ";
            }
            i++;
        }
    
protected voidreportFatalError(java.lang.String msgId, java.lang.Object[] args)
Convenience function used in all XML scanners.

        fErrorReporter.reportError(fEntityScanner, XMLMessageFormatter.XML_DOMAIN,
                msgId, args,
                XMLErrorReporter.SEVERITY_FATAL_ERROR);
    
public voidreset(com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager componentManager)

param
componentManager The component manager.
throws
SAXException Throws exception if required features and properties cannot be found.

    //
    // XMLComponent methods
    //
    
                                               
       
      
        
		try {
			fParserSettings = componentManager.getFeature(PARSER_SETTINGS);
		} catch (XMLConfigurationException e) {
			fParserSettings = true;
		}

		if (!fParserSettings) {
			// parser settings have not been changed
			init();
			return;
		}

        
        // Xerces properties
        fSymbolTable = (SymbolTable)componentManager.getProperty(SYMBOL_TABLE);
        fErrorReporter = (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER);
        fEntityManager = (XMLEntityManager)componentManager.getProperty(ENTITY_MANAGER);
        
        //this step is extra because we have separated the storage of entity
        fEntityStore = fEntityManager.getEntityStore() ;
        
        // sax features
        try {
            fValidation = componentManager.getFeature(VALIDATION);
        } catch (XMLConfigurationException e) {
            fValidation = false;
        }
        try {
            fNamespaces = componentManager.getFeature(NAMESPACES);
        }
        catch (XMLConfigurationException e) {
            fNamespaces = true;
        }
        try {
            fNotifyCharRefs = componentManager.getFeature(NOTIFY_CHAR_REFS);
        } catch (XMLConfigurationException e) {
            fNotifyCharRefs = false;
        }
        
        init();
    
protected voidreset()

        init();

        // DTD preparsing defaults:
        fValidation = true;
        fNotifyCharRefs = false;

    
public voidreset(com.sun.org.apache.xerces.internal.impl.PropertyManager propertyManager)

        init();
        // Xerces properties
        fSymbolTable = (SymbolTable)propertyManager.getProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY);
        
        fErrorReporter = (XMLErrorReporter)propertyManager.getProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY);
        
        fEntityManager = (XMLEntityManager)propertyManager.getProperty(ENTITY_MANAGER);
        fEntityStore = fEntityManager.getEntityStore() ;
        fEntityScanner = (XMLEntityScanner)fEntityManager.getEntityScanner() ;
        //fEntityManager.reset();
        // DTD preparsing defaults:
        fValidation = false;
        fNotifyCharRefs = false;
        
    
protected voidscanAttributeValue(com.sun.org.apache.xerces.internal.xni.XMLString value, com.sun.org.apache.xerces.internal.xni.XMLString nonNormalizedValue, java.lang.String atName, com.sun.org.apache.xerces.internal.xni.XMLAttributes attributes, int attrIndex, boolean checkEntities)
Scans an attribute value and normalizes whitespace converting all whitespace characters to space characters. [10] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'"

param
value The XMLString to fill in with the value.
param
nonNormalizedValue The XMLString to fill in with the non-normalized value.
param
atName The name of the attribute being parsed (for error msgs).
param
attributes The attributes list for the scanned attribute.
param
attrIndex The index of the attribute to use from the list.
param
checkEntities true if undeclared entities should be reported as VC violation, false if undeclared entities should be reported as WFC violation. Note: This method uses fStringBuffer2, anything in it at the time of calling is lost.

        XMLStringBuffer stringBuffer = null;
        // quote
        int quote = fEntityScanner.peekChar();
        if (quote != '\'" && quote != '"") {
            reportFatalError("OpenQuoteExpected", new Object[]{atName});
        }
        
        fEntityScanner.scanChar();
        int entityDepth = fEntityDepth;
        
        int c = fEntityScanner.scanLiteral(quote, value);
        if (DEBUG_ATTR_NORMALIZATION) {
            System.out.println("** scanLiteral -> \""
                    + value.toString() + "\"");
        }
        if(fNeedNonNormalizedValue){
            fStringBuffer2.clear();
            fStringBuffer2.append(value);
        }
        if(fEntityScanner.whiteSpaceLen > 0)
            normalizeWhitespace(value);
        if (DEBUG_ATTR_NORMALIZATION) {
            System.out.println("** normalizeWhitespace -> \""
                    + value.toString() + "\"");
        }
        if (c != quote) {
            fScanningAttribute = true;
            stringBuffer = getStringBuffer();
            stringBuffer.clear();
            do {
                stringBuffer.append(value);
                if (DEBUG_ATTR_NORMALIZATION) {
                    System.out.println("** value2: \""
                            + stringBuffer.toString() + "\"");
                }
                if (c == '&") {
                    fEntityScanner.skipChar('&");
                    if (entityDepth == fEntityDepth && fNeedNonNormalizedValue ) {
                        fStringBuffer2.append('&");
                    }
                    if (fEntityScanner.skipChar('#")) {
                        if (entityDepth == fEntityDepth && fNeedNonNormalizedValue ) {
                            fStringBuffer2.append('#");
                        }
                        int ch ;
                        if (fNeedNonNormalizedValue)
                            ch = scanCharReferenceValue(stringBuffer, fStringBuffer2);
                        else
                            ch = scanCharReferenceValue(stringBuffer, null);
                        
                        if (ch != -1) {
                            if (DEBUG_ATTR_NORMALIZATION) {
                                System.out.println("** value3: \""
                                        + stringBuffer.toString()
                                        + "\"");
                            }
                        }
                    } else {
                        String entityName = fEntityScanner.scanName();
                        if (entityName == null) {
                            reportFatalError("NameRequiredInReference", null);
                        } else if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
                            fStringBuffer2.append(entityName);
                        }
                        if (!fEntityScanner.skipChar(';")) {
                            reportFatalError("SemicolonRequiredInReference",
                                    new Object []{entityName});
                        } else if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
                            fStringBuffer2.append(';");
                        }
                        if (entityName == fAmpSymbol) {
                            stringBuffer.append('&");
                            if (DEBUG_ATTR_NORMALIZATION) {
                                System.out.println("** value5: \""
                                        + stringBuffer.toString()
                                        + "\"");
                            }
                        } else if (entityName == fAposSymbol) {
                            stringBuffer.append('\'");
                            if (DEBUG_ATTR_NORMALIZATION) {
                                System.out.println("** value7: \""
                                        + stringBuffer.toString()
                                        + "\"");
                            }
                        } else if (entityName == fLtSymbol) {
                            stringBuffer.append('<");
                            if (DEBUG_ATTR_NORMALIZATION) {
                                System.out.println("** value9: \""
                                        + stringBuffer.toString()
                                        + "\"");
                            }
                        } else if (entityName == fGtSymbol) {
                            stringBuffer.append('>");
                            if (DEBUG_ATTR_NORMALIZATION) {
                                System.out.println("** valueB: \""
                                        + stringBuffer.toString()
                                        + "\"");
                            }
                        } else if (entityName == fQuotSymbol) {
                            stringBuffer.append('"");
                            if (DEBUG_ATTR_NORMALIZATION) {
                                System.out.println("** valueD: \""
                                        + stringBuffer.toString()
                                        + "\"");
                            }
                        } else {
                            if (fEntityStore.isExternalEntity(entityName)) {
                                reportFatalError("ReferenceToExternalEntity",
                                        new Object[] { entityName });
                            } else {
                                if (!fEntityStore.isDeclaredEntity(entityName)) {
                                    //WFC & VC: Entity Declared
                                    if (checkEntities) {
                                        if (fValidation) {
                                            fErrorReporter.reportError(fEntityScanner,XMLMessageFormatter.XML_DOMAIN,
                                                    "EntityNotDeclared",
                                                    new Object[]{entityName},
                                                    XMLErrorReporter.SEVERITY_ERROR);
                                        }
                                    } else {
                                        reportFatalError("EntityNotDeclared",
                                                new Object[]{entityName});
                                    }
                                }
                                fEntityManager.startEntity(entityName, true);
                            }
                        }
                    }
                } else if (c == '<") {
                    reportFatalError("LessthanInAttValue",
                            new Object[] { null, atName });
                            fEntityScanner.scanChar();
                            if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
                                fStringBuffer2.append((char)c);
                            }
                } else if (c == '%" || c == ']") {
                    fEntityScanner.scanChar();
                    stringBuffer.append((char)c);
                    if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
                        fStringBuffer2.append((char)c);
                    }
                    if (DEBUG_ATTR_NORMALIZATION) {
                        System.out.println("** valueF: \""
                                + stringBuffer.toString() + "\"");
                    }
                } else if (c == '\n" || c == '\r") {
                    fEntityScanner.scanChar();
                    stringBuffer.append(' ");
                    if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
                        fStringBuffer2.append('\n");
                    }
                } else if (c != -1 && XMLChar.isHighSurrogate(c)) {
                    if (scanSurrogates(fStringBuffer3)) {
                        stringBuffer.append(fStringBuffer3);
                        if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
                            fStringBuffer2.append(fStringBuffer3);
                        }
                        if (DEBUG_ATTR_NORMALIZATION) {
                            System.out.println("** valueI: \""
                                    + stringBuffer.toString()
                                    + "\"");
                        }
                    }
                } else if (c != -1 && isInvalidLiteral(c)) {
                    reportFatalError("InvalidCharInAttValue",
                            new Object[] {Integer.toString(c, 16)});
                            fEntityScanner.scanChar();
                            if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
                                fStringBuffer2.append((char)c);
                            }
                }
                c = fEntityScanner.scanLiteral(quote, value);
                if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
                    fStringBuffer2.append(value);
                }
                if(fEntityScanner.whiteSpaceLen > 0)
                    normalizeWhitespace(value);
                //Todo ::Move this check  to Attributes , do conversion
                //only if attribute is being accessed. -Venu
            } while (c != quote || entityDepth != fEntityDepth);
            stringBuffer.append(value);
            if (DEBUG_ATTR_NORMALIZATION) {
                System.out.println("** valueN: \""
                        + stringBuffer.toString() + "\"");
            }
            value.setValues(stringBuffer);
            fScanningAttribute = false;
        }
        if(fNeedNonNormalizedValue)
            nonNormalizedValue.setValues(fStringBuffer2);
        
        // quote
        int cquote = fEntityScanner.scanChar();
        if (cquote != quote) {
            reportFatalError("CloseQuoteExpected", new Object[]{atName});
        }
    
protected intscanCharReferenceValue(com.sun.org.apache.xerces.internal.util.XMLStringBuffer buf, com.sun.org.apache.xerces.internal.util.XMLStringBuffer buf2)
Scans a character reference and append the corresponding chars to the specified buffer.

[66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'
Note: This method uses fStringBuffer, anything in it at the time of calling is lost.

param
buf the character buffer to append chars to
param
buf2 the character buffer to append non-normalized chars to
return
the character value or (-1) on conversion failure

        // scan hexadecimal value
        boolean hex = false;
        if (fEntityScanner.skipChar('x")) {
            if (buf2 != null) { buf2.append('x"); }
            hex = true;
            fStringBuffer3.clear();
            boolean digit = true;
            
            int c = fEntityScanner.peekChar();
            digit = (c >= '0" && c <= '9") ||
                    (c >= 'a" && c <= 'f") ||
                    (c >= 'A" && c <= 'F");
            if (digit) {
                if (buf2 != null) { buf2.append((char)c); }
                fEntityScanner.scanChar();
                fStringBuffer3.append((char)c);
                
                do {
                    c = fEntityScanner.peekChar();
                    digit = (c >= '0" && c <= '9") ||
                            (c >= 'a" && c <= 'f") ||
                            (c >= 'A" && c <= 'F");
                    if (digit) {
                        if (buf2 != null) { buf2.append((char)c); }
                        fEntityScanner.scanChar();
                        fStringBuffer3.append((char)c);
                    }
                } while (digit);
            } else {
                reportFatalError("HexdigitRequiredInCharRef", null);
            }
        }
        
        // scan decimal value
        else {
            fStringBuffer3.clear();
            boolean digit = true;
            
            int c = fEntityScanner.peekChar();
            digit = c >= '0" && c <= '9";
            if (digit) {
                if (buf2 != null) { buf2.append((char)c); }
                fEntityScanner.scanChar();
                fStringBuffer3.append((char)c);
                
                do {
                    c = fEntityScanner.peekChar();
                    digit = c >= '0" && c <= '9";
                    if (digit) {
                        if (buf2 != null) { buf2.append((char)c); }
                        fEntityScanner.scanChar();
                        fStringBuffer3.append((char)c);
                    }
                } while (digit);
            } else {
                reportFatalError("DigitRequiredInCharRef", null);
            }
        }
        
        // end
        if (!fEntityScanner.skipChar(';")) {
            reportFatalError("SemicolonRequiredInCharRef", null);
        }
        if (buf2 != null) { buf2.append(';"); }
        
        // convert string to number
        int value = -1;
        try {
            value = Integer.parseInt(fStringBuffer3.toString(),
                    hex ? 16 : 10);
            
            // character reference must be a valid XML character
            if (isInvalid(value)) {
                StringBuffer errorBuf = new StringBuffer(fStringBuffer3.length + 1);
                if (hex) errorBuf.append('x");
                errorBuf.append(fStringBuffer3.ch, fStringBuffer3.offset, fStringBuffer3.length);
                reportFatalError("InvalidCharRef",
                        new Object[]{errorBuf.toString()});
            }
        } catch (NumberFormatException e) {
            // Conversion failed, let -1 value drop through.
            // If we end up here, the character reference was invalid.
            StringBuffer errorBuf = new StringBuffer(fStringBuffer3.length + 1);
            if (hex) errorBuf.append('x");
            errorBuf.append(fStringBuffer3.ch, fStringBuffer3.offset, fStringBuffer3.length);
            reportFatalError("InvalidCharRef",
                    new Object[]{errorBuf.toString()});
        }
        
        // append corresponding chars to the given buffer
        if (!XMLChar.isSupplemental(value)) {
            buf.append((char) value);
        } else {
            // character is supplemental, split it into surrogate chars
            buf.append(XMLChar.highSurrogate(value));
            buf.append(XMLChar.lowSurrogate(value));
        }
        
        // char refs notification code
        if (fNotifyCharRefs && value != -1) {
            String literal = "#" + (hex ? "x" : "") + fStringBuffer3.toString();
            if (!fScanningAttribute) {
                fCharRefLiteral = literal;
            }
        }
        
        return value;
    
protected voidscanComment(com.sun.org.apache.xerces.internal.util.XMLStringBuffer text)
Scans a comment.

[15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'

Note: Called after scanning past '<!--' Note: This method uses fString, anything in it at the time of calling is lost.

param
text The buffer to fill in with the text.

        
        //System.out.println( "XMLScanner#scanComment# In Scan Comment" );
        // text
        // REVISIT: handle invalid character, eof
        text.clear();
        while (fEntityScanner.scanData("--", text)) {
            int c = fEntityScanner.peekChar();
            
            //System.out.println( "XMLScanner#scanComment#text.toString() == " + text.toString() );
            //System.out.println( "XMLScanner#scanComment#c == " + c );
            
            if (c != -1) {
                if (XMLChar.isHighSurrogate(c)) {
                    scanSurrogates(text);
                }
                if (isInvalidLiteral(c)) {
                    reportFatalError("InvalidCharInComment",
                            new Object[] { Integer.toHexString(c) });
                            fEntityScanner.scanChar();
                }
            }
        }
        if (!fEntityScanner.skipChar('>")) {
            reportFatalError("DashDashInComment", null);
        }
        
    
protected voidscanExternalID(java.lang.String[] identifiers, boolean optionalSystemId)
Scans External ID and return the public and system IDs.

param
identifiers An array of size 2 to return the system id, and public id (in that order).
param
optionalSystemId Specifies whether the system id is optional. Note: This method uses fString and fStringBuffer, anything in them at the time of calling is lost.

        
        String systemId = null;
        String publicId = null;
        if (fEntityScanner.skipString("PUBLIC")) {
            if (!fEntityScanner.skipSpaces()) {
                reportFatalError("SpaceRequiredAfterPUBLIC", null);
            }
            scanPubidLiteral(fString);
            publicId = fString.toString();
            
            if (!fEntityScanner.skipSpaces() && !optionalSystemId) {
                reportFatalError("SpaceRequiredBetweenPublicAndSystem", null);
            }
        }
        
        if (publicId != null || fEntityScanner.skipString("SYSTEM")) {
            if (publicId == null && !fEntityScanner.skipSpaces()) {
                reportFatalError("SpaceRequiredAfterSYSTEM", null);
            }
            int quote = fEntityScanner.peekChar();
            if (quote != '\'" && quote != '"") {
                if (publicId != null && optionalSystemId) {
                    // looks like we don't have any system id
                    // simply return the public id
                    identifiers[0] = null;
                    identifiers[1] = publicId;
                    return;
                }
                reportFatalError("QuoteRequiredInSystemID", null);
            }
            fEntityScanner.scanChar();
            XMLString ident = fString;
            if (fEntityScanner.scanLiteral(quote, ident) != quote) {
                fStringBuffer.clear();
                do {
                    fStringBuffer.append(ident);
                    int c = fEntityScanner.peekChar();
                    if (XMLChar.isMarkup(c) || c == ']") {
                        fStringBuffer.append((char)fEntityScanner.scanChar());
                    }
                } while (fEntityScanner.scanLiteral(quote, ident) != quote);
                fStringBuffer.append(ident);
                ident = fStringBuffer;
            }
            systemId = ident.toString();
            if (!fEntityScanner.skipChar(quote)) {
                reportFatalError("SystemIDUnterminated", null);
            }
        }
        
        // store result in array
        identifiers[0] = systemId;
        identifiers[1] = publicId;
    
protected voidscanPI(com.sun.org.apache.xerces.internal.util.XMLStringBuffer data)
Scans a processing instruction.

[16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
[17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))

        
        // target
        fReportEntity = false;
        String target = fEntityScanner.scanName();
        if (target == null) {
            reportFatalError("PITargetRequired", null);
        }
        
        // scan data
        scanPIData(target, data);
        fReportEntity = true;
        
    
protected voidscanPIData(java.lang.String target, com.sun.org.apache.xerces.internal.util.XMLStringBuffer data)
Scans a processing data. This is needed to handle the situation where a document starts with a processing instruction whose target name starts with "xml". (e.g. xmlfoo) This method would always read the whole data. We have while loop and data is buffered until delimeter is encountered.

param
target The PI target
param
data The string to fill in with the data

        
        // check target
        if (target.length() == 3) {
            char c0 = Character.toLowerCase(target.charAt(0));
            char c1 = Character.toLowerCase(target.charAt(1));
            char c2 = Character.toLowerCase(target.charAt(2));
            if (c0 == 'x" && c1 == 'm" && c2 == 'l") {
                reportFatalError("ReservedPITarget", null);
            }
        }
        
        // spaces
        if (!fEntityScanner.skipSpaces()) {
            if (fEntityScanner.skipString("?>")) {
                // we found the end, there is no data just return
                return;
            } else {
                // if there is data there should be some space
                reportFatalError("SpaceRequiredInPI", null);
            }
        }
        
        // since scanData appends the parsed data to the buffer passed
        // a while loop would append the whole of parsed data to the buffer(data:XMLStringBuffer)
        //until all of the data is buffered.
        if (fEntityScanner.scanData("?>", data)) {
            do {
                int c = fEntityScanner.peekChar();
                if (c != -1) {
                    if (XMLChar.isHighSurrogate(c)) {
                        scanSurrogates(data);
                    } else if (isInvalidLiteral(c)) {
                        reportFatalError("InvalidCharInPI",
                                new Object[]{Integer.toHexString(c)});
                                fEntityScanner.scanChar();
                    }
                }
            } while (fEntityScanner.scanData("?>", data));
        }
        
    
public java.lang.StringscanPseudoAttribute(boolean scanningTextDecl, com.sun.org.apache.xerces.internal.xni.XMLString value)
Scans a pseudo attribute.

param
scanningTextDecl True if scanning this pseudo-attribute for a TextDecl; false if scanning XMLDecl. This flag is needed to report the correct type of error.
param
value The string to fill in with the attribute value.
return
The name of the attribute Note: This method uses fStringBuffer2, anything in it at the time of calling is lost.

        
        String name = fEntityScanner.scanName();
        // XMLEntityManager.print(fEntityManager.getCurrentEntity());
        
        if (name == null) {
            reportFatalError("PseudoAttrNameExpected", null);
        }
        fEntityScanner.skipSpaces();
        if (!fEntityScanner.skipChar('=")) {
            reportFatalError(scanningTextDecl ? "EqRequiredInTextDecl"
                    : "EqRequiredInXMLDecl", new Object[]{name});
        }
        fEntityScanner.skipSpaces();
        int quote = fEntityScanner.peekChar();
        if (quote != '\'" && quote != '"") {
            reportFatalError(scanningTextDecl ? "QuoteRequiredInTextDecl"
                    : "QuoteRequiredInXMLDecl" , new Object[]{name});
        }
        fEntityScanner.scanChar();
        int c = fEntityScanner.scanLiteral(quote, value);
        if (c != quote) {
            fStringBuffer2.clear();
            do {
                fStringBuffer2.append(value);
                if (c != -1) {
                    if (c == '&" || c == '%" || c == '<" || c == ']") {
                        fStringBuffer2.append((char)fEntityScanner.scanChar());
                    } else if (XMLChar.isHighSurrogate(c)) {
                        scanSurrogates(fStringBuffer2);
                    } else if (isInvalidLiteral(c)) {
                        String key = scanningTextDecl
                                ? "InvalidCharInTextDecl" : "InvalidCharInXMLDecl";
                        reportFatalError(key,
                                new Object[] {Integer.toString(c, 16)});
                                fEntityScanner.scanChar();
                    }
                }
                c = fEntityScanner.scanLiteral(quote, value);
            } while (c != quote);
            fStringBuffer2.append(value);
            value.setValues(fStringBuffer2);
        }
        if (!fEntityScanner.skipChar(quote)) {
            reportFatalError(scanningTextDecl ? "CloseQuoteMissingInTextDecl"
                    : "CloseQuoteMissingInXMLDecl",
                    new Object[]{name});
        }
        
        // return
        return name;
        
    
protected booleanscanPubidLiteral(com.sun.org.apache.xerces.internal.xni.XMLString literal)
Scans public ID literal. [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'" [13] PubidChar::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] The returned string is normalized according to the following rule, from http://www.w3.org/TR/REC-xml#dt-pubid: Before a match is attempted, all strings of white space in the public identifier must be normalized to single space characters (#x20), and leading and trailing white space must be removed.

param
literal The string to fill in with the public ID literal.
return
True on success. Note: This method uses fStringBuffer, anything in it at the time of calling is lost.

        int quote = fEntityScanner.scanChar();
        if (quote != '\'" && quote != '"") {
            reportFatalError("QuoteRequiredInPublicID", null);
            return false;
        }
        
        fStringBuffer.clear();
        // skip leading whitespace
        boolean skipSpace = true;
        boolean dataok = true;
        while (true) {
            int c = fEntityScanner.scanChar();
            if (c == ' " || c == '\n" || c == '\r") {
                if (!skipSpace) {
                    // take the first whitespace as a space and skip the others
                    fStringBuffer.append(' ");
                    skipSpace = true;
                }
            } else if (c == quote) {
                if (skipSpace) {
                    // if we finished on a space let's trim it
                    fStringBuffer.length--;
                }
                literal.setValues(fStringBuffer);
                break;
            } else if (XMLChar.isPubid(c)) {
                fStringBuffer.append((char)c);
                skipSpace = false;
            } else if (c == -1) {
                reportFatalError("PublicIDUnterminated", null);
                return false;
            } else {
                dataok = false;
                reportFatalError("InvalidCharInPublicID",
                        new Object[]{Integer.toHexString(c)});
            }
        }
        return dataok;
    
protected booleanscanSurrogates(com.sun.org.apache.xerces.internal.util.XMLStringBuffer buf)
Scans surrogates and append them to the specified buffer.

Note: This assumes the current char has already been identified as a high surrogate.

param
buf The StringBuffer to append the read surrogates to.
return
True if it succeeded.

        
        int high = fEntityScanner.scanChar();
        int low = fEntityScanner.peekChar();
        if (!XMLChar.isLowSurrogate(low)) {
            reportFatalError("InvalidCharInContent",
                    new Object[] {Integer.toString(high, 16)});
                    return false;
        }
        fEntityScanner.scanChar();
        
        // convert surrogates to supplemental character
        int c = XMLChar.supplemental((char)high, (char)low);
        
        // supplemental character must be a valid XML character
        if (isInvalid(c)) {
            reportFatalError("InvalidCharInContent",
                    new Object[]{Integer.toString(c, 16)});
                    return false;
        }
        
        // fill in the buffer
        buf.append((char)high);
        buf.append((char)low);
        
        return true;
        
    
protected voidscanXMLDeclOrTextDecl(boolean scanningTextDecl, java.lang.String[] pseudoAttributeValues)
Scans an XML or text declaration.

[23] XMLDecl ::= ''
[24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
[80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" )
[81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
[32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'")
| ('"' ('yes' | 'no') '"'))

[77] TextDecl ::= ''

param
scanningTextDecl True if a text declaration is to be scanned instead of an XML declaration.
param
pseudoAttributeValues An array of size 3 to return the version, encoding and standalone pseudo attribute values (in that order). Note: This method uses fString, anything in it at the time of calling is lost.

        
        // pseudo-attribute values
        String version = null;
        String encoding = null;
        String standalone = null;
        
        // scan pseudo-attributes
        final int STATE_VERSION = 0;
        final int STATE_ENCODING = 1;
        final int STATE_STANDALONE = 2;
        final int STATE_DONE = 3;
        int state = STATE_VERSION;
        
        boolean dataFoundForTarget = false;
        boolean sawSpace = fEntityScanner.skipSpaces();
        while (fEntityScanner.peekChar() != '?") {
            dataFoundForTarget = true;
            String name = scanPseudoAttribute(scanningTextDecl, fString);
            switch (state) {
                case STATE_VERSION: {
                    if (name.equals(fVersionSymbol)) {
                        if (!sawSpace) {
                            reportFatalError(scanningTextDecl
                                    ? "SpaceRequiredBeforeVersionInTextDecl"
                                    : "SpaceRequiredBeforeVersionInXMLDecl",
                                    null);
                        }
                        version = fString.toString();
                        state = STATE_ENCODING;
                        if (!versionSupported(version)) {
                            reportFatalError("VersionNotSupported",
                                    new Object[]{version});
                        }
                        
                        if (version.equals("1.1")) {
                            Entity.ScannedEntity top = fEntityManager.getTopLevelEntity();
                            if (top != null && (top.version == null || top.version.equals("1.0"))) {
                                reportFatalError("VersionMismatch", null);
                            }
                            fEntityManager.setScannerVersion(Constants.XML_VERSION_1_1);
                        }
                        
                    } else if (name.equals(fEncodingSymbol)) {
                        if (!scanningTextDecl) {
                            reportFatalError("VersionInfoRequired", null);
                        }
                        if (!sawSpace) {
                            reportFatalError(scanningTextDecl
                                    ? "SpaceRequiredBeforeEncodingInTextDecl"
                                    : "SpaceRequiredBeforeEncodingInXMLDecl",
                                    null);
                        }
                        encoding = fString.toString();
                        state = scanningTextDecl ? STATE_DONE : STATE_STANDALONE;
                    } else {
                        if (scanningTextDecl) {
                            reportFatalError("EncodingDeclRequired", null);
                        } else {
                            reportFatalError("VersionInfoRequired", null);
                        }
                    }
                    break;
                }
                case STATE_ENCODING: {
                    if (name.equals(fEncodingSymbol)) {
                        if (!sawSpace) {
                            reportFatalError(scanningTextDecl
                                    ? "SpaceRequiredBeforeEncodingInTextDecl"
                                    : "SpaceRequiredBeforeEncodingInXMLDecl",
                                    null);
                        }
                        encoding = fString.toString();
                        state = scanningTextDecl ? STATE_DONE : STATE_STANDALONE;
                        // TODO: check encoding name; set encoding on
                        //       entity scanner
                    } else if (!scanningTextDecl && name.equals(fStandaloneSymbol)) {
                        if (!sawSpace) {
                            reportFatalError("SpaceRequiredBeforeStandalone",
                                    null);
                        }
                        standalone = fString.toString();
                        state = STATE_DONE;
                        if (!standalone.equals("yes") && !standalone.equals("no")) {
                            reportFatalError("SDDeclInvalid", null);
                        }
                    } else {
                        reportFatalError("EncodingDeclRequired", null);
                    }
                    break;
                }
                case STATE_STANDALONE: {
                    if (name.equals(fStandaloneSymbol)) {
                        if (!sawSpace) {
                            reportFatalError("SpaceRequiredBeforeStandalone",
                                    null);
                        }
                        standalone = fString.toString();
                        state = STATE_DONE;
                        if (!standalone.equals("yes") && !standalone.equals("no")) {
                            reportFatalError("SDDeclInvalid", null);
                        }
                    } else {
                        reportFatalError("EncodingDeclRequired", null);
                    }
                    break;
                }
                default: {
                    reportFatalError("NoMorePseudoAttributes", null);
                }
            }
            sawSpace = fEntityScanner.skipSpaces();
        }
        // REVISIT: should we remove this error reporting?
        if (scanningTextDecl && state != STATE_DONE) {
            reportFatalError("MorePseudoAttributes", null);
        }
        
        // If there is no data in the xml or text decl then we fail to report error
        // for version or encoding info above.
        if (scanningTextDecl) {
            if (!dataFoundForTarget && encoding == null) {
                reportFatalError("EncodingDeclRequired", null);
            }
        } else {
            if (!dataFoundForTarget && version == null) {
                reportFatalError("VersionInfoRequired", null);
            }
        }
        
        // end
        if (!fEntityScanner.skipChar('?")) {
            reportFatalError("XMLDeclUnterminated", null);
        }
        if (!fEntityScanner.skipChar('>")) {
            reportFatalError("XMLDeclUnterminated", null);
            
        }
        
        // fill in return array
        pseudoAttributeValues[0] = version;
        pseudoAttributeValues[1] = encoding;
        pseudoAttributeValues[2] = standalone;
        
    
public voidsetFeature(java.lang.String featureId, boolean value)

        
        if (VALIDATION.equals(featureId)) {
            fValidation = value;
        } else if (NOTIFY_CHAR_REFS.equals(featureId)) {
            fNotifyCharRefs = value;
        }
    
public voidsetProperty(java.lang.String propertyId, java.lang.Object value)
Sets the value of a property during parsing.

param
propertyId
param
value

        
        // Xerces properties
        if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
            String property =
                    propertyId.substring(Constants.XERCES_PROPERTY_PREFIX.length());
            if (property.equals(Constants.SYMBOL_TABLE_PROPERTY)) {
                fSymbolTable = (SymbolTable)value;
            } else if (property.equals(Constants.ERROR_REPORTER_PROPERTY)) {
                fErrorReporter = (XMLErrorReporter)value;
            } else if (property.equals(Constants.ENTITY_MANAGER_PROPERTY)) {
                fEntityManager = (XMLEntityManager)value;
            }
        }
                /*else if(propertyId.equals(Constants.STAX_PROPERTIES)){
            fStaxProperties = (HashMap)value;
            //TODO::discuss with neeraj what are his thoughts on passing properties.
            //For now use this
        }*/
        
    
protected voidsetPropertyManager(com.sun.org.apache.xerces.internal.impl.PropertyManager propertyManager)

        fPropertyManager = propertyManager ;
    
public voidstartEntity(java.lang.String name, com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier identifier, java.lang.String encoding, com.sun.org.apache.xerces.internal.xni.Augmentations augs)
This method notifies of the start of an entity. The document entity has the pseudo-name of "[xml]" the DTD has the pseudo-name of "[dtd]" parameter entity names start with '%'; and general entities are just specified by their name.

param
name The name of the entity.
param
identifier The resource identifier.
param
encoding The auto-detected IANA encoding name of the entity stream. This value will be null in those situations where the entity encoding is not auto-detected (e.g. internal entities or a document entity that is parsed from a java.io.Reader).
throws
XNIException Thrown by handler to signal an error.

        
        // keep track of the entity depth
        fEntityDepth++;
        // must reset entity scanner
        fEntityScanner = fEntityManager.getEntityScanner();
        fEntityStore = fEntityManager.getEntityStore() ;
    
protected booleanversionSupported(java.lang.String version)

        return version.equals("1.0") || version.equals("1.1");