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

XMLEntityManager

public class XMLEntityManager extends Object implements XMLEntityResolver, XMLComponent
Will keep track of current entity. The entity manager handles the registration of general and parameter entities; resolves entities; and starts entities. The entity manager is a central component in a standard parser configuration and this class works directly with the entity scanner to manage the underlying xni.

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

  • http://xml.org/sax/features/validation
  • http://xml.org/sax/features/external-general-entities
  • http://xml.org/sax/features/external-parameter-entities
  • http://apache.org/xml/features/allow-java-encodings
  • http://apache.org/xml/properties/internal/symbol-table
  • http://apache.org/xml/properties/internal/error-reporter
  • http://apache.org/xml/properties/internal/entity-resolver
author
Andy Clark, IBM
author
Arnaud Le Hors, IBM
author
K.Venugopal SUN Microsystems
author
Neeraj Bajaj SUN Microsystems
author
Sunitha Reddy SUN Microsystems
version
$Id: XMLEntityManager.java,v 1.13 2007/03/16 16:13:11 spericas Exp $

Fields Summary
public static final int
DEFAULT_BUFFER_SIZE
Default buffer size (2048).
public static final int
DEFAULT_XMLDECL_BUFFER_SIZE
Default buffer size before we've finished with the XMLDecl:
public static final int
DEFAULT_INTERNAL_BUFFER_SIZE
Default internal entity buffer size (1024).
protected static final String
VALIDATION
Feature identifier: validation.
protected boolean
fStrictURI
standard uri conformant (strict uri). http://apache.org/xml/features/standard-uri-conformant
protected static final String
EXTERNAL_GENERAL_ENTITIES
Feature identifier: external general entities.
protected static final String
EXTERNAL_PARAMETER_ENTITIES
Feature identifier: external parameter entities.
protected static final String
ALLOW_JAVA_ENCODINGS
Feature identifier: allow Java encodings.
protected static final String
WARN_ON_DUPLICATE_ENTITYDEF
Feature identifier: warn on duplicate EntityDef
protected static final String
SYMBOL_TABLE
Property identifier: symbol table.
protected static final String
ERROR_REPORTER
Property identifier: error reporter.
protected static final String
STANDARD_URI_CONFORMANT
Feature identifier: standard uri conformant
protected static final String
ENTITY_RESOLVER
Property identifier: entity resolver.
protected static final String
STAX_ENTITY_RESOLVER
protected static final String
VALIDATION_MANAGER
protected static final String
BUFFER_SIZE
property identifier: buffer size.
protected static final String
SECURITY_MANAGER
property identifier: security manager.
protected static final String
PARSER_SETTINGS
private static final String[]
RECOGNIZED_FEATURES
Recognized features.
private static final Boolean[]
FEATURE_DEFAULTS
Feature defaults.
private static final String[]
RECOGNIZED_PROPERTIES
Recognized properties.
private static final Object[]
PROPERTY_DEFAULTS
Property defaults.
private static final String
XMLEntity
private static final String
DTDEntity
private static final boolean
DEBUG_BUFFER
Debug printing of buffer. This debugging flag works best when you resize the DEFAULT_BUFFER_SIZE down to something reasonable like 64 characters.
protected boolean
fWarnDuplicateEntityDef
warn on duplicate Entity declaration. http://apache.org/xml/features/warn-on-duplicate-entitydef
private static final boolean
DEBUG_ENTITIES
Debug some basic entities.
private static final boolean
DEBUG_ENCODINGS
Debug switching readers for encodings.
private static final boolean
DEBUG_RESOLVER
protected boolean
fValidation
Validation. This feature identifier is: http://xml.org/sax/features/validation
protected boolean
fExternalGeneralEntities
External general entities. This feature identifier is: http://xml.org/sax/features/external-general-entities
protected boolean
fExternalParameterEntities
External parameter entities. This feature identifier is: http://xml.org/sax/features/external-parameter-entities
protected boolean
fAllowJavaEncodings
Allow Java encoding names. This feature identifier is: http://apache.org/xml/features/allow-java-encodings
protected SymbolTable
fSymbolTable
Symbol table. This property identifier is: http://apache.org/xml/properties/internal/symbol-table
protected XMLErrorReporter
fErrorReporter
Error reporter. This property identifier is: http://apache.org/xml/properties/internal/error-reporter
protected XMLEntityResolver
fEntityResolver
Entity resolver. This property identifier is: http://apache.org/xml/properties/internal/entity-resolver
protected StaxEntityResolverWrapper
fStaxEntityResolver
Stax Entity Resolver. This property identifier is XMLInputFactory.ENTITY_RESOLVER
protected PropertyManager
fPropertyManager
Property Manager. This is used from Stax
protected ValidationManager
fValidationManager
Validation manager. This property identifier is: http://apache.org/xml/properties/internal/validation-manager
protected int
fBufferSize
Buffer size. We get this value from a property. The default size is used if the input buffer size property is not specified. REVISIT: do we need a property for internal entity buffer size?
protected SecurityManager
fSecurityManager
protected boolean
fStandalone
True if the document entity is standalone. This should really only be set by the document source (e.g. XMLDocumentScanner).
protected boolean
fInExternalSubset
protected XMLEntityHandler
fEntityHandler
Entity handler.
protected XMLEntityScanner
fEntityScanner
Current entity scanner
protected XMLEntityScanner
fXML10EntityScanner
XML 1.0 entity scanner.
protected XMLEntityScanner
fXML11EntityScanner
XML 1.1 entity scanner.
protected int
fEntityExpansionLimit
entity expansion limit (contains useful data if and only if fSecurityManager is non-null)
protected int
fEntityExpansionCount
count of entities expanded:
protected Hashtable
fEntities
Entities.
protected Stack
fEntityStack
Entity stack.
protected Entity$ScannedEntity
fCurrentEntity
Current entity.
protected Hashtable
fDeclaredEntities
Shared declared entities. XXX understand it more deeply, why are we doing this ?? Is it really required ?
protected XMLEntityStorage
fEntityStorage
protected final Object[]
defaultEncoding
private final XMLResourceIdentifierImpl
fResourceIdentifier
Resource identifer.
private final Augmentations
fEntityAugs
Augmentations for entities.
private CharacterBufferPool
fBufferPool
Pool of character buffers.
protected Vector
fOwnReaders
private static String
gUserDir
private static URI
gUserDirURI
private static boolean[]
gNeedEscaping
private static char[]
gAfterEscaping1
private static char[]
gAfterEscaping2
private static char[]
gHexChs
Constructors Summary
public XMLEntityManager()
If this constructor is used to create the object, reset() should be invoked on this object


    //
    // Constructors
    //
    
                         
      
        fEntityStorage = new XMLEntityStorage(this) ;
        setScannerVersion(Constants.XML_VERSION_1_0);
    
public XMLEntityManager(PropertyManager propertyManager)
Default constructor.

        fPropertyManager = propertyManager ;
        //pass a reference to current entity being scanned
        //fEntityStorage = new XMLEntityStorage(fCurrentEntity) ;
        fEntityStorage = new XMLEntityStorage(this) ;
        fEntityScanner = new XMLEntityScanner(propertyManager, this) ;
        reset(propertyManager);
    
public XMLEntityManager(XMLEntityManager entityManager)
Constructs an entity manager that shares the specified entity declarations during each parse.

REVISIT: We might want to think about the "right" way to expose the list of declared entities. For now, the knowledge how to access the entity declarations is implicit.



        // save shared entity declarations
        fDeclaredEntities = entityManager != null
                          ? entityManager.getEntityStore().getDeclaredEntities() : null;

        setScannerVersion(Constants.XML_VERSION_1_0);
    
Methods Summary
public static voidabsolutizeAgainstUserDir(com.sun.org.apache.xerces.internal.util.URI uri)
Absolutizes a URI using the current value of the "user.dir" property as the base URI. If the URI is already absolute, this is a no-op.

param
uri the URI to absolutize

        uri.absolutize(getUserDir());
    
public voidaddExternalEntity(java.lang.String name, java.lang.String publicId, java.lang.String literalSystemId, java.lang.String baseSystemId)
Adds an external entity declaration.

Note: This method ignores subsequent entity declarations.

Note: The name should be a unique symbol. The SymbolTable can be used for this purpose.

param
name The name of the entity.
param
publicId The public identifier of the entity.
param
literalSystemId The system identifier of the entity.
param
baseSystemId The base system identifier of the entity. This is the system identifier of the entity where the entity being added and is used to expand the system identifier when the system identifier is a relative URI. When null the system identifier of the first external entity on the stack is used instead.
see
SymbolTable

        if (!fEntities.containsKey(name)) {
            if (baseSystemId == null) {
                // search for the first external entity on the stack
                int size = fEntityStack.size();
                if (size == 0 && fCurrentEntity != null && fCurrentEntity.entityLocation != null) {
                    baseSystemId = fCurrentEntity.entityLocation.getExpandedSystemId();
                }
                for (int i = size - 1; i >= 0 ; i--) {
                    Entity.ScannedEntity externalEntity =
                            (Entity.ScannedEntity)fEntityStack.elementAt(i);
                    if (externalEntity.entityLocation != null && externalEntity.entityLocation.getExpandedSystemId() != null) {
                        baseSystemId = externalEntity.entityLocation.getExpandedSystemId();
                        break;
                    }
                }
            }
            Entity entity = new Entity.ExternalEntity(name,
                    new XMLEntityDescriptionImpl(name, publicId, literalSystemId, baseSystemId,
                    expandSystemId(literalSystemId, baseSystemId, false)), null, fInExternalSubset);
            fEntities.put(name, entity);
        } else{
            if(fWarnDuplicateEntityDef){
                fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                        "MSG_DUPLICATE_ENTITY_DEFINITION",
                        new Object[]{ name },
                        XMLErrorReporter.SEVERITY_WARNING );
            }
        }
        
    
public voidaddInternalEntity(java.lang.String name, java.lang.String text)
Adds an internal entity declaration.

Note: This method ignores subsequent entity declarations.

Note: The name should be a unique symbol. The SymbolTable can be used for this purpose.

param
name The name of the entity.
param
text The text of the entity.
see
SymbolTable

        if (!fEntities.containsKey(name)) {
            Entity entity = new Entity.InternalEntity(name, text, fInExternalSubset);
            fEntities.put(name, entity);
        } else{
            if(fWarnDuplicateEntityDef){
                fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                        "MSG_DUPLICATE_ENTITY_DEFINITION",
                        new Object[]{ name },
                        XMLErrorReporter.SEVERITY_WARNING );
            }
        }
        
    
public voidaddUnparsedEntity(java.lang.String name, java.lang.String publicId, java.lang.String systemId, java.lang.String baseSystemId, java.lang.String notation)
Adds an unparsed entity declaration.

Note: This method ignores subsequent entity declarations.

Note: The name should be a unique symbol. The SymbolTable can be used for this purpose.

param
name The name of the entity.
param
publicId The public identifier of the entity.
param
systemId The system identifier of the entity.
param
notation The name of the notation.
see
SymbolTable

        if (!fEntities.containsKey(name)) {
            Entity.ExternalEntity entity = new Entity.ExternalEntity(name,
                    new XMLEntityDescriptionImpl(name, publicId, systemId, baseSystemId, null),
                    notation, fInExternalSubset);
            fEntities.put(name, entity);
        } else{
            if(fWarnDuplicateEntityDef){
                fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                        "MSG_DUPLICATE_ENTITY_DEFINITION",
                        new Object[]{ name },
                        XMLErrorReporter.SEVERITY_WARNING );
            }
        }
    
public voidcloseReaders()
Close all opened InputStreams and Readers opened by this parser.

    
                   
       
        // close all readers
        for (int i = fOwnReaders.size()-1; i >= 0; i--) {
            try {
                ((Reader)fOwnReaders.elementAt(i)).close();
            } catch (IOException e) {
                // ignore
            }
        }
        // and clear the list
        fOwnReaders.removeAllElements();
    
protected java.io.ReadercreateReader(java.io.InputStream inputStream, java.lang.String encoding, java.lang.Boolean isBigEndian)
Creates a reader capable of reading the given input stream in the specified encoding.

param
inputStream The input stream.
param
encoding The encoding name that the input stream is encoded using. If the user has specified that Java encoding names are allowed, then the encoding name may be a Java encoding name; otherwise, it is an ianaEncoding name.
param
isBigEndian For encodings (like uCS-4), whose names cannot specify a byte order, this tells whether the order is bigEndian. null menas unknown or not relevant.
return
Returns a reader.


        // normalize encoding name
        if (encoding == null) {
            encoding = "UTF-8";
        }

        // try to use an optimized reader
        String ENCODING = encoding.toUpperCase(Locale.ENGLISH);
        if (ENCODING.equals("UTF-8")) {
            if (DEBUG_ENCODINGS) {
                System.out.println("$$$ creating UTF8Reader");
            }
            return new UTF8Reader(inputStream, fBufferSize, fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN), fErrorReporter.getLocale() );
        }
        if (ENCODING.equals("US-ASCII")) {
            if (DEBUG_ENCODINGS) {
                System.out.println("$$$ creating ASCIIReader");
            }
            return new ASCIIReader(inputStream, fBufferSize, fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN), fErrorReporter.getLocale());
        }
        if(ENCODING.equals("ISO-10646-UCS-4")) {
            if(isBigEndian != null) {
                boolean isBE = isBigEndian.booleanValue();
                if(isBE) {
                    return new UCSReader(inputStream, UCSReader.UCS4BE);
                } else {
                    return new UCSReader(inputStream, UCSReader.UCS4LE);
                }
            } else {
                fErrorReporter.reportError(this.getEntityScanner(),XMLMessageFormatter.XML_DOMAIN,
                        "EncodingByteOrderUnsupported",
                        new Object[] { encoding },
                        XMLErrorReporter.SEVERITY_FATAL_ERROR);
            }
        }
        if(ENCODING.equals("ISO-10646-UCS-2")) {
            if(isBigEndian != null) { // sould never happen with this encoding...
                boolean isBE = isBigEndian.booleanValue();
                if(isBE) {
                    return new UCSReader(inputStream, UCSReader.UCS2BE);
                } else {
                    return new UCSReader(inputStream, UCSReader.UCS2LE);
                }
            } else {
                fErrorReporter.reportError(this.getEntityScanner(),XMLMessageFormatter.XML_DOMAIN,
                        "EncodingByteOrderUnsupported",
                        new Object[] { encoding },
                        XMLErrorReporter.SEVERITY_FATAL_ERROR);
            }
        }

        // check for valid name
        boolean validIANA = XMLChar.isValidIANAEncoding(encoding);
        boolean validJava = XMLChar.isValidJavaEncoding(encoding);
        if (!validIANA || (fAllowJavaEncodings && !validJava)) {
            fErrorReporter.reportError(this.getEntityScanner(),XMLMessageFormatter.XML_DOMAIN,
                    "EncodingDeclInvalid",
                    new Object[] { encoding },
                    XMLErrorReporter.SEVERITY_FATAL_ERROR);
                    // NOTE: AndyH suggested that, on failure, we use ISO Latin 1
                    //       because every byte is a valid ISO Latin 1 character.
                    //       It may not translate correctly but if we failed on
                    //       the encoding anyway, then we're expecting the content
                    //       of the document to be bad. This will just prevent an
                    //       invalid UTF-8 sequence to be detected. This is only
                    //       important when continue-after-fatal-error is turned
                    //       on. -Ac
                    encoding = "ISO-8859-1";
        }

        // try to use a Java reader
        String javaEncoding = EncodingMap.getIANA2JavaMapping(ENCODING);
        if (javaEncoding == null) {
            if(fAllowJavaEncodings) {
                javaEncoding = encoding;
            } else {
                fErrorReporter.reportError(this.getEntityScanner(),XMLMessageFormatter.XML_DOMAIN,
                        "EncodingDeclInvalid",
                        new Object[] { encoding },
                        XMLErrorReporter.SEVERITY_FATAL_ERROR);
                        // see comment above.
                        javaEncoding = "ISO8859_1";
            }
        }
        if (DEBUG_ENCODINGS) {
            System.out.print("$$$ creating Java InputStreamReader: encoding="+javaEncoding);
            if (javaEncoding == encoding) {
                System.out.print(" (IANA encoding)");
            }
            System.out.println();
        }
        return new BufferedReader( new InputStreamReader(inputStream, javaEncoding));
        
    
public voidendEntity()

        
        // call handler
        if (DEBUG_BUFFER) {
            System.out.print("(endEntity: ");
            print();
            System.out.println();
        }                
        //pop the entity from the stack 
        Entity.ScannedEntity entity = fEntityStack.size() > 0 ? (Entity.ScannedEntity)fEntityStack.pop() : null ;
        
        if (fEntityHandler != null) {
            //so this is the last opened entity, signal it to current fEntityHandler using Augmentation
            if(entity == null){
                fEntityAugs.removeAllItems();
                fEntityAugs.putItem(Constants.LAST_ENTITY, Boolean.TRUE);
                fEntityHandler.endEntity(fCurrentEntity.name, fEntityAugs);
                fEntityAugs.removeAllItems();
            }else{
                fEntityHandler.endEntity(fCurrentEntity.name, null);
            }
        }
        //check if it is a document entity
        boolean documentEntity = fCurrentEntity.name == XMLEntity;
        
        //close the reader
        if(fCurrentEntity != null){
            //close the reader
            try{
                fCurrentEntity.reader.close();
            }catch(IOException ex){
                throw new XNIException(ex);
            }
        }
        
        //set popped entity as current entity
        fCurrentEntity = entity;
        fEntityScanner.setCurrentEntity(fCurrentEntity);
        
        //check if there are any entity left in the stack -- if there are
        //no entries EOF has been reached.        
        // throw exception when it is the last entity but it is not a document entity
        
        if(fCurrentEntity == null & !documentEntity){
            throw new EOFException() ;
        }
         
        if (DEBUG_BUFFER) {
            System.out.print(")endEntity: ");
            print();
            System.out.println();
        }
        
    
public voidendExternalSubset()

        fInExternalSubset = false;
    
protected static java.lang.StringescapeNonUSAscii(java.lang.String str)
Escape invalid URI characters. Passed a URI that contains invalid characters (like spaces, non-ASCII Unicode characters, and the like), this function percent encodes the invalid characters per the URI specification (i.e., as a sequence of %-encoded UTF-8 octets). N.B. There are two problems. If the URI contains a '%' character, that might be an indication that the URI has already been escaped by the author, or it might be an invalid '%'. In the former case, it's important not to escape it, or we'll wind up with invalid, doubly-escaped '%'s. In the latter, the URI is broken if we don't encode it. Similarly, a '#' character might be the start of a fragment identifier or it might be an invalid '#'. Given that the former is vastly more likely than the latter in each case (most users are familiar with the magic status of '%' and '#' and they occur relatively infrequently in filenames, and if the user parses a proper Java File, we will already have %-escaped the URI), we simply assume that %'s and #'s are legit. Very rarely, we may be wrong. If so, tell the user to fix the clearly broken URI.

        if (str == null) {
            return str;
        }
        
        // get UTF-8 bytes for the string
        StringBuffer buffer = new StringBuffer();
        byte[] bytes = null;
        byte b;
        try {
            bytes = str.getBytes("UTF-8");
        } catch (java.io.UnsupportedEncodingException e) {
            // should never happen
            return str;
        }
        int len = bytes.length;
        int ch;

        // for each byte
        for (int i = 0; i < len; i++) {
            b = bytes[i];
            // for non-ascii character: make it positive, then escape
            if (b < 0) {
                ch = b + 256;
                buffer.append('%");
                buffer.append(gHexChs[ch >> 4]);
                buffer.append(gHexChs[ch & 0xf]);
            }
            else if (b != '%" && b != '#" && gNeedEscaping[b]) {
                buffer.append('%");
                buffer.append(gAfterEscaping1[b]);
                buffer.append(gAfterEscaping2[b]);
            }
            else {
                buffer.append((char)b);
            }
        }
        return buffer.toString();
    
public static java.lang.StringexpandSystemId(java.lang.String systemId)
Expands a system id and returns the system id as a URI, if it can be expanded. A return value of null means that the identifier is already expanded. An exception thrown indicates a failure to expand the id.

param
systemId The systemId to be expanded.
return
Returns the URI string representing the expanded system identifier. A null value indicates that the given system identifier is already expanded.

        return expandSystemId(systemId, null);
    
public static java.lang.StringexpandSystemId(java.lang.String systemId, java.lang.String baseSystemId)
Expands a system id and returns the system id as a URI, if it can be expanded. A return value of null means that the identifier is already expanded. An exception thrown indicates a failure to expand the id.

param
systemId The systemId to be expanded.
return
Returns the URI string representing the expanded system identifier. A null value indicates that the given system identifier is already expanded.


        // check for bad parameters id
        if (systemId == null || systemId.length() == 0) {
            return systemId;
        }
        // if id already expanded, return
        try {
            URI uri = new URI(systemId);
            if (uri != null) {
                return systemId;
            }
        } catch (URI.MalformedURIException e) {
            // continue on...
        }
        // normalize id
        String id = fixURI(systemId);

        // normalize base
        URI base = null;
        URI uri = null;
        try {
            if (baseSystemId == null || baseSystemId.length() == 0 ||
                    baseSystemId.equals(systemId)) {
                String dir = getUserDir().toString();
                base = new URI("file", "", dir, null, null);
            } else {
                try {
                    base = new URI(fixURI(baseSystemId));
                } catch (URI.MalformedURIException e) {
                    if (baseSystemId.indexOf(':") != -1) {
                        // for xml schemas we might have baseURI with
                        // a specified drive
                        base = new URI("file", "", fixURI(baseSystemId), null, null);
                    } else {
                        String dir = getUserDir().toString();
                        dir = dir + fixURI(baseSystemId);
                        base = new URI("file", "", dir, null, null);
                    }
                }
            }
            // expand id
            uri = new URI(base, id);
        } catch (Exception e) {
            // let it go through

        }

        if (uri == null) {
            return systemId;
        }
        return uri.toString();

    
public static java.lang.StringexpandSystemId(java.lang.String systemId, java.lang.String baseSystemId, boolean strict)
Expands a system id and returns the system id as a URI, if it can be expanded. A return value of null means that the identifier is already expanded. An exception thrown indicates a failure to expand the id.

param
systemId The systemId to be expanded.
return
Returns the URI string representing the expanded system identifier. A null value indicates that the given system identifier is already expanded.

            
        // check if there is a system id before 
        // trying to expand it.
        if (systemId == null) {
            return null;
        }

        // system id has to be a valid URI
        if (strict) {


            // check if there is a system id before 
            // trying to expand it.
            if (systemId == null) {
                return null;
            }

            try {
                // if it's already an absolute one, return it
                new URI(systemId);
                return systemId;
            }
            catch (URI.MalformedURIException ex) {
            }
            URI base = null;
            // if there isn't a base uri, use the working directory
            if (baseSystemId == null || baseSystemId.length() == 0) {
                base = new URI("file", "", getUserDir().toString(), null, null);
            }
            // otherwise, use the base uri
            else {
                try {
                    base = new URI(baseSystemId);
                }
                catch (URI.MalformedURIException e) {
                    // assume "base" is also a relative uri
                    String dir = getUserDir().toString();
                    dir = dir + baseSystemId;
                    base = new URI("file", "", dir, null, null);
                }
            }
            // absolutize the system id using the base
            URI uri = new URI(base, systemId);
            // return the string rep of the new uri (an absolute one)
            return uri.toString();

            // if any exception is thrown, it'll get thrown to the caller.
        }

        // Assume the URIs are well-formed. If it turns out they're not, try fixing them up.
        try {
            return expandSystemIdStrictOff(systemId, baseSystemId);
        }
        catch (URI.MalformedURIException e) {
            // continue on...
        }

        // check for bad parameters id
        if (systemId.length() == 0) {
            return systemId;
        }

        // normalize id
        String id = fixURI(systemId);
        
        // normalize base
        URI base = null;
        URI uri = null;
        try {
            if (baseSystemId == null || baseSystemId.length() == 0 ||
                baseSystemId.equals(systemId)) {
                base = getUserDir();
            }
            else {
                try {
                    base = new URI(fixURI(baseSystemId).trim());
                }
                catch (URI.MalformedURIException e) {
                    if (baseSystemId.indexOf(':") != -1) {
                        // for xml schemas we might have baseURI with
                        // a specified drive
                        base = new URI("file", "", fixURI(baseSystemId).trim(), null, null);
                    }
                    else {
                        base = new URI(getUserDir(), fixURI(baseSystemId));
                    }
                }
             }
             // expand id
             uri = new URI(base, id.trim());
        }
        catch (Exception e) {
            // let it go through
            
        }

        if (uri == null) {
            return systemId;
        }
        return uri.toString();

    
private static java.lang.StringexpandSystemIdStrictOff(java.lang.String systemId, java.lang.String baseSystemId)
Helper method for expandSystemId(String,String,boolean):String


        systemId = escapeNonUSAscii(systemId);
        baseSystemId = escapeNonUSAscii(baseSystemId);

        URI systemURI = new URI(systemId, true);
        // If it's already an absolute one, return it
        if (systemURI.isAbsoluteURI()) {
            if (systemURI.getScheme().length() > 1) {
                return systemId;
            }
            /** 
             * If the scheme's length is only one character,
             * it's likely that this was intended as a file
             * path. Fixing this up in expandSystemId to
             * maintain backwards compatibility.
             */
            throw new URI.MalformedURIException();
        }

        // If there isn't a base URI, use the working directory
        URI baseURI = null;
        if (baseSystemId == null || baseSystemId.length() == 0) {
            baseURI = getUserDir();
        }
        else {
            baseURI = new URI(baseSystemId, true);
            if (!baseURI.isAbsoluteURI()) {
                // assume "base" is also a relative uri
                baseURI.absolutize(getUserDir());
            }
        }

        // absolutize the system identifier using the base URI
        systemURI.absolutize(baseURI);
        
        // return the string rep of the new uri (an absolute one)
        return systemURI.toString();

        // if any exception is thrown, it'll get thrown to the caller.

    
private static java.lang.StringexpandSystemIdStrictOn(java.lang.String systemId, java.lang.String baseSystemId)
Helper method for expandSystemId(String,String,boolean):String


        URI systemURI = new URI(systemId, true);
        // If it's already an absolute one, return it
        if (systemURI.isAbsoluteURI()) {
            return systemId;
        }

        // If there isn't a base URI, use the working directory
        URI baseURI = null;
        if (baseSystemId == null || baseSystemId.length() == 0) {
            baseURI = getUserDir();
        }
        else {
            baseURI = new URI(baseSystemId, true);
            if (!baseURI.isAbsoluteURI()) {
                // assume "base" is also a relative uri
                baseURI.absolutize(getUserDir());
            }
        }

        // absolutize the system identifier using the base URI
        systemURI.absolutize(baseURI);

        // return the string rep of the new uri (an absolute one)
        return systemURI.toString();

        // if any exception is thrown, it'll get thrown to the caller.

    
protected static java.lang.StringfixURI(java.lang.String str)
Fixes a platform dependent filename to standard URI form.

param
str The string to fix.
return
Returns the fixed URI string.


        // handle platform dependent strings
        str = str.replace(java.io.File.separatorChar, '/");

        // Windows fix
        if (str.length() >= 2) {
            char ch1 = str.charAt(1);
            // change "C:blah" to "/C:blah"
            if (ch1 == ':") {
                char ch0 = Character.toUpperCase(str.charAt(0));
                if (ch0 >= 'A" && ch0 <= 'Z") {
                    str = "/" + str;
                }
            }
            // change "//blah" to "file://blah"
            else if (ch1 == '/" && str.charAt(0) == '/") {
                str = "file:" + str;
            }
        }

        // done
        return str;

    
public intgetColumnNumber()
Return the column number where the current document event ends.

Warning: The return value from the method is intended only as an approximation for the sake of error reporting; it is not intended to provide sufficient information to edit the character content of the original XML document.

The return value is an approximation of the column number in the document entity or external parsed entity where the markup triggering the event appears.

If possible, the SAX driver should provide the line position of the first character after the text associated with the document event.

If possible, the SAX driver should provide the line position of the first character after the text associated with the document event. The first column in each line is column 1.

return
The column number, or -1 if none is available.

        if (fCurrentEntity != null) {
            if (fCurrentEntity.isExternal()) {
                return fCurrentEntity.columnNumber;
            } else {
                // search for the first external entity on the stack
                int size = fEntityStack.size();
                for (int i=size-1; i>0 ; i--) {
                    Entity.ScannedEntity firstExternalEntity = (Entity.ScannedEntity)fEntityStack.elementAt(i);
                    if (firstExternalEntity.isExternal()) {
                        return firstExternalEntity.columnNumber;
                    }
                }
            }
        }

        return -1;
    
public com.sun.xml.internal.stream.Entity$ScannedEntitygetCurrentEntity()
Return the current entity being scanned. Current entity is SET using startEntity function.

return
Entity.ScannedEntity

        return fCurrentEntity ;
    
public com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifiergetCurrentResourceIdentifier()

        return fResourceIdentifier;
    
protected java.lang.Object[]getEncodingName(byte[] b4, int count)
Returns the IANA encoding name that is auto-detected from the bytes specified, with the endian-ness of that encoding where appropriate.

param
b4 The first four bytes of the input.
param
count The number of bytes actually read.
return
a 2-element array: the first element, an IANA-encoding string, the second element a Boolean which is true iff the document is big endian, false if it's little-endian, and null if the distinction isn't relevant.


        if (count < 2) {
            return defaultEncoding;
        }

        // UTF-16, with BOM
        int b0 = b4[0] & 0xFF;
        int b1 = b4[1] & 0xFF;
        if (b0 == 0xFE && b1 == 0xFF) {
            // UTF-16, big-endian
            return new Object [] {"UTF-16BE", new Boolean(true)};
        }
        if (b0 == 0xFF && b1 == 0xFE) {
            // UTF-16, little-endian
            return new Object [] {"UTF-16LE", new Boolean(false)};
        }

        // default to UTF-8 if we don't have enough bytes to make a
        // good determination of the encoding
        if (count < 3) {
            return defaultEncoding;
        }

        // UTF-8 with a BOM
        int b2 = b4[2] & 0xFF;
        if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF) {
            return defaultEncoding;
        }

        // default to UTF-8 if we don't have enough bytes to make a
        // good determination of the encoding
        if (count < 4) {
            return defaultEncoding;
        }

        // other encodings
        int b3 = b4[3] & 0xFF;
        if (b0 == 0x00 && b1 == 0x00 && b2 == 0x00 && b3 == 0x3C) {
            // UCS-4, big endian (1234)
            return new Object [] {"ISO-10646-UCS-4", new Boolean(true)};
        }
        if (b0 == 0x3C && b1 == 0x00 && b2 == 0x00 && b3 == 0x00) {
            // UCS-4, little endian (4321)
            return new Object [] {"ISO-10646-UCS-4", new Boolean(false)};
        }
        if (b0 == 0x00 && b1 == 0x00 && b2 == 0x3C && b3 == 0x00) {
            // UCS-4, unusual octet order (2143)
            // REVISIT: What should this be?
            return new Object [] {"ISO-10646-UCS-4", null};
        }
        if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x00) {
            // UCS-4, unusual octect order (3412)
            // REVISIT: What should this be?
            return new Object [] {"ISO-10646-UCS-4", null};
        }
        if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F) {
            // UTF-16, big-endian, no BOM
            // (or could turn out to be UCS-2...
            // REVISIT: What should this be?
            return new Object [] {"UTF-16BE", new Boolean(true)};
        }
        if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00) {
            // UTF-16, little-endian, no BOM
            // (or could turn out to be UCS-2...
            return new Object [] {"UTF-16LE", new Boolean(false)};
        }
        if (b0 == 0x4C && b1 == 0x6F && b2 == 0xA7 && b3 == 0x94) {
            // EBCDIC
            // a la xerces1, return CP037 instead of EBCDIC here
            return new Object [] {"CP037", null};
        }

        return defaultEncoding;

    
public com.sun.org.apache.xerces.internal.impl.XMLEntityScannergetEntityScanner()
return the entity responsible for reading the entity

        
        if(fEntityScanner == null) {
            // default to 1.0
            if(fXML10EntityScanner == null) {
                fXML10EntityScanner = new XMLEntityScanner();
            }
            fXML10EntityScanner.reset(fSymbolTable, this, fErrorReporter);
            fEntityScanner = fXML10EntityScanner;
        }
        return fEntityScanner;
        
    
public com.sun.xml.internal.stream.XMLEntityStoragegetEntityStore()
get the entity storage object from entity manager

        return fEntityStorage ;
    
public java.lang.StringgetExpandedSystemId()
Return the expanded system identifier for the current document event.

The return value is the expanded system identifier of the document entity or of the external parsed entity in which the markup triggering the event appears.

If the system identifier is a URL, the parser must resolve it fully before passing it to the application.

return
A string containing the expanded system identifier, or null if none is available.

        if (fCurrentEntity != null) {
            if (fCurrentEntity.entityLocation != null &&
                    fCurrentEntity.entityLocation.getExpandedSystemId() != null ) {
                return fCurrentEntity.entityLocation.getExpandedSystemId();
            } else {
                // search for the first external entity on the stack
                int size = fEntityStack.size();
                for (int i = size - 1; i >= 0 ; i--) {
                    Entity.ScannedEntity externalEntity =
                            (Entity.ScannedEntity)fEntityStack.elementAt(i);

                    if (externalEntity.entityLocation != null &&
                            externalEntity.entityLocation.getExpandedSystemId() != null) {
                        return externalEntity.entityLocation.getExpandedSystemId();
                    }
                }
            }
        }
        return null;
    
public java.lang.BooleangetFeatureDefault(java.lang.String featureId)
Returns the default state for a feature, or null if this component does not want to report a default value for this feature.

param
featureId The feature identifier.
since
Xerces 2.2.0

        for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
            if (RECOGNIZED_FEATURES[i].equals(featureId)) {
                return FEATURE_DEFAULTS[i];
            }
        }
        return null;
    
public intgetLineNumber()
Return the line number where the current document event ends.

Warning: The return value from the method is intended only as an approximation for the sake of error reporting; it is not intended to provide sufficient information to edit the character content of the original XML document.

The return value is an approximation of the line number in the document entity or external parsed entity where the markup triggering the event appears.

If possible, the SAX driver should provide the line position of the first character after the text associated with the document event. The first line in the document is line 1.

return
The line number, or -1 if none is available.

        if (fCurrentEntity != null) {
            if (fCurrentEntity.isExternal()) {
                return fCurrentEntity.lineNumber;
            } else {
                // search for the first external entity on the stack
                int size = fEntityStack.size();
                for (int i=size-1; i>0 ; i--) {
                    Entity.ScannedEntity firstExternalEntity = (Entity.ScannedEntity)fEntityStack.elementAt(i);
                    if (firstExternalEntity.isExternal()) {
                        return firstExternalEntity.lineNumber;
                    }
                }
            }
        }

        return -1;

    
public java.lang.StringgetLiteralSystemId()
Return the literal system identifier for the current document event.

The return value is the literal system identifier of the document entity or of the external parsed entity in which the markup triggering the event appears.

return
A string containing the literal system identifier, or null if none is available.

        if (fCurrentEntity != null) {
            if (fCurrentEntity.entityLocation != null &&
                    fCurrentEntity.entityLocation.getLiteralSystemId() != null ) {
                return fCurrentEntity.entityLocation.getLiteralSystemId();
            } else {
                // search for the first external entity on the stack
                int size = fEntityStack.size();
                for (int i = size - 1; i >= 0 ; i--) {
                    Entity.ScannedEntity externalEntity =
                            (Entity.ScannedEntity)fEntityStack.elementAt(i);

                    if (externalEntity.entityLocation != null &&
                            externalEntity.entityLocation.getLiteralSystemId() != null) {
                        return externalEntity.entityLocation.getLiteralSystemId();
                    }
                }
            }
        }
        return null;
    
public java.lang.ObjectgetPropertyDefault(java.lang.String propertyId)
Returns the default state for a property, or null if this component does not want to report a default value for this property.

param
propertyId The property identifier.
since
Xerces 2.2.0

        for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
            if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
                return PROPERTY_DEFAULTS[i];
            }
        }
        return null;
    
public java.lang.StringgetPublicId()
Return the public identifier for the current document event.

The return value is the public identifier of the document entity or of the external parsed entity in which the markup triggering the event appears.

return
A string containing the public identifier, or null if none is available.

        return (fCurrentEntity != null && fCurrentEntity.entityLocation != null) ? fCurrentEntity.entityLocation.getPublicId() : null;
    
public java.lang.String[]getRecognizedFeatures()
Returns a list of feature identifiers that are recognized by this component. This method may return null if no features are recognized by this component.

        return (String[])(RECOGNIZED_FEATURES.clone());
    
public java.lang.String[]getRecognizedProperties()
Returns a list of property identifiers that are recognized by this component. This method may return null if no properties are recognized by this component.

        return (String[])(RECOGNIZED_PROPERTIES.clone());
    
public com.sun.xml.internal.stream.Entity$ScannedEntitygetTopLevelEntity()
Return the top level entity handled by this manager, or null if no entity was added.

        return (Entity.ScannedEntity) 
            (fEntityStack.empty() ? null : fEntityStack.elementAt(0));
    
private static synchronized com.sun.org.apache.xerces.internal.util.URIgetUserDir()

    // initialize the above 3 arrays
     
        for (int i = 0; i <= 0x1f; i++) {
            gNeedEscaping[i] = true;
            gAfterEscaping1[i] = gHexChs[i >> 4];
            gAfterEscaping2[i] = gHexChs[i & 0xf];
        }
        gNeedEscaping[0x7f] = true;
        gAfterEscaping1[0x7f] = '7";
        gAfterEscaping2[0x7f] = 'F";
        char[] escChs = {' ", '<", '>", '#", '%", '"", '{", '}",
                         '|", '\\", '^", '~", '[", ']", '`"};
        int len = escChs.length;
        char ch;
        for (int i = 0; i < len; i++) {
            ch = escChs[i];
            gNeedEscaping[ch] = true;
            gAfterEscaping1[ch] = gHexChs[ch >> 4];
            gAfterEscaping2[ch] = gHexChs[ch & 0xf];
        }
    
        // get the user.dir property
        String userDir = "";
        try {
            userDir = System.getProperty("user.dir");
        }
        catch (SecurityException se) {
        }

        // return empty string if property value is empty string.
        if (userDir.length() == 0) 
            return new URI("file", "", "", null, null);
        // compute the new escaped value if the new property value doesn't
        // match the previous one
        if (gUserDirURI != null && userDir.equals(gUserDir)) {
            return gUserDirURI;
        }

        // record the new value as the global property value
        gUserDir = userDir;

        char separator = java.io.File.separatorChar;
        userDir = userDir.replace(separator, '/");

        int len = userDir.length(), ch;
        StringBuffer buffer = new StringBuffer(len*3);
        // change C:/blah to /C:/blah
        if (len >= 2 && userDir.charAt(1) == ':") {
            ch = Character.toUpperCase(userDir.charAt(0));
            if (ch >= 'A" && ch <= 'Z") {
                buffer.append('/");
            }
        }

        // for each character in the path
        int i = 0;
        for (; i < len; i++) {
            ch = userDir.charAt(i);
            // if it's not an ASCII character, break here, and use UTF-8 encoding
            if (ch >= 128)
                break;
            if (gNeedEscaping[ch]) {
                buffer.append('%");
                buffer.append(gAfterEscaping1[ch]);
                buffer.append(gAfterEscaping2[ch]);
                // record the fact that it's escaped
            }
            else {
                buffer.append((char)ch);
            }
        }

        // we saw some non-ascii character
        if (i < len) {
            // get UTF-8 bytes for the remaining sub-string
            byte[] bytes = null;
            byte b;
            try {
                bytes = userDir.substring(i).getBytes("UTF-8");
            } catch (java.io.UnsupportedEncodingException e) {
                // should never happen
                return new URI("file", "", userDir, null, null);
            }
            len = bytes.length;

            // for each byte
            for (i = 0; i < len; i++) {
                b = bytes[i];
                // for non-ascii character: make it positive, then escape
                if (b < 0) {
                    ch = b + 256;
                    buffer.append('%");
                    buffer.append(gHexChs[ch >> 4]);
                    buffer.append(gHexChs[ch & 0xf]);
                }
                else if (gNeedEscaping[b]) {
                    buffer.append('%");
                    buffer.append(gAfterEscaping1[b]);
                    buffer.append(gAfterEscaping2[b]);
                }
                else {
                    buffer.append((char)b);
                }
            }
        }

        // change blah/blah to blah/blah/
        if (!userDir.endsWith("/"))
            buffer.append('/");

        gUserDirURI = new URI("file", "", buffer.toString(), null, null);

        return gUserDirURI;
    
public booleanisDeclaredEntity(java.lang.String entityName)

        
        Entity entity = (Entity)fEntities.get(entityName);
        return entity != null;
    
public booleanisEntityDeclInExternalSubset(java.lang.String entityName)
Checks whether the declaration of an entity given by name is // in the external subset.

param
entityName The name of the entity to check.
return
True if the entity was declared in the external subset, false otherwise (including when the entity is not declared).

        
        Entity entity = (Entity)fEntities.get(entityName);
        if (entity == null) {
            return false;
        }
        return entity.isEntityDeclInExternalSubset();
    
public booleanisExternalEntity(java.lang.String entityName)
Checks whether an entity given by name is external.

param
entityName The name of the entity to check.
return
True if the entity is external, false otherwise (including when the entity is not declared).

        
        Entity entity = (Entity)fEntities.get(entityName);
        if (entity == null) {
            return false;
        }
        return entity.isExternal();
    
public booleanisStandalone()
Returns true if the document entity is standalone.

        return fStandalone;
    
public booleanisUnparsedEntity(java.lang.String entityName)

        
        Entity entity = (Entity)fEntities.get(entityName);
        if (entity == null) {
            return false;
        }
        return entity.isUnparsed();
    
final voidprint()
Prints the contents of the buffer.

        if (DEBUG_BUFFER) {
            if (fCurrentEntity != null) {
                System.out.print('[");
                System.out.print(fCurrentEntity.count);
                System.out.print(' ");
                System.out.print(fCurrentEntity.position);
                if (fCurrentEntity.count > 0) {
                    System.out.print(" \"");
                    for (int i = 0; i < fCurrentEntity.count; i++) {
                        if (i == fCurrentEntity.position) {
                            System.out.print('^");
                        }
                        char c = fCurrentEntity.ch[i];
                        switch (c) {
                            case '\n": {
                                System.out.print("\\n");
                                break;
                            }
                            case '\r": {
                                System.out.print("\\r");
                                break;
                            }
                            case '\t": {
                                System.out.print("\\t");
                                break;
                            }
                            case '\\": {
                                System.out.print("\\\\");
                                break;
                            }
                            default: {
                                System.out.print(c);
                            }
                        }
                    }
                    if (fCurrentEntity.position == fCurrentEntity.count) {
                        System.out.print('^");
                    }
                    System.out.print('"");
                }
                System.out.print(']");
                System.out.print(" @ ");
                System.out.print(fCurrentEntity.lineNumber);
                System.out.print(',");
                System.out.print(fCurrentEntity.columnNumber);
            } else {
                System.out.print("*NO CURRENT ENTITY*");
            }
        }
    
public voidreset(com.sun.org.apache.xerces.internal.impl.PropertyManager propertyManager)

        //reset fEntityStorage
        fEntityStorage.reset(propertyManager);
        //reset XMLEntityReaderImpl
        fEntityScanner.reset(propertyManager);
        // 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);
        try {
            fStaxEntityResolver = (StaxEntityResolverWrapper)propertyManager.getProperty(STAX_ENTITY_RESOLVER);
        } catch (XMLConfigurationException e) {
            fStaxEntityResolver = null;
        }
        
        // initialize state
        //fStandalone = false;
        fEntities.clear();
        fEntityStack.removeAllElements();
        fCurrentEntity = null;
        fValidation = false;
        fExternalGeneralEntities = true;
        fExternalParameterEntities = true;
        fAllowJavaEncodings = true ;
        
        //test();
    
public voidreset(com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager componentManager)
Resets the component. The component can query the component manager about any features and properties that affect the operation of the component.

param
componentManager The component manager.
throws
SAXException Thrown by component on initialization error. For example, if a feature or property is required for the operation of the component, the component manager may throw a SAXNotRecognizedException or a SAXNotSupportedException.


        boolean parser_settings;
        try {
                parser_settings = componentManager.getFeature(PARSER_SETTINGS);
        } catch (XMLConfigurationException e) {
                parser_settings = true;
        }

        if (!parser_settings) {
            // parser settings have not been changed
            reset();
            if(fEntityScanner != null){
                fEntityScanner.reset(componentManager);
            }
            if(fEntityStorage != null){
                fEntityStorage.reset(componentManager);            
            }
            return;
        }
        
        // sax features
        try {
            fValidation = componentManager.getFeature(VALIDATION);
        } catch (XMLConfigurationException e) {
            fValidation = false;
        }
        try {
            fExternalGeneralEntities = componentManager.getFeature(EXTERNAL_GENERAL_ENTITIES);
        } catch (XMLConfigurationException e) {
            fExternalGeneralEntities = true;
        }
        try {
            fExternalParameterEntities = componentManager.getFeature(EXTERNAL_PARAMETER_ENTITIES);
        } catch (XMLConfigurationException e) {
            fExternalParameterEntities = true;
        }
        
        // xerces features
        try {
            fAllowJavaEncodings = componentManager.getFeature(ALLOW_JAVA_ENCODINGS);
        } catch (XMLConfigurationException e) {
            fAllowJavaEncodings = false;
        }
        
        try {
            fWarnDuplicateEntityDef = componentManager.getFeature(WARN_ON_DUPLICATE_ENTITYDEF);
        } catch (XMLConfigurationException e) {
            fWarnDuplicateEntityDef = false;
        }
        try {
            fStrictURI = componentManager.getFeature(STANDARD_URI_CONFORMANT);
        } catch (XMLConfigurationException e) {
            fStrictURI = false;
        }
        
        // xerces properties
        fSymbolTable = (SymbolTable)componentManager.getProperty(SYMBOL_TABLE);
        fErrorReporter = (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER);
        try {
            fEntityResolver = (XMLEntityResolver)componentManager.getProperty(ENTITY_RESOLVER);
        } catch (XMLConfigurationException e) {
            fEntityResolver = null;
        }
        
        try {
            fStaxEntityResolver = (StaxEntityResolverWrapper)componentManager.getProperty(STAX_ENTITY_RESOLVER);
        } catch (XMLConfigurationException e) {
            fStaxEntityResolver = null;
        }
        
        try {
            fValidationManager = (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER);
        }
        catch (XMLConfigurationException e) {
            fValidationManager = null;
        }
        try {
            fSecurityManager = (SecurityManager)componentManager.getProperty(SECURITY_MANAGER);
        }
        catch (XMLConfigurationException e) {
            fSecurityManager = null;
        }

        //reset general state
        reset();
        
        fEntityScanner.reset(componentManager);
        fEntityStorage.reset(componentManager);
        
    
public voidreset()

        fEntityExpansionLimit = (fSecurityManager != null)?fSecurityManager.getEntityExpansionLimit():0;
                
        // initialize state
        fStandalone = false;
        fEntities.clear();
        fEntityStack.removeAllElements();
        fEntityExpansionCount = 0;

        fCurrentEntity = null;
        // reset scanner
        if(fXML10EntityScanner != null){
            fXML10EntityScanner.reset(fSymbolTable, this, fErrorReporter);
        }
        if(fXML11EntityScanner != null) {
            fXML11EntityScanner.reset(fSymbolTable, this, fErrorReporter);
        }

        // DEBUG
        if (DEBUG_ENTITIES) {
            addInternalEntity("text", "Hello, World.");
            addInternalEntity("empty-element", "<foo/>");
            addInternalEntity("balanced-element", "<foo></foo>");
            addInternalEntity("balanced-element-with-text", "<foo>Hello, World</foo>");
            addInternalEntity("balanced-element-with-entity", "<foo>&text;</foo>");
            addInternalEntity("unbalanced-entity", "<foo>");
            addInternalEntity("recursive-entity", "<foo>&recursive-entity2;</foo>");
            addInternalEntity("recursive-entity2", "<bar>&recursive-entity3;</bar>");
            addInternalEntity("recursive-entity3", "<baz>&recursive-entity;</baz>");
            try {
                addExternalEntity("external-text", null, "external-text.ent", "test/external-text.xml");
                addExternalEntity("external-balanced-element", null, "external-balanced-element.ent", "test/external-balanced-element.xml");
                addExternalEntity("one", null, "ent/one.ent", "test/external-entity.xml");
                addExternalEntity("two", null, "ent/two.ent", "test/ent/one.xml");
            }
            catch (IOException ex) {
                // should never happen
            }
        }

        // copy declared entities
        if (fDeclaredEntities != null) {
            java.util.Enumeration keys = fDeclaredEntities.keys();
            while (keys.hasMoreElements()) {
                Object key = keys.nextElement();
                Object value = fDeclaredEntities.get(key);
                fEntities.put(key, value);
            }
        }
        fEntityHandler = null;
               
        // reset scanner
        //if(fEntityScanner!=null)
          //  fEntityScanner.reset(fSymbolTable, this,fErrorReporter);
        
    
public com.sun.org.apache.xerces.internal.xni.parser.XMLInputSourceresolveEntity(com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier resourceIdentifier)
Resolves the specified public and system identifiers. This method first attempts to resolve the entity based on the EntityResolver registered by the application. If no entity resolver is registered or if the registered entity handler is unable to resolve the entity, then default entity resolution will occur.

param
publicId The public identifier of the entity.
param
systemId The system identifier of the entity.
param
baseSystemId The base system identifier of the entity. This is the system identifier of the current entity and is used to expand the system identifier when the system identifier is a relative URI.
return
Returns an input source that wraps the resolved entity. This method will never return null.
throws
IOException Thrown on i/o error.
throws
XNIException Thrown by entity resolver to signal an error.

        if(resourceIdentifier == null ) return null;
        String publicId = resourceIdentifier.getPublicId();
        String literalSystemId = resourceIdentifier.getLiteralSystemId();
        String baseSystemId = resourceIdentifier.getBaseSystemId();
        String expandedSystemId = resourceIdentifier.getExpandedSystemId();
        String namespace = resourceIdentifier.getNamespace();
        
        // if no base systemId given, assume that it's relative
        // to the systemId of the current scanned entity
        // Sometimes the system id is not (properly) expanded.
        // We need to expand the system id if:
        // a. the expanded one was null; or
        // b. the base system id was null, but becomes non-null from the current entity.
        boolean needExpand = (expandedSystemId == null);
        // REVISIT:  why would the baseSystemId ever be null?  if we
        // didn't have to make this check we wouldn't have to reuse the
        // fXMLResourceIdentifier object...
        if (baseSystemId == null && fCurrentEntity != null && fCurrentEntity.entityLocation != null) {
            baseSystemId = fCurrentEntity.entityLocation.getExpandedSystemId();
            if (baseSystemId != null)
                needExpand = true;
        }
        if (needExpand)
            expandedSystemId = expandSystemId(literalSystemId, baseSystemId,false);
        
        // give the entity resolver a chance
        XMLInputSource xmlInputSource = null;
        
        if (fEntityResolver != null) {
            resourceIdentifier.setBaseSystemId(baseSystemId);
            resourceIdentifier.setExpandedSystemId(expandedSystemId);
            xmlInputSource = fEntityResolver.resolveEntity(resourceIdentifier);
        }
        
        // do default resolution
        // REVISIT: what's the correct behavior if the user provided an entity
        // resolver (fEntityResolver != null), but resolveEntity doesn't return
        // an input source (xmlInputSource == null)?
        // do we do default resolution, or do we just return null? -SG
        if (xmlInputSource == null) {
            // REVISIT: when systemId is null, I think we should return null.
            //          is this the right solution? -SG
            //if (systemId != null)
            xmlInputSource = new XMLInputSource(publicId, literalSystemId, baseSystemId);
        }
        
        if (DEBUG_RESOLVER) {
            System.err.println("XMLEntityManager.resolveEntity(" + publicId + ")");
            System.err.println(" = " + xmlInputSource);
        }
        
        return xmlInputSource;
        
    
public com.sun.xml.internal.stream.StaxXMLInputSourceresolveEntityAsPerStax(com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier resourceIdentifier)

        
        if(resourceIdentifier == null ) return null;
        
        String publicId = resourceIdentifier.getPublicId();
        String literalSystemId = resourceIdentifier.getLiteralSystemId();
        String baseSystemId = resourceIdentifier.getBaseSystemId();
        String expandedSystemId = resourceIdentifier.getExpandedSystemId();
        // if no base systemId given, assume that it's relative
        // to the systemId of the current scanned entity
        // Sometimes the system id is not (properly) expanded.
        // We need to expand the system id if:
        // a. the expanded one was null; or
        // b. the base system id was null, but becomes non-null from the current entity.
        boolean needExpand = (expandedSystemId == null);
        // REVISIT:  why would the baseSystemId ever be null?  if we
        // didn't have to make this check we wouldn't have to reuse the
        // fXMLResourceIdentifier object...
        if (baseSystemId == null && fCurrentEntity != null && fCurrentEntity.entityLocation != null) {
            baseSystemId = fCurrentEntity.entityLocation.getExpandedSystemId();
            if (baseSystemId != null)
                needExpand = true;
        }
        if (needExpand)
            expandedSystemId = expandSystemId(literalSystemId, baseSystemId,false);
        
        // give the entity resolver a chance
        StaxXMLInputSource staxInputSource = null;
        XMLInputSource xmlInputSource = null;

        XMLResourceIdentifierImpl ri = null;
        
        if (resourceIdentifier instanceof XMLResourceIdentifierImpl) {
            ri = (XMLResourceIdentifierImpl)resourceIdentifier;
        } else {
            fResourceIdentifier.clear();
            ri = fResourceIdentifier;
        }
        ri.setValues(publicId, literalSystemId, baseSystemId, expandedSystemId);
        if(DEBUG_RESOLVER){
            System.out.println("BEFORE Calling resolveEntity") ;
        }
        
        //either of Stax or Xerces would be null
        if(fStaxEntityResolver != null){
            staxInputSource = fStaxEntityResolver.resolveEntity(ri);
        }
        
        if(fEntityResolver != null){
            xmlInputSource = fEntityResolver.resolveEntity(ri);
        }
        
        if(xmlInputSource != null){
            //wrap this XMLInputSource to StaxInputSource
            staxInputSource = new StaxXMLInputSource(xmlInputSource);
        }
        
        // do default resolution
        //this works for both stax & Xerces, if staxInputSource is null, it means parser need to revert to default resolution
        if (staxInputSource == null) {
            // REVISIT: when systemId is null, I think we should return null.
            //          is this the right solution? -SG
            //if (systemId != null)
            staxInputSource = new StaxXMLInputSource(new XMLInputSource(publicId, literalSystemId, baseSystemId));
        }else if(staxInputSource.hasXMLStreamOrXMLEventReader()){
            //Waiting for the clarification from EG. - nb
        }
        
        if (DEBUG_RESOLVER) {
            System.err.println("XMLEntityManager.resolveEntity(" + publicId + ")");
            System.err.println(" = " + xmlInputSource);
        }
        
        return staxInputSource;
        
    
public voidsetEntityHandler(com.sun.org.apache.xerces.internal.impl.XMLEntityHandler entityHandler)
Sets the entity handler. When an entity starts and ends, the entity handler is notified of the change.

param
entityHandler The new entity handler.

        fEntityHandler = (XMLEntityHandler) entityHandler;
    
public voidsetFeature(java.lang.String featureId, boolean state)
Sets the state of a feature. This method is called by the component manager any time after reset when a feature changes state.

Note: Components should silently ignore features that do not affect the operation of the component.

param
featureId The feature identifier.
param
state The state of the feature.
throws
SAXNotRecognizedException The component should not throw this exception.
throws
SAXNotSupportedException The component should not throw this exception.

        
        // xerces features
        if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
            final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
            if (suffixLength == Constants.ALLOW_JAVA_ENCODINGS_FEATURE.length() && 
                featureId.endsWith(Constants.ALLOW_JAVA_ENCODINGS_FEATURE)) {
                fAllowJavaEncodings = state;
            }
        }
        
    
public static voidsetInstanceFollowRedirects(java.net.HttpURLConnection urlCon, boolean followRedirects)
Attempt to set whether redirects will be followed for an HttpURLConnection. This may fail on earlier JDKs which do not support setting this preference.

        try {
            Method method = HttpURLConnection.class.getMethod("setInstanceFollowRedirects", new Class[] {Boolean.TYPE});
            method.invoke(urlCon, new Object[] {followRedirects ? Boolean.TRUE : Boolean.FALSE});
        }
        // setInstanceFollowRedirects doesn't exist.
        catch (Exception exc) {}
    
public voidsetProperty(java.lang.String propertyId, java.lang.Object value)
Sets the value of a property. This method is called by the component manager any time after reset when a property changes value.

Note: Components should silently ignore properties that do not affect the operation of the component.

param
propertyId The property identifier.
param
value The value of the property.
throws
SAXNotRecognizedException The component should not throw this exception.
throws
SAXNotSupportedException The component should not throw this exception.

        // Xerces properties
        if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
            final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
        	
            if (suffixLength == Constants.SYMBOL_TABLE_PROPERTY.length() && 
                propertyId.endsWith(Constants.SYMBOL_TABLE_PROPERTY)) {
                fSymbolTable = (SymbolTable)value;
                return;
            }
            if (suffixLength == Constants.ERROR_REPORTER_PROPERTY.length() && 
                propertyId.endsWith(Constants.ERROR_REPORTER_PROPERTY)) {
                fErrorReporter = (XMLErrorReporter)value;
                return;
            }
            if (suffixLength == Constants.ENTITY_RESOLVER_PROPERTY.length() && 
                propertyId.endsWith(Constants.ENTITY_RESOLVER_PROPERTY)) {
                fEntityResolver = (XMLEntityResolver)value;
                return;
            }
            if (suffixLength == Constants.BUFFER_SIZE_PROPERTY.length() && 
                propertyId.endsWith(Constants.BUFFER_SIZE_PROPERTY)) {
                Integer bufferSize = (Integer)value;
                if (bufferSize != null &&
                    bufferSize.intValue() > DEFAULT_XMLDECL_BUFFER_SIZE) {
                    fBufferSize = bufferSize.intValue();
                    fEntityScanner.setBufferSize(fBufferSize);
                    fBufferPool.setExternalBufferSize(fBufferSize);
                }
            }
            if (suffixLength == Constants.SECURITY_MANAGER_PROPERTY.length() && 
                propertyId.endsWith(Constants.SECURITY_MANAGER_PROPERTY)) {
                fSecurityManager = (SecurityManager)value; 
                fEntityExpansionLimit = (fSecurityManager != null)?fSecurityManager.getEntityExpansionLimit():0;
            }
        }
        
    
public voidsetScannerVersion(short version)


        if(version == Constants.XML_VERSION_1_0) {
            if(fXML10EntityScanner == null) {
                fXML10EntityScanner = new XMLEntityScanner();
            }
            fXML10EntityScanner.reset(fSymbolTable, this, fErrorReporter);
            fEntityScanner = fXML10EntityScanner;
            fEntityScanner.setCurrentEntity(fCurrentEntity);
        } else {
            if(fXML11EntityScanner == null) {
                fXML11EntityScanner = new XML11EntityScanner();
            }
            fXML11EntityScanner.reset(fSymbolTable, this, fErrorReporter);
            fEntityScanner = fXML11EntityScanner;
            fEntityScanner.setCurrentEntity(fCurrentEntity);
        }
        
    
public voidsetStandalone(boolean standalone)
Sets whether the document entity is standalone.

param
standalone True if document entity is standalone.

        fStandalone = standalone;
    
public java.lang.StringsetupCurrentEntity(java.lang.String name, com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource xmlInputSource, boolean literal, boolean isExternal)
This method uses the passed-in XMLInputSource to make fCurrentEntity usable for reading.

param
name name of the entity (XML is it's the document entity)
param
xmlInputSource the input source, with sufficient information to begin scanning characters.
param
literal True if this entity is started within a literal value.
param
isExternal whether this entity should be treated as an internal or external entity.
throws
IOException if anything can't be read XNIException If any parser-specific goes wrong.
return
the encoding of the new entity or null if a character stream was employed

        // get information
        
        final String publicId = xmlInputSource.getPublicId();
        String literalSystemId = xmlInputSource.getSystemId();
        String baseSystemId = xmlInputSource.getBaseSystemId();
        String encoding = xmlInputSource.getEncoding();
        final boolean encodingExternallySpecified = (encoding != null);
        Boolean isBigEndian = null;        
        
        // create reader
        InputStream stream = null;
        Reader reader = xmlInputSource.getCharacterStream();
        
        // First chance checking strict URI
        String expandedSystemId = expandSystemId(literalSystemId, baseSystemId, fStrictURI);
        if (baseSystemId == null) {
            baseSystemId = expandedSystemId;
        }
        if (reader == null) {
            stream = xmlInputSource.getByteStream();
            if (stream == null) {
                URL location = new URL(expandedSystemId); 
                URLConnection connect = location.openConnection();
                if (!(connect instanceof HttpURLConnection)) {
                    stream = connect.getInputStream();
                }
                else {
                    boolean followRedirects = true;
                    
                    // setup URLConnection if we have an HTTPInputSource
                    if (xmlInputSource instanceof HTTPInputSource) {
                        final HttpURLConnection urlConnection = (HttpURLConnection) connect;
                        final HTTPInputSource httpInputSource = (HTTPInputSource) xmlInputSource;
                        
                        // set request properties
                        Iterator propIter = httpInputSource.getHTTPRequestProperties();
                        while (propIter.hasNext()) {
                            Map.Entry entry = (Map.Entry) propIter.next();
                            urlConnection.setRequestProperty((String) entry.getKey(), (String) entry.getValue());
                        }
                        
                        // set preference for redirection
                        followRedirects = httpInputSource.getFollowHTTPRedirects();
                        if (!followRedirects) {
                            setInstanceFollowRedirects(urlConnection, followRedirects);
                        }
                    }
                    
                    stream = connect.getInputStream();
                    
                    // REVISIT: If the URLConnection has external encoding
                    // information, we should be reading it here. It's located
                    // in the charset parameter of Content-Type. -- mrglavas
                    
                    if (followRedirects) {
                        String redirect = connect.getURL().toString();
                        // E43: Check if the URL was redirected, and then
                        // update literal and expanded system IDs if needed.
                        if (!redirect.equals(expandedSystemId)) {
                            literalSystemId = redirect;
                            expandedSystemId = redirect;
                        }
                    }
                }
            }
            
            // wrap this stream in RewindableInputStream
            stream = new RewindableInputStream(stream);
            
            // perform auto-detect of encoding if necessary
            if (encoding == null) {
                // read first four bytes and determine encoding
                final byte[] b4 = new byte[4];
                int count = 0;
                for (; count<4; count++ ) {
                    b4[count] = (byte)stream.read();
                }
                if (count == 4) {
                    Object [] encodingDesc = getEncodingName(b4, count);
                    encoding = (String)(encodingDesc[0]);
                    isBigEndian = (Boolean)(encodingDesc[1]);
                    
                    stream.reset();                    
                    // Special case UTF-8 files with BOM created by Microsoft
                    // tools. It's more efficient to consume the BOM than make
                    // the reader perform extra checks. -Ac
                    if (count > 2 && encoding.equals("UTF-8")) {
                        int b0 = b4[0] & 0xFF;
                        int b1 = b4[1] & 0xFF;
                        int b2 = b4[2] & 0xFF;
                        if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF) {
                            // ignore first three bytes...
                            stream.skip(3);
                        }
                    }
                    reader = createReader(stream, encoding, isBigEndian);
                } else {
                    reader = createReader(stream, encoding, isBigEndian);
                }
            }
            
            // use specified encoding
            else {
                encoding = encoding.toUpperCase(Locale.ENGLISH);
                
                // If encoding is UTF-8, consume BOM if one is present.
                if (encoding.equals("UTF-8")) {
                    final int[] b3 = new int[3];
                    int count = 0;
                    for (; count < 3; ++count) {
                        b3[count] = stream.read();
                        if (b3[count] == -1)
                            break;
                    }
                    if (count == 3) {
                        if (b3[0] != 0xEF || b3[1] != 0xBB || b3[2] != 0xBF) {
                            // First three bytes are not BOM, so reset.
                            stream.reset();
                        }
                    } else {
                        stream.reset();
                    }
                }
                // If encoding is UTF-16, we still need to read the first four bytes
                // in order to discover the byte order.
                else if (encoding.equals("UTF-16")) {
                    final int[] b4 = new int[4];
                    int count = 0;
                    for (; count < 4; ++count) {
                        b4[count] = stream.read();
                        if (b4[count] == -1)
                            break;
                    }
                    stream.reset();
                    
                    String utf16Encoding = "UTF-16";
                    if (count >= 2) {
                        final int b0 = b4[0];
                        final int b1 = b4[1];
                        if (b0 == 0xFE && b1 == 0xFF) {
                            // UTF-16, big-endian
                            utf16Encoding = "UTF-16BE";
                            isBigEndian = Boolean.TRUE;
                        }
                        else if (b0 == 0xFF && b1 == 0xFE) {
                            // UTF-16, little-endian
                            utf16Encoding = "UTF-16LE";
                            isBigEndian = Boolean.FALSE;
                        }
                        else if (count == 4) {
                            final int b2 = b4[2];
                            final int b3 = b4[3];
                            if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F) {
                                // UTF-16, big-endian, no BOM
                                utf16Encoding = "UTF-16BE";
                                isBigEndian = Boolean.TRUE;
                            }
                            if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00) {
                                // UTF-16, little-endian, no BOM
                                utf16Encoding = "UTF-16LE";
                                isBigEndian = Boolean.FALSE;
                            }
                        }
                    }
                    reader = createReader(stream, utf16Encoding, isBigEndian);
                }
                // If encoding is UCS-4, we still need to read the first four bytes
                // in order to discover the byte order.
                else if (encoding.equals("ISO-10646-UCS-4")) {
                    final int[] b4 = new int[4];
                    int count = 0;
                    for (; count < 4; ++count) {
                        b4[count] = stream.read();
                        if (b4[count] == -1)
                            break;
                    }
                    stream.reset();
                    
                    // Ignore unusual octet order for now.
                    if (count == 4) {
                        // UCS-4, big endian (1234)
                        if (b4[0] == 0x00 && b4[1] == 0x00 && b4[2] == 0x00 && b4[3] == 0x3C) {
                            isBigEndian = Boolean.TRUE;
                        }
                        // UCS-4, little endian (1234)
                        else if (b4[0] == 0x3C && b4[1] == 0x00 && b4[2] == 0x00 && b4[3] == 0x00) {
                            isBigEndian = Boolean.FALSE;
                        }
                    }
                }
                // If encoding is UCS-2, we still need to read the first four bytes
                // in order to discover the byte order.
                else if (encoding.equals("ISO-10646-UCS-2")) {
                    final int[] b4 = new int[4];
                    int count = 0;
                    for (; count < 4; ++count) {
                        b4[count] = stream.read();
                        if (b4[count] == -1)
                            break;
                    }
                    stream.reset();
                    
                    if (count == 4) {
                        // UCS-2, big endian
                        if (b4[0] == 0x00 && b4[1] == 0x3C && b4[2] == 0x00 && b4[3] == 0x3F) {
                            isBigEndian = Boolean.TRUE;
                        }
                        // UCS-2, little endian
                        else if (b4[0] == 0x3C && b4[1] == 0x00 && b4[2] == 0x3F && b4[3] == 0x00) {
                            isBigEndian = Boolean.FALSE;
                        }
                    }
                }
                
                reader = createReader(stream, encoding, isBigEndian);
            }
            
            // read one character at a time so we don't jump too far
            // ahead, converting characters from the byte stream in
            // the wrong encoding
            if (DEBUG_ENCODINGS) {
                System.out.println("$$$ no longer wrapping reader in OneCharReader");
            }
            //reader = new OneCharReader(reader);
        }
        
        // We've seen a new Reader.
        // Push it on the stack so we can close it later.
        //fOwnReaders.add(reader);
        
        // push entity on stack
        if (fCurrentEntity != null) {
            fEntityStack.push(fCurrentEntity);
        }
        
        // create entity
        /* if encoding is specified externally, 'encoding' information present 
         * in the prolog of the XML document is not considered. Hence, prolog can
         * be read in Chunks of data instead of byte by byte.  
         */
        fCurrentEntity = new com.sun.xml.internal.stream.Entity.ScannedEntity(name,new XMLResourceIdentifierImpl(publicId, literalSystemId, baseSystemId, expandedSystemId),stream, reader, encoding, literal, encodingExternallySpecified, isExternal);        
        fCurrentEntity.setEncodingExternallySpecified(encodingExternallySpecified);
        fEntityScanner.setCurrentEntity(fCurrentEntity);
        fResourceIdentifier.setValues(publicId, literalSystemId, baseSystemId, expandedSystemId);
        return encoding;
    
public voidstartDTDEntity(com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource xmlInputSource)
Starts the DTD entity. The DTD entity has the "[dtd]" pseudo-name.

param
xmlInputSource The input source of the DTD entity.
throws
IOException Thrown on i/o error.
throws
XNIException Thrown by entity handler to signal an error.

        startEntity(DTDEntity, xmlInputSource, false, true);
    
public voidstartDocumentEntity(com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource xmlInputSource)
Starts the document entity. The document entity has the "[xml]" pseudo-name.

param
xmlInputSource The input source of the document entity.
throws
IOException Thrown on i/o error.
throws
XNIException Thrown by entity handler to signal an error.

        startEntity(XMLEntity, xmlInputSource, false, true);
    
public voidstartEntity(java.lang.String entityName, boolean literal)
Starts a named entity.

param
entityName The name of the entity to start.
param
literal True if this entity is started within a literal value.
throws
IOException Thrown on i/o error.
throws
XNIException Thrown by entity handler to signal an error.

        
        // was entity declared?
        Entity entity = (Entity)fEntityStorage.getDeclaredEntities().get(entityName);
        if (entity == null) {
            if (fEntityHandler != null) {
                String encoding = null;
                fResourceIdentifier.clear();
                fEntityAugs.removeAllItems();
                fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE);
                fEntityHandler.startEntity(entityName, fResourceIdentifier, encoding, fEntityAugs);
                fEntityAugs.removeAllItems();
                fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE);
                fEntityHandler.endEntity(entityName, fEntityAugs);
            }
            return;
        }
        
        // should we skip external entities?
        boolean external = entity.isExternal();
        if (external) {
            boolean unparsed = entity.isUnparsed();
            boolean parameter = entityName.startsWith("%");
            boolean general = !parameter;
            if (unparsed || (general && !fExternalGeneralEntities) ||
                    (parameter && !fExternalParameterEntities)) {
                
                if (fEntityHandler != null) {
                    fResourceIdentifier.clear();
                    final String encoding = null;
                    Entity.ExternalEntity externalEntity = (Entity.ExternalEntity)entity;
                    //REVISIT:  since we're storing expandedSystemId in the
                    // externalEntity, how could this have got here if it wasn't already
                    // expanded??? - neilg
                    String extLitSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getLiteralSystemId() : null);
                    String extBaseSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getBaseSystemId() : null);
                    String expandedSystemId = expandSystemId(extLitSysId, extBaseSysId);
                    fResourceIdentifier.setValues(
                            (externalEntity.entityLocation != null ? externalEntity.entityLocation.getPublicId() : null),
                            extLitSysId, extBaseSysId, expandedSystemId);
                    fEntityAugs.removeAllItems();
                    fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE);
                    fEntityHandler.startEntity(entityName, fResourceIdentifier, encoding, fEntityAugs);
                    fEntityAugs.removeAllItems();
                    fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE);
                    fEntityHandler.endEntity(entityName, fEntityAugs);
                }
                return;
            }
        }
        
        // is entity recursive?
        int size = fEntityStack.size();
        for (int i = size; i >= 0; i--) {
            Entity activeEntity = i == size
                    ? fCurrentEntity
                    : (Entity)fEntityStack.elementAt(i);
            if (activeEntity.name == entityName) {
                String path = entityName;
                for (int j = i + 1; j < size; j++) {
                    activeEntity = (Entity)fEntityStack.elementAt(j);
                    path = path + " -> " + activeEntity.name;
                }
                path = path + " -> " + fCurrentEntity.name;
                path = path + " -> " + entityName;
                fErrorReporter.reportError(this.getEntityScanner(),XMLMessageFormatter.XML_DOMAIN,
                        "RecursiveReference",
                        new Object[] { entityName, path },
                        XMLErrorReporter.SEVERITY_FATAL_ERROR);
                        
                        if (fEntityHandler != null) {
                            fResourceIdentifier.clear();
                            final String encoding = null;
                            if (external) {
                                Entity.ExternalEntity externalEntity = (Entity.ExternalEntity)entity;
                                // REVISIT:  for the same reason above...
                                String extLitSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getLiteralSystemId() : null);
                                String extBaseSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getBaseSystemId() : null);
                                String expandedSystemId = expandSystemId(extLitSysId, extBaseSysId);
                                fResourceIdentifier.setValues(
                                        (externalEntity.entityLocation != null ? externalEntity.entityLocation.getPublicId() : null),
                                        extLitSysId, extBaseSysId, expandedSystemId);
                            }
                            fEntityAugs.removeAllItems();
                            fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE);
                            fEntityHandler.startEntity(entityName, fResourceIdentifier, encoding, fEntityAugs);
                            fEntityAugs.removeAllItems();
                            fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE);
                            fEntityHandler.endEntity(entityName, fEntityAugs);
                        }
                        
                        return;
            }
        }
        
        // resolve external entity
        StaxXMLInputSource staxInputSource = null;
        XMLInputSource xmlInputSource = null ;
        
        if (external) {
            Entity.ExternalEntity externalEntity = (Entity.ExternalEntity)entity;
            staxInputSource = resolveEntityAsPerStax(externalEntity.entityLocation);
            /** xxx:  Waiting from the EG
             * //simply return if there was entity resolver registered and application
             * //returns either XMLStreamReader or XMLEventReader.
             * if(staxInputSource.hasXMLStreamOrXMLEventReader()) return ;
             */
            xmlInputSource = staxInputSource.getXMLInputSource() ;
        }
        // wrap internal entity
        else {
            Entity.InternalEntity internalEntity = (Entity.InternalEntity)entity;
            Reader reader = new StringReader(internalEntity.text);
            xmlInputSource = new XMLInputSource(null, null, null, reader, null);
        }
        
        // start the entity
        startEntity(entityName, xmlInputSource, literal, external);
        
    
public voidstartEntity(java.lang.String name, com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource xmlInputSource, boolean literal, boolean isExternal)
Starts an entity.

This method can be used to insert an application defined XML entity stream into the parsing stream.

param
name The name of the entity.
param
xmlInputSource The input source of the entity.
param
literal True if this entity is started within a literal value.
param
isExternal whether this entity should be treated as an internal or external entity.
throws
IOException Thrown on i/o error.
throws
XNIException Thrown by entity handler to signal an error.

       
        String encoding = setupCurrentEntity(name, xmlInputSource, literal, isExternal);
        
        //when entity expansion limit is set by the Application, we need to
        //check for the entity expansion limit set by the parser, if number of entity
        //expansions exceeds the entity expansion limit, parser will throw fatal error.
        // Note that this represents the nesting level of open entities.
        fEntityExpansionCount++;
        if( fSecurityManager != null && fEntityExpansionCount > fEntityExpansionLimit ){
            fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                                             "EntityExpansionLimitExceeded",
                                             new Object[]{new Integer(fEntityExpansionLimit) },
                                             XMLErrorReporter.SEVERITY_FATAL_ERROR );
            // is there anything better to do than reset the counter?
            // at least one can envision debugging applications where this might
            // be useful...
            fEntityExpansionCount = 0;
        }

        // call handler
        if (fEntityHandler != null) {
            fEntityHandler.startEntity(name, fResourceIdentifier, encoding, null);
        }
        
    
public voidstartExternalSubset()

        fInExternalSubset = true;
    
public voidtest()

        //System.out.println("TESTING: Added familytree to entityManager");
        //Usecase1
        fEntityStorage.addExternalEntity("entityUsecase1",null,
                "/space/home/stax/sun/6thJan2004/zephyr/data/test.txt",
                "/space/home/stax/sun/6thJan2004/zephyr/data/entity.xml");

        //Usecase2
        fEntityStorage.addInternalEntity("entityUsecase2","<Test>value</Test>");
        fEntityStorage.addInternalEntity("entityUsecase3","value3");
        fEntityStorage.addInternalEntity("text", "Hello World.");
        fEntityStorage.addInternalEntity("empty-element", "<foo/>");
        fEntityStorage.addInternalEntity("balanced-element", "<foo></foo>");
        fEntityStorage.addInternalEntity("balanced-element-with-text", "<foo>Hello, World</foo>");
        fEntityStorage.addInternalEntity("balanced-element-with-entity", "<foo>&text;</foo>");
        fEntityStorage.addInternalEntity("unbalanced-entity", "<foo>");
        fEntityStorage.addInternalEntity("recursive-entity", "<foo>&recursive-entity2;</foo>");
        fEntityStorage.addInternalEntity("recursive-entity2", "<bar>&recursive-entity3;</bar>");
        fEntityStorage.addInternalEntity("recursive-entity3", "<baz>&recursive-entity;</baz>");
        fEntityStorage.addInternalEntity("ch","©");
        fEntityStorage.addInternalEntity("ch1","T");
        fEntityStorage.addInternalEntity("% ch2","param");