Source Code Cross Referenced for XMLEntityManager.java in  » 6.0-JDK-Modules » sjsxp » com » sun » xml » stream » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » sjsxp » com.sun.xml.stream 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $Id: XMLEntityManager.java,v 1.6 2007/03/16 14:48:45 spericas Exp $
0003:         */
0004:
0005:        /*
0006:         * The contents of this file are subject to the terms
0007:         * of the Common Development and Distribution License
0008:         * (the License).  You may not use this file except in
0009:         * compliance with the License.
0010:         * 
0011:         * You can obtain a copy of the license at
0012:         * https://glassfish.dev.java.net/public/CDDLv1.0.html.
0013:         * See the License for the specific language governing
0014:         * permissions and limitations under the License.
0015:         * 
0016:         * When distributing Covered Code, include this CDDL
0017:         * Header Notice in each file and include the License file
0018:         * at https://glassfish.dev.java.net/public/CDDLv1.0.html.
0019:         * If applicable, add the following below the CDDL Header,
0020:         * with the fields enclosed by brackets [] replaced by
0021:         * you own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         * 
0024:         * [Name of File] [ver.__] [Date]
0025:         * 
0026:         * Copyright 2006 Sun Microsystems Inc. All Rights Reserved
0027:         */
0028:
0029:        /*
0030:         * The Apache Software License, Version 1.1
0031:         *
0032:         *
0033:         * Copyright (c) 1999-2002 The Apache Software Foundation.
0034:         * All rights reserved.
0035:         *
0036:         * Redistribution and use in source and binary forms, with or without
0037:         * modification, are permitted provided that the following conditions
0038:         * are met:
0039:         *
0040:         * 1. Redistributions of source code must retain the above copyright
0041:         *    notice, this list of conditions and the following disclaimer.
0042:         *
0043:         * 2. Redistributions in binary form must reproduce the above copyright
0044:         *    notice, this list of conditions and the following disclaimer in
0045:         *    the documentation and/or other materials provided with the
0046:         *    distribution.
0047:         *
0048:         * 3. The end-user documentation included with the redistribution,
0049:         *    if any, must include the following acknowledgment:
0050:         *       "This product includes software developed by the
0051:         *        Apache Software Foundation (http://www.apache.org/)."
0052:         *    Alternately, this acknowledgment may appear in the software itself,
0053:         *    if and wherever such third-party acknowledgments normally appear.
0054:         *
0055:         * 4. The names "Xerces" and "Apache Software Foundation" must
0056:         *    not be used to endorse or promote products derived from this
0057:         *    software without prior written permission. For written
0058:         *    permission, please contact apache@apache.org.
0059:         *
0060:         * 5. Products derived from this software may not be called "Apache",
0061:         *    nor may "Apache" appear in their name, without prior written
0062:         *    permission of the Apache Software Foundation.
0063:         *
0064:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0065:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0066:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0067:         * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0068:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0069:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0070:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0071:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0072:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0073:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0074:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0075:         * SUCH DAMAGE.
0076:         */
0077:
0078:        package com.sun.xml.stream;
0079:
0080:        import java.io.*;
0081:        import java.io.BufferedReader;
0082:        import java.net.URL;
0083:        import java.util.*;
0084:
0085:        import com.sun.xml.stream.xerces.impl.io.*;
0086:        import com.sun.xml.stream.xerces.impl.msg.XMLMessageFormatter;
0087:        import com.sun.xml.stream.xerces.util.*;
0088:        import com.sun.xml.stream.xerces.xni.XMLResourceIdentifier;
0089:        import com.sun.xml.stream.xerces.xni.XNIException;
0090:        import com.sun.xml.stream.xerces.xni.parser.*;
0091:
0092:        /**
0093:         * Will keep track of current entity.
0094:         *
0095:         * The entity manager handles the registration of general and parameter
0096:         * entities; resolves entities; and starts entities. The entity manager
0097:         * is a central component in a standard parser configuration and this
0098:         * class works directly with the entity scanner to manage the underlying
0099:         * xni.
0100:         * <p>
0101:         * This component requires the following features and properties from the
0102:         * component manager that uses it:
0103:         * <ul>
0104:         *  <li>http://xml.org/sax/features/validation</li>
0105:         *  <li>http://xml.org/sax/features/external-general-entities</li>
0106:         *  <li>http://xml.org/sax/features/external-parameter-entities</li>
0107:         *  <li>http://apache.org/xml/features/allow-java-encodings</li>
0108:         *  <li>http://apache.org/xml/properties/internal/symbol-table</li>
0109:         *  <li>http://apache.org/xml/properties/internal/error-reporter</li>
0110:         *  <li>http://apache.org/xml/properties/internal/entity-resolver</li>
0111:         * </ul>
0112:         *
0113:         *
0114:         * @author Andy Clark, IBM
0115:         * @author Arnaud  Le Hors, IBM
0116:         * @author K.Venugopal SUN Microsystems
0117:         * @author Neeraj Bajaj SUN Microsystems
0118:         *
0119:         * @version $Id: XMLEntityManager.java,v 1.6 2007/03/16 14:48:45 spericas Exp $
0120:         */
0121:        public class XMLEntityManager implements  XMLComponent,
0122:                XMLEntityResolver {
0123:
0124:            //
0125:            // Constants
0126:            //
0127:
0128:            /** Default buffer size (2048). */
0129:            public static final int DEFAULT_BUFFER_SIZE = 8192;
0130:
0131:            /** Default buffer size before we've finished with the XMLDecl:  */
0132:            public static final int DEFAULT_XMLDECL_BUFFER_SIZE = 64;
0133:
0134:            /** Default internal entity buffer size (1024). */
0135:            public static final int DEFAULT_INTERNAL_BUFFER_SIZE = 1024;
0136:
0137:            // feature identifiers
0138:
0139:            /** Feature identifier: validation. */
0140:            protected static final String VALIDATION = Constants.SAX_FEATURE_PREFIX
0141:                    + Constants.VALIDATION_FEATURE;
0142:
0143:            /** Feature identifier: external general entities. */
0144:            protected static final String EXTERNAL_GENERAL_ENTITIES = Constants.SAX_FEATURE_PREFIX
0145:                    + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE;
0146:
0147:            /** Feature identifier: external parameter entities. */
0148:            protected static final String EXTERNAL_PARAMETER_ENTITIES = Constants.SAX_FEATURE_PREFIX
0149:                    + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE;
0150:
0151:            /** Feature identifier: allow Java encodings. */
0152:            protected static final String ALLOW_JAVA_ENCODINGS = Constants.XERCES_FEATURE_PREFIX
0153:                    + Constants.ALLOW_JAVA_ENCODINGS_FEATURE;
0154:
0155:            /** Feature identifier: warn on duplicate EntityDef */
0156:            protected static final String WARN_ON_DUPLICATE_ENTITYDEF = Constants.XERCES_FEATURE_PREFIX
0157:                    + Constants.WARN_ON_DUPLICATE_ENTITYDEF_FEATURE;
0158:
0159:            // property identifiers
0160:
0161:            /** Property identifier: symbol table. */
0162:            protected static final String SYMBOL_TABLE = Constants.XERCES_PROPERTY_PREFIX
0163:                    + Constants.SYMBOL_TABLE_PROPERTY;
0164:
0165:            /** Property identifier: error reporter. */
0166:            protected static final String ERROR_REPORTER = Constants.XERCES_PROPERTY_PREFIX
0167:                    + Constants.ERROR_REPORTER_PROPERTY;
0168:
0169:            /** Property identifier: entity resolver. */
0170:            protected static final String ENTITY_RESOLVER = Constants.XERCES_PROPERTY_PREFIX
0171:                    + Constants.ENTITY_RESOLVER_PROPERTY;
0172:
0173:            protected static final String STAX_ENTITY_RESOLVER = Constants.XERCES_PROPERTY_PREFIX
0174:                    + Constants.STAX_ENTITY_RESOLVER_PROPERTY;
0175:
0176:            // property identifier:  ValidationManager
0177:            protected static final String VALIDATION_MANAGER = Constants.XERCES_PROPERTY_PREFIX
0178:                    + Constants.VALIDATION_MANAGER_PROPERTY;
0179:
0180:            /** property identifier: buffer size. */
0181:            protected static final String BUFFER_SIZE = Constants.XERCES_PROPERTY_PREFIX
0182:                    + Constants.BUFFER_SIZE_PROPERTY;
0183:
0184:            // recognized features and properties
0185:
0186:            /** Recognized features. */
0187:            private static final String[] RECOGNIZED_FEATURES = { VALIDATION,
0188:                    EXTERNAL_GENERAL_ENTITIES, EXTERNAL_PARAMETER_ENTITIES,
0189:                    ALLOW_JAVA_ENCODINGS, WARN_ON_DUPLICATE_ENTITYDEF };
0190:
0191:            /** Feature defaults. */
0192:            private static final Boolean[] FEATURE_DEFAULTS = { null,
0193:                    Boolean.TRUE, Boolean.TRUE, Boolean.FALSE, Boolean.FALSE, };
0194:
0195:            /** Recognized properties. */
0196:            private static final String[] RECOGNIZED_PROPERTIES = {
0197:                    SYMBOL_TABLE, ERROR_REPORTER, ENTITY_RESOLVER,
0198:                    VALIDATION_MANAGER, BUFFER_SIZE };
0199:
0200:            /** Property defaults. */
0201:            private static final Object[] PROPERTY_DEFAULTS = { null, null,
0202:                    null, null, new Integer(DEFAULT_BUFFER_SIZE), };
0203:
0204:            private static final String XMLEntity = "[xml]".intern();
0205:            private static final String DTDEntity = "[dtd]".intern();
0206:
0207:            // debugging
0208:
0209:            /**
0210:             * Debug printing of buffer. This debugging flag works best when you
0211:             * resize the DEFAULT_BUFFER_SIZE down to something reasonable like
0212:             * 64 characters.
0213:             */
0214:            private static final boolean DEBUG_BUFFER = false;
0215:
0216:            /** Debug some basic entities. */
0217:            private static final boolean DEBUG_ENTITIES = false;
0218:
0219:            /** Debug switching readers for encodings. */
0220:            private static final boolean DEBUG_ENCODINGS = false;
0221:
0222:            // should be diplayed trace resolving messages
0223:            private static final boolean DEBUG_RESOLVER = false;
0224:
0225:            //
0226:            // Data
0227:            //
0228:
0229:            // features
0230:
0231:            /**
0232:             * Validation. This feature identifier is:
0233:             * http://xml.org/sax/features/validation
0234:             */
0235:            protected boolean fValidation;
0236:
0237:            /**
0238:             * External general entities. This feature identifier is:
0239:             * http://xml.org/sax/features/external-general-entities
0240:             */
0241:            protected boolean fExternalGeneralEntities;
0242:
0243:            /**
0244:             * External parameter entities. This feature identifier is:
0245:             * http://xml.org/sax/features/external-parameter-entities
0246:             */
0247:            protected boolean fExternalParameterEntities;
0248:
0249:            /**
0250:             * Allow Java encoding names. This feature identifier is:
0251:             * http://apache.org/xml/features/allow-java-encodings
0252:             */
0253:            protected boolean fAllowJavaEncodings = true;
0254:
0255:            // properties
0256:
0257:            /**
0258:             * Symbol table. This property identifier is:
0259:             * http://apache.org/xml/properties/internal/symbol-table
0260:             */
0261:            protected SymbolTable fSymbolTable;
0262:
0263:            /**
0264:             * Error reporter. This property identifier is:
0265:             * http://apache.org/xml/properties/internal/error-reporter
0266:             */
0267:            protected XMLErrorReporter fErrorReporter;
0268:
0269:            /**
0270:             * Entity resolver. This property identifier is:
0271:             * http://apache.org/xml/properties/internal/entity-resolver
0272:             */
0273:            protected XMLEntityResolver fEntityResolver;
0274:            protected StaxEntityResolverWrapper fStaxEntityResolver;
0275:            protected PropertyManager fPropertyManager;
0276:
0277:            // settings
0278:
0279:            /**
0280:             * Buffer size. We get this value from a property. The default size
0281:             * is used if the input buffer size property is not specified.
0282:             * REVISIT: do we need a property for internal entity buffer size?
0283:             */
0284:            protected int fBufferSize = DEFAULT_BUFFER_SIZE;
0285:
0286:            /**
0287:             * True if the document entity is standalone. This should really
0288:             * only be set by the document source (e.g. XMLDocumentScanner).
0289:             */
0290:            protected boolean fStandalone;
0291:
0292:            // are the entities being parsed in the external subset?
0293:            // NOTE:  this *is not* the same as whether they're external entities!
0294:            protected boolean fInExternalSubset = false;
0295:
0296:            // handlers
0297:
0298:            /** Entity handler. */
0299:            protected XMLEntityHandler fEntityHandler;
0300:
0301:            protected XMLEntityReaderImpl fEntityReader;
0302:
0303:            // entities
0304:
0305:            /** Entities. */
0306:            protected Hashtable fEntities = new Hashtable();
0307:
0308:            /** Entity stack. */
0309:            protected Stack fEntityStack = new Stack();
0310:
0311:            /** Current entity. */
0312:            protected Entity.ScannedEntity fCurrentEntity = null;
0313:
0314:            // shared context
0315:
0316:            /** Shared declared entities.
0317:             * XXX understand it more deeply, why are we doing this ?? Is it really required ?
0318:             */
0319:            protected Hashtable fDeclaredEntities;
0320:
0321:            protected XMLEntityStorage fEntityStorage;
0322:
0323:            protected final Object[] defaultEncoding = new Object[] { "UTF-8",
0324:                    null };
0325:
0326:            // temp vars
0327:
0328:            /** Resource identifer. */
0329:            private final XMLResourceIdentifierImpl fResourceIdentifier = new XMLResourceIdentifierImpl();
0330:
0331:            //
0332:            // Constructors
0333:            //
0334:
0335:            /**
0336:             * If this constructor is used to create the object, reset() should be invoked on this object
0337:             */
0338:            public XMLEntityManager() {
0339:                //pass a reference to current entity being scanned
0340:                //fEntityStorage = new XMLEntityStorage(fCurrentEntity) ;
0341:                fEntityStorage = new XMLEntityStorage(this );
0342:                fEntityReader = new XMLEntityReaderImpl(this );
0343:            } // <init>()
0344:
0345:            /** Default constructor. */
0346:            public XMLEntityManager(PropertyManager propertyManager) {
0347:                fPropertyManager = propertyManager;
0348:                //pass a reference to current entity being scanned
0349:                //fEntityStorage = new XMLEntityStorage(fCurrentEntity) ;
0350:                fEntityStorage = new XMLEntityStorage(this );
0351:                fEntityReader = new XMLEntityReaderImpl(propertyManager, this );
0352:                reset(propertyManager);
0353:            } // <init>()
0354:
0355:            /** get the entity storage object from entity manager */
0356:            public XMLEntityStorage getEntityStore() {
0357:                return fEntityStorage;
0358:            }
0359:
0360:            /** return the entity responsible for reading the entity */
0361:            public XMLEntityReader getEntityReader() {
0362:                return fEntityReader;
0363:            }
0364:
0365:            //
0366:            // Public methods
0367:            //
0368:
0369:            /**
0370:             * Sets whether the document entity is standalone.
0371:             *
0372:             * @param standalone True if document entity is standalone.
0373:             */
0374:            public void setStandalone(boolean standalone) {
0375:                fStandalone = standalone;
0376:            }
0377:
0378:            // setStandalone(boolean)
0379:
0380:            /** Returns true if the document entity is standalone. */
0381:            public boolean isStandalone() {
0382:                return fStandalone;
0383:            } //isStandalone():boolean
0384:
0385:            /**
0386:             * Sets the entity handler. When an entity starts and ends, the
0387:             * entity handler is notified of the change.
0388:             *
0389:             * @param entityHandler The new entity handler.
0390:             */
0391:            public void setEntityHandler(XMLEntityHandler entityHandler) {
0392:                fEntityHandler = entityHandler;
0393:            } // setEntityHandler(XMLEntityHandler)
0394:
0395:            //this function returns StaxXMLInputSource
0396:            public StaxXMLInputSource resolveEntityAsPerStax(
0397:                    XMLResourceIdentifier resourceIdentifier)
0398:                    throws java.io.IOException {
0399:
0400:                if (resourceIdentifier == null)
0401:                    return null;
0402:
0403:                String publicId = resourceIdentifier.getPublicId();
0404:                String literalSystemId = resourceIdentifier
0405:                        .getLiteralSystemId();
0406:                String baseSystemId = resourceIdentifier.getBaseSystemId();
0407:                String expandedSystemId = resourceIdentifier
0408:                        .getExpandedSystemId();
0409:                // if no base systemId given, assume that it's relative
0410:                // to the systemId of the current scanned entity
0411:                // Sometimes the system id is not (properly) expanded.
0412:                // We need to expand the system id if:
0413:                // a. the expanded one was null; or
0414:                // b. the base system id was null, but becomes non-null from the current entity.
0415:                boolean needExpand = (expandedSystemId == null);
0416:                // REVISIT:  why would the baseSystemId ever be null?  if we
0417:                // didn't have to make this check we wouldn't have to reuse the
0418:                // fXMLResourceIdentifier object...
0419:                if (baseSystemId == null && fCurrentEntity != null
0420:                        && fCurrentEntity.entityLocation != null) {
0421:                    baseSystemId = fCurrentEntity.entityLocation
0422:                            .getExpandedSystemId();
0423:                    if (baseSystemId != null)
0424:                        needExpand = true;
0425:                }
0426:                if (needExpand)
0427:                    expandedSystemId = expandSystemId(literalSystemId,
0428:                            baseSystemId);
0429:
0430:                // give the entity resolver a chance
0431:                StaxXMLInputSource xmlInputSource = null;
0432:                if (fStaxEntityResolver != null) {
0433:                    if (DEBUG_RESOLVER) {
0434:                        System.out.println("fStaxEntityResolver != null");
0435:                    }
0436:                    XMLResourceIdentifierImpl ri = null;
0437:                    if (resourceIdentifier instanceof  XMLResourceIdentifierImpl) {
0438:                        ri = (XMLResourceIdentifierImpl) resourceIdentifier;
0439:                    } else {
0440:                        fResourceIdentifier.clear();
0441:                        ri = fResourceIdentifier;
0442:                    }
0443:                    ri.setValues(publicId, literalSystemId, baseSystemId,
0444:                            expandedSystemId);
0445:                    if (DEBUG_RESOLVER) {
0446:                        System.out.println("BEFORE Calling resolveEntity");
0447:                    }
0448:                    xmlInputSource = fStaxEntityResolver.resolveEntity(ri);
0449:                }
0450:
0451:                // do default resolution
0452:                if (xmlInputSource == null) {
0453:                    // REVISIT: when systemId is null, I think we should return null.
0454:                    //          is this the right solution? -SG
0455:                    //if (systemId != null)
0456:                    xmlInputSource = new StaxXMLInputSource(new XMLInputSource(
0457:                            publicId, literalSystemId, baseSystemId));
0458:                } else if (xmlInputSource.hasXMLStreamOrXMLEventReader()) {
0459:                    //Waiting for the clarification from EG. - nb
0460:                }
0461:
0462:                if (DEBUG_RESOLVER) {
0463:                    System.err.println("XMLEntityManager.resolveEntity("
0464:                            + publicId + ")");
0465:                    System.err.println(" = " + xmlInputSource);
0466:                }
0467:
0468:                return xmlInputSource;
0469:
0470:            }
0471:
0472:            /**
0473:             * Resolves the specified public and system identifiers. This
0474:             * method first attempts to resolve the entity based on the
0475:             * EntityResolver registered by the application. If no entity
0476:             * resolver is registered or if the registered entity handler
0477:             * is unable to resolve the entity, then default entity
0478:             * resolution will occur.
0479:             *
0480:             * @param publicId     The public identifier of the entity.
0481:             * @param systemId     The system identifier of the entity.
0482:             * @param baseSystemId The base system identifier of the entity.
0483:             *                     This is the system identifier of the current
0484:             *                     entity and is used to expand the system
0485:             *                     identifier when the system identifier is a
0486:             *                     relative URI.
0487:             *
0488:             * @return Returns an input source that wraps the resolved entity.
0489:             *         This method will never return null.
0490:             *
0491:             * @throws IOException  Thrown on i/o error.
0492:             * @throws XNIException Thrown by entity resolver to signal an error.
0493:             */
0494:            public XMLInputSource resolveEntity(
0495:                    XMLResourceIdentifier resourceIdentifier)
0496:                    throws IOException, XNIException {
0497:                if (resourceIdentifier == null)
0498:                    return null;
0499:                String publicId = resourceIdentifier.getPublicId();
0500:                String literalSystemId = resourceIdentifier
0501:                        .getLiteralSystemId();
0502:                String baseSystemId = resourceIdentifier.getBaseSystemId();
0503:                String expandedSystemId = resourceIdentifier
0504:                        .getExpandedSystemId();
0505:                // if no base systemId given, assume that it's relative
0506:                // to the systemId of the current scanned entity
0507:                // Sometimes the system id is not (properly) expanded.
0508:                // We need to expand the system id if:
0509:                // a. the expanded one was null; or
0510:                // b. the base system id was null, but becomes non-null from the current entity.
0511:                boolean needExpand = (expandedSystemId == null);
0512:                // REVISIT:  why would the baseSystemId ever be null?  if we
0513:                // didn't have to make this check we wouldn't have to reuse the
0514:                // fXMLResourceIdentifier object...
0515:                if (baseSystemId == null && fCurrentEntity != null
0516:                        && fCurrentEntity.entityLocation != null) {
0517:                    baseSystemId = fCurrentEntity.entityLocation
0518:                            .getExpandedSystemId();
0519:                    if (baseSystemId != null)
0520:                        needExpand = true;
0521:                }
0522:                if (needExpand)
0523:                    expandedSystemId = expandSystemId(literalSystemId,
0524:                            baseSystemId);
0525:
0526:                // give the entity resolver a chance
0527:                XMLInputSource xmlInputSource = null;
0528:                if (fEntityResolver != null) {
0529:                    XMLResourceIdentifierImpl ri = null;
0530:                    if (resourceIdentifier instanceof  XMLResourceIdentifierImpl) {
0531:                        ri = (XMLResourceIdentifierImpl) resourceIdentifier;
0532:                    } else {
0533:                        fResourceIdentifier.clear();
0534:                        ri = fResourceIdentifier;
0535:                    }
0536:                    ri.setValues(publicId, literalSystemId, baseSystemId,
0537:                            expandedSystemId);
0538:                    xmlInputSource = fEntityResolver.resolveEntity(ri);
0539:                }
0540:
0541:                // do default resolution
0542:                // REVISIT: what's the correct behavior if the user provided an entity
0543:                // resolver (fEntityResolver != null), but resolveEntity doesn't return
0544:                // an input source (xmlInputSource == null)?
0545:                // do we do default resolution, or do we just return null? -SG
0546:                if (xmlInputSource == null) {
0547:                    // REVISIT: when systemId is null, I think we should return null.
0548:                    //          is this the right solution? -SG
0549:                    //if (systemId != null)
0550:                    xmlInputSource = new XMLInputSource(publicId,
0551:                            literalSystemId, baseSystemId);
0552:                }
0553:
0554:                if (DEBUG_RESOLVER) {
0555:                    System.err.println("XMLEntityManager.resolveEntity("
0556:                            + publicId + ")");
0557:                    System.err.println(" = " + xmlInputSource);
0558:                }
0559:
0560:                return xmlInputSource;
0561:
0562:            } // resolveEntity(XMLResourceIdentifier):XMLInputSource
0563:
0564:            /**
0565:             * Starts a named entity.
0566:             *
0567:             * @param entityName The name of the entity to start.
0568:             * @param literal    True if this entity is started within a literal
0569:             *                   value.
0570:             *
0571:             * @throws IOException  Thrown on i/o error.
0572:             * @throws XNIException Thrown by entity handler to signal an error.
0573:             */
0574:            public void startEntity(String entityName, boolean literal)
0575:                    throws IOException, XNIException {
0576:
0577:                // was entity declared?
0578:                Entity entity = (Entity) fEntityStorage.getDeclaredEntities()
0579:                        .get(entityName);
0580:                if (entity == null) {
0581:                    if (fEntityHandler != null) {
0582:                        String encoding = null;
0583:                        fResourceIdentifier.clear();
0584:                        fEntityHandler.startEntity(entityName,
0585:                                fResourceIdentifier, encoding);
0586:                        fEntityHandler.endEntity(entityName);
0587:                    }
0588:                    return;
0589:                }
0590:
0591:                // should we skip external entities?
0592:                boolean external = entity.isExternal();
0593:                if (external) {
0594:                    boolean unparsed = entity.isUnparsed();
0595:                    boolean parameter = entityName.startsWith("%");
0596:                    boolean general = !parameter;
0597:                    if (unparsed || (general && !fExternalGeneralEntities)
0598:                            || (parameter && !fExternalParameterEntities)) {
0599:
0600:                        if (fEntityHandler != null) {
0601:                            fResourceIdentifier.clear();
0602:                            final String encoding = null;
0603:                            Entity.ExternalEntity externalEntity = (Entity.ExternalEntity) entity;
0604:                            //REVISIT:  since we're storing expandedSystemId in the
0605:                            // externalEntity, how could this have got here if it wasn't already
0606:                            // expanded??? - neilg
0607:                            String extLitSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation
0608:                                    .getLiteralSystemId()
0609:                                    : null);
0610:                            String extBaseSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation
0611:                                    .getBaseSystemId()
0612:                                    : null);
0613:                            String expandedSystemId = expandSystemId(
0614:                                    extLitSysId, extBaseSysId);
0615:                            fResourceIdentifier
0616:                                    .setValues(
0617:                                            (externalEntity.entityLocation != null ? externalEntity.entityLocation
0618:                                                    .getPublicId()
0619:                                                    : null), extLitSysId,
0620:                                            extBaseSysId, expandedSystemId);
0621:                            fEntityHandler.startEntity(entityName,
0622:                                    fResourceIdentifier, encoding);
0623:                            fEntityHandler.endEntity(entityName);
0624:                        }
0625:                        return;
0626:                    }
0627:                }
0628:
0629:                // is entity recursive?
0630:                int size = fEntityStack.size();
0631:                for (int i = size; i >= 0; i--) {
0632:                    Entity activeEntity = i == size ? fCurrentEntity
0633:                            : (Entity) fEntityStack.elementAt(i);
0634:                    if (activeEntity.name == entityName) {
0635:                        String path = entityName;
0636:                        for (int j = i + 1; j < size; j++) {
0637:                            activeEntity = (Entity) fEntityStack.elementAt(j);
0638:                            path = path + " -> " + activeEntity.name;
0639:                        }
0640:                        path = path + " -> " + fCurrentEntity.name;
0641:                        path = path + " -> " + entityName;
0642:                        fErrorReporter.reportError(this .getEntityReader(),
0643:                                XMLMessageFormatter.XML_DOMAIN,
0644:                                "RecursiveReference", new Object[] {
0645:                                        entityName, path },
0646:                                XMLErrorReporter.SEVERITY_FATAL_ERROR);
0647:
0648:                        if (fEntityHandler != null) {
0649:                            fResourceIdentifier.clear();
0650:                            final String encoding = null;
0651:                            if (external) {
0652:                                Entity.ExternalEntity externalEntity = (Entity.ExternalEntity) entity;
0653:                                // REVISIT:  for the same reason above...
0654:                                String extLitSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation
0655:                                        .getLiteralSystemId()
0656:                                        : null);
0657:                                String extBaseSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation
0658:                                        .getBaseSystemId()
0659:                                        : null);
0660:                                String expandedSystemId = expandSystemId(
0661:                                        extLitSysId, extBaseSysId);
0662:                                fResourceIdentifier
0663:                                        .setValues(
0664:                                                (externalEntity.entityLocation != null ? externalEntity.entityLocation
0665:                                                        .getPublicId()
0666:                                                        : null), extLitSysId,
0667:                                                extBaseSysId, expandedSystemId);
0668:                            }
0669:                            fEntityHandler.startEntity(entityName,
0670:                                    fResourceIdentifier, encoding);
0671:                            //xxx
0672:                            fEntityHandler.endEntity(entityName);
0673:                        }
0674:
0675:                        return;
0676:                    }
0677:                }
0678:
0679:                // resolve external entity
0680:                StaxXMLInputSource staxInputSource = null;
0681:                XMLInputSource xmlInputSource = null;
0682:
0683:                if (external) {
0684:                    Entity.ExternalEntity externalEntity = (Entity.ExternalEntity) entity;
0685:                    staxInputSource = resolveEntityAsPerStax(externalEntity.entityLocation);
0686:                    /** xxx:  Waiting from the EG
0687:                     * //simply return if there was entity resolver registered and application
0688:                     * //returns either XMLStreamReader or XMLEventReader.
0689:                     * if(staxInputSource.hasXMLStreamOrXMLEventReader()) return ;
0690:                     */
0691:                    xmlInputSource = staxInputSource.getXMLInputSource();
0692:                }
0693:                // wrap internal entity
0694:                else {
0695:                    Entity.InternalEntity internalEntity = (Entity.InternalEntity) entity;
0696:                    Reader reader = new StringReader(internalEntity.text);
0697:                    xmlInputSource = new XMLInputSource(null, null, null,
0698:                            reader, null);
0699:                }
0700:
0701:                // start the entity
0702:                startEntity(entityName, xmlInputSource, literal, external);
0703:
0704:            } // startEntity(String,boolean)
0705:
0706:            /**
0707:             * Starts the document entity. The document entity has the "[xml]"
0708:             * pseudo-name.
0709:             *
0710:             * @param xmlInputSource The input source of the document entity.
0711:             *
0712:             * @throws IOException  Thrown on i/o error.
0713:             * @throws XNIException Thrown by entity handler to signal an error.
0714:             */
0715:            public void startDocumentEntity(XMLInputSource xmlInputSource)
0716:                    throws IOException, XNIException {
0717:                startEntity(XMLEntity, xmlInputSource, false, true);
0718:            } // startDocumentEntity(XMLInputSource)
0719:
0720:            //xxx these methods are not required.
0721:            /**
0722:             * Starts the DTD entity. The DTD entity has the "[dtd]"
0723:             * pseudo-name.
0724:             *
0725:             * @param xmlInputSource The input source of the DTD entity.
0726:             *
0727:             * @throws IOException  Thrown on i/o error.
0728:             * @throws XNIException Thrown by entity handler to signal an error.
0729:             */
0730:            public void startDTDEntity(XMLInputSource xmlInputSource)
0731:                    throws IOException, XNIException {
0732:                startEntity(DTDEntity, xmlInputSource, false, true);
0733:            } // startDTDEntity(XMLInputSource)
0734:
0735:            // indicate start of external subset so that
0736:            // location of entity decls can be tracked
0737:            public void startExternalSubset() {
0738:                fInExternalSubset = true;
0739:            }
0740:
0741:            public void endExternalSubset() {
0742:                fInExternalSubset = false;
0743:            }
0744:
0745:            /**
0746:             * Starts an entity.
0747:             * <p>
0748:             * This method can be used to insert an application defined XML
0749:             * entity stream into the parsing stream.
0750:             *
0751:             * @param name           The name of the entity.
0752:             * @param xmlInputSource The input source of the entity.
0753:             * @param literal        True if this entity is started within a
0754:             *                       literal value.
0755:             * @param isExternal    whether this entity should be treated as an internal or external entity.
0756:             *
0757:             * @throws IOException  Thrown on i/o error.
0758:             * @throws XNIException Thrown by entity handler to signal an error.
0759:             */
0760:            public void startEntity(String name, XMLInputSource xmlInputSource,
0761:                    boolean literal, boolean isExternal) throws IOException,
0762:                    XNIException {
0763:
0764:                final String publicId = xmlInputSource.getPublicId();
0765:                final String literalSystemId = xmlInputSource.getSystemId();
0766:                String baseSystemId = xmlInputSource.getBaseSystemId();
0767:                String encoding = xmlInputSource.getEncoding();
0768:                Boolean isBigEndian = null;
0769:
0770:                // create reader
0771:                InputStream stream = null;
0772:                Reader reader = xmlInputSource.getCharacterStream();
0773:                String expandedSystemId = expandSystemId(literalSystemId,
0774:                        baseSystemId);
0775:                if (baseSystemId == null) {
0776:                    baseSystemId = expandedSystemId;
0777:                }
0778:                if (reader == null) {
0779:                    stream = xmlInputSource.getByteStream();
0780:                    if (stream == null) {
0781:                        //create the buffered inputstream.
0782:                        stream = new BufferedInputStream(new URL(
0783:                                expandedSystemId).openStream());
0784:                    }
0785:                    // wrap this stream in RewindableInputStream
0786:                    stream = new RewindableInputStream(stream);
0787:
0788:                    // perform auto-detect of encoding if necessary
0789:                    if (encoding == null) {
0790:                        // read first four bytes and determine encoding
0791:                        final byte[] b4 = new byte[4];
0792:                        int count = 0;
0793:                        for (; count < 4; count++) {
0794:                            b4[count] = (byte) stream.read();
0795:                        }
0796:                        if (count == 4) {
0797:                            Object[] encodingDesc = getEncodingName(b4, count);
0798:                            encoding = (String) (encodingDesc[0]);
0799:                            isBigEndian = (Boolean) (encodingDesc[1]);
0800:                            stream.reset();
0801:                            int offset = 0;
0802:                            // Special case UTF-8 files with BOM created by Microsoft
0803:                            // tools. It's more efficient to consume the BOM than make
0804:                            // the reader perform extra checks. -Ac
0805:                            if (count > 2 && encoding.equals("UTF-8")) {
0806:                                int b0 = b4[0] & 0xFF;
0807:                                int b1 = b4[1] & 0xFF;
0808:                                int b2 = b4[2] & 0xFF;
0809:                                //consume the byte order mark
0810:                                if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF) {
0811:                                    // ignore first three bytes...
0812:                                    stream.skip(3);
0813:                                }
0814:                            }
0815:                            reader = createReader(stream, encoding, isBigEndian);
0816:                        } else {
0817:                            reader = createReader(stream, encoding, isBigEndian);
0818:                        }
0819:                    }
0820:
0821:                    // use specified encoding
0822:                    else {
0823:                        reader = createReader(stream, encoding, isBigEndian);
0824:                    }
0825:
0826:                    // read one character at a time so we don't jump too far
0827:                    // ahead, converting characters from the byte stream in
0828:                    // the wrong encoding
0829:                    if (DEBUG_ENCODINGS) {
0830:                        System.out
0831:                                .println("$$$ no longer wrapping reader in OneCharReader");
0832:                    }
0833:                    //reader = new OneCharReader(reader);
0834:                }
0835:
0836:                // we've seen a new Reader. put it in a list, so that
0837:                // we can close it later.
0838:                //fOwnReaders.addElement(reader);
0839:
0840:                // push entity on stack  before we open new entity
0841:                if (fCurrentEntity != null) {
0842:                    fEntityStack.push(fCurrentEntity);
0843:                }
0844:
0845:                //System.out.println("Setting the fCurrentEntity, entity name = " + name );
0846:                // create entity
0847:                fCurrentEntity = new Entity.ScannedEntity(
0848:                        name,
0849:                        new XMLResourceIdentifierImpl(publicId,
0850:                                literalSystemId, baseSystemId, expandedSystemId),
0851:                        stream, reader, encoding, literal, false, isExternal);
0852:
0853:                //xxx provide the current entity to the reader, is this right way to do ??
0854:                fEntityReader.setCurrentEntity(fCurrentEntity);
0855:                //System.out.println(" fCurrentEntity set = " + fCurrentEntity );
0856:
0857:                fResourceIdentifier.setValues(publicId, literalSystemId,
0858:                        baseSystemId, expandedSystemId);
0859:                // call handler
0860:                if (fEntityHandler != null) {
0861:                    fEntityHandler.startEntity(name, fResourceIdentifier,
0862:                            encoding);
0863:                }
0864:
0865:            } // startEntity(String,XMLInputSource)
0866:
0867:            /**
0868:             * Return the current entity being scanned. Current entity is SET using startEntity function.
0869:             * @return Entity.ScannedEntity
0870:             */
0871:
0872:            public Entity.ScannedEntity getCurrentEntity() {
0873:                return fCurrentEntity;
0874:            }
0875:
0876:            // a list of Readers ever seen
0877:            protected Vector fOwnReaders = new Vector();
0878:
0879:            /**
0880:             * Close all opened InputStreams and Readers opened by this parser.
0881:             */
0882:            public void closeReaders() {
0883:                // close all readers
0884:                for (int i = fOwnReaders.size() - 1; i >= 0; i--) {
0885:                    try {
0886:                        ((Reader) fOwnReaders.elementAt(i)).close();
0887:                    } catch (IOException e) {
0888:                        // ignore
0889:                    }
0890:                }
0891:                // and clear the list
0892:                fOwnReaders.removeAllElements();
0893:            }
0894:
0895:            public void endEntity() throws IOException, XNIException {
0896:
0897:                // call handler
0898:                if (DEBUG_BUFFER) {
0899:                    System.out.print("(endEntity: ");
0900:                    print();
0901:                    System.out.println();
0902:                }
0903:                //System.out.println("Closing the Entity = " + fCurrentEntity.name);
0904:
0905:                if (fEntityHandler != null) {
0906:                    fEntityHandler.endEntity(fCurrentEntity.name);
0907:                }
0908:
0909:                //close the reader
0910:                if (fCurrentEntity != null) {
0911:                    //close the reader
0912:                    try {
0913:                        fCurrentEntity.close();
0914:                    } catch (IOException ex) {
0915:                        throw new XNIException(ex);
0916:                    }
0917:                }
0918:                // pop stack
0919:                // REVISIT: we are done with the current entity, should close
0920:                //          the associated reader
0921:                //fCurrentEntity.reader.close();
0922:                // Now we close all readers after we finish parsing
0923:
0924:                //fCurrentEntity = fEntityStack.size() > 0 ? (Entity.ScannedEntity)fEntityStack.pop() : null;
0925:                //close the reader
0926:
0927:                fCurrentEntity = fEntityStack.size() > 0 ? (Entity.ScannedEntity) fEntityStack
0928:                        .pop()
0929:                        : null;
0930:
0931:                fEntityReader.setCurrentEntity(fCurrentEntity);
0932:
0933:                //check if there are any entity left in the stack -- if there are
0934:                //no entries EOF has been reached.
0935:                //REVISIT: throwing an exception is very unclean -- and takes
0936:                //lot of time too
0937:                /**
0938:                 * if(fCurrentEntity == null ){
0939:                 * throw new EOFException() ;
0940:                 * }
0941:                 */
0942:                if (DEBUG_BUFFER) {
0943:                    System.out.print(")endEntity: ");
0944:                    print();
0945:                    System.out.println();
0946:                }
0947:
0948:            } // endEntity()
0949:
0950:            //
0951:            // XMLComponent methods
0952:            //
0953:            public void reset(PropertyManager propertyManager) {
0954:                //reset fEntityStorage
0955:                fEntityStorage.reset(propertyManager);
0956:                //reset XMLEntityReaderImpl
0957:                fEntityReader.reset(propertyManager);
0958:                // xerces properties
0959:                fSymbolTable = (SymbolTable) propertyManager
0960:                        .getProperty(Constants.XERCES_PROPERTY_PREFIX
0961:                                + Constants.SYMBOL_TABLE_PROPERTY);
0962:                fErrorReporter = (XMLErrorReporter) propertyManager
0963:                        .getProperty(Constants.XERCES_PROPERTY_PREFIX
0964:                                + Constants.ERROR_REPORTER_PROPERTY);
0965:                try {
0966:                    fStaxEntityResolver = (StaxEntityResolverWrapper) propertyManager
0967:                            .getProperty(STAX_ENTITY_RESOLVER);
0968:                } catch (XMLConfigurationException e) {
0969:                    fStaxEntityResolver = null;
0970:                }
0971:
0972:                // initialize state
0973:                //fStandalone = false;
0974:                fEntities.clear();
0975:                fEntityStack.removeAllElements();
0976:                fCurrentEntity = null;
0977:                fValidation = false;
0978:                fExternalGeneralEntities = true;
0979:                fExternalParameterEntities = true;
0980:                fAllowJavaEncodings = true;
0981:
0982:                //test();
0983:            }
0984:
0985:            /**
0986:             * public void reset(){
0987:             * fEntities.clear();
0988:             * fEntityStack.removeAllElements();
0989:             * fCurrentEntity = null;
0990:             * //test();
0991:             * }
0992:             */
0993:            /**
0994:             * Resets the component. The component can query the component manager
0995:             * about any features and properties that affect the operation of the
0996:             * component.
0997:             *
0998:             * @param componentManager The component manager.
0999:             *
1000:             * @throws SAXException Thrown by component on initialization error.
1001:             *                      For example, if a feature or property is
1002:             *                      required for the operation of the component, the
1003:             *                      component manager may throw a
1004:             *                      SAXNotRecognizedException or a
1005:             *                      SAXNotSupportedException.
1006:             */
1007:            public void reset(XMLComponentManager componentManager)
1008:                    throws XMLConfigurationException {
1009:
1010:                // sax features
1011:                try {
1012:                    fValidation = componentManager.getFeature(VALIDATION);
1013:                } catch (XMLConfigurationException e) {
1014:                    fValidation = false;
1015:                }
1016:                try {
1017:                    fExternalGeneralEntities = componentManager
1018:                            .getFeature(EXTERNAL_GENERAL_ENTITIES);
1019:                } catch (XMLConfigurationException e) {
1020:                    fExternalGeneralEntities = true;
1021:                }
1022:                try {
1023:                    fExternalParameterEntities = componentManager
1024:                            .getFeature(EXTERNAL_PARAMETER_ENTITIES);
1025:                } catch (XMLConfigurationException e) {
1026:                    fExternalParameterEntities = true;
1027:                }
1028:
1029:                // xerces features
1030:                try {
1031:                    fAllowJavaEncodings = componentManager
1032:                            .getFeature(ALLOW_JAVA_ENCODINGS);
1033:                } catch (XMLConfigurationException e) {
1034:                    fAllowJavaEncodings = false;
1035:                }
1036:
1037:                // xerces properties
1038:                fSymbolTable = (SymbolTable) componentManager
1039:                        .getProperty(SYMBOL_TABLE);
1040:                fErrorReporter = (XMLErrorReporter) componentManager
1041:                        .getProperty(ERROR_REPORTER);
1042:                try {
1043:                    fEntityResolver = (XMLEntityResolver) componentManager
1044:                            .getProperty(ENTITY_RESOLVER);
1045:                } catch (XMLConfigurationException e) {
1046:                    fEntityResolver = null;
1047:                }
1048:
1049:                try {
1050:                    fStaxEntityResolver = (StaxEntityResolverWrapper) componentManager
1051:                            .getProperty(STAX_ENTITY_RESOLVER);
1052:                } catch (XMLConfigurationException e) {
1053:                    fStaxEntityResolver = null;
1054:                }
1055:
1056:                // initialize state
1057:                fStandalone = false;
1058:                fEntities.clear();
1059:                fEntityStack.removeAllElements();
1060:
1061:                fCurrentEntity = null;
1062:                /**
1063:                 * // DEBUG
1064:                 * if (DEBUG_ENTITIES) {
1065:                 * addInternalEntity("text", "Hello World.");
1066:                 * addInternalEntity("empty-element", "<foo/>");
1067:                 * addInternalEntity("balanced-element", "<foo></foo>");
1068:                 * addInternalEntity("balanced-element-with-text", "<foo>Hello, World</foo>");
1069:                 * addInternalEntity("balanced-element-with-entity", "<foo>&text;</foo>");
1070:                 * addInternalEntity("unbalanced-entity", "<foo>");
1071:                 * addInternalEntity("recursive-entity", "<foo>&recursive-entity2;</foo>");
1072:                 * addInternalEntity("recursive-entity2", "<bar>&recursive-entity3;</bar>");
1073:                 * addInternalEntity("recursive-entity3", "<baz>&recursive-entity;</baz>");
1074:                 *
1075:                 * addExternalEntity("external-text", null, "external-text.ent", "test/external-text.xml");
1076:                 * addExternalEntity("external-balanced-element", null, "external-balanced-element.ent", "test/external-balanced-element.xml");
1077:                 * addExternalEntity("one", null, "ent/one.ent", "test/external-entity.xml");
1078:                 * addExternalEntity("two", null, "ent/two.ent", "test/ent/one.xml");
1079:                 * }
1080:                 */
1081:                // copy declared entities
1082:                //test();
1083:                if (fDeclaredEntities != null) {
1084:                    java.util.Enumeration keys = fDeclaredEntities.keys();
1085:                    while (keys.hasMoreElements()) {
1086:                        Object key = keys.nextElement();
1087:                        Object value = fDeclaredEntities.get(key);
1088:                        fEntities.put(key, value);
1089:                    }
1090:                }
1091:
1092:            } // reset(XMLComponentManager)
1093:
1094:            /**
1095:             * Returns a list of feature identifiers that are recognized by
1096:             * this component. This method may return null if no features
1097:             * are recognized by this component.
1098:             */
1099:            public String[] getRecognizedFeatures() {
1100:                return (String[]) (RECOGNIZED_FEATURES.clone());
1101:            } // getRecognizedFeatures():String[]
1102:
1103:            /**
1104:             * Sets the state of a feature. This method is called by the component
1105:             * manager any time after reset when a feature changes state.
1106:             * <p>
1107:             * <strong>Note:</strong> Components should silently ignore features
1108:             * that do not affect the operation of the component.
1109:             *
1110:             * @param featureId The feature identifier.
1111:             * @param state     The state of the feature.
1112:             *
1113:             * @throws SAXNotRecognizedException The component should not throw
1114:             *                                   this exception.
1115:             * @throws SAXNotSupportedException The component should not throw
1116:             *                                  this exception.
1117:             */
1118:            public void setFeature(String featureId, boolean state)
1119:                    throws XMLConfigurationException {
1120:
1121:                // xerces features
1122:                if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
1123:                    String feature = featureId
1124:                            .substring(Constants.XERCES_FEATURE_PREFIX.length());
1125:                    if (feature.equals(Constants.ALLOW_JAVA_ENCODINGS_FEATURE)) {
1126:                        fAllowJavaEncodings = state;
1127:                    }
1128:                }
1129:
1130:            } // setFeature(String,boolean)
1131:
1132:            public void setProperty(String name, Object value) {
1133:            }
1134:
1135:            /**
1136:             * Returns a list of property identifiers that are recognized by
1137:             * this component. This method may return null if no properties
1138:             * are recognized by this component.
1139:             */
1140:            public String[] getRecognizedProperties() {
1141:                return (String[]) (RECOGNIZED_PROPERTIES.clone());
1142:            } // getRecognizedProperties():String[]
1143:
1144:            /**
1145:             * Returns the default state for a feature, or null if this
1146:             * component does not want to report a default value for this
1147:             * feature.
1148:             *
1149:             * @param featureId The feature identifier.
1150:             *
1151:             * @since Xerces 2.2.0
1152:             */
1153:            public Boolean getFeatureDefault(String featureId) {
1154:                for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
1155:                    if (RECOGNIZED_FEATURES[i].equals(featureId)) {
1156:                        return FEATURE_DEFAULTS[i];
1157:                    }
1158:                }
1159:                return null;
1160:            } // getFeatureDefault(String):Boolean
1161:
1162:            /**
1163:             * Returns the default state for a property, or null if this
1164:             * component does not want to report a default value for this
1165:             * property.
1166:             *
1167:             * @param propertyId The property identifier.
1168:             *
1169:             * @since Xerces 2.2.0
1170:             */
1171:            public Object getPropertyDefault(String propertyId) {
1172:                for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
1173:                    if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
1174:                        return PROPERTY_DEFAULTS[i];
1175:                    }
1176:                }
1177:                return null;
1178:            } // getPropertyDefault(String):Object
1179:
1180:            //
1181:            // Public static methods
1182:            //
1183:
1184:            /**
1185:             * Expands a system id and returns the system id as a URI, if
1186:             * it can be expanded. A return value of null means that the
1187:             * identifier is already expanded. An exception thrown
1188:             * indicates a failure to expand the id.
1189:             *
1190:             * @param systemId The systemId to be expanded.
1191:             *
1192:             * @return Returns the URI string representing the expanded system
1193:             *         identifier. A null value indicates that the given
1194:             *         system identifier is already expanded.
1195:             *
1196:             */
1197:            public static String expandSystemId(String systemId) {
1198:                return expandSystemId(systemId, null);
1199:            } // expandSystemId(String):String
1200:
1201:            // current value of the "user.dir" property
1202:            private static String gUserDir;
1203:            // escaped value of the current "user.dir" property
1204:            private static String gEscapedUserDir;
1205:            // which ASCII characters need to be escaped
1206:            private static boolean gNeedEscaping[] = new boolean[128];
1207:            // the first hex character if a character needs to be escaped
1208:            private static char gAfterEscaping1[] = new char[128];
1209:            // the second hex character if a character needs to be escaped
1210:            private static char gAfterEscaping2[] = new char[128];
1211:            private static char[] gHexChs = { '0', '1', '2', '3', '4', '5',
1212:                    '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
1213:            // initialize the above 3 arrays
1214:            static {
1215:                for (int i = 0; i <= 0x1f; i++) {
1216:                    gNeedEscaping[i] = true;
1217:                    gAfterEscaping1[i] = gHexChs[i >> 4];
1218:                    gAfterEscaping2[i] = gHexChs[i & 0xf];
1219:                }
1220:                gNeedEscaping[0x7f] = true;
1221:                gAfterEscaping1[0x7f] = '7';
1222:                gAfterEscaping2[0x7f] = 'F';
1223:                char[] escChs = { ' ', '<', '>', '#', '%', '"', '{', '}', '|',
1224:                        '\\', '^', '~', '[', ']', '`' };
1225:                int len = escChs.length;
1226:                char ch;
1227:                for (int i = 0; i < len; i++) {
1228:                    ch = escChs[i];
1229:                    gNeedEscaping[ch] = true;
1230:                    gAfterEscaping1[ch] = gHexChs[ch >> 4];
1231:                    gAfterEscaping2[ch] = gHexChs[ch & 0xf];
1232:                }
1233:            }
1234:
1235:            // To escape the "user.dir" system property, by using %HH to represent
1236:            // special ASCII characters: 0x00~0x1F, 0x7F, ' ', '<', '>', '#', '%'
1237:            // and '"'. It's a static method, so needs to be synchronized.
1238:            // this method looks heavy, but since the system property isn't expected
1239:            // to change often, so in most cases, we only need to return the string
1240:            // that was escaped before.
1241:            // According to the URI spec, non-ASCII characters (whose value >= 128)
1242:            // need to be escaped too.
1243:            // REVISIT: don't know how to escape non-ASCII characters, especially
1244:            // which encoding to use. Leave them for now.
1245:            private static synchronized String getUserDir() {
1246:                // get the user.dir property
1247:                String userDir = "";
1248:                try {
1249:                    userDir = System.getProperty("user.dir");
1250:                } catch (SecurityException se) {
1251:                }
1252:
1253:                // return empty string if property value is empty string.
1254:                if (userDir.length() == 0)
1255:                    return "";
1256:
1257:                // compute the new escaped value if the new property value doesn't
1258:                // match the previous one
1259:                if (userDir.equals(gUserDir)) {
1260:                    return gEscapedUserDir;
1261:                }
1262:
1263:                // record the new value as the global property value
1264:                gUserDir = userDir;
1265:
1266:                char separator = java.io.File.separatorChar;
1267:                userDir = userDir.replace(separator, '/');
1268:
1269:                int len = userDir.length(), ch;
1270:                StringBuffer buffer = new StringBuffer(len * 3);
1271:                // change C:/blah to /C:/blah
1272:                if (len >= 2 && userDir.charAt(1) == ':') {
1273:                    ch = Character.toUpperCase(userDir.charAt(0));
1274:                    if (ch >= 'A' && ch <= 'Z') {
1275:                        buffer.append('/');
1276:                    }
1277:                }
1278:
1279:                // for each character in the path
1280:                int i = 0;
1281:                for (; i < len; i++) {
1282:                    ch = userDir.charAt(i);
1283:                    // if it's not an ASCII character, break here, and use UTF-8 encoding
1284:                    if (ch >= 128)
1285:                        break;
1286:                    if (gNeedEscaping[ch]) {
1287:                        buffer.append('%');
1288:                        buffer.append(gAfterEscaping1[ch]);
1289:                        buffer.append(gAfterEscaping2[ch]);
1290:                        // record the fact that it's escaped
1291:                    } else {
1292:                        buffer.append((char) ch);
1293:                    }
1294:                }
1295:
1296:                // we saw some non-ascii character
1297:                if (i < len) {
1298:                    // get UTF-8 bytes for the remaining sub-string
1299:                    byte[] bytes = null;
1300:                    byte b;
1301:                    try {
1302:                        bytes = userDir.substring(i).getBytes("UTF-8");
1303:                    } catch (java.io.UnsupportedEncodingException e) {
1304:                        // should never happen
1305:                        return userDir;
1306:                    }
1307:                    len = bytes.length;
1308:
1309:                    // for each byte
1310:                    for (i = 0; i < len; i++) {
1311:                        b = bytes[i];
1312:                        // for non-ascii character: make it positive, then escape
1313:                        if (b < 0) {
1314:                            ch = b + 256;
1315:                            buffer.append('%');
1316:                            buffer.append(gHexChs[ch >> 4]);
1317:                            buffer.append(gHexChs[ch & 0xf]);
1318:                        } else if (gNeedEscaping[b]) {
1319:                            buffer.append('%');
1320:                            buffer.append(gAfterEscaping1[b]);
1321:                            buffer.append(gAfterEscaping2[b]);
1322:                        } else {
1323:                            buffer.append((char) b);
1324:                        }
1325:                    }
1326:                }
1327:
1328:                // change blah/blah to blah/blah/
1329:                if (!userDir.endsWith("/"))
1330:                    buffer.append('/');
1331:
1332:                gEscapedUserDir = buffer.toString();
1333:
1334:                return gEscapedUserDir;
1335:            }
1336:
1337:            /**
1338:             * Expands a system id and returns the system id as a URI, if
1339:             * it can be expanded. A return value of null means that the
1340:             * identifier is already expanded. An exception thrown
1341:             * indicates a failure to expand the id.
1342:             *
1343:             * @param systemId The systemId to be expanded.
1344:             *
1345:             * @return Returns the URI string representing the expanded system
1346:             *         identifier. A null value indicates that the given
1347:             *         system identifier is already expanded.
1348:             *
1349:             */
1350:            public static String expandSystemId(String systemId,
1351:                    String baseSystemId) {
1352:
1353:                // check for bad parameters id
1354:                if (systemId == null || systemId.length() == 0) {
1355:                    return systemId;
1356:                }
1357:                // if id already expanded, return
1358:                try {
1359:                    URI uri = new URI(systemId);
1360:                    if (uri != null) {
1361:                        return systemId;
1362:                    }
1363:                } catch (URI.MalformedURIException e) {
1364:                    // continue on...
1365:                }
1366:                // normalize id
1367:                String id = fixURI(systemId);
1368:
1369:                // normalize base
1370:                URI base = null;
1371:                URI uri = null;
1372:                try {
1373:                    if (baseSystemId == null || baseSystemId.length() == 0
1374:                            || baseSystemId.equals(systemId)) {
1375:                        String dir = getUserDir();
1376:                        base = new URI("file", "", dir, null, null);
1377:                    } else {
1378:                        try {
1379:                            base = new URI(fixURI(baseSystemId));
1380:                        } catch (URI.MalformedURIException e) {
1381:                            if (baseSystemId.indexOf(':') != -1) {
1382:                                // for xml schemas we might have baseURI with
1383:                                // a specified drive
1384:                                base = new URI("file", "",
1385:                                        fixURI(baseSystemId), null, null);
1386:                            } else {
1387:                                String dir = getUserDir();
1388:                                dir = dir + fixURI(baseSystemId);
1389:                                base = new URI("file", "", dir, null, null);
1390:                            }
1391:                        }
1392:                    }
1393:                    // expand id
1394:                    uri = new URI(base, id);
1395:                } catch (Exception e) {
1396:                    // let it go through
1397:
1398:                }
1399:
1400:                if (uri == null) {
1401:                    return systemId;
1402:                }
1403:                return uri.toString();
1404:
1405:            } // expandSystemId(String,String):String
1406:
1407:            //
1408:            // Protected methods
1409:            //
1410:
1411:            /**
1412:             * Returns the IANA encoding name that is auto-detected from
1413:             * the bytes specified, with the endian-ness of that encoding where appropriate.
1414:             *
1415:             * @param b4    The first four bytes of the input.
1416:             * @param count The number of bytes actually read.
1417:             * @return a 2-element array:  the first element, an IANA-encoding string,
1418:             *  the second element a Boolean which is true iff the document is big endian, false
1419:             *  if it's little-endian, and null if the distinction isn't relevant.
1420:             */
1421:            protected Object[] getEncodingName(byte[] b4, int count) {
1422:
1423:                if (count < 2) {
1424:                    return defaultEncoding;
1425:                }
1426:
1427:                // UTF-16, with BOM
1428:                int b0 = b4[0] & 0xFF;
1429:                int b1 = b4[1] & 0xFF;
1430:                if (b0 == 0xFE && b1 == 0xFF) {
1431:                    // UTF-16, big-endian
1432:                    return new Object[] { "UTF-16BE", new Boolean(true) };
1433:                }
1434:                if (b0 == 0xFF && b1 == 0xFE) {
1435:                    // UTF-16, little-endian
1436:                    return new Object[] { "UTF-16LE", new Boolean(false) };
1437:                }
1438:
1439:                // default to UTF-8 if we don't have enough bytes to make a
1440:                // good determination of the encoding
1441:                if (count < 3) {
1442:                    return defaultEncoding;
1443:                }
1444:
1445:                // UTF-8 with a BOM
1446:                int b2 = b4[2] & 0xFF;
1447:                if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF) {
1448:                    return defaultEncoding;
1449:                }
1450:
1451:                // default to UTF-8 if we don't have enough bytes to make a
1452:                // good determination of the encoding
1453:                if (count < 4) {
1454:                    return defaultEncoding;
1455:                }
1456:
1457:                // other encodings
1458:                int b3 = b4[3] & 0xFF;
1459:                if (b0 == 0x00 && b1 == 0x00 && b2 == 0x00 && b3 == 0x3C) {
1460:                    // UCS-4, big endian (1234)
1461:                    return new Object[] { "ISO-10646-UCS-4", new Boolean(true) };
1462:                }
1463:                if (b0 == 0x3C && b1 == 0x00 && b2 == 0x00 && b3 == 0x00) {
1464:                    // UCS-4, little endian (4321)
1465:                    return new Object[] { "ISO-10646-UCS-4", new Boolean(false) };
1466:                }
1467:                if (b0 == 0x00 && b1 == 0x00 && b2 == 0x3C && b3 == 0x00) {
1468:                    // UCS-4, unusual octet order (2143)
1469:                    // REVISIT: What should this be?
1470:                    return new Object[] { "ISO-10646-UCS-4", null };
1471:                }
1472:                if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x00) {
1473:                    // UCS-4, unusual octect order (3412)
1474:                    // REVISIT: What should this be?
1475:                    return new Object[] { "ISO-10646-UCS-4", null };
1476:                }
1477:                if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F) {
1478:                    // UTF-16, big-endian, no BOM
1479:                    // (or could turn out to be UCS-2...
1480:                    // REVISIT: What should this be?
1481:                    return new Object[] { "UTF-16BE", new Boolean(true) };
1482:                }
1483:                if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00) {
1484:                    // UTF-16, little-endian, no BOM
1485:                    // (or could turn out to be UCS-2...
1486:                    return new Object[] { "UTF-16LE", new Boolean(false) };
1487:                }
1488:                if (b0 == 0x4C && b1 == 0x6F && b2 == 0xA7 && b3 == 0x94) {
1489:                    // EBCDIC
1490:                    // a la xerces1, return CP037 instead of EBCDIC here
1491:                    return new Object[] { "CP037", null };
1492:                }
1493:
1494:                return defaultEncoding;
1495:
1496:            } // getEncodingName(byte[],int):Object[]
1497:
1498:            /**
1499:             * Creates a reader capable of reading the given input stream in
1500:             * the specified encoding.
1501:             *
1502:             * @param inputStream  The input stream.
1503:             * @param encoding     The encoding name that the input stream is
1504:             *                     encoded using. If the user has specified that
1505:             *                     Java encoding names are allowed, then the
1506:             *                     encoding name may be a Java encoding name;
1507:             *                     otherwise, it is an ianaEncoding name.
1508:             * @param isBigEndian   For encodings (like uCS-4), whose names cannot
1509:             *                      specify a byte order, this tells whether the order is bigEndian.  null menas
1510:             *                      unknown or not relevant.
1511:             *
1512:             * @return Returns a reader.
1513:             */
1514:            protected Reader createReader(InputStream inputStream,
1515:                    String encoding, Boolean isBigEndian) throws IOException {
1516:
1517:                // normalize encoding name
1518:                if (encoding == null) {
1519:                    encoding = "UTF-8";
1520:                }
1521:
1522:                // try to use an optimized reader
1523:                String ENCODING = encoding.toUpperCase(Locale.ENGLISH);
1524:                if (ENCODING.equals("UTF-8")) {
1525:                    if (DEBUG_ENCODINGS) {
1526:                        System.out.println("$$$ creating UTF8Reader");
1527:                    }
1528:                    return new UTF8Reader(
1529:                            inputStream,
1530:                            fBufferSize,
1531:                            fErrorReporter
1532:                                    .getMessageFormatter(XMLMessageFormatter.XML_DOMAIN),
1533:                            fErrorReporter.getLocale());
1534:                }
1535:                if (ENCODING.equals("US-ASCII")) {
1536:                    if (DEBUG_ENCODINGS) {
1537:                        System.out.println("$$$ creating ASCIIReader");
1538:                    }
1539:                    return new ASCIIReader(
1540:                            inputStream,
1541:                            fBufferSize,
1542:                            fErrorReporter
1543:                                    .getMessageFormatter(XMLMessageFormatter.XML_DOMAIN),
1544:                            fErrorReporter.getLocale());
1545:                }
1546:                if (ENCODING.equals("ISO-10646-UCS-4")) {
1547:                    if (isBigEndian != null) {
1548:                        boolean isBE = isBigEndian.booleanValue();
1549:                        if (isBE) {
1550:                            return new UCSReader(inputStream, UCSReader.UCS4BE);
1551:                        } else {
1552:                            return new UCSReader(inputStream, UCSReader.UCS4LE);
1553:                        }
1554:                    } else {
1555:                        fErrorReporter.reportError(this .getEntityReader(),
1556:                                XMLMessageFormatter.XML_DOMAIN,
1557:                                "EncodingByteOrderUnsupported",
1558:                                new Object[] { encoding },
1559:                                XMLErrorReporter.SEVERITY_FATAL_ERROR);
1560:                    }
1561:                }
1562:                if (ENCODING.equals("ISO-10646-UCS-2")) {
1563:                    if (isBigEndian != null) { // sould never happen with this encoding...
1564:                        boolean isBE = isBigEndian.booleanValue();
1565:                        if (isBE) {
1566:                            return new UCSReader(inputStream, UCSReader.UCS2BE);
1567:                        } else {
1568:                            return new UCSReader(inputStream, UCSReader.UCS2LE);
1569:                        }
1570:                    } else {
1571:                        fErrorReporter.reportError(this .getEntityReader(),
1572:                                XMLMessageFormatter.XML_DOMAIN,
1573:                                "EncodingByteOrderUnsupported",
1574:                                new Object[] { encoding },
1575:                                XMLErrorReporter.SEVERITY_FATAL_ERROR);
1576:                    }
1577:                }
1578:
1579:                // check for valid name
1580:                boolean validIANA = XMLChar.isValidIANAEncoding(encoding);
1581:                boolean validJava = XMLChar.isValidJavaEncoding(encoding);
1582:                if (!validIANA || (fAllowJavaEncodings && !validJava)) {
1583:                    fErrorReporter.reportError(this .getEntityReader(),
1584:                            XMLMessageFormatter.XML_DOMAIN,
1585:                            "EncodingDeclInvalid", new Object[] { encoding },
1586:                            XMLErrorReporter.SEVERITY_FATAL_ERROR);
1587:                    // NOTE: AndyH suggested that, on failure, we use ISO Latin 1
1588:                    //       because every byte is a valid ISO Latin 1 character.
1589:                    //       It may not translate correctly but if we failed on
1590:                    //       the encoding anyway, then we're expecting the content
1591:                    //       of the document to be bad. This will just prevent an
1592:                    //       invalid UTF-8 sequence to be detected. This is only
1593:                    //       important when continue-after-fatal-error is turned
1594:                    //       on. -Ac
1595:                    encoding = "ISO-8859-1";
1596:                }
1597:
1598:                // try to use a Java reader
1599:                String javaEncoding = EncodingMap.getIANA2JavaMapping(ENCODING);
1600:                if (javaEncoding == null) {
1601:                    if (fAllowJavaEncodings) {
1602:                        javaEncoding = encoding;
1603:                    } else {
1604:                        fErrorReporter.reportError(this .getEntityReader(),
1605:                                XMLMessageFormatter.XML_DOMAIN,
1606:                                "EncodingDeclInvalid",
1607:                                new Object[] { encoding },
1608:                                XMLErrorReporter.SEVERITY_FATAL_ERROR);
1609:                        // see comment above.
1610:                        javaEncoding = "ISO8859_1";
1611:                    }
1612:                }
1613:                if (DEBUG_ENCODINGS) {
1614:                    System.out
1615:                            .print("$$$ creating Java InputStreamReader: encoding="
1616:                                    + javaEncoding);
1617:                    if (javaEncoding == encoding) {
1618:                        System.out.print(" (IANA encoding)");
1619:                    }
1620:                    System.out.println();
1621:                }
1622:                return new BufferedReader(new InputStreamReader(inputStream,
1623:                        javaEncoding));
1624:
1625:            } // createReader(InputStream,String, Boolean): Reader
1626:
1627:            /**
1628:             * Return the public identifier for the current document event.
1629:             * <p>
1630:             * The return value is the public identifier of the document
1631:             * entity or of the external parsed entity in which the markup
1632:             * triggering the event appears.
1633:             *
1634:             * @return A string containing the public identifier, or
1635:             *         null if none is available.
1636:             */
1637:            public String getPublicId() {
1638:                return (fCurrentEntity != null && fCurrentEntity.entityLocation != null) ? fCurrentEntity.entityLocation
1639:                        .getPublicId()
1640:                        : null;
1641:            } // getPublicId():String
1642:
1643:            /**
1644:             * Return the expanded system identifier for the current document event.
1645:             * <p>
1646:             * The return value is the expanded system identifier of the document
1647:             * entity or of the external parsed entity in which the markup
1648:             * triggering the event appears.
1649:             * <p>
1650:             * If the system identifier is a URL, the parser must resolve it
1651:             * fully before passing it to the application.
1652:             *
1653:             * @return A string containing the expanded system identifier, or null
1654:             *         if none is available.
1655:             */
1656:            public String getExpandedSystemId() {
1657:                if (fCurrentEntity != null) {
1658:                    if (fCurrentEntity.entityLocation != null
1659:                            && fCurrentEntity.entityLocation
1660:                                    .getExpandedSystemId() != null) {
1661:                        return fCurrentEntity.entityLocation
1662:                                .getExpandedSystemId();
1663:                    } else {
1664:                        // search for the first external entity on the stack
1665:                        int size = fEntityStack.size();
1666:                        for (int i = size - 1; i >= 0; i--) {
1667:                            Entity.ScannedEntity externalEntity = (Entity.ScannedEntity) fEntityStack
1668:                                    .elementAt(i);
1669:
1670:                            if (externalEntity.entityLocation != null
1671:                                    && externalEntity.entityLocation
1672:                                            .getExpandedSystemId() != null) {
1673:                                return externalEntity.entityLocation
1674:                                        .getExpandedSystemId();
1675:                            }
1676:                        }
1677:                    }
1678:                }
1679:                return null;
1680:            } // getExpandedSystemId():String
1681:
1682:            /**
1683:             * Return the literal system identifier for the current document event.
1684:             * <p>
1685:             * The return value is the literal system identifier of the document
1686:             * entity or of the external parsed entity in which the markup
1687:             * triggering the event appears.
1688:             * <p>
1689:             * @return A string containing the literal system identifier, or null
1690:             *         if none is available.
1691:             */
1692:            public String getLiteralSystemId() {
1693:                if (fCurrentEntity != null) {
1694:                    if (fCurrentEntity.entityLocation != null
1695:                            && fCurrentEntity.entityLocation
1696:                                    .getLiteralSystemId() != null) {
1697:                        return fCurrentEntity.entityLocation
1698:                                .getLiteralSystemId();
1699:                    } else {
1700:                        // search for the first external entity on the stack
1701:                        int size = fEntityStack.size();
1702:                        for (int i = size - 1; i >= 0; i--) {
1703:                            Entity.ScannedEntity externalEntity = (Entity.ScannedEntity) fEntityStack
1704:                                    .elementAt(i);
1705:
1706:                            if (externalEntity.entityLocation != null
1707:                                    && externalEntity.entityLocation
1708:                                            .getLiteralSystemId() != null) {
1709:                                return externalEntity.entityLocation
1710:                                        .getLiteralSystemId();
1711:                            }
1712:                        }
1713:                    }
1714:                }
1715:                return null;
1716:            } // getLiteralSystemId():String
1717:
1718:            /**
1719:             * Return the line number where the current document event ends.
1720:             * <p>
1721:             * <strong>Warning:</strong> The return value from the method
1722:             * is intended only as an approximation for the sake of error
1723:             * reporting; it is not intended to provide sufficient information
1724:             * to edit the character content of the original XML document.
1725:             * <p>
1726:             * The return value is an approximation of the line number
1727:             * in the document entity or external parsed entity where the
1728:             * markup triggering the event appears.
1729:             * <p>
1730:             * If possible, the SAX driver should provide the line position
1731:             * of the first character after the text associated with the document
1732:             * event.  The first line in the document is line 1.
1733:             *
1734:             * @return The line number, or -1 if none is available.
1735:             */
1736:            public int getLineNumber() {
1737:                if (fCurrentEntity != null) {
1738:                    if (fCurrentEntity.isExternal()) {
1739:                        return fCurrentEntity.lineNumber;
1740:                    } else {
1741:                        // search for the first external entity on the stack
1742:                        int size = fEntityStack.size();
1743:                        for (int i = size - 1; i > 0; i--) {
1744:                            Entity.ScannedEntity firstExternalEntity = (Entity.ScannedEntity) fEntityStack
1745:                                    .elementAt(i);
1746:                            if (firstExternalEntity.isExternal()) {
1747:                                return firstExternalEntity.lineNumber;
1748:                            }
1749:                        }
1750:                    }
1751:                }
1752:
1753:                return -1;
1754:
1755:            } // getLineNumber():int
1756:
1757:            /**
1758:             * Return the column number where the current document event ends.
1759:             * <p>
1760:             * <strong>Warning:</strong> The return value from the method
1761:             * is intended only as an approximation for the sake of error
1762:             * reporting; it is not intended to provide sufficient information
1763:             * to edit the character content of the original XML document.
1764:             * <p>
1765:             * The return value is an approximation of the column number
1766:             * in the document entity or external parsed entity where the
1767:             * markup triggering the event appears.
1768:             * <p>
1769:             * If possible, the SAX driver should provide the line position
1770:             * of the first character after the text associated with the document
1771:             * event.
1772:             * <p>
1773:             * If possible, the SAX driver should provide the line position
1774:             * of the first character after the text associated with the document
1775:             * event.  The first column in each line is column 1.
1776:             *
1777:             * @return The column number, or -1 if none is available.
1778:             */
1779:            public int getColumnNumber() {
1780:                if (fCurrentEntity != null) {
1781:                    if (fCurrentEntity.isExternal()) {
1782:                        return fCurrentEntity.columnNumber;
1783:                    } else {
1784:                        // search for the first external entity on the stack
1785:                        int size = fEntityStack.size();
1786:                        for (int i = size - 1; i > 0; i--) {
1787:                            Entity.ScannedEntity firstExternalEntity = (Entity.ScannedEntity) fEntityStack
1788:                                    .elementAt(i);
1789:                            if (firstExternalEntity.isExternal()) {
1790:                                return firstExternalEntity.columnNumber;
1791:                            }
1792:                        }
1793:                    }
1794:                }
1795:
1796:                return -1;
1797:            } // getColumnNumber():int
1798:
1799:            //
1800:            // Protected static methods
1801:            //
1802:
1803:            /**
1804:             * Fixes a platform dependent filename to standard URI form.
1805:             *
1806:             * @param str The string to fix.
1807:             *
1808:             * @return Returns the fixed URI string.
1809:             */
1810:            protected static String fixURI(String str) {
1811:
1812:                // handle platform dependent strings
1813:                str = str.replace(java.io.File.separatorChar, '/');
1814:
1815:                // Windows fix
1816:                if (str.length() >= 2) {
1817:                    char ch1 = str.charAt(1);
1818:                    // change "C:blah" to "/C:blah"
1819:                    if (ch1 == ':') {
1820:                        char ch0 = Character.toUpperCase(str.charAt(0));
1821:                        if (ch0 >= 'A' && ch0 <= 'Z') {
1822:                            str = "/" + str;
1823:                        }
1824:                    }
1825:                    // change "//blah" to "file://blah"
1826:                    else if (ch1 == '/' && str.charAt(0) == '/') {
1827:                        str = "file:" + str;
1828:                    }
1829:                }
1830:
1831:                // done
1832:                return str;
1833:
1834:            } // fixURI(String):String
1835:
1836:            //
1837:            // Package visible methods
1838:            //
1839:            /** Prints the contents of the buffer. */
1840:            final void print() {
1841:                if (DEBUG_BUFFER) {
1842:                    if (fCurrentEntity != null) {
1843:                        System.out.print('[');
1844:                        System.out.print(fCurrentEntity.count);
1845:                        System.out.print(' ');
1846:                        System.out.print(fCurrentEntity.position);
1847:                        if (fCurrentEntity.count > 0) {
1848:                            System.out.print(" \"");
1849:                            for (int i = 0; i < fCurrentEntity.count; i++) {
1850:                                if (i == fCurrentEntity.position) {
1851:                                    System.out.print('^');
1852:                                }
1853:                                char c = fCurrentEntity.ch[i];
1854:                                switch (c) {
1855:                                case '\n': {
1856:                                    System.out.print("\\n");
1857:                                    break;
1858:                                }
1859:                                case '\r': {
1860:                                    System.out.print("\\r");
1861:                                    break;
1862:                                }
1863:                                case '\t': {
1864:                                    System.out.print("\\t");
1865:                                    break;
1866:                                }
1867:                                case '\\': {
1868:                                    System.out.print("\\\\");
1869:                                    break;
1870:                                }
1871:                                default: {
1872:                                    System.out.print(c);
1873:                                }
1874:                                }
1875:                            }
1876:                            if (fCurrentEntity.position == fCurrentEntity.count) {
1877:                                System.out.print('^');
1878:                            }
1879:                            System.out.print('"');
1880:                        }
1881:                        System.out.print(']');
1882:                        System.out.print(" @ ");
1883:                        System.out.print(fCurrentEntity.lineNumber);
1884:                        System.out.print(',');
1885:                        System.out.print(fCurrentEntity.columnNumber);
1886:                    } else {
1887:                        System.out.print("*NO CURRENT ENTITY*");
1888:                    }
1889:                }
1890:            } // print()
1891:
1892:            // This class wraps the byte inputstreams we're presented with.
1893:            // We need it because java.io.InputStreams don't provide
1894:            // functionality to reread processed bytes, and they have a habit
1895:            // of reading more than one character when you call their read()
1896:            // methods.  This means that, once we discover the true (declared)
1897:            // encoding of a document, we can neither backtrack to read the
1898:            // whole doc again nor start reading where we are with a new
1899:            // reader.
1900:            //
1901:            // This class allows rewinding an inputStream by allowing a mark
1902:            // to be set, and the stream reset to that position.  <strong>The
1903:            // class assumes that it needs to read one character per
1904:            // invocation when it's read() method is inovked, but uses the
1905:            // underlying InputStream's read(char[], offset length) method--it
1906:            // won't buffer data read this way!</strong>
1907:            //
1908:            // @author Neil Graham, IBM
1909:            // @author Glenn Marcy, IBM
1910:
1911:            protected final class RewindableInputStream extends InputStream {
1912:
1913:                private InputStream fInputStream;
1914:                private byte[] fData;
1915:                private int fStartOffset;
1916:                private int fEndOffset;
1917:                private int fOffset;
1918:                private int fLength;
1919:                private int fMark;
1920:
1921:                public RewindableInputStream(InputStream is) {
1922:                    fData = new byte[DEFAULT_XMLDECL_BUFFER_SIZE];
1923:                    fInputStream = is;
1924:                    fStartOffset = 0;
1925:                    fEndOffset = -1;
1926:                    fOffset = 0;
1927:                    fLength = 0;
1928:                    fMark = 0;
1929:                }
1930:
1931:                public void setStartOffset(int offset) {
1932:                    fStartOffset = offset;
1933:                }
1934:
1935:                public void rewind() {
1936:                    fOffset = fStartOffset;
1937:                }
1938:
1939:                public int read() throws IOException {
1940:                    int b = 0;
1941:                    if (fOffset < fLength) {
1942:                        return fData[fOffset++] & 0xff;
1943:                    }
1944:                    if (fOffset == fEndOffset) {
1945:                        return -1;
1946:                    }
1947:                    if (fOffset == fData.length) {
1948:                        byte[] newData = new byte[fOffset << 1];
1949:                        System.arraycopy(fData, 0, newData, 0, fOffset);
1950:                        fData = newData;
1951:                    }
1952:                    b = fInputStream.read();
1953:                    if (b == -1) {
1954:                        fEndOffset = fOffset;
1955:                        return -1;
1956:                    }
1957:                    fData[fLength++] = (byte) b;
1958:                    fOffset++;
1959:                    return b & 0xff;
1960:                }
1961:
1962:                public int read(byte[] b, int off, int len) throws IOException {
1963:                    int bytesLeft = fLength - fOffset;
1964:                    if (bytesLeft == 0) {
1965:                        if (fOffset == fEndOffset) {
1966:                            return -1;
1967:                        }
1968:                        return fInputStream.read(b, off, len);
1969:                        /**
1970:                         * //System.out.println("fCurrentEntitty = " + fCurrentEntity );
1971:                         * //System.out.println("fInputStream = " + fInputStream );
1972:                         * // better get some more for the voracious reader...
1973:                         * if(fCurrentEntity.mayReadChunks) {
1974:                         * return fInputStream.read(b, off, len);
1975:                         * }
1976:                         *
1977:                         * int returnedVal = read();
1978:                         * if(returnedVal == -1) {
1979:                         * fEndOffset = fOffset;
1980:                         * return -1;
1981:                         * }
1982:                         * b[off] = (byte)returnedVal;
1983:                         * return 1;
1984:                         */
1985:                    }
1986:                    if (len < bytesLeft) {
1987:                        if (len <= 0) {
1988:                            return 0;
1989:                        }
1990:                    } else {
1991:                        len = bytesLeft;
1992:                    }
1993:                    if (b != null) {
1994:                        System.arraycopy(fData, fOffset, b, off, len);
1995:                    }
1996:                    fOffset += len;
1997:                    return len;
1998:                }
1999:
2000:                public long skip(long n) throws IOException {
2001:                    int bytesLeft;
2002:                    if (n <= 0) {
2003:                        return 0;
2004:                    }
2005:                    bytesLeft = fLength - fOffset;
2006:                    if (bytesLeft == 0) {
2007:                        if (fOffset == fEndOffset) {
2008:                            return 0;
2009:                        }
2010:                        return fInputStream.skip(n);
2011:                    }
2012:                    if (n <= bytesLeft) {
2013:                        fOffset += n;
2014:                        return n;
2015:                    }
2016:                    fOffset += bytesLeft;
2017:                    if (fOffset == fEndOffset) {
2018:                        return bytesLeft;
2019:                    }
2020:                    n -= bytesLeft;
2021:                    /*
2022:                     * In a manner of speaking, when this class isn't permitting more
2023:                     * than one byte at a time to be read, it is "blocking".  The
2024:                     * available() method should indicate how much can be read without
2025:                     * blocking, so while we're in this mode, it should only indicate
2026:                     * that bytes in its buffer are available; otherwise, the result of
2027:                     * available() on the underlying InputStream is appropriate.
2028:                     */
2029:                    return fInputStream.skip(n) + bytesLeft;
2030:                }
2031:
2032:                public int available() throws IOException {
2033:                    int bytesLeft = fLength - fOffset;
2034:                    if (bytesLeft == 0) {
2035:                        if (fOffset == fEndOffset) {
2036:                            return -1;
2037:                        }
2038:                        return fCurrentEntity.mayReadChunks ? fInputStream
2039:                                .available() : 0;
2040:                    }
2041:                    return bytesLeft;
2042:                }
2043:
2044:                public void mark(int howMuch) {
2045:                    fMark = fOffset;
2046:                }
2047:
2048:                public void reset() {
2049:                    fOffset = fMark;
2050:                    //test();
2051:                }
2052:
2053:                public boolean markSupported() {
2054:                    return true;
2055:                }
2056:
2057:                public void close() throws IOException {
2058:                    if (fInputStream != null) {
2059:                        fInputStream.close();
2060:                        fInputStream = null;
2061:                    }
2062:                }
2063:            } // end of RewindableInputStream class
2064:
2065:            public void test() {
2066:                //System.out.println("TESTING: Added familytree to entityManager");
2067:                //Usecase1
2068:                fEntityStorage
2069:                        .addExternalEntity(
2070:                                "entityUsecase1",
2071:                                null,
2072:                                "/space/home/stax/sun/6thJan2004/zephyr/data/test.txt",
2073:                                "/space/home/stax/sun/6thJan2004/zephyr/data/entity.xml");
2074:
2075:                //Usecase2
2076:                fEntityStorage.addInternalEntity("entityUsecase2",
2077:                        "<Test>value</Test>");
2078:                fEntityStorage.addInternalEntity("entityUsecase3", "value3");
2079:                fEntityStorage.addInternalEntity("text", "Hello World.");
2080:                fEntityStorage.addInternalEntity("empty-element", "<foo/>");
2081:                fEntityStorage.addInternalEntity("balanced-element",
2082:                        "<foo></foo>");
2083:                fEntityStorage.addInternalEntity("balanced-element-with-text",
2084:                        "<foo>Hello, World</foo>");
2085:                fEntityStorage.addInternalEntity(
2086:                        "balanced-element-with-entity", "<foo>&text;</foo>");
2087:                fEntityStorage.addInternalEntity("unbalanced-entity", "<foo>");
2088:                fEntityStorage.addInternalEntity("recursive-entity",
2089:                        "<foo>&recursive-entity2;</foo>");
2090:                fEntityStorage.addInternalEntity("recursive-entity2",
2091:                        "<bar>&recursive-entity3;</bar>");
2092:                fEntityStorage.addInternalEntity("recursive-entity3",
2093:                        "<baz>&recursive-entity;</baz>");
2094:                fEntityStorage.addInternalEntity("ch", "&#x00A9;");
2095:                fEntityStorage.addInternalEntity("ch1", "&#84;");
2096:                fEntityStorage.addInternalEntity("% ch2", "param");
2097:            }
2098:
2099:        } // class XMLEntityManager
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.