Source Code Cross Referenced for XIncludeHandler.java in  » XML » xerces-2_9_1 » org » apache » xerces » xinclude » 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 » XML » xerces 2_9_1 » org.apache.xerces.xinclude 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         * 
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         * 
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:
0018:        package org.apache.xerces.xinclude;
0019:
0020:        import java.io.CharConversionException;
0021:        import java.io.IOException;
0022:        import java.util.ArrayList;
0023:        import java.util.Enumeration;
0024:        import java.util.Locale;
0025:        import java.util.Stack;
0026:        import java.util.StringTokenizer;
0027:
0028:        import org.apache.xerces.impl.Constants;
0029:        import org.apache.xerces.impl.XMLEntityManager;
0030:        import org.apache.xerces.impl.XMLErrorReporter;
0031:        import org.apache.xerces.impl.io.MalformedByteSequenceException;
0032:        import org.apache.xerces.impl.msg.XMLMessageFormatter;
0033:        import org.apache.xerces.util.AugmentationsImpl;
0034:        import org.apache.xerces.util.HTTPInputSource;
0035:        import org.apache.xerces.util.IntStack;
0036:        import org.apache.xerces.util.ParserConfigurationSettings;
0037:        import org.apache.xerces.util.SecurityManager;
0038:        import org.apache.xerces.util.SymbolTable;
0039:        import org.apache.xerces.util.URI;
0040:        import org.apache.xerces.util.XMLAttributesImpl;
0041:        import org.apache.xerces.util.XMLLocatorWrapper;
0042:        import org.apache.xerces.util.XMLResourceIdentifierImpl;
0043:        import org.apache.xerces.util.XMLChar;
0044:        import org.apache.xerces.util.XMLSymbols;
0045:        import org.apache.xerces.util.URI.MalformedURIException;
0046:        import org.apache.xerces.xni.Augmentations;
0047:        import org.apache.xerces.xni.NamespaceContext;
0048:        import org.apache.xerces.xni.QName;
0049:        import org.apache.xerces.xni.XMLAttributes;
0050:        import org.apache.xerces.xni.XMLDTDHandler;
0051:        import org.apache.xerces.xni.XMLDocumentHandler;
0052:        import org.apache.xerces.xni.XMLLocator;
0053:        import org.apache.xerces.xni.XMLResourceIdentifier;
0054:        import org.apache.xerces.xni.XMLString;
0055:        import org.apache.xerces.xni.XNIException;
0056:        import org.apache.xerces.xni.parser.XMLComponent;
0057:        import org.apache.xerces.xni.parser.XMLComponentManager;
0058:        import org.apache.xerces.xni.parser.XMLConfigurationException;
0059:        import org.apache.xerces.xni.parser.XMLDTDFilter;
0060:        import org.apache.xerces.xni.parser.XMLDTDSource;
0061:        import org.apache.xerces.xni.parser.XMLDocumentFilter;
0062:        import org.apache.xerces.xni.parser.XMLDocumentSource;
0063:        import org.apache.xerces.xni.parser.XMLEntityResolver;
0064:        import org.apache.xerces.xni.parser.XMLInputSource;
0065:        import org.apache.xerces.xni.parser.XMLParserConfiguration;
0066:        import org.apache.xerces.xpointer.XPointerHandler;
0067:        import org.apache.xerces.xpointer.XPointerProcessor;
0068:
0069:        /**
0070:         * <p>
0071:         * This is a pipeline component which performs XInclude handling, according to the
0072:         * W3C specification for XML Inclusions.
0073:         * </p>
0074:         * <p>
0075:         * This component analyzes each event in the pipeline, looking for &lt;include&gt;
0076:         * elements. An &lt;include&gt; element is one which has a namespace of
0077:         * <code>http://www.w3.org/2001/XInclude</code> and a localname of <code>include</code>.
0078:         * When it finds an &lt;include&gt; element, it attempts to include the file specified
0079:         * in the <code>href</code> attribute of the element.  If inclusion succeeds, all
0080:         * children of the &lt;include&gt; element are ignored (with the exception of
0081:         * checking for invalid children as outlined in the specification).  If the inclusion
0082:         * fails, the &lt;fallback&gt; child of the &lt;include&gt; element is processed.
0083:         * </p>
0084:         * <p>
0085:         * See the <a href="http://www.w3.org/TR/xinclude/">XInclude specification</a> for
0086:         * more information on how XInclude is to be used.
0087:         * </p>
0088:         * <p>
0089:         * This component requires the following features and properties from the
0090:         * component manager that uses it:
0091:         * <ul>
0092:         *  <li>http://xml.org/sax/features/allow-dtd-events-after-endDTD</li>
0093:         *  <li>http://apache.org/xml/properties/internal/error-reporter</li>
0094:         *  <li>http://apache.org/xml/properties/internal/entity-resolver</li>
0095:         * </ul>
0096:         * Optional property:
0097:         * <ul>
0098:         *  <li>http://apache.org/xml/properties/input-buffer-size</li>
0099:         * </ul>
0100:         * 
0101:         * Furthermore, the <code>NamespaceContext</code> used in the pipeline is required
0102:         * to be an instance of <code>XIncludeNamespaceSupport</code>.
0103:         * </p>
0104:         * <p>
0105:         * Currently, this implementation has only partial support for the XInclude specification.
0106:         * Specifically, it is missing support for XPointer document fragments.  Thus, only whole
0107:         * documents can be included using this component in the pipeline.
0108:         * </p>
0109:         *
0110:         * @author Peter McCracken, IBM
0111:         * @author Michael Glavassevich, IBM
0112:         *
0113:         * @version $Id: XIncludeHandler.java 572045 2007-09-02 17:32:09Z mrglavas $
0114:         *
0115:         * @see XIncludeNamespaceSupport
0116:         */
0117:        public class XIncludeHandler implements  XMLComponent,
0118:                XMLDocumentFilter, XMLDTDFilter {
0119:
0120:            public final static String XINCLUDE_DEFAULT_CONFIGURATION = "org.apache.xerces.parsers.XIncludeParserConfiguration";
0121:            public final static String HTTP_ACCEPT = "Accept";
0122:            public final static String HTTP_ACCEPT_LANGUAGE = "Accept-Language";
0123:            public final static String XPOINTER = "xpointer";
0124:
0125:            public final static String XINCLUDE_NS_URI = "http://www.w3.org/2001/XInclude"
0126:                    .intern();
0127:            public final static String XINCLUDE_INCLUDE = "include".intern();
0128:            public final static String XINCLUDE_FALLBACK = "fallback".intern();
0129:
0130:            public final static String XINCLUDE_PARSE_XML = "xml".intern();
0131:            public final static String XINCLUDE_PARSE_TEXT = "text".intern();
0132:
0133:            public final static String XINCLUDE_ATTR_HREF = "href".intern();
0134:            public final static String XINCLUDE_ATTR_PARSE = "parse".intern();
0135:            public final static String XINCLUDE_ATTR_ENCODING = "encoding"
0136:                    .intern();
0137:            public final static String XINCLUDE_ATTR_ACCEPT = "accept".intern();
0138:            public final static String XINCLUDE_ATTR_ACCEPT_LANGUAGE = "accept-language"
0139:                    .intern();
0140:
0141:            // Top Level Information Items have [included] property in infoset
0142:            public final static String XINCLUDE_INCLUDED = "[included]"
0143:                    .intern();
0144:
0145:            /** The identifier for the Augmentation that contains the current base URI */
0146:            public final static String CURRENT_BASE_URI = "currentBaseURI";
0147:
0148:            // used for adding [base URI] attributes
0149:            private final static String XINCLUDE_BASE = "base".intern();
0150:            private final static QName XML_BASE_QNAME = new QName(
0151:                    XMLSymbols.PREFIX_XML, XINCLUDE_BASE,
0152:                    (XMLSymbols.PREFIX_XML + ":" + XINCLUDE_BASE).intern(),
0153:                    NamespaceContext.XML_URI);
0154:
0155:            // used for adding [language] attributes
0156:            private final static String XINCLUDE_LANG = "lang".intern();
0157:            private final static QName XML_LANG_QNAME = new QName(
0158:                    XMLSymbols.PREFIX_XML, XINCLUDE_LANG,
0159:                    (XMLSymbols.PREFIX_XML + ":" + XINCLUDE_LANG).intern(),
0160:                    NamespaceContext.XML_URI);
0161:
0162:            private final static QName NEW_NS_ATTR_QNAME = new QName(
0163:                    XMLSymbols.PREFIX_XMLNS, "", XMLSymbols.PREFIX_XMLNS + ":",
0164:                    NamespaceContext.XMLNS_URI);
0165:
0166:            // Processing States
0167:            private final static int STATE_NORMAL_PROCESSING = 1;
0168:            // we go into this state after a successful include (thus we ignore the children
0169:            // of the include) or after a fallback
0170:            private final static int STATE_IGNORE = 2;
0171:            // we go into this state after a failed include.  If we don't encounter a fallback
0172:            // before we reach the end include tag, it's a fatal error
0173:            private final static int STATE_EXPECT_FALLBACK = 3;
0174:
0175:            // recognized features and properties
0176:
0177:            /** Feature identifier: validation. */
0178:            protected static final String VALIDATION = Constants.SAX_FEATURE_PREFIX
0179:                    + Constants.VALIDATION_FEATURE;
0180:
0181:            /** Feature identifier: schema validation. */
0182:            protected static final String SCHEMA_VALIDATION = Constants.XERCES_FEATURE_PREFIX
0183:                    + Constants.SCHEMA_VALIDATION_FEATURE;
0184:
0185:            /** Feature identifier: dynamic validation. */
0186:            protected static final String DYNAMIC_VALIDATION = Constants.XERCES_FEATURE_PREFIX
0187:                    + Constants.DYNAMIC_VALIDATION_FEATURE;
0188:
0189:            /** Feature identifier: allow notation and unparsed entity events to be sent out of order. */
0190:            protected static final String ALLOW_UE_AND_NOTATION_EVENTS = Constants.SAX_FEATURE_PREFIX
0191:                    + Constants.ALLOW_DTD_EVENTS_AFTER_ENDDTD_FEATURE;
0192:
0193:            /** Feature identifier: fixup base URIs. */
0194:            protected static final String XINCLUDE_FIXUP_BASE_URIS = Constants.XERCES_FEATURE_PREFIX
0195:                    + Constants.XINCLUDE_FIXUP_BASE_URIS_FEATURE;
0196:
0197:            /** Feature identifier: fixup language. */
0198:            protected static final String XINCLUDE_FIXUP_LANGUAGE = Constants.XERCES_FEATURE_PREFIX
0199:                    + Constants.XINCLUDE_FIXUP_LANGUAGE_FEATURE;
0200:
0201:            /** Property identifier: JAXP schema language. */
0202:            protected static final String JAXP_SCHEMA_LANGUAGE = Constants.JAXP_PROPERTY_PREFIX
0203:                    + Constants.SCHEMA_LANGUAGE;
0204:
0205:            /** Property identifier: symbol table. */
0206:            protected static final String SYMBOL_TABLE = Constants.XERCES_PROPERTY_PREFIX
0207:                    + Constants.SYMBOL_TABLE_PROPERTY;
0208:
0209:            /** Property identifier: error reporter. */
0210:            protected static final String ERROR_REPORTER = Constants.XERCES_PROPERTY_PREFIX
0211:                    + Constants.ERROR_REPORTER_PROPERTY;
0212:
0213:            /** Property identifier: entity resolver. */
0214:            protected static final String ENTITY_RESOLVER = Constants.XERCES_PROPERTY_PREFIX
0215:                    + Constants.ENTITY_RESOLVER_PROPERTY;
0216:
0217:            /** property identifier: security manager. */
0218:            protected static final String SECURITY_MANAGER = Constants.XERCES_PROPERTY_PREFIX
0219:                    + Constants.SECURITY_MANAGER_PROPERTY;
0220:
0221:            /** property identifier: buffer size. */
0222:            protected static final String BUFFER_SIZE = Constants.XERCES_PROPERTY_PREFIX
0223:                    + Constants.BUFFER_SIZE_PROPERTY;
0224:
0225:            protected static final String PARSER_SETTINGS = Constants.XERCES_FEATURE_PREFIX
0226:                    + Constants.PARSER_SETTINGS;
0227:
0228:            /** Recognized features. */
0229:            private static final String[] RECOGNIZED_FEATURES = {
0230:                    ALLOW_UE_AND_NOTATION_EVENTS, XINCLUDE_FIXUP_BASE_URIS,
0231:                    XINCLUDE_FIXUP_LANGUAGE };
0232:
0233:            /** Feature defaults. */
0234:            private static final Boolean[] FEATURE_DEFAULTS = { Boolean.TRUE,
0235:                    Boolean.TRUE, Boolean.TRUE };
0236:
0237:            /** Recognized properties. */
0238:            private static final String[] RECOGNIZED_PROPERTIES = {
0239:                    ERROR_REPORTER, ENTITY_RESOLVER, SECURITY_MANAGER,
0240:                    BUFFER_SIZE };
0241:
0242:            /** Property defaults. */
0243:            private static final Object[] PROPERTY_DEFAULTS = { null, null,
0244:                    null, new Integer(XMLEntityManager.DEFAULT_BUFFER_SIZE) };
0245:
0246:            // instance variables
0247:
0248:            // for XMLDocumentFilter
0249:            protected XMLDocumentHandler fDocumentHandler;
0250:            protected XMLDocumentSource fDocumentSource;
0251:
0252:            // for XMLDTDFilter
0253:            protected XMLDTDHandler fDTDHandler;
0254:            protected XMLDTDSource fDTDSource;
0255:
0256:            // for XIncludeHandler
0257:            protected XIncludeHandler fParentXIncludeHandler;
0258:
0259:            // for buffer size in XIncludeTextReader
0260:            protected int fBufferSize = XMLEntityManager.DEFAULT_BUFFER_SIZE;
0261:
0262:            // It "feels wrong" to store this value here.  However,
0263:            // calculating it can be time consuming, so we cache it.
0264:            // It's never going to change in the lifetime of this XIncludeHandler
0265:            protected String fParentRelativeURI;
0266:
0267:            // we cache the child parser configuration, so we don't have to re-create
0268:            // the objects when the parser is re-used
0269:            protected XMLParserConfiguration fChildConfig;
0270:
0271:            // The cached child parser configuration, may contain a
0272:            // XInclude or XPointer Handler.  Cache both these
0273:            protected XMLParserConfiguration fXIncludeChildConfig;
0274:            protected XMLParserConfiguration fXPointerChildConfig;
0275:
0276:            // The XPointerProcessor
0277:            protected XPointerProcessor fXPtrProcessor = null;
0278:
0279:            protected XMLLocator fDocLocation;
0280:            protected XMLLocatorWrapper fXIncludeLocator = new XMLLocatorWrapper();
0281:            protected XIncludeMessageFormatter fXIncludeMessageFormatter = new XIncludeMessageFormatter();
0282:            protected XIncludeNamespaceSupport fNamespaceContext;
0283:            protected SymbolTable fSymbolTable;
0284:            protected XMLErrorReporter fErrorReporter;
0285:            protected XMLEntityResolver fEntityResolver;
0286:            protected SecurityManager fSecurityManager;
0287:
0288:            // these are needed for text include processing
0289:            protected XIncludeTextReader fXInclude10TextReader;
0290:            protected XIncludeTextReader fXInclude11TextReader;
0291:
0292:            // these are needed for XML Base processing
0293:            protected final XMLResourceIdentifier fCurrentBaseURI;
0294:            protected final IntStack fBaseURIScope;
0295:            protected final Stack fBaseURI;
0296:            protected final Stack fLiteralSystemID;
0297:            protected final Stack fExpandedSystemID;
0298:
0299:            // these are needed for Language Fixup
0300:            protected final IntStack fLanguageScope;
0301:            protected final Stack fLanguageStack;
0302:            protected String fCurrentLanguage;
0303:
0304:            protected String fHrefFromParent;
0305:
0306:            // used for passing features on to child XIncludeHandler objects
0307:            protected ParserConfigurationSettings fSettings;
0308:
0309:            // The current element depth.  We start at depth 0 (before we've reached any elements).
0310:            // The first element is at depth 1.
0311:            private int fDepth;
0312:
0313:            // The current element depth of the result infoset.
0314:            private int fResultDepth;
0315:
0316:            // this value must be at least 1
0317:            private static final int INITIAL_SIZE = 8;
0318:
0319:            // Used to ensure that fallbacks are always children of include elements,
0320:            // and that include elements are never children of other include elements.
0321:            // An index contains true if the ancestor of the current element which resides
0322:            // at that depth was an include element.
0323:            private boolean[] fSawInclude = new boolean[INITIAL_SIZE];
0324:
0325:            // Ensures that only one fallback element can be at a single depth.
0326:            // An index contains true if we have seen any fallback elements at that depth,
0327:            // and it is only reset to false when the end tag of the parent is encountered.
0328:            private boolean[] fSawFallback = new boolean[INITIAL_SIZE];
0329:
0330:            // The state of the processor at each given depth.
0331:            private int[] fState = new int[INITIAL_SIZE];
0332:
0333:            // buffering the necessary DTD events
0334:            private final ArrayList fNotations;
0335:            private final ArrayList fUnparsedEntities;
0336:
0337:            // flags which control whether base URI or language fixup is performed.
0338:            private boolean fFixupBaseURIs = true;
0339:            private boolean fFixupLanguage = true;
0340:
0341:            // for SAX compatibility.
0342:            // Has the value of the ALLOW_UE_AND_NOTATION_EVENTS feature
0343:            private boolean fSendUEAndNotationEvents;
0344:
0345:            // track the version of the document being parsed
0346:            private boolean fIsXML11;
0347:
0348:            // track whether a DTD is being parsed
0349:            private boolean fInDTD;
0350:
0351:            // tracks whether content has been reported on the child pipeline
0352:            boolean fHasIncludeReportedContent;
0353:
0354:            // track whether the root element of the result infoset has been processed
0355:            private boolean fSeenRootElement;
0356:
0357:            // track whether the child config needs its features refreshed
0358:            private boolean fNeedCopyFeatures = true;
0359:
0360:            // Constructors
0361:
0362:            public XIncludeHandler() {
0363:                fDepth = 0;
0364:
0365:                fSawFallback[fDepth] = false;
0366:                fSawInclude[fDepth] = false;
0367:                fState[fDepth] = STATE_NORMAL_PROCESSING;
0368:                fNotations = new ArrayList();
0369:                fUnparsedEntities = new ArrayList();
0370:
0371:                fBaseURIScope = new IntStack();
0372:                fBaseURI = new Stack();
0373:                fLiteralSystemID = new Stack();
0374:                fExpandedSystemID = new Stack();
0375:                fCurrentBaseURI = new XMLResourceIdentifierImpl();
0376:
0377:                fLanguageScope = new IntStack();
0378:                fLanguageStack = new Stack();
0379:                fCurrentLanguage = null;
0380:            }
0381:
0382:            // XMLComponent methods
0383:
0384:            public void reset(XMLComponentManager componentManager)
0385:                    throws XNIException {
0386:                fNamespaceContext = null;
0387:                fDepth = 0;
0388:                fResultDepth = isRootDocument() ? 0 : fParentXIncludeHandler
0389:                        .getResultDepth();
0390:                fNotations.clear();
0391:                fUnparsedEntities.clear();
0392:                fParentRelativeURI = null;
0393:                fIsXML11 = false;
0394:                fInDTD = false;
0395:                fSeenRootElement = false;
0396:
0397:                fBaseURIScope.clear();
0398:                fBaseURI.clear();
0399:                fLiteralSystemID.clear();
0400:                fExpandedSystemID.clear();
0401:                fLanguageScope.clear();
0402:                fLanguageStack.clear();
0403:
0404:                // REVISIT: Find a better method for maintaining
0405:                // the state of the XInclude processor. These arrays
0406:                // can potentially grow quite large. Cleaning them
0407:                // out on reset may be very time consuming. -- mrglavas
0408:                //
0409:                // clear the previous settings from the arrays
0410:                for (int i = 0; i < fState.length; ++i) {
0411:                    fState[i] = STATE_NORMAL_PROCESSING;
0412:                }
0413:                for (int i = 0; i < fSawFallback.length; ++i) {
0414:                    fSawFallback[i] = false;
0415:                }
0416:                for (int i = 0; i < fSawInclude.length; ++i) {
0417:                    fSawInclude[i] = false;
0418:                }
0419:
0420:                try {
0421:                    if (!componentManager.getFeature(PARSER_SETTINGS)) {
0422:                        // if parser settings have not changed return.
0423:                        return;
0424:                    }
0425:                } catch (XMLConfigurationException e) {
0426:                }
0427:
0428:                // parser settings changed. Need to refresh features on child config.
0429:                fNeedCopyFeatures = true;
0430:
0431:                try {
0432:                    fSendUEAndNotationEvents = componentManager
0433:                            .getFeature(ALLOW_UE_AND_NOTATION_EVENTS);
0434:                    if (fChildConfig != null) {
0435:                        fChildConfig.setFeature(ALLOW_UE_AND_NOTATION_EVENTS,
0436:                                fSendUEAndNotationEvents);
0437:                    }
0438:                } catch (XMLConfigurationException e) {
0439:                }
0440:
0441:                try {
0442:                    fFixupBaseURIs = componentManager
0443:                            .getFeature(XINCLUDE_FIXUP_BASE_URIS);
0444:                    if (fChildConfig != null) {
0445:                        fChildConfig.setFeature(XINCLUDE_FIXUP_BASE_URIS,
0446:                                fFixupBaseURIs);
0447:                    }
0448:                } catch (XMLConfigurationException e) {
0449:                    fFixupBaseURIs = true;
0450:                }
0451:
0452:                try {
0453:                    fFixupLanguage = componentManager
0454:                            .getFeature(XINCLUDE_FIXUP_LANGUAGE);
0455:                    if (fChildConfig != null) {
0456:                        fChildConfig.setFeature(XINCLUDE_FIXUP_LANGUAGE,
0457:                                fFixupLanguage);
0458:                    }
0459:                } catch (XMLConfigurationException e) {
0460:                    fFixupLanguage = true;
0461:                }
0462:
0463:                // Get symbol table.
0464:                try {
0465:                    SymbolTable value = (SymbolTable) componentManager
0466:                            .getProperty(SYMBOL_TABLE);
0467:                    if (value != null) {
0468:                        fSymbolTable = value;
0469:                        if (fChildConfig != null) {
0470:                            fChildConfig.setProperty(SYMBOL_TABLE, value);
0471:                        }
0472:                    }
0473:                } catch (XMLConfigurationException e) {
0474:                    fSymbolTable = null;
0475:                }
0476:
0477:                // Get error reporter.
0478:                try {
0479:                    XMLErrorReporter value = (XMLErrorReporter) componentManager
0480:                            .getProperty(ERROR_REPORTER);
0481:                    if (value != null) {
0482:                        setErrorReporter(value);
0483:                        if (fChildConfig != null) {
0484:                            fChildConfig.setProperty(ERROR_REPORTER, value);
0485:                        }
0486:                    }
0487:                } catch (XMLConfigurationException e) {
0488:                    fErrorReporter = null;
0489:                }
0490:
0491:                // Get entity resolver.
0492:                try {
0493:                    XMLEntityResolver value = (XMLEntityResolver) componentManager
0494:                            .getProperty(ENTITY_RESOLVER);
0495:
0496:                    if (value != null) {
0497:                        fEntityResolver = value;
0498:                        if (fChildConfig != null) {
0499:                            fChildConfig.setProperty(ENTITY_RESOLVER, value);
0500:                        }
0501:                    }
0502:                } catch (XMLConfigurationException e) {
0503:                    fEntityResolver = null;
0504:                }
0505:
0506:                // Get security manager.
0507:                try {
0508:                    SecurityManager value = (SecurityManager) componentManager
0509:                            .getProperty(SECURITY_MANAGER);
0510:
0511:                    if (value != null) {
0512:                        fSecurityManager = value;
0513:                        if (fChildConfig != null) {
0514:                            fChildConfig.setProperty(SECURITY_MANAGER, value);
0515:                        }
0516:                    }
0517:                } catch (XMLConfigurationException e) {
0518:                    fSecurityManager = null;
0519:                }
0520:
0521:                // Get buffer size.
0522:                try {
0523:                    Integer value = (Integer) componentManager
0524:                            .getProperty(BUFFER_SIZE);
0525:
0526:                    if (value != null && value.intValue() > 0) {
0527:                        fBufferSize = value.intValue();
0528:                        if (fChildConfig != null) {
0529:                            fChildConfig.setProperty(BUFFER_SIZE, value);
0530:                        }
0531:                    } else {
0532:                        fBufferSize = ((Integer) getPropertyDefault(BUFFER_SIZE))
0533:                                .intValue();
0534:                    }
0535:                } catch (XMLConfigurationException e) {
0536:                    fBufferSize = ((Integer) getPropertyDefault(BUFFER_SIZE))
0537:                            .intValue();
0538:                }
0539:
0540:                // Reset XML 1.0 text reader.
0541:                if (fXInclude10TextReader != null) {
0542:                    fXInclude10TextReader.setBufferSize(fBufferSize);
0543:                }
0544:                // Reset XML 1.1 text reader.
0545:                if (fXInclude11TextReader != null) {
0546:                    fXInclude11TextReader.setBufferSize(fBufferSize);
0547:                }
0548:
0549:                fSettings = new ParserConfigurationSettings();
0550:                copyFeatures(componentManager, fSettings);
0551:
0552:                // We don't want a schema validator on the new pipeline,
0553:                // so if it was enabled, we set the feature to false. 
0554:                try {
0555:                    if (componentManager.getFeature(SCHEMA_VALIDATION)) {
0556:                        fSettings.setFeature(SCHEMA_VALIDATION, false);
0557:                        // If the value of the JAXP 1.2 schema language property
0558:                        // is http://www.w3.org/2001/XMLSchema we're only validating 
0559:                        // against XML schema so we disable validation on the new pipeline.
0560:                        if (Constants.NS_XMLSCHEMA.equals(componentManager
0561:                                .getProperty(JAXP_SCHEMA_LANGUAGE))) {
0562:                            fSettings.setFeature(VALIDATION, false);
0563:                        }
0564:                        // If the validation feature was also enabled we turn on
0565:                        // dynamic validation, so that DTD validation is performed
0566:                        // on the included documents only if they have a DOCTYPE. 
0567:                        // This is consistent with the behaviour on the main pipeline.
0568:                        else if (componentManager.getFeature(VALIDATION)) {
0569:                            fSettings.setFeature(DYNAMIC_VALIDATION, true);
0570:                        }
0571:                    }
0572:                } catch (XMLConfigurationException e) {
0573:                }
0574:
0575:                // Don't reset fChildConfig -- we don't want it to share the same components.
0576:                // It will be reset when it is actually used to parse something.
0577:            } // reset(XMLComponentManager)
0578:
0579:            /**
0580:             * Returns a list of feature identifiers that are recognized by
0581:             * this component. This method may return null if no features
0582:             * are recognized by this component.
0583:             */
0584:            public String[] getRecognizedFeatures() {
0585:                return (String[]) (RECOGNIZED_FEATURES.clone());
0586:            } // getRecognizedFeatures():String[]
0587:
0588:            /**
0589:             * Sets the state of a feature. This method is called by the component
0590:             * manager any time after reset when a feature changes state.
0591:             * <p>
0592:             * <strong>Note:</strong> Components should silently ignore features
0593:             * that do not affect the operation of the component.
0594:             *
0595:             * @param featureId The feature identifier.
0596:             * @param state     The state of the feature.
0597:             *
0598:             * @throws SAXNotRecognizedException The component should not throw
0599:             *                                   this exception.
0600:             * @throws SAXNotSupportedException The component should not throw
0601:             *                                  this exception.
0602:             */
0603:            public void setFeature(String featureId, boolean state)
0604:                    throws XMLConfigurationException {
0605:                if (featureId.equals(ALLOW_UE_AND_NOTATION_EVENTS)) {
0606:                    fSendUEAndNotationEvents = state;
0607:                }
0608:                if (fSettings != null) {
0609:                    fNeedCopyFeatures = true;
0610:                    fSettings.setFeature(featureId, state);
0611:                }
0612:            } // setFeature(String,boolean)
0613:
0614:            /**
0615:             * Returns a list of property identifiers that are recognized by
0616:             * this component. This method may return null if no properties
0617:             * are recognized by this component.
0618:             */
0619:            public String[] getRecognizedProperties() {
0620:                return (String[]) (RECOGNIZED_PROPERTIES.clone());
0621:            } // getRecognizedProperties():String[]
0622:
0623:            /**
0624:             * Sets the value of a property. This method is called by the component
0625:             * manager any time after reset when a property changes value.
0626:             * <p>
0627:             * <strong>Note:</strong> Components should silently ignore properties
0628:             * that do not affect the operation of the component.
0629:             *
0630:             * @param propertyId The property identifier.
0631:             * @param value      The value of the property.
0632:             *
0633:             * @throws SAXNotRecognizedException The component should not throw
0634:             *                                   this exception.
0635:             * @throws SAXNotSupportedException The component should not throw
0636:             *                                  this exception.
0637:             */
0638:            public void setProperty(String propertyId, Object value)
0639:                    throws XMLConfigurationException {
0640:                if (propertyId.equals(SYMBOL_TABLE)) {
0641:                    fSymbolTable = (SymbolTable) value;
0642:                    if (fChildConfig != null) {
0643:                        fChildConfig.setProperty(propertyId, value);
0644:                    }
0645:                    return;
0646:                }
0647:                if (propertyId.equals(ERROR_REPORTER)) {
0648:                    setErrorReporter((XMLErrorReporter) value);
0649:                    if (fChildConfig != null) {
0650:                        fChildConfig.setProperty(propertyId, value);
0651:                    }
0652:                    return;
0653:                }
0654:                if (propertyId.equals(ENTITY_RESOLVER)) {
0655:                    fEntityResolver = (XMLEntityResolver) value;
0656:                    if (fChildConfig != null) {
0657:                        fChildConfig.setProperty(propertyId, value);
0658:                    }
0659:                    return;
0660:                }
0661:                if (propertyId.equals(SECURITY_MANAGER)) {
0662:                    fSecurityManager = (SecurityManager) value;
0663:                    if (fChildConfig != null) {
0664:                        fChildConfig.setProperty(propertyId, value);
0665:                    }
0666:                    return;
0667:                }
0668:                if (propertyId.equals(BUFFER_SIZE)) {
0669:                    Integer bufferSize = (Integer) value;
0670:                    if (fChildConfig != null) {
0671:                        fChildConfig.setProperty(propertyId, value);
0672:                    }
0673:                    if (bufferSize != null && bufferSize.intValue() > 0) {
0674:                        fBufferSize = bufferSize.intValue();
0675:                        // Reset XML 1.0 text reader.
0676:                        if (fXInclude10TextReader != null) {
0677:                            fXInclude10TextReader.setBufferSize(fBufferSize);
0678:                        }
0679:                        // Reset XML 1.1 text reader.
0680:                        if (fXInclude11TextReader != null) {
0681:                            fXInclude11TextReader.setBufferSize(fBufferSize);
0682:                        }
0683:                    }
0684:                    return;
0685:                }
0686:
0687:            } // setProperty(String,Object)
0688:
0689:            /**
0690:             * Returns the default state for a feature, or null if this
0691:             * component does not want to report a default value for this
0692:             * feature.
0693:             *
0694:             * @param featureId The feature identifier.
0695:             *
0696:             * @since Xerces 2.2.0
0697:             */
0698:            public Boolean getFeatureDefault(String featureId) {
0699:                for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
0700:                    if (RECOGNIZED_FEATURES[i].equals(featureId)) {
0701:                        return FEATURE_DEFAULTS[i];
0702:                    }
0703:                }
0704:                return null;
0705:            } // getFeatureDefault(String):Boolean
0706:
0707:            /**
0708:             * Returns the default state for a property, or null if this
0709:             * component does not want to report a default value for this
0710:             * property.
0711:             *
0712:             * @param propertyId The property identifier.
0713:             *
0714:             * @since Xerces 2.2.0
0715:             */
0716:            public Object getPropertyDefault(String propertyId) {
0717:                for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
0718:                    if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
0719:                        return PROPERTY_DEFAULTS[i];
0720:                    }
0721:                }
0722:                return null;
0723:            } // getPropertyDefault(String):Object
0724:
0725:            public void setDocumentHandler(XMLDocumentHandler handler) {
0726:                if (fDocumentHandler != handler) {
0727:                    fDocumentHandler = handler;
0728:                    if (fXIncludeChildConfig != null) {
0729:                        fXIncludeChildConfig.setDocumentHandler(handler);
0730:                    }
0731:                    if (fXPointerChildConfig != null) {
0732:                        fXPointerChildConfig.setDocumentHandler(handler);
0733:                    }
0734:                }
0735:            }
0736:
0737:            public XMLDocumentHandler getDocumentHandler() {
0738:                return fDocumentHandler;
0739:            }
0740:
0741:            // XMLDocumentHandler methods
0742:
0743:            /**
0744:             * Event sent at the start of the document.
0745:             *
0746:             * A fatal error will occur here, if it is detected that this document has been processed
0747:             * before.
0748:             *
0749:             * This event is only passed on to the document handler if this is the root document.
0750:             */
0751:            public void startDocument(XMLLocator locator, String encoding,
0752:                    NamespaceContext namespaceContext, Augmentations augs)
0753:                    throws XNIException {
0754:
0755:                // we do this to ensure that the proper location is reported in errors
0756:                // otherwise, the locator from the root document would always be used
0757:                fErrorReporter.setDocumentLocator(locator);
0758:
0759:                if (!(namespaceContext instanceof  XIncludeNamespaceSupport)) {
0760:                    reportFatalError("IncompatibleNamespaceContext");
0761:                }
0762:                fNamespaceContext = (XIncludeNamespaceSupport) namespaceContext;
0763:                fDocLocation = locator;
0764:                fXIncludeLocator.setLocator(fDocLocation);
0765:
0766:                // initialize the current base URI
0767:                setupCurrentBaseURI(locator);
0768:                saveBaseURI();
0769:                if (augs == null) {
0770:                    augs = new AugmentationsImpl();
0771:                }
0772:                augs.putItem(CURRENT_BASE_URI, fCurrentBaseURI);
0773:
0774:                // abort here if we detect a recursive include
0775:                if (!isRootDocument()) {
0776:                    fParentXIncludeHandler.fHasIncludeReportedContent = true;
0777:                    if (fParentXIncludeHandler
0778:                            .searchForRecursiveIncludes(fCurrentBaseURI
0779:                                    .getExpandedSystemId())) {
0780:                        reportFatalError("RecursiveInclude",
0781:                                new Object[] { fCurrentBaseURI
0782:                                        .getExpandedSystemId() });
0783:                    }
0784:                }
0785:
0786:                // initialize the current language
0787:                fCurrentLanguage = XMLSymbols.EMPTY_STRING;
0788:                saveLanguage(fCurrentLanguage);
0789:
0790:                if (isRootDocument() && fDocumentHandler != null) {
0791:                    fDocumentHandler.startDocument(fXIncludeLocator, encoding,
0792:                            namespaceContext, augs);
0793:                }
0794:            }
0795:
0796:            public void xmlDecl(String version, String encoding,
0797:                    String standalone, Augmentations augs) throws XNIException {
0798:                fIsXML11 = "1.1".equals(version);
0799:                if (isRootDocument() && fDocumentHandler != null) {
0800:                    fDocumentHandler.xmlDecl(version, encoding, standalone,
0801:                            augs);
0802:                }
0803:            }
0804:
0805:            public void doctypeDecl(String rootElement, String publicId,
0806:                    String systemId, Augmentations augs) throws XNIException {
0807:                if (isRootDocument() && fDocumentHandler != null) {
0808:                    fDocumentHandler.doctypeDecl(rootElement, publicId,
0809:                            systemId, augs);
0810:                }
0811:            }
0812:
0813:            public void comment(XMLString text, Augmentations augs)
0814:                    throws XNIException {
0815:                if (!fInDTD) {
0816:                    if (fDocumentHandler != null
0817:                            && getState() == STATE_NORMAL_PROCESSING) {
0818:                        fDepth++;
0819:                        augs = modifyAugmentations(augs);
0820:                        fDocumentHandler.comment(text, augs);
0821:                        fDepth--;
0822:                    }
0823:                } else if (fDTDHandler != null) {
0824:                    fDTDHandler.comment(text, augs);
0825:                }
0826:            }
0827:
0828:            public void processingInstruction(String target, XMLString data,
0829:                    Augmentations augs) throws XNIException {
0830:                if (!fInDTD) {
0831:                    if (fDocumentHandler != null
0832:                            && getState() == STATE_NORMAL_PROCESSING) {
0833:                        // we need to change the depth like this so that modifyAugmentations() works
0834:                        fDepth++;
0835:                        augs = modifyAugmentations(augs);
0836:                        fDocumentHandler.processingInstruction(target, data,
0837:                                augs);
0838:                        fDepth--;
0839:                    }
0840:                } else if (fDTDHandler != null) {
0841:                    fDTDHandler.processingInstruction(target, data, augs);
0842:                }
0843:            }
0844:
0845:            public void startElement(QName element, XMLAttributes attributes,
0846:                    Augmentations augs) throws XNIException {
0847:                fDepth++;
0848:                int lastState = getState(fDepth - 1);
0849:                // If the last two states were fallback then this must be a descendant of an include
0850:                // child which isn't a fallback. The specification says we should ignore such elements
0851:                // and their children.
0852:                if (lastState == STATE_EXPECT_FALLBACK
0853:                        && getState(fDepth - 2) == STATE_EXPECT_FALLBACK) {
0854:                    setState(STATE_IGNORE);
0855:                } else {
0856:                    setState(lastState);
0857:                }
0858:
0859:                // we process the xml:base and xml:lang attributes regardless
0860:                // of what type of element it is.
0861:                processXMLBaseAttributes(attributes);
0862:                if (fFixupLanguage) {
0863:                    processXMLLangAttributes(attributes);
0864:                }
0865:
0866:                if (isIncludeElement(element)) {
0867:                    boolean success = this .handleIncludeElement(attributes);
0868:                    if (success) {
0869:                        setState(STATE_IGNORE);
0870:                    } else {
0871:                        setState(STATE_EXPECT_FALLBACK);
0872:                    }
0873:                } else if (isFallbackElement(element)) {
0874:                    this .handleFallbackElement();
0875:                } else if (hasXIncludeNamespace(element)) {
0876:                    if (getSawInclude(fDepth - 1)) {
0877:                        reportFatalError("IncludeChild",
0878:                                new Object[] { element.rawname });
0879:                    }
0880:                    if (getSawFallback(fDepth - 1)) {
0881:                        reportFatalError("FallbackChild",
0882:                                new Object[] { element.rawname });
0883:                    }
0884:                    if (getState() == STATE_NORMAL_PROCESSING) {
0885:                        if (fResultDepth++ == 0) {
0886:                            checkMultipleRootElements();
0887:                        }
0888:                        if (fDocumentHandler != null) {
0889:                            augs = modifyAugmentations(augs);
0890:                            attributes = processAttributes(attributes);
0891:                            fDocumentHandler.startElement(element, attributes,
0892:                                    augs);
0893:                        }
0894:                    }
0895:                } else if (getState() == STATE_NORMAL_PROCESSING) {
0896:                    if (fResultDepth++ == 0) {
0897:                        checkMultipleRootElements();
0898:                    }
0899:                    if (fDocumentHandler != null) {
0900:                        augs = modifyAugmentations(augs);
0901:                        attributes = processAttributes(attributes);
0902:                        fDocumentHandler
0903:                                .startElement(element, attributes, augs);
0904:                    }
0905:                }
0906:            }
0907:
0908:            public void emptyElement(QName element, XMLAttributes attributes,
0909:                    Augmentations augs) throws XNIException {
0910:                fDepth++;
0911:                int lastState = getState(fDepth - 1);
0912:                // If the last two states were fallback then this must be a descendant of an include
0913:                // child which isn't a fallback. The specification says we should ignore such elements
0914:                // and their children.
0915:                if (lastState == STATE_EXPECT_FALLBACK
0916:                        && getState(fDepth - 2) == STATE_EXPECT_FALLBACK) {
0917:                    setState(STATE_IGNORE);
0918:                } else {
0919:                    setState(lastState);
0920:                }
0921:
0922:                // we process the xml:base and xml:lang attributes regardless
0923:                // of what type of element it is.
0924:                processXMLBaseAttributes(attributes);
0925:                if (fFixupLanguage) {
0926:                    processXMLLangAttributes(attributes);
0927:                }
0928:
0929:                if (isIncludeElement(element)) {
0930:                    boolean success = this .handleIncludeElement(attributes);
0931:                    if (success) {
0932:                        setState(STATE_IGNORE);
0933:                    } else {
0934:                        reportFatalError("NoFallback");
0935:                    }
0936:                } else if (isFallbackElement(element)) {
0937:                    this .handleFallbackElement();
0938:                } else if (hasXIncludeNamespace(element)) {
0939:                    if (getSawInclude(fDepth - 1)) {
0940:                        reportFatalError("IncludeChild",
0941:                                new Object[] { element.rawname });
0942:                    }
0943:                    if (getSawFallback(fDepth - 1)) {
0944:                        reportFatalError("FallbackChild",
0945:                                new Object[] { element.rawname });
0946:                    }
0947:                    if (getState() == STATE_NORMAL_PROCESSING) {
0948:                        if (fResultDepth == 0) {
0949:                            checkMultipleRootElements();
0950:                        }
0951:                        if (fDocumentHandler != null) {
0952:                            augs = modifyAugmentations(augs);
0953:                            attributes = processAttributes(attributes);
0954:                            fDocumentHandler.emptyElement(element, attributes,
0955:                                    augs);
0956:                        }
0957:                    }
0958:                } else if (getState() == STATE_NORMAL_PROCESSING) {
0959:                    if (fResultDepth == 0) {
0960:                        checkMultipleRootElements();
0961:                    }
0962:                    if (fDocumentHandler != null) {
0963:                        augs = modifyAugmentations(augs);
0964:                        attributes = processAttributes(attributes);
0965:                        fDocumentHandler
0966:                                .emptyElement(element, attributes, augs);
0967:                    }
0968:                }
0969:                // reset the out of scope stack elements
0970:                setSawFallback(fDepth + 1, false);
0971:                setSawInclude(fDepth, false);
0972:
0973:                // check if an xml:base has gone out of scope
0974:                if (fBaseURIScope.size() > 0 && fDepth == fBaseURIScope.peek()) {
0975:                    // pop the values from the stack
0976:                    restoreBaseURI();
0977:                }
0978:                fDepth--;
0979:            }
0980:
0981:            public void endElement(QName element, Augmentations augs)
0982:                    throws XNIException {
0983:
0984:                if (isIncludeElement(element)) {
0985:                    // if we're ending an include element, and we were expecting a fallback
0986:                    // we check to see if the children of this include element contained a fallback
0987:                    if (getState() == STATE_EXPECT_FALLBACK
0988:                            && !getSawFallback(fDepth + 1)) {
0989:                        reportFatalError("NoFallback");
0990:                    }
0991:                }
0992:                if (isFallbackElement(element)) {
0993:                    // the state would have been set to normal processing if we were expecting the fallback element
0994:                    // now that we're done processing it, we should ignore all the other children of the include element
0995:                    if (getState() == STATE_NORMAL_PROCESSING) {
0996:                        setState(STATE_IGNORE);
0997:                    }
0998:                } else if (getState() == STATE_NORMAL_PROCESSING) {
0999:                    --fResultDepth;
1000:                    if (fDocumentHandler != null) {
1001:                        fDocumentHandler.endElement(element, augs);
1002:                    }
1003:                }
1004:
1005:                // reset the out of scope stack elements
1006:                setSawFallback(fDepth + 1, false);
1007:                setSawInclude(fDepth, false);
1008:
1009:                // check if an xml:base has gone out of scope
1010:                if (fBaseURIScope.size() > 0 && fDepth == fBaseURIScope.peek()) {
1011:                    // pop the values from the stack
1012:                    restoreBaseURI();
1013:                }
1014:
1015:                // check if an xml:lang has gone out of scope
1016:                if (fLanguageScope.size() > 0
1017:                        && fDepth == fLanguageScope.peek()) {
1018:                    // pop the language from the stack
1019:                    fCurrentLanguage = restoreLanguage();
1020:                }
1021:
1022:                fDepth--;
1023:            }
1024:
1025:            public void startGeneralEntity(String name,
1026:                    XMLResourceIdentifier resId, String encoding,
1027:                    Augmentations augs) throws XNIException {
1028:                if (getState() == STATE_NORMAL_PROCESSING) {
1029:                    if (fResultDepth == 0) {
1030:                        if (augs != null
1031:                                && Boolean.TRUE.equals(augs
1032:                                        .getItem(Constants.ENTITY_SKIPPED))) {
1033:                            reportFatalError("UnexpandedEntityReferenceIllegal");
1034:                        }
1035:                    } else if (fDocumentHandler != null) {
1036:                        fDocumentHandler.startGeneralEntity(name, resId,
1037:                                encoding, augs);
1038:                    }
1039:                }
1040:            }
1041:
1042:            public void textDecl(String version, String encoding,
1043:                    Augmentations augs) throws XNIException {
1044:                if (fDocumentHandler != null
1045:                        && getState() == STATE_NORMAL_PROCESSING) {
1046:                    fDocumentHandler.textDecl(version, encoding, augs);
1047:                }
1048:            }
1049:
1050:            public void endGeneralEntity(String name, Augmentations augs)
1051:                    throws XNIException {
1052:                if (fDocumentHandler != null
1053:                        && getState() == STATE_NORMAL_PROCESSING
1054:                        && fResultDepth != 0) {
1055:                    fDocumentHandler.endGeneralEntity(name, augs);
1056:                }
1057:            }
1058:
1059:            public void characters(XMLString text, Augmentations augs)
1060:                    throws XNIException {
1061:                if (getState() == STATE_NORMAL_PROCESSING) {
1062:                    if (fResultDepth == 0) {
1063:                        checkWhitespace(text);
1064:                    } else if (fDocumentHandler != null) {
1065:                        // we need to change the depth like this so that modifyAugmentations() works
1066:                        fDepth++;
1067:                        augs = modifyAugmentations(augs);
1068:                        fDocumentHandler.characters(text, augs);
1069:                        fDepth--;
1070:                    }
1071:                }
1072:            }
1073:
1074:            public void ignorableWhitespace(XMLString text, Augmentations augs)
1075:                    throws XNIException {
1076:                if (fDocumentHandler != null
1077:                        && getState() == STATE_NORMAL_PROCESSING
1078:                        && fResultDepth != 0) {
1079:                    fDocumentHandler.ignorableWhitespace(text, augs);
1080:                }
1081:            }
1082:
1083:            public void startCDATA(Augmentations augs) throws XNIException {
1084:                if (fDocumentHandler != null
1085:                        && getState() == STATE_NORMAL_PROCESSING
1086:                        && fResultDepth != 0) {
1087:                    fDocumentHandler.startCDATA(augs);
1088:                }
1089:            }
1090:
1091:            public void endCDATA(Augmentations augs) throws XNIException {
1092:                if (fDocumentHandler != null
1093:                        && getState() == STATE_NORMAL_PROCESSING
1094:                        && fResultDepth != 0) {
1095:                    fDocumentHandler.endCDATA(augs);
1096:                }
1097:            }
1098:
1099:            public void endDocument(Augmentations augs) throws XNIException {
1100:                if (isRootDocument()) {
1101:                    if (!fSeenRootElement) {
1102:                        reportFatalError("RootElementRequired");
1103:                    }
1104:                    if (fDocumentHandler != null) {
1105:                        fDocumentHandler.endDocument(augs);
1106:                    }
1107:                }
1108:            }
1109:
1110:            public void setDocumentSource(XMLDocumentSource source) {
1111:                fDocumentSource = source;
1112:            }
1113:
1114:            public XMLDocumentSource getDocumentSource() {
1115:                return fDocumentSource;
1116:            }
1117:
1118:            // DTDHandler methods
1119:            // We are only interested in the notation and unparsed entity declarations,
1120:            // the rest we just pass on
1121:
1122:            /* (non-Javadoc)
1123:             * @see org.apache.xerces.xni.XMLDTDHandler#attributeDecl(java.lang.String, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, org.apache.xerces.xni.XMLString, org.apache.xerces.xni.XMLString, org.apache.xerces.xni.Augmentations)
1124:             */
1125:            public void attributeDecl(String elementName, String attributeName,
1126:                    String type, String[] enumeration, String defaultType,
1127:                    XMLString defaultValue,
1128:                    XMLString nonNormalizedDefaultValue,
1129:                    Augmentations augmentations) throws XNIException {
1130:                if (fDTDHandler != null) {
1131:                    fDTDHandler.attributeDecl(elementName, attributeName, type,
1132:                            enumeration, defaultType, defaultValue,
1133:                            nonNormalizedDefaultValue, augmentations);
1134:                }
1135:            }
1136:
1137:            /* (non-Javadoc)
1138:             * @see org.apache.xerces.xni.XMLDTDHandler#elementDecl(java.lang.String, java.lang.String, org.apache.xerces.xni.Augmentations)
1139:             */
1140:            public void elementDecl(String name, String contentModel,
1141:                    Augmentations augmentations) throws XNIException {
1142:                if (fDTDHandler != null) {
1143:                    fDTDHandler.elementDecl(name, contentModel, augmentations);
1144:                }
1145:            }
1146:
1147:            /* (non-Javadoc)
1148:             * @see org.apache.xerces.xni.XMLDTDHandler#endAttlist(org.apache.xerces.xni.Augmentations)
1149:             */
1150:            public void endAttlist(Augmentations augmentations)
1151:                    throws XNIException {
1152:                if (fDTDHandler != null) {
1153:                    fDTDHandler.endAttlist(augmentations);
1154:                }
1155:            }
1156:
1157:            /* (non-Javadoc)
1158:             * @see org.apache.xerces.xni.XMLDTDHandler#endConditional(org.apache.xerces.xni.Augmentations)
1159:             */
1160:            public void endConditional(Augmentations augmentations)
1161:                    throws XNIException {
1162:                if (fDTDHandler != null) {
1163:                    fDTDHandler.endConditional(augmentations);
1164:                }
1165:            }
1166:
1167:            /* (non-Javadoc)
1168:             * @see org.apache.xerces.xni.XMLDTDHandler#endDTD(org.apache.xerces.xni.Augmentations)
1169:             */
1170:            public void endDTD(Augmentations augmentations) throws XNIException {
1171:                if (fDTDHandler != null) {
1172:                    fDTDHandler.endDTD(augmentations);
1173:                }
1174:                fInDTD = false;
1175:            }
1176:
1177:            /* (non-Javadoc)
1178:             * @see org.apache.xerces.xni.XMLDTDHandler#endExternalSubset(org.apache.xerces.xni.Augmentations)
1179:             */
1180:            public void endExternalSubset(Augmentations augmentations)
1181:                    throws XNIException {
1182:                if (fDTDHandler != null) {
1183:                    fDTDHandler.endExternalSubset(augmentations);
1184:                }
1185:            }
1186:
1187:            /* (non-Javadoc)
1188:             * @see org.apache.xerces.xni.XMLDTDHandler#endParameterEntity(java.lang.String, org.apache.xerces.xni.Augmentations)
1189:             */
1190:            public void endParameterEntity(String name,
1191:                    Augmentations augmentations) throws XNIException {
1192:                if (fDTDHandler != null) {
1193:                    fDTDHandler.endParameterEntity(name, augmentations);
1194:                }
1195:            }
1196:
1197:            /* (non-Javadoc)
1198:             * @see org.apache.xerces.xni.XMLDTDHandler#externalEntityDecl(java.lang.String, org.apache.xerces.xni.XMLResourceIdentifier, org.apache.xerces.xni.Augmentations)
1199:             */
1200:            public void externalEntityDecl(String name,
1201:                    XMLResourceIdentifier identifier,
1202:                    Augmentations augmentations) throws XNIException {
1203:                if (fDTDHandler != null) {
1204:                    fDTDHandler.externalEntityDecl(name, identifier,
1205:                            augmentations);
1206:                }
1207:            }
1208:
1209:            /* (non-Javadoc)
1210:             * @see org.apache.xerces.xni.XMLDTDHandler#getDTDSource()
1211:             */
1212:            public XMLDTDSource getDTDSource() {
1213:                return fDTDSource;
1214:            }
1215:
1216:            /* (non-Javadoc)
1217:             * @see org.apache.xerces.xni.XMLDTDHandler#ignoredCharacters(org.apache.xerces.xni.XMLString, org.apache.xerces.xni.Augmentations)
1218:             */
1219:            public void ignoredCharacters(XMLString text,
1220:                    Augmentations augmentations) throws XNIException {
1221:                if (fDTDHandler != null) {
1222:                    fDTDHandler.ignoredCharacters(text, augmentations);
1223:                }
1224:            }
1225:
1226:            /* (non-Javadoc)
1227:             * @see org.apache.xerces.xni.XMLDTDHandler#internalEntityDecl(java.lang.String, org.apache.xerces.xni.XMLString, org.apache.xerces.xni.XMLString, org.apache.xerces.xni.Augmentations)
1228:             */
1229:            public void internalEntityDecl(String name, XMLString text,
1230:                    XMLString nonNormalizedText, Augmentations augmentations)
1231:                    throws XNIException {
1232:                if (fDTDHandler != null) {
1233:                    fDTDHandler.internalEntityDecl(name, text,
1234:                            nonNormalizedText, augmentations);
1235:                }
1236:            }
1237:
1238:            /* (non-Javadoc)
1239:             * @see org.apache.xerces.xni.XMLDTDHandler#notationDecl(java.lang.String, org.apache.xerces.xni.XMLResourceIdentifier, org.apache.xerces.xni.Augmentations)
1240:             */
1241:            public void notationDecl(String name,
1242:                    XMLResourceIdentifier identifier,
1243:                    Augmentations augmentations) throws XNIException {
1244:                this .addNotation(name, identifier, augmentations);
1245:                if (fDTDHandler != null) {
1246:                    fDTDHandler.notationDecl(name, identifier, augmentations);
1247:                }
1248:            }
1249:
1250:            /* (non-Javadoc)
1251:             * @see org.apache.xerces.xni.XMLDTDHandler#setDTDSource(org.apache.xerces.xni.parser.XMLDTDSource)
1252:             */
1253:            public void setDTDSource(XMLDTDSource source) {
1254:                fDTDSource = source;
1255:            }
1256:
1257:            /* (non-Javadoc)
1258:             * @see org.apache.xerces.xni.XMLDTDHandler#startAttlist(java.lang.String, org.apache.xerces.xni.Augmentations)
1259:             */
1260:            public void startAttlist(String elementName,
1261:                    Augmentations augmentations) throws XNIException {
1262:                if (fDTDHandler != null) {
1263:                    fDTDHandler.startAttlist(elementName, augmentations);
1264:                }
1265:            }
1266:
1267:            /* (non-Javadoc)
1268:             * @see org.apache.xerces.xni.XMLDTDHandler#startConditional(short, org.apache.xerces.xni.Augmentations)
1269:             */
1270:            public void startConditional(short type, Augmentations augmentations)
1271:                    throws XNIException {
1272:                if (fDTDHandler != null) {
1273:                    fDTDHandler.startConditional(type, augmentations);
1274:                }
1275:            }
1276:
1277:            /* (non-Javadoc)
1278:             * @see org.apache.xerces.xni.XMLDTDHandler#startDTD(org.apache.xerces.xni.XMLLocator, org.apache.xerces.xni.Augmentations)
1279:             */
1280:            public void startDTD(XMLLocator locator, Augmentations augmentations)
1281:                    throws XNIException {
1282:                fInDTD = true;
1283:                if (fDTDHandler != null) {
1284:                    fDTDHandler.startDTD(locator, augmentations);
1285:                }
1286:            }
1287:
1288:            /* (non-Javadoc)
1289:             * @see org.apache.xerces.xni.XMLDTDHandler#startExternalSubset(org.apache.xerces.xni.XMLResourceIdentifier, org.apache.xerces.xni.Augmentations)
1290:             */
1291:            public void startExternalSubset(XMLResourceIdentifier identifier,
1292:                    Augmentations augmentations) throws XNIException {
1293:                if (fDTDHandler != null) {
1294:                    fDTDHandler.startExternalSubset(identifier, augmentations);
1295:                }
1296:            }
1297:
1298:            /* (non-Javadoc)
1299:             * @see org.apache.xerces.xni.XMLDTDHandler#startParameterEntity(java.lang.String, org.apache.xerces.xni.XMLResourceIdentifier, java.lang.String, org.apache.xerces.xni.Augmentations)
1300:             */
1301:            public void startParameterEntity(String name,
1302:                    XMLResourceIdentifier identifier, String encoding,
1303:                    Augmentations augmentations) throws XNIException {
1304:                if (fDTDHandler != null) {
1305:                    fDTDHandler.startParameterEntity(name, identifier,
1306:                            encoding, augmentations);
1307:                }
1308:            }
1309:
1310:            /* (non-Javadoc)
1311:             * @see org.apache.xerces.xni.XMLDTDHandler#unparsedEntityDecl(java.lang.String, org.apache.xerces.xni.XMLResourceIdentifier, java.lang.String, org.apache.xerces.xni.Augmentations)
1312:             */
1313:            public void unparsedEntityDecl(String name,
1314:                    XMLResourceIdentifier identifier, String notation,
1315:                    Augmentations augmentations) throws XNIException {
1316:                this .addUnparsedEntity(name, identifier, notation,
1317:                        augmentations);
1318:                if (fDTDHandler != null) {
1319:                    fDTDHandler.unparsedEntityDecl(name, identifier, notation,
1320:                            augmentations);
1321:                }
1322:            }
1323:
1324:            /* (non-Javadoc)
1325:             * @see org.apache.xerces.xni.parser.XMLDTDSource#getDTDHandler()
1326:             */
1327:            public XMLDTDHandler getDTDHandler() {
1328:                return fDTDHandler;
1329:            }
1330:
1331:            /* (non-Javadoc)
1332:             * @see org.apache.xerces.xni.parser.XMLDTDSource#setDTDHandler(org.apache.xerces.xni.XMLDTDHandler)
1333:             */
1334:            public void setDTDHandler(XMLDTDHandler handler) {
1335:                fDTDHandler = handler;
1336:            }
1337:
1338:            // XIncludeHandler methods
1339:
1340:            private void setErrorReporter(XMLErrorReporter reporter) {
1341:                fErrorReporter = reporter;
1342:                if (fErrorReporter != null) {
1343:                    fErrorReporter.putMessageFormatter(
1344:                            XIncludeMessageFormatter.XINCLUDE_DOMAIN,
1345:                            fXIncludeMessageFormatter);
1346:                    // this ensures the proper location is displayed in error messages
1347:                    if (fDocLocation != null) {
1348:                        fErrorReporter.setDocumentLocator(fDocLocation);
1349:                    }
1350:                }
1351:            }
1352:
1353:            protected void handleFallbackElement() {
1354:                if (!getSawInclude(fDepth - 1)) {
1355:                    if (getState() == STATE_IGNORE) {
1356:                        return;
1357:                    }
1358:                    reportFatalError("FallbackParent");
1359:                }
1360:
1361:                setSawInclude(fDepth, false);
1362:                fNamespaceContext.setContextInvalid();
1363:
1364:                if (getSawFallback(fDepth)) {
1365:                    reportFatalError("MultipleFallbacks");
1366:                } else {
1367:                    setSawFallback(fDepth, true);
1368:                }
1369:
1370:                // Either the state is STATE_EXPECT_FALLBACK or it's STATE_IGNORE.
1371:                // If we're ignoring, we want to stay ignoring. But if we're expecting this fallback element,
1372:                // we want to signal that we should process the children.
1373:                if (getState() == STATE_EXPECT_FALLBACK) {
1374:                    setState(STATE_NORMAL_PROCESSING);
1375:                }
1376:            }
1377:
1378:            protected boolean handleIncludeElement(XMLAttributes attributes)
1379:                    throws XNIException {
1380:                if (getSawInclude(fDepth - 1)) {
1381:                    reportFatalError("IncludeChild",
1382:                            new Object[] { XINCLUDE_INCLUDE });
1383:                }
1384:                if (getState() == STATE_IGNORE) {
1385:                    return true;
1386:                }
1387:                setSawInclude(fDepth, true);
1388:                fNamespaceContext.setContextInvalid();
1389:
1390:                // TODO: does Java use IURIs by default?
1391:                //       [Definition: An internationalized URI reference, or IURI, is a URI reference that directly uses [Unicode] characters.]
1392:                // TODO: figure out what section 4.1.1 of the XInclude spec is talking about
1393:                //       has to do with disallowed ASCII character escaping
1394:                //       this ties in with the above IURI section, but I suspect Java already does it
1395:
1396:                String href = attributes.getValue(XINCLUDE_ATTR_HREF);
1397:                String parse = attributes.getValue(XINCLUDE_ATTR_PARSE);
1398:                String xpointer = attributes.getValue(XPOINTER);
1399:                String accept = attributes.getValue(XINCLUDE_ATTR_ACCEPT);
1400:                String acceptLanguage = attributes
1401:                        .getValue(XINCLUDE_ATTR_ACCEPT_LANGUAGE);
1402:
1403:                if (parse == null) {
1404:                    parse = XINCLUDE_PARSE_XML;
1405:                }
1406:                if (href == null) {
1407:                    href = XMLSymbols.EMPTY_STRING;
1408:                }
1409:                if (href.length() == 0 && XINCLUDE_PARSE_XML.equals(parse)) {
1410:                    if (xpointer == null) {
1411:                        reportFatalError("XpointerMissing");
1412:                    } else {
1413:                        // When parse="xml" and an xpointer is specified treat 
1414:                        // all absences of the href attribute as a resource error.
1415:                        Locale locale = (fErrorReporter != null) ? fErrorReporter
1416:                                .getLocale()
1417:                                : null;
1418:                        String reason = fXIncludeMessageFormatter
1419:                                .formatMessage(locale, "XPointerStreamability",
1420:                                        null);
1421:                        reportResourceError("XMLResourceError", new Object[] {
1422:                                href, reason });
1423:                        return false;
1424:                    }
1425:                }
1426:
1427:                URI hrefURI = null;
1428:
1429:                // Check whether href is correct and perform escaping as per section 4.1.1 of the XInclude spec.
1430:                // Report fatal error if the href value contains a fragment identifier or if the value after
1431:                // escaping is a syntactically invalid URI or IRI.
1432:                try {
1433:                    hrefURI = new URI(href, true);
1434:                    if (hrefURI.getFragment() != null) {
1435:                        reportFatalError("HrefFragmentIdentifierIllegal",
1436:                                new Object[] { href });
1437:                    }
1438:                } catch (URI.MalformedURIException exc) {
1439:                    String newHref = escapeHref(href);
1440:                    if (href != newHref) {
1441:                        href = newHref;
1442:                        try {
1443:                            hrefURI = new URI(href, true);
1444:                            if (hrefURI.getFragment() != null) {
1445:                                reportFatalError(
1446:                                        "HrefFragmentIdentifierIllegal",
1447:                                        new Object[] { href });
1448:                            }
1449:                        } catch (URI.MalformedURIException exc2) {
1450:                            reportFatalError("HrefSyntacticallyInvalid",
1451:                                    new Object[] { href });
1452:                        }
1453:                    } else {
1454:                        reportFatalError("HrefSyntacticallyInvalid",
1455:                                new Object[] { href });
1456:                    }
1457:                }
1458:
1459:                // Verify that if an accept and/or an accept-language attribute exist
1460:                // that the value(s) don't contain disallowed characters.
1461:                if (accept != null && !isValidInHTTPHeader(accept)) {
1462:                    reportFatalError("AcceptMalformed", null);
1463:                    accept = null;
1464:                }
1465:                if (acceptLanguage != null
1466:                        && !isValidInHTTPHeader(acceptLanguage)) {
1467:                    reportFatalError("AcceptLanguageMalformed", null);
1468:                    acceptLanguage = null;
1469:                }
1470:
1471:                XMLInputSource includedSource = null;
1472:                if (fEntityResolver != null) {
1473:                    try {
1474:                        XMLResourceIdentifier resourceIdentifier = new XMLResourceIdentifierImpl(
1475:                                null, href, fCurrentBaseURI
1476:                                        .getExpandedSystemId(),
1477:                                XMLEntityManager.expandSystemId(href,
1478:                                        fCurrentBaseURI.getExpandedSystemId(),
1479:                                        false));
1480:
1481:                        includedSource = fEntityResolver
1482:                                .resolveEntity(resourceIdentifier);
1483:
1484:                        if (includedSource != null
1485:                                && !(includedSource instanceof  HTTPInputSource)
1486:                                && (accept != null || acceptLanguage != null)
1487:                                && includedSource.getCharacterStream() == null
1488:                                && includedSource.getByteStream() == null) {
1489:
1490:                            includedSource = createInputSource(includedSource
1491:                                    .getPublicId(), includedSource
1492:                                    .getSystemId(), includedSource
1493:                                    .getBaseSystemId(), accept, acceptLanguage);
1494:                        }
1495:                    } catch (IOException e) {
1496:                        reportResourceError("XMLResourceError", new Object[] {
1497:                                href, e.getMessage() });
1498:                        return false;
1499:                    }
1500:                }
1501:
1502:                if (includedSource == null) {
1503:                    // setup an HTTPInputSource if either of the content negotation attributes were specified.
1504:                    if (accept != null || acceptLanguage != null) {
1505:                        includedSource = createInputSource(null, href,
1506:                                fCurrentBaseURI.getExpandedSystemId(), accept,
1507:                                acceptLanguage);
1508:                    } else {
1509:                        includedSource = new XMLInputSource(null, href,
1510:                                fCurrentBaseURI.getExpandedSystemId());
1511:                    }
1512:                }
1513:
1514:                if (parse.equals(XINCLUDE_PARSE_XML)) {
1515:                    // Instead of always creating a new configuration, the first one can be reused
1516:                    if ((xpointer != null && fXPointerChildConfig == null)
1517:                            || (xpointer == null && fXIncludeChildConfig == null)) {
1518:
1519:                        String parserName = XINCLUDE_DEFAULT_CONFIGURATION;
1520:                        if (xpointer != null)
1521:                            parserName = "org.apache.xerces.parsers.XPointerParserConfiguration";
1522:
1523:                        fChildConfig = (XMLParserConfiguration) ObjectFactory
1524:                                .newInstance(parserName, ObjectFactory
1525:                                        .findClassLoader(), true);
1526:
1527:                        // use the same symbol table, error reporter, entity resolver, security manager and buffer size.
1528:                        if (fSymbolTable != null)
1529:                            fChildConfig
1530:                                    .setProperty(SYMBOL_TABLE, fSymbolTable);
1531:                        if (fErrorReporter != null)
1532:                            fChildConfig.setProperty(ERROR_REPORTER,
1533:                                    fErrorReporter);
1534:                        if (fEntityResolver != null)
1535:                            fChildConfig.setProperty(ENTITY_RESOLVER,
1536:                                    fEntityResolver);
1537:                        fChildConfig.setProperty(SECURITY_MANAGER,
1538:                                fSecurityManager);
1539:                        fChildConfig.setProperty(BUFFER_SIZE, new Integer(
1540:                                fBufferSize));
1541:
1542:                        // features must be copied to child configuration
1543:                        fNeedCopyFeatures = true;
1544:
1545:                        // use the same namespace context
1546:                        fChildConfig.setProperty(
1547:                                Constants.XERCES_PROPERTY_PREFIX
1548:                                        + Constants.NAMESPACE_CONTEXT_PROPERTY,
1549:                                fNamespaceContext);
1550:
1551:                        fChildConfig.setFeature(XINCLUDE_FIXUP_BASE_URIS,
1552:                                fFixupBaseURIs);
1553:
1554:                        fChildConfig.setFeature(XINCLUDE_FIXUP_LANGUAGE,
1555:                                fFixupLanguage);
1556:
1557:                        // If the xpointer attribute is present
1558:                        if (xpointer != null) {
1559:
1560:                            XPointerHandler newHandler = (XPointerHandler) fChildConfig
1561:                                    .getProperty(Constants.XERCES_PROPERTY_PREFIX
1562:                                            + Constants.XPOINTER_HANDLER_PROPERTY);
1563:
1564:                            fXPtrProcessor = newHandler;
1565:
1566:                            // ???
1567:                            ((XPointerHandler) fXPtrProcessor)
1568:                                    .setProperty(
1569:                                            Constants.XERCES_PROPERTY_PREFIX
1570:                                                    + Constants.NAMESPACE_CONTEXT_PROPERTY,
1571:                                            fNamespaceContext);
1572:
1573:                            ((XPointerHandler) fXPtrProcessor).setProperty(
1574:                                    XINCLUDE_FIXUP_BASE_URIS,
1575:                                    fFixupBaseURIs ? Boolean.TRUE
1576:                                            : Boolean.FALSE);
1577:
1578:                            ((XPointerHandler) fXPtrProcessor).setProperty(
1579:                                    XINCLUDE_FIXUP_LANGUAGE,
1580:                                    fFixupLanguage ? Boolean.TRUE
1581:                                            : Boolean.FALSE);
1582:
1583:                            if (fErrorReporter != null)
1584:                                ((XPointerHandler) fXPtrProcessor).setProperty(
1585:                                        ERROR_REPORTER, fErrorReporter);
1586:                            // ???
1587:
1588:                            newHandler.setParent(this );
1589:                            newHandler.setHref(href);
1590:                            newHandler.setXIncludeLocator(fXIncludeLocator);
1591:                            newHandler.setDocumentHandler(this 
1592:                                    .getDocumentHandler());
1593:                            fXPointerChildConfig = fChildConfig;
1594:                        } else {
1595:                            XIncludeHandler newHandler = (XIncludeHandler) fChildConfig
1596:                                    .getProperty(Constants.XERCES_PROPERTY_PREFIX
1597:                                            + Constants.XINCLUDE_HANDLER_PROPERTY);
1598:
1599:                            newHandler.setParent(this );
1600:                            newHandler.setHref(href);
1601:                            newHandler.setXIncludeLocator(fXIncludeLocator);
1602:                            newHandler.setDocumentHandler(this 
1603:                                    .getDocumentHandler());
1604:                            fXIncludeChildConfig = fChildConfig;
1605:                        }
1606:                    }
1607:
1608:                    // If an xpointer attribute is present
1609:                    if (xpointer != null) {
1610:                        fChildConfig = fXPointerChildConfig;
1611:
1612:                        // Parse the XPointer expression
1613:                        try {
1614:                            ((XPointerProcessor) fXPtrProcessor)
1615:                                    .parseXPointer(xpointer);
1616:
1617:                        } catch (XNIException ex) {
1618:                            // report the XPointer error as a resource error
1619:                            reportResourceError("XMLResourceError",
1620:                                    new Object[] { href, ex.getMessage() });
1621:                            return false;
1622:                        }
1623:                    } else {
1624:                        fChildConfig = fXIncludeChildConfig;
1625:                    }
1626:
1627:                    // set all features on parserConfig to match this parser configuration
1628:                    if (fNeedCopyFeatures) {
1629:                        copyFeatures(fSettings, fChildConfig);
1630:                    }
1631:                    fNeedCopyFeatures = false;
1632:
1633:                    try {
1634:                        fHasIncludeReportedContent = false;
1635:                        fNamespaceContext.pushScope();
1636:
1637:                        fChildConfig.parse(includedSource);
1638:                        // necessary to make sure proper location is reported to the application and in errors
1639:                        fXIncludeLocator.setLocator(fDocLocation);
1640:                        if (fErrorReporter != null) {
1641:                            fErrorReporter.setDocumentLocator(fDocLocation);
1642:                        }
1643:
1644:                        // If the xpointer attribute is present
1645:                        if (xpointer != null) {
1646:                            // and it was not resolved
1647:                            if (!((XPointerProcessor) fXPtrProcessor)
1648:                                    .isXPointerResolved()) {
1649:                                Locale locale = (fErrorReporter != null) ? fErrorReporter
1650:                                        .getLocale()
1651:                                        : null;
1652:                                String reason = fXIncludeMessageFormatter
1653:                                        .formatMessage(
1654:                                                locale,
1655:                                                "XPointerResolutionUnsuccessful",
1656:                                                null);
1657:                                reportResourceError("XMLResourceError",
1658:                                        new Object[] { href, reason });
1659:                                // use the fallback
1660:                                return false;
1661:                            }
1662:                        }
1663:                    } catch (XNIException e) {
1664:                        // necessary to make sure proper location is reported to the application and in errors
1665:                        fXIncludeLocator.setLocator(fDocLocation);
1666:                        if (fErrorReporter != null) {
1667:                            fErrorReporter.setDocumentLocator(fDocLocation);
1668:                        }
1669:                        reportFatalError("XMLParseError", new Object[] { href });
1670:                    } catch (IOException e) {
1671:                        // necessary to make sure proper location is reported to the application and in errors
1672:                        fXIncludeLocator.setLocator(fDocLocation);
1673:                        if (fErrorReporter != null) {
1674:                            fErrorReporter.setDocumentLocator(fDocLocation);
1675:                        }
1676:                        // If the start document event has been seen on the child pipeline it
1677:                        // means the resource was successfully opened and we started reporting
1678:                        // document events. If an IOException is thrown after the start document
1679:                        // event we had a failure midstream and cannot recover.
1680:                        if (fHasIncludeReportedContent) {
1681:                            throw new XNIException(e);
1682:                        }
1683:                        // In other circumstances an IOException indicates that we had trouble 
1684:                        // accessing or opening the file, not that it was an invalid XML file. So we 
1685:                        // send a resource error, not a fatal error.
1686:                        reportResourceError("XMLResourceError", new Object[] {
1687:                                href, e.getMessage() });
1688:                        return false;
1689:                    } finally {
1690:                        fNamespaceContext.popScope();
1691:                    }
1692:                } else if (parse.equals(XINCLUDE_PARSE_TEXT)) {
1693:                    // we only care about encoding for parse="text"
1694:                    String encoding = attributes
1695:                            .getValue(XINCLUDE_ATTR_ENCODING);
1696:                    includedSource.setEncoding(encoding);
1697:                    XIncludeTextReader textReader = null;
1698:
1699:                    try {
1700:                        fHasIncludeReportedContent = false;
1701:
1702:                        // Setup the appropriate text reader.
1703:                        if (!fIsXML11) {
1704:                            if (fXInclude10TextReader == null) {
1705:                                fXInclude10TextReader = new XIncludeTextReader(
1706:                                        includedSource, this , fBufferSize);
1707:                            } else {
1708:                                fXInclude10TextReader
1709:                                        .setInputSource(includedSource);
1710:                            }
1711:                            textReader = fXInclude10TextReader;
1712:                        } else {
1713:                            if (fXInclude11TextReader == null) {
1714:                                fXInclude11TextReader = new XInclude11TextReader(
1715:                                        includedSource, this , fBufferSize);
1716:                            } else {
1717:                                fXInclude11TextReader
1718:                                        .setInputSource(includedSource);
1719:                            }
1720:                            textReader = fXInclude11TextReader;
1721:                        }
1722:                        textReader.setErrorReporter(fErrorReporter);
1723:                        textReader.parse();
1724:                    }
1725:                    // encoding errors
1726:                    catch (MalformedByteSequenceException ex) {
1727:                        fErrorReporter.reportError(ex.getDomain(), ex.getKey(),
1728:                                ex.getArguments(),
1729:                                XMLErrorReporter.SEVERITY_FATAL_ERROR, ex);
1730:                    } catch (CharConversionException e) {
1731:                        fErrorReporter.reportError(
1732:                                XMLMessageFormatter.XML_DOMAIN,
1733:                                "CharConversionFailure", null,
1734:                                XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
1735:                    } catch (IOException e) {
1736:                        // If a characters event has already been sent down the pipeline it
1737:                        // means the resource was successfully opened and that this IOException
1738:                        // is from a failure midstream from which we cannot recover.
1739:                        if (fHasIncludeReportedContent) {
1740:                            throw new XNIException(e);
1741:                        }
1742:                        reportResourceError("TextResourceError", new Object[] {
1743:                                href, e.getMessage() });
1744:                        return false;
1745:                    } finally {
1746:                        if (textReader != null) {
1747:                            try {
1748:                                textReader.close();
1749:                            } catch (IOException e) {
1750:                                reportResourceError("TextResourceError",
1751:                                        new Object[] { href, e.getMessage() });
1752:                                return false;
1753:                            }
1754:                        }
1755:                    }
1756:                } else {
1757:                    reportFatalError("InvalidParseValue",
1758:                            new Object[] { parse });
1759:                }
1760:                return true;
1761:            }
1762:
1763:            /**
1764:             * Returns true if the element has the namespace "http://www.w3.org/2001/XInclude"
1765:             * @param element the element to check
1766:             * @return true if the element has the namespace "http://www.w3.org/2001/XInclude"
1767:             */
1768:            protected boolean hasXIncludeNamespace(QName element) {
1769:                // REVISIT: The namespace of this element should be bound
1770:                // already. Why are we looking it up from the namespace
1771:                // context? -- mrglavas
1772:                return element.uri == XINCLUDE_NS_URI
1773:                        || fNamespaceContext.getURI(element.prefix) == XINCLUDE_NS_URI;
1774:            }
1775:
1776:            /**
1777:             * Checks if the element is an &lt;include&gt; element.  The element must have
1778:             * the XInclude namespace, and a local name of "include".
1779:             *
1780:             * @param element the element to check
1781:             * @return true if the element is an &lt;include&gt; element
1782:             * @see #hasXIncludeNamespace(QName)
1783:             */
1784:            protected boolean isIncludeElement(QName element) {
1785:                return element.localpart.equals(XINCLUDE_INCLUDE)
1786:                        && hasXIncludeNamespace(element);
1787:            }
1788:
1789:            /**
1790:             * Checks if the element is an &lt;fallback&gt; element.  The element must have
1791:             * the XInclude namespace, and a local name of "fallback".
1792:             *
1793:             * @param element the element to check
1794:             * @return true if the element is an &lt;fallback; element
1795:             * @see #hasXIncludeNamespace(QName)
1796:             */
1797:            protected boolean isFallbackElement(QName element) {
1798:                return element.localpart.equals(XINCLUDE_FALLBACK)
1799:                        && hasXIncludeNamespace(element);
1800:            }
1801:
1802:            /**
1803:             * Returns true if the current [base URI] is the same as the [base URI] that
1804:             * was in effect on the include parent.  This method should <em>only</em> be called
1805:             * when the current element is a top level included element, i.e. the direct child
1806:             * of a fallback element, or the root elements in an included document.
1807:             * The "include parent" is the element which, in the result infoset, will be the
1808:             * direct parent of the current element.
1809:             * @return true if the [base URIs] are the same string
1810:             */
1811:            protected boolean sameBaseURIAsIncludeParent() {
1812:                String parentBaseURI = getIncludeParentBaseURI();
1813:                String baseURI = fCurrentBaseURI.getExpandedSystemId();
1814:                // REVISIT: should we use File#sameFile() ?
1815:                //          I think the benefit of using it is that it resolves host names
1816:                //          instead of just doing a string comparison.
1817:                // TODO: [base URI] is still an open issue with the working group.
1818:                //       They're deciding if xml:base should be added if the [base URI] is different in terms
1819:                //       of resolving relative references, or if it should be added if they are different at all.
1820:                //       Revisit this after a final decision has been made.
1821:                //       The decision also affects whether we output the file name of the URI, or just the path.
1822:                return parentBaseURI != null && parentBaseURI.equals(baseURI);
1823:            }
1824:
1825:            /**
1826:             * Returns true if the current [language] is equivalent to the [language] that
1827:             * was in effect on the include parent, taking case-insensitivity into account
1828:             * as per [RFC 3066].  This method should <em>only</em> be called when the
1829:             * current element is a top level included element, i.e. the direct child
1830:             * of a fallback element, or the root elements in an included document.
1831:             * The "include parent" is the element which, in the result infoset, will be the
1832:             * direct parent of the current element.
1833:             * 
1834:             * @return true if the [language] properties have the same value
1835:             * taking case-insensitivity into account as per [RFC 3066].
1836:             */
1837:            protected boolean sameLanguageAsIncludeParent() {
1838:                String parentLanguage = getIncludeParentLanguage();
1839:                return parentLanguage != null
1840:                        && parentLanguage.equalsIgnoreCase(fCurrentLanguage);
1841:            }
1842:
1843:            protected void setupCurrentBaseURI(XMLLocator locator) {
1844:                fCurrentBaseURI.setBaseSystemId(locator.getBaseSystemId());
1845:
1846:                if (locator.getLiteralSystemId() != null) {
1847:                    fCurrentBaseURI.setLiteralSystemId(locator
1848:                            .getLiteralSystemId());
1849:                } else {
1850:                    fCurrentBaseURI.setLiteralSystemId(fHrefFromParent);
1851:                }
1852:
1853:                String expandedSystemId = locator.getExpandedSystemId();
1854:                if (expandedSystemId == null) {
1855:                    // attempt to expand it ourselves
1856:                    try {
1857:                        expandedSystemId = XMLEntityManager.expandSystemId(
1858:                                fCurrentBaseURI.getLiteralSystemId(),
1859:                                fCurrentBaseURI.getBaseSystemId(), false);
1860:                        if (expandedSystemId == null) {
1861:                            expandedSystemId = fCurrentBaseURI
1862:                                    .getLiteralSystemId();
1863:                        }
1864:                    } catch (MalformedURIException e) {
1865:                        reportFatalError("ExpandedSystemId");
1866:                    }
1867:                }
1868:                fCurrentBaseURI.setExpandedSystemId(expandedSystemId);
1869:            }
1870:
1871:            /**
1872:             * Checks if the file indicated by the given system id has already been
1873:             * included in the current stack.
1874:             * @param includedSysId the system id to check for inclusion
1875:             * @return true if the source has already been included
1876:             */
1877:            protected boolean searchForRecursiveIncludes(String includedSysId) {
1878:                if (includedSysId.equals(fCurrentBaseURI.getExpandedSystemId())) {
1879:                    return true;
1880:                } else if (fParentXIncludeHandler == null) {
1881:                    return false;
1882:                } else {
1883:                    return fParentXIncludeHandler
1884:                            .searchForRecursiveIncludes(includedSysId);
1885:                }
1886:            }
1887:
1888:            /**
1889:             * Returns true if the current element is a top level included item.  This means
1890:             * it's either the child of a fallback element, or the top level item in an
1891:             * included document
1892:             * @return true if the current element is a top level included item
1893:             */
1894:            protected boolean isTopLevelIncludedItem() {
1895:                return isTopLevelIncludedItemViaInclude()
1896:                        || isTopLevelIncludedItemViaFallback();
1897:            }
1898:
1899:            protected boolean isTopLevelIncludedItemViaInclude() {
1900:                return fDepth == 1 && !isRootDocument();
1901:            }
1902:
1903:            protected boolean isTopLevelIncludedItemViaFallback() {
1904:                // Technically, this doesn't check if the parent was a fallback, it also
1905:                // would return true if any of the parent's sibling elements were fallbacks.
1906:                // However, this doesn't matter, since we will always be ignoring elements
1907:                // whose parent's siblings were fallbacks.
1908:                return getSawFallback(fDepth - 1);
1909:            }
1910:
1911:            /**
1912:             * Processes the XMLAttributes object of startElement() calls.  Performs the following tasks:
1913:             * <ul>
1914:             * <li> If the element is a top level included item whose [base URI] is different from the
1915:             * [base URI] of the include parent, then an xml:base attribute is added to specify the
1916:             * true [base URI]
1917:             * <li> For all namespace prefixes which are in-scope in an included item, but not in scope
1918:             * in the include parent, a xmlns:prefix attribute is added
1919:             * <li> For all attributes with a type of ENTITY, ENTITIES or NOTATIONS, the notations and
1920:             * unparsed entities are processed as described in the spec, sections 4.5.1 and 4.5.2
1921:             * </ul>
1922:             * @param attributes
1923:             * @return the processed XMLAttributes
1924:             */
1925:            protected XMLAttributes processAttributes(XMLAttributes attributes) {
1926:                if (isTopLevelIncludedItem()) {
1927:                    // Modify attributes to fix the base URI (spec 4.5.5).
1928:                    // We only do it to top level included elements, which have a different
1929:                    // base URI than their include parent.
1930:                    if (fFixupBaseURIs && !sameBaseURIAsIncludeParent()) {
1931:                        if (attributes == null) {
1932:                            attributes = new XMLAttributesImpl();
1933:                        }
1934:
1935:                        // This causes errors with schema validation, if the schema doesn't
1936:                        // specify that these elements can have an xml:base attribute
1937:                        String uri = null;
1938:                        try {
1939:                            uri = this .getRelativeBaseURI();
1940:                        } catch (MalformedURIException e) {
1941:                            // this shouldn't ever happen, since by definition, we had to traverse
1942:                            // the same URIs to even get to this place
1943:                            uri = fCurrentBaseURI.getExpandedSystemId();
1944:                        }
1945:                        int index = attributes.addAttribute(XML_BASE_QNAME,
1946:                                XMLSymbols.fCDATASymbol, uri);
1947:                        attributes.setSpecified(index, true);
1948:                    }
1949:
1950:                    // Modify attributes to perform language-fixup (spec 4.5.6).
1951:                    // We only do it to top level included elements, which have a different
1952:                    // [language] than their include parent.
1953:                    if (fFixupLanguage && !sameLanguageAsIncludeParent()) {
1954:                        if (attributes == null) {
1955:                            attributes = new XMLAttributesImpl();
1956:                        }
1957:                        int index = attributes.addAttribute(XML_LANG_QNAME,
1958:                                XMLSymbols.fCDATASymbol, fCurrentLanguage);
1959:                        attributes.setSpecified(index, true);
1960:                    }
1961:
1962:                    // Modify attributes of included items to do namespace-fixup. (spec 4.5.4)
1963:                    Enumeration inscopeNS = fNamespaceContext.getAllPrefixes();
1964:                    while (inscopeNS.hasMoreElements()) {
1965:                        String prefix = (String) inscopeNS.nextElement();
1966:                        String parentURI = fNamespaceContext
1967:                                .getURIFromIncludeParent(prefix);
1968:                        String uri = fNamespaceContext.getURI(prefix);
1969:                        if (parentURI != uri && attributes != null) {
1970:                            if (prefix == XMLSymbols.EMPTY_STRING) {
1971:                                if (attributes.getValue(
1972:                                        NamespaceContext.XMLNS_URI,
1973:                                        XMLSymbols.PREFIX_XMLNS) == null) {
1974:                                    if (attributes == null) {
1975:                                        attributes = new XMLAttributesImpl();
1976:                                    }
1977:
1978:                                    QName ns = (QName) NEW_NS_ATTR_QNAME
1979:                                            .clone();
1980:                                    ns.prefix = null;
1981:                                    ns.localpart = XMLSymbols.PREFIX_XMLNS;
1982:                                    ns.rawname = XMLSymbols.PREFIX_XMLNS;
1983:                                    int index = attributes.addAttribute(ns,
1984:                                            XMLSymbols.fCDATASymbol,
1985:                                            uri != null ? uri
1986:                                                    : XMLSymbols.EMPTY_STRING);
1987:                                    attributes.setSpecified(index, true);
1988:                                    // Need to re-declare this prefix in the current context
1989:                                    // in order for the SAX parser to report the appropriate
1990:                                    // start and end prefix mapping events. -- mrglavas
1991:                                    fNamespaceContext
1992:                                            .declarePrefix(prefix, uri);
1993:                                }
1994:                            } else if (attributes.getValue(
1995:                                    NamespaceContext.XMLNS_URI, prefix) == null) {
1996:                                if (attributes == null) {
1997:                                    attributes = new XMLAttributesImpl();
1998:                                }
1999:
2000:                                QName ns = (QName) NEW_NS_ATTR_QNAME.clone();
2001:                                ns.localpart = prefix;
2002:                                ns.rawname += prefix;
2003:                                ns.rawname = (fSymbolTable != null) ? fSymbolTable
2004:                                        .addSymbol(ns.rawname)
2005:                                        : ns.rawname.intern();
2006:                                int index = attributes.addAttribute(ns,
2007:                                        XMLSymbols.fCDATASymbol,
2008:                                        uri != null ? uri
2009:                                                : XMLSymbols.EMPTY_STRING);
2010:                                attributes.setSpecified(index, true);
2011:                                // Need to re-declare this prefix in the current context
2012:                                // in order for the SAX parser to report the appropriate 
2013:                                // start and end prefix mapping events. -- mrglavas
2014:                                fNamespaceContext.declarePrefix(prefix, uri);
2015:                            }
2016:                        }
2017:                    }
2018:                }
2019:
2020:                if (attributes != null) {
2021:                    int length = attributes.getLength();
2022:                    for (int i = 0; i < length; i++) {
2023:                        String type = attributes.getType(i);
2024:                        String value = attributes.getValue(i);
2025:                        if (type == XMLSymbols.fENTITYSymbol) {
2026:                            this .checkUnparsedEntity(value);
2027:                        }
2028:                        if (type == XMLSymbols.fENTITIESSymbol) {
2029:                            // 4.5.1 - Unparsed Entities
2030:                            StringTokenizer st = new StringTokenizer(value);
2031:                            while (st.hasMoreTokens()) {
2032:                                String entName = st.nextToken();
2033:                                this .checkUnparsedEntity(entName);
2034:                            }
2035:                        } else if (type == XMLSymbols.fNOTATIONSymbol) {
2036:                            // 4.5.2 - Notations
2037:                            this .checkNotation(value);
2038:                        }
2039:                        /* We actually don't need to do anything for 4.5.3, because at this stage the
2040:                         * value of the attribute is just a string. It will be taken care of later
2041:                         * in the pipeline, when the IDREFs are actually resolved against IDs.
2042:                         *
2043:                         * if (type == XMLSymbols.fIDREFSymbol || type == XMLSymbols.fIDREFSSymbol) { }
2044:                         */
2045:                    }
2046:                }
2047:
2048:                return attributes;
2049:            }
2050:
2051:            /**
2052:             * Returns a URI, relative to the include parent's base URI, of the current
2053:             * [base URI].  For instance, if the current [base URI] was "dir1/dir2/file.xml"
2054:             * and the include parent's [base URI] was "dir/", this would return "dir2/file.xml".
2055:             * @return the relative URI
2056:             */
2057:            protected String getRelativeBaseURI() throws MalformedURIException {
2058:                int includeParentDepth = getIncludeParentDepth();
2059:                String relativeURI = this .getRelativeURI(includeParentDepth);
2060:                if (isRootDocument()) {
2061:                    return relativeURI;
2062:                } else {
2063:                    if (relativeURI.equals("")) {
2064:                        relativeURI = fCurrentBaseURI.getLiteralSystemId();
2065:                    }
2066:
2067:                    if (includeParentDepth == 0) {
2068:                        if (fParentRelativeURI == null) {
2069:                            fParentRelativeURI = fParentXIncludeHandler
2070:                                    .getRelativeBaseURI();
2071:                        }
2072:                        if (fParentRelativeURI.equals("")) {
2073:                            return relativeURI;
2074:                        }
2075:
2076:                        URI base = new URI(fParentRelativeURI, true);
2077:                        URI uri = new URI(base, relativeURI);
2078:
2079:                        /** Check whether the scheme components are equal. */
2080:                        final String baseScheme = base.getScheme();
2081:                        final String literalScheme = uri.getScheme();
2082:                        if (!isEqual(baseScheme, literalScheme)) {
2083:                            return relativeURI;
2084:                        }
2085:
2086:                        /** Check whether the authority components are equal. */
2087:                        final String baseAuthority = base.getAuthority();
2088:                        final String literalAuthority = uri.getAuthority();
2089:                        if (!isEqual(baseAuthority, literalAuthority)) {
2090:                            return uri.getSchemeSpecificPart();
2091:                        }
2092:
2093:                        /** 
2094:                         * The scheme and authority components are equal,
2095:                         * return the path and the possible query and/or
2096:                         * fragment which follow.
2097:                         */
2098:                        final String literalPath = uri.getPath();
2099:                        final String literalQuery = uri.getQueryString();
2100:                        final String literalFragment = uri.getFragment();
2101:                        if (literalQuery != null || literalFragment != null) {
2102:                            StringBuffer buffer = new StringBuffer();
2103:                            if (literalPath != null) {
2104:                                buffer.append(literalPath);
2105:                            }
2106:                            if (literalQuery != null) {
2107:                                buffer.append('?');
2108:                                buffer.append(literalQuery);
2109:                            }
2110:                            if (literalFragment != null) {
2111:                                buffer.append('#');
2112:                                buffer.append(literalFragment);
2113:                            }
2114:                            return buffer.toString();
2115:                        }
2116:                        return literalPath;
2117:                    } else {
2118:                        return relativeURI;
2119:                    }
2120:                }
2121:            }
2122:
2123:            /**
2124:             * Returns the [base URI] of the include parent.
2125:             * @return the base URI of the include parent.
2126:             */
2127:            private String getIncludeParentBaseURI() {
2128:                int depth = getIncludeParentDepth();
2129:                if (!isRootDocument() && depth == 0) {
2130:                    return fParentXIncludeHandler.getIncludeParentBaseURI();
2131:                } else {
2132:                    return this .getBaseURI(depth);
2133:                }
2134:            }
2135:
2136:            /**
2137:             * Returns the [language] of the include parent.
2138:             * 
2139:             * @return the language property of the include parent.
2140:             */
2141:            private String getIncludeParentLanguage() {
2142:                int depth = getIncludeParentDepth();
2143:                if (!isRootDocument() && depth == 0) {
2144:                    return fParentXIncludeHandler.getIncludeParentLanguage();
2145:                } else {
2146:                    return getLanguage(depth);
2147:                }
2148:            }
2149:
2150:            /**
2151:             * Returns the depth of the include parent.  Here, the include parent is
2152:             * calculated as the last non-include or non-fallback element. It is assumed
2153:             * this method is called when the current element is a top level included item.
2154:             * Returning 0 indicates that the top level element in this document
2155:             * was an include element.
2156:             * @return the depth of the top level include element
2157:             */
2158:            private int getIncludeParentDepth() {
2159:                // We don't start at fDepth, since it is either the top level included item,
2160:                // or an include element, when this method is called.
2161:                for (int i = fDepth - 1; i >= 0; i--) {
2162:                    // This technically might not always return the first non-include/fallback
2163:                    // element that it comes to, since sawFallback() returns true if a fallback
2164:                    // was ever encountered at that depth.  However, if a fallback was encountered
2165:                    // at that depth, and it wasn't the direct descendant of the current element
2166:                    // then we can't be in a situation where we're calling this method (because
2167:                    // we'll always be in STATE_IGNORE)
2168:                    if (!getSawInclude(i) && !getSawFallback(i)) {
2169:                        return i;
2170:                    }
2171:                }
2172:                // shouldn't get here, since depth 0 should never have an include element or
2173:                // a fallback element
2174:                return 0;
2175:            }
2176:
2177:            /** 
2178:             * Returns the current element depth of the result infoset.
2179:             */
2180:            private int getResultDepth() {
2181:                return fResultDepth;
2182:            }
2183:
2184:            /**
2185:             * Modify the augmentations.  Add an [included] infoset item, if the current
2186:             * element is a top level included item.
2187:             * @param augs the Augmentations to modify.
2188:             * @return the modified Augmentations
2189:             */
2190:            protected Augmentations modifyAugmentations(Augmentations augs) {
2191:                return modifyAugmentations(augs, false);
2192:            }
2193:
2194:            /**
2195:             * Modify the augmentations.  Add an [included] infoset item, if <code>force</code>
2196:             * is true, or if the current element is a top level included item.
2197:             * @param augs the Augmentations to modify.
2198:             * @param force whether to force modification
2199:             * @return the modified Augmentations
2200:             */
2201:            protected Augmentations modifyAugmentations(Augmentations augs,
2202:                    boolean force) {
2203:                if (force || isTopLevelIncludedItem()) {
2204:                    if (augs == null) {
2205:                        augs = new AugmentationsImpl();
2206:                    }
2207:                    augs.putItem(XINCLUDE_INCLUDED, Boolean.TRUE);
2208:                }
2209:                return augs;
2210:            }
2211:
2212:            protected int getState(int depth) {
2213:                return fState[depth];
2214:            }
2215:
2216:            protected int getState() {
2217:                return fState[fDepth];
2218:            }
2219:
2220:            protected void setState(int state) {
2221:                if (fDepth >= fState.length) {
2222:                    int[] newarray = new int[fDepth * 2];
2223:                    System.arraycopy(fState, 0, newarray, 0, fState.length);
2224:                    fState = newarray;
2225:                }
2226:                fState[fDepth] = state;
2227:            }
2228:
2229:            /**
2230:             * Records that an &lt;fallback&gt; was encountered at the specified depth,
2231:             * as an ancestor of the current element, or as a sibling of an ancestor of the
2232:             * current element.
2233:             *
2234:             * @param depth
2235:             * @param val
2236:             */
2237:            protected void setSawFallback(int depth, boolean val) {
2238:                if (depth >= fSawFallback.length) {
2239:                    boolean[] newarray = new boolean[depth * 2];
2240:                    System.arraycopy(fSawFallback, 0, newarray, 0,
2241:                            fSawFallback.length);
2242:                    fSawFallback = newarray;
2243:                }
2244:                fSawFallback[depth] = val;
2245:            }
2246:
2247:            /**
2248:             * Returns whether an &lt;fallback&gt; was encountered at the specified depth,
2249:             * as an ancestor of the current element, or as a sibling of an ancestor of the
2250:             * current element.
2251:             *
2252:             * @param depth
2253:             */
2254:            protected boolean getSawFallback(int depth) {
2255:                if (depth >= fSawFallback.length) {
2256:                    return false;
2257:                }
2258:                return fSawFallback[depth];
2259:            }
2260:
2261:            /**
2262:             * Records that an &lt;include&gt; was encountered at the specified depth,
2263:             * as an ancestor of the current item.
2264:             *
2265:             * @param depth
2266:             * @param val
2267:             */
2268:            protected void setSawInclude(int depth, boolean val) {
2269:                if (depth >= fSawInclude.length) {
2270:                    boolean[] newarray = new boolean[depth * 2];
2271:                    System.arraycopy(fSawInclude, 0, newarray, 0,
2272:                            fSawInclude.length);
2273:                    fSawInclude = newarray;
2274:                }
2275:                fSawInclude[depth] = val;
2276:            }
2277:
2278:            /**
2279:             * Return whether an &lt;include&gt; was encountered at the specified depth,
2280:             * as an ancestor of the current item.
2281:             *
2282:             * @param depth
2283:             * @return true if an include was seen at the given depth, false otherwise
2284:             */
2285:            protected boolean getSawInclude(int depth) {
2286:                if (depth >= fSawInclude.length) {
2287:                    return false;
2288:                }
2289:                return fSawInclude[depth];
2290:            }
2291:
2292:            protected void reportResourceError(String key) {
2293:                this .reportFatalError(key, null);
2294:            }
2295:
2296:            protected void reportResourceError(String key, Object[] args) {
2297:                this .reportError(key, args, XMLErrorReporter.SEVERITY_WARNING);
2298:            }
2299:
2300:            protected void reportFatalError(String key) {
2301:                this .reportFatalError(key, null);
2302:            }
2303:
2304:            protected void reportFatalError(String key, Object[] args) {
2305:                this .reportError(key, args,
2306:                        XMLErrorReporter.SEVERITY_FATAL_ERROR);
2307:            }
2308:
2309:            private void reportError(String key, Object[] args, short severity) {
2310:                if (fErrorReporter != null) {
2311:                    fErrorReporter.reportError(
2312:                            XIncludeMessageFormatter.XINCLUDE_DOMAIN, key,
2313:                            args, severity);
2314:                }
2315:                // we won't worry about when error reporter is null, since there should always be
2316:                // at least the default error reporter
2317:            }
2318:
2319:            /**
2320:             * Set the parent of this XIncludeHandler in the tree
2321:             * @param parent
2322:             */
2323:            protected void setParent(XIncludeHandler parent) {
2324:                fParentXIncludeHandler = parent;
2325:            }
2326:
2327:            protected void setHref(String href) {
2328:                fHrefFromParent = href;
2329:            }
2330:
2331:            protected void setXIncludeLocator(XMLLocatorWrapper locator) {
2332:                fXIncludeLocator = locator;
2333:            }
2334:
2335:            // used to know whether to pass declarations to the document handler
2336:            protected boolean isRootDocument() {
2337:                return fParentXIncludeHandler == null;
2338:            }
2339:
2340:            /**
2341:             * Caches an unparsed entity.
2342:             * @param name the name of the unparsed entity
2343:             * @param identifier the location of the unparsed entity
2344:             * @param augmentations any Augmentations that were on the original unparsed entity declaration
2345:             */
2346:            protected void addUnparsedEntity(String name,
2347:                    XMLResourceIdentifier identifier, String notation,
2348:                    Augmentations augmentations) {
2349:                UnparsedEntity ent = new UnparsedEntity();
2350:                ent.name = name;
2351:                ent.systemId = identifier.getLiteralSystemId();
2352:                ent.publicId = identifier.getPublicId();
2353:                ent.baseURI = identifier.getBaseSystemId();
2354:                ent.expandedSystemId = identifier.getExpandedSystemId();
2355:                ent.notation = notation;
2356:                ent.augmentations = augmentations;
2357:                fUnparsedEntities.add(ent);
2358:            }
2359:
2360:            /**
2361:             * Caches a notation.
2362:             * @param name the name of the notation
2363:             * @param identifier the location of the notation
2364:             * @param augmentations any Augmentations that were on the original notation declaration
2365:             */
2366:            protected void addNotation(String name,
2367:                    XMLResourceIdentifier identifier,
2368:                    Augmentations augmentations) {
2369:                Notation not = new Notation();
2370:                not.name = name;
2371:                not.systemId = identifier.getLiteralSystemId();
2372:                not.publicId = identifier.getPublicId();
2373:                not.baseURI = identifier.getBaseSystemId();
2374:                not.expandedSystemId = identifier.getExpandedSystemId();
2375:                not.augmentations = augmentations;
2376:                fNotations.add(not);
2377:            }
2378:
2379:            /**
2380:             * Checks if an UnparsedEntity with the given name was declared in the DTD of the document
2381:             * for the current pipeline.  If so, then the notation for the UnparsedEntity is checked.
2382:             * If that turns out okay, then the UnparsedEntity is passed to the root pipeline to
2383:             * be checked for conflicts, and sent to the root DTDHandler.
2384:             *
2385:             * @param entName the name of the UnparsedEntity to check
2386:             */
2387:            protected void checkUnparsedEntity(String entName) {
2388:                UnparsedEntity ent = new UnparsedEntity();
2389:                ent.name = entName;
2390:                int index = fUnparsedEntities.indexOf(ent);
2391:                if (index != -1) {
2392:                    ent = (UnparsedEntity) fUnparsedEntities.get(index);
2393:                    // first check the notation of the unparsed entity
2394:                    checkNotation(ent.notation);
2395:                    checkAndSendUnparsedEntity(ent);
2396:                }
2397:            }
2398:
2399:            /**
2400:             * Checks if a Notation with the given name was declared in the DTD of the document
2401:             * for the current pipeline.  If so, that Notation is passed to the root pipeline to
2402:             * be checked for conflicts, and sent to the root DTDHandler
2403:             *
2404:             * @param notName the name of the Notation to check
2405:             */
2406:            protected void checkNotation(String notName) {
2407:                Notation not = new Notation();
2408:                not.name = notName;
2409:                int index = fNotations.indexOf(not);
2410:                if (index != -1) {
2411:                    not = (Notation) fNotations.get(index);
2412:                    checkAndSendNotation(not);
2413:                }
2414:            }
2415:
2416:            /**
2417:             * The purpose of this method is to check if an UnparsedEntity conflicts with a previously
2418:             * declared entity in the current pipeline stack.  If there is no conflict, the
2419:             * UnparsedEntity is sent by the root pipeline.
2420:             *
2421:             * @param ent the UnparsedEntity to check for conflicts
2422:             */
2423:            protected void checkAndSendUnparsedEntity(UnparsedEntity ent) {
2424:                if (isRootDocument()) {
2425:                    int index = fUnparsedEntities.indexOf(ent);
2426:                    if (index == -1) {
2427:                        // There is no unparsed entity with the same name that we have sent.
2428:                        // Calling unparsedEntityDecl() will add the entity to our local store,
2429:                        // and also send the unparsed entity to the DTDHandler
2430:                        XMLResourceIdentifier id = new XMLResourceIdentifierImpl(
2431:                                ent.publicId, ent.systemId, ent.baseURI,
2432:                                ent.expandedSystemId);
2433:                        addUnparsedEntity(ent.name, id, ent.notation,
2434:                                ent.augmentations);
2435:                        if (fSendUEAndNotationEvents && fDTDHandler != null) {
2436:                            fDTDHandler.unparsedEntityDecl(ent.name, id,
2437:                                    ent.notation, ent.augmentations);
2438:                        }
2439:                    } else {
2440:                        UnparsedEntity localEntity = (UnparsedEntity) fUnparsedEntities
2441:                                .get(index);
2442:                        if (!ent.isDuplicate(localEntity)) {
2443:                            reportFatalError("NonDuplicateUnparsedEntity",
2444:                                    new Object[] { ent.name });
2445:                        }
2446:                    }
2447:                } else {
2448:                    fParentXIncludeHandler.checkAndSendUnparsedEntity(ent);
2449:                }
2450:            }
2451:
2452:            /**
2453:             * The purpose of this method is to check if a Notation conflicts with a previously
2454:             * declared notation in the current pipeline stack.  If there is no conflict, the
2455:             * Notation is sent by the root pipeline.
2456:             *
2457:             * @param not the Notation to check for conflicts
2458:             */
2459:            protected void checkAndSendNotation(Notation not) {
2460:                if (isRootDocument()) {
2461:                    int index = fNotations.indexOf(not);
2462:                    if (index == -1) {
2463:                        // There is no notation with the same name that we have sent.
2464:                        XMLResourceIdentifier id = new XMLResourceIdentifierImpl(
2465:                                not.publicId, not.systemId, not.baseURI,
2466:                                not.expandedSystemId);
2467:                        addNotation(not.name, id, not.augmentations);
2468:                        if (fSendUEAndNotationEvents && fDTDHandler != null) {
2469:                            fDTDHandler.notationDecl(not.name, id,
2470:                                    not.augmentations);
2471:                        }
2472:                    } else {
2473:                        Notation localNotation = (Notation) fNotations
2474:                                .get(index);
2475:                        if (!not.isDuplicate(localNotation)) {
2476:                            reportFatalError("NonDuplicateNotation",
2477:                                    new Object[] { not.name });
2478:                        }
2479:                    }
2480:                } else {
2481:                    fParentXIncludeHandler.checkAndSendNotation(not);
2482:                }
2483:            }
2484:
2485:            /**
2486:             * Checks whether the string only contains white space characters.
2487:             * 
2488:             * @param value the text to check
2489:             */
2490:            private void checkWhitespace(XMLString value) {
2491:                int end = value.offset + value.length;
2492:                for (int i = value.offset; i < end; ++i) {
2493:                    if (!XMLChar.isSpace(value.ch[i])) {
2494:                        reportFatalError("ContentIllegalAtTopLevel");
2495:                        return;
2496:                    }
2497:                }
2498:            }
2499:
2500:            /**
2501:             * Checks whether the root element has already been processed.
2502:             */
2503:            private void checkMultipleRootElements() {
2504:                if (getRootElementProcessed()) {
2505:                    reportFatalError("MultipleRootElements");
2506:                }
2507:                setRootElementProcessed(true);
2508:            }
2509:
2510:            /**
2511:             * Sets whether the root element has been processed.
2512:             */
2513:            private void setRootElementProcessed(boolean seenRoot) {
2514:                if (isRootDocument()) {
2515:                    fSeenRootElement = seenRoot;
2516:                    return;
2517:                }
2518:                fParentXIncludeHandler.setRootElementProcessed(seenRoot);
2519:            }
2520:
2521:            /**
2522:             * Returns whether the root element has been processed.
2523:             */
2524:            private boolean getRootElementProcessed() {
2525:                return isRootDocument() ? fSeenRootElement
2526:                        : fParentXIncludeHandler.getRootElementProcessed();
2527:            }
2528:
2529:            // It would be nice if we didn't have to repeat code like this, but there's no interface that has
2530:            // setFeature() and addRecognizedFeatures() that the objects have in common.
2531:            protected void copyFeatures(XMLComponentManager from,
2532:                    ParserConfigurationSettings to) {
2533:                Enumeration features = Constants.getXercesFeatures();
2534:                copyFeatures1(features, Constants.XERCES_FEATURE_PREFIX, from,
2535:                        to);
2536:                features = Constants.getSAXFeatures();
2537:                copyFeatures1(features, Constants.SAX_FEATURE_PREFIX, from, to);
2538:            }
2539:
2540:            protected void copyFeatures(XMLComponentManager from,
2541:                    XMLParserConfiguration to) {
2542:                Enumeration features = Constants.getXercesFeatures();
2543:                copyFeatures1(features, Constants.XERCES_FEATURE_PREFIX, from,
2544:                        to);
2545:                features = Constants.getSAXFeatures();
2546:                copyFeatures1(features, Constants.SAX_FEATURE_PREFIX, from, to);
2547:            }
2548:
2549:            private void copyFeatures1(Enumeration features,
2550:                    String featurePrefix, XMLComponentManager from,
2551:                    ParserConfigurationSettings to) {
2552:                while (features.hasMoreElements()) {
2553:                    String featureId = featurePrefix
2554:                            + (String) features.nextElement();
2555:
2556:                    to.addRecognizedFeatures(new String[] { featureId });
2557:
2558:                    try {
2559:                        to.setFeature(featureId, from.getFeature(featureId));
2560:                    } catch (XMLConfigurationException e) {
2561:                        // componentManager doesn't support this feature,
2562:                        // so we won't worry about it
2563:                    }
2564:                }
2565:            }
2566:
2567:            private void copyFeatures1(Enumeration features,
2568:                    String featurePrefix, XMLComponentManager from,
2569:                    XMLParserConfiguration to) {
2570:                while (features.hasMoreElements()) {
2571:                    String featureId = featurePrefix
2572:                            + (String) features.nextElement();
2573:                    boolean value = from.getFeature(featureId);
2574:
2575:                    try {
2576:                        to.setFeature(featureId, value);
2577:                    } catch (XMLConfigurationException e) {
2578:                        // componentManager doesn't support this feature,
2579:                        // so we won't worry about it
2580:                    }
2581:                }
2582:            }
2583:
2584:            // This is a storage class to hold information about the notations.
2585:            // We're not using XMLNotationDecl because we don't want to lose the augmentations.
2586:            protected static class Notation {
2587:                public String name;
2588:                public String systemId;
2589:                public String baseURI;
2590:                public String publicId;
2591:                public String expandedSystemId;
2592:                public Augmentations augmentations;
2593:
2594:                // equals() returns true if two Notations have the same name.
2595:                // Useful for searching Vectors for notations with the same name
2596:                public boolean equals(Object obj) {
2597:                    if (obj == null) {
2598:                        return false;
2599:                    }
2600:                    if (obj instanceof  Notation) {
2601:                        Notation other = (Notation) obj;
2602:                        return name.equals(other.name);
2603:                    }
2604:                    return false;
2605:                }
2606:
2607:                // from 4.5.2
2608:                // Notation items with the same [name], [system identifier],
2609:                // [public identifier], and [declaration base URI] are considered
2610:                // to be duplicate. An application may also be able to detect that 
2611:                // notations are duplicate through other means. For instance, the URI 
2612:                // resulting from combining the system identifier and the declaration 
2613:                // base URI is the same.
2614:                public boolean isDuplicate(Object obj) {
2615:                    if (obj != null && obj instanceof  Notation) {
2616:                        Notation other = (Notation) obj;
2617:                        return name.equals(other.name)
2618:                                && isEqual(publicId, other.publicId)
2619:                                && isEqual(expandedSystemId,
2620:                                        other.expandedSystemId);
2621:                    }
2622:                    return false;
2623:                }
2624:
2625:                private boolean isEqual(String one, String two) {
2626:                    return (one == two || (one != null && one.equals(two)));
2627:                }
2628:            }
2629:
2630:            // This is a storage class to hold information about the unparsed entities.
2631:            // We're not using XMLEntityDecl because we don't want to lose the augmentations.
2632:            protected static class UnparsedEntity {
2633:                public String name;
2634:                public String systemId;
2635:                public String baseURI;
2636:                public String publicId;
2637:                public String expandedSystemId;
2638:                public String notation;
2639:                public Augmentations augmentations;
2640:
2641:                // equals() returns true if two UnparsedEntities have the same name.
2642:                // Useful for searching Vectors for entities with the same name
2643:                public boolean equals(Object obj) {
2644:                    if (obj == null) {
2645:                        return false;
2646:                    }
2647:                    if (obj instanceof  UnparsedEntity) {
2648:                        UnparsedEntity other = (UnparsedEntity) obj;
2649:                        return name.equals(other.name);
2650:                    }
2651:                    return false;
2652:                }
2653:
2654:                // from 4.5.1:
2655:                // Unparsed entity items with the same [name], [system identifier],
2656:                // [public identifier], [declaration base URI], [notation name], and
2657:                // [notation] are considered to be duplicate. An application may also 
2658:                // be able to detect that unparsed entities are duplicate through other 
2659:                // means. For instance, the URI resulting from combining the system 
2660:                // identifier and the declaration base URI is the same.
2661:                public boolean isDuplicate(Object obj) {
2662:                    if (obj != null && obj instanceof  UnparsedEntity) {
2663:                        UnparsedEntity other = (UnparsedEntity) obj;
2664:                        return name.equals(other.name)
2665:                                && isEqual(publicId, other.publicId)
2666:                                && isEqual(expandedSystemId,
2667:                                        other.expandedSystemId)
2668:                                && isEqual(notation, other.notation);
2669:                    }
2670:                    return false;
2671:                }
2672:
2673:                private boolean isEqual(String one, String two) {
2674:                    return (one == two || (one != null && one.equals(two)));
2675:                }
2676:            }
2677:
2678:            // The following methods are used for XML Base processing
2679:
2680:            /**
2681:             * Saves the current base URI to the top of the stack.
2682:             */
2683:            protected void saveBaseURI() {
2684:                fBaseURIScope.push(fDepth);
2685:                fBaseURI.push(fCurrentBaseURI.getBaseSystemId());
2686:                fLiteralSystemID.push(fCurrentBaseURI.getLiteralSystemId());
2687:                fExpandedSystemID.push(fCurrentBaseURI.getExpandedSystemId());
2688:            }
2689:
2690:            /**
2691:             * Discards the URIs at the top of the stack, and restores the ones beneath it.
2692:             */
2693:            protected void restoreBaseURI() {
2694:                fBaseURI.pop();
2695:                fLiteralSystemID.pop();
2696:                fExpandedSystemID.pop();
2697:                fBaseURIScope.pop();
2698:                fCurrentBaseURI.setBaseSystemId((String) fBaseURI.peek());
2699:                fCurrentBaseURI.setLiteralSystemId((String) fLiteralSystemID
2700:                        .peek());
2701:                fCurrentBaseURI.setExpandedSystemId((String) fExpandedSystemID
2702:                        .peek());
2703:            }
2704:
2705:            // The following methods are used for language processing
2706:
2707:            /**
2708:             * Saves the given language on the top of the stack.
2709:             * 
2710:             * @param language the language to push onto the stack.
2711:             */
2712:            protected void saveLanguage(String language) {
2713:                fLanguageScope.push(fDepth);
2714:                fLanguageStack.push(language);
2715:            }
2716:
2717:            /**
2718:             * Discards the language at the top of the stack, and returns the one beneath it.
2719:             */
2720:            public String restoreLanguage() {
2721:                fLanguageStack.pop();
2722:                fLanguageScope.pop();
2723:                return (String) fLanguageStack.peek();
2724:            }
2725:
2726:            /**
2727:             * Gets the base URI that was in use at that depth
2728:             * @param depth
2729:             * @return the base URI
2730:             */
2731:            public String getBaseURI(int depth) {
2732:                int scope = scopeOfBaseURI(depth);
2733:                return (String) fExpandedSystemID.elementAt(scope);
2734:            }
2735:
2736:            /**
2737:             * Gets the language that was in use at that depth.
2738:             * @param depth
2739:             * @return the language
2740:             */
2741:            public String getLanguage(int depth) {
2742:                int scope = scopeOfLanguage(depth);
2743:                return (String) fLanguageStack.elementAt(scope);
2744:            }
2745:
2746:            /**
2747:             * Returns a relative URI, which when resolved against the base URI at the
2748:             * specified depth, will create the current base URI.
2749:             * This is accomplished by merged the literal system IDs.
2750:             * @param depth the depth at which to start creating the relative URI
2751:             * @return a relative URI to convert the base URI at the given depth to the current
2752:             *         base URI
2753:             */
2754:            public String getRelativeURI(int depth)
2755:                    throws MalformedURIException {
2756:                // The literal system id at the location given by "start" is *in focus* at
2757:                // the given depth. So we need to adjust it to the next scope, so that we
2758:                // only process out of focus literal system ids
2759:                int start = scopeOfBaseURI(depth) + 1;
2760:                if (start == fBaseURIScope.size()) {
2761:                    // If that is the last system id, then we don't need a relative URI
2762:                    return "";
2763:                }
2764:                URI uri = new URI("file", (String) fLiteralSystemID
2765:                        .elementAt(start));
2766:                for (int i = start + 1; i < fBaseURIScope.size(); i++) {
2767:                    uri = new URI(uri, (String) fLiteralSystemID.elementAt(i));
2768:                }
2769:                return uri.getPath();
2770:            }
2771:
2772:            // We need to find two consecutive elements in the scope stack,
2773:            // such that the first is lower than 'depth' (or equal), and the
2774:            // second is higher.
2775:            private int scopeOfBaseURI(int depth) {
2776:                for (int i = fBaseURIScope.size() - 1; i >= 0; i--) {
2777:                    if (fBaseURIScope.elementAt(i) <= depth)
2778:                        return i;
2779:                }
2780:                // we should never get here, because 0 was put on the stack in startDocument()
2781:                return -1;
2782:            }
2783:
2784:            private int scopeOfLanguage(int depth) {
2785:                for (int i = fLanguageScope.size() - 1; i >= 0; i--) {
2786:                    if (fLanguageScope.elementAt(i) <= depth)
2787:                        return i;
2788:                }
2789:                // we should never get here, because 0 was put on the stack in startDocument()
2790:                return -1;
2791:            }
2792:
2793:            /**
2794:             * Search for a xml:base attribute, and if one is found, put the new base URI into
2795:             * effect.
2796:             */
2797:            protected void processXMLBaseAttributes(XMLAttributes attributes) {
2798:                String baseURIValue = attributes.getValue(
2799:                        NamespaceContext.XML_URI, "base");
2800:                if (baseURIValue != null) {
2801:                    try {
2802:                        String expandedValue = XMLEntityManager.expandSystemId(
2803:                                baseURIValue, fCurrentBaseURI
2804:                                        .getExpandedSystemId(), false);
2805:                        fCurrentBaseURI.setLiteralSystemId(baseURIValue);
2806:                        fCurrentBaseURI.setBaseSystemId(fCurrentBaseURI
2807:                                .getExpandedSystemId());
2808:                        fCurrentBaseURI.setExpandedSystemId(expandedValue);
2809:
2810:                        // push the new values on the stack
2811:                        saveBaseURI();
2812:                    } catch (MalformedURIException e) {
2813:                        // REVISIT: throw error here
2814:                    }
2815:                }
2816:            }
2817:
2818:            /**
2819:             * Search for a xml:lang attribute, and if one is found, put the new 
2820:             * [language] into effect.
2821:             */
2822:            protected void processXMLLangAttributes(XMLAttributes attributes) {
2823:                String language = attributes.getValue(NamespaceContext.XML_URI,
2824:                        "lang");
2825:                if (language != null) {
2826:                    fCurrentLanguage = language;
2827:                    saveLanguage(fCurrentLanguage);
2828:                }
2829:            }
2830:
2831:            /**
2832:             * Returns <code>true</code> if the given string 
2833:             * would be valid in an HTTP header.
2834:             * 
2835:             * @param value string to check
2836:             * @return <code>true</code> if the given string
2837:             * would be valid in an HTTP header
2838:             */
2839:            private boolean isValidInHTTPHeader(String value) {
2840:                char ch;
2841:                for (int i = value.length() - 1; i >= 0; --i) {
2842:                    ch = value.charAt(i);
2843:                    if (ch < 0x20 || ch > 0x7E) {
2844:                        return false;
2845:                    }
2846:                }
2847:                return true;
2848:            }
2849:
2850:            /**
2851:             * Returns a new <code>XMLInputSource</code> from the given parameters.
2852:             */
2853:            private XMLInputSource createInputSource(String publicId,
2854:                    String systemId, String baseSystemId, String accept,
2855:                    String acceptLanguage) {
2856:
2857:                HTTPInputSource httpSource = new HTTPInputSource(publicId,
2858:                        systemId, baseSystemId);
2859:                if (accept != null && accept.length() > 0) {
2860:                    httpSource.setHTTPRequestProperty(
2861:                            XIncludeHandler.HTTP_ACCEPT, accept);
2862:                }
2863:                if (acceptLanguage != null && acceptLanguage.length() > 0) {
2864:                    httpSource.setHTTPRequestProperty(
2865:                            XIncludeHandler.HTTP_ACCEPT_LANGUAGE,
2866:                            acceptLanguage);
2867:                }
2868:                return httpSource;
2869:            }
2870:
2871:            private boolean isEqual(String one, String two) {
2872:                return (one == two || (one != null && one.equals(two)));
2873:            }
2874:
2875:            // which ASCII characters need to be escaped
2876:            private static final boolean gNeedEscaping[] = new boolean[128];
2877:            // the first hex character if a character needs to be escaped
2878:            private static final char gAfterEscaping1[] = new char[128];
2879:            // the second hex character if a character needs to be escaped
2880:            private static final char gAfterEscaping2[] = new char[128];
2881:            private static final char[] gHexChs = { '0', '1', '2', '3', '4',
2882:                    '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
2883:            // initialize the above 3 arrays
2884:            static {
2885:                char[] escChs = { ' ', '<', '>', '"', '{', '}', '|', '\\', '^',
2886:                        '`' };
2887:                int len = escChs.length;
2888:                char ch;
2889:                for (int i = 0; i < len; i++) {
2890:                    ch = escChs[i];
2891:                    gNeedEscaping[ch] = true;
2892:                    gAfterEscaping1[ch] = gHexChs[ch >> 4];
2893:                    gAfterEscaping2[ch] = gHexChs[ch & 0xf];
2894:                }
2895:            }
2896:
2897:            //
2898:            // Escape an href value according to (4.1.1):
2899:            //
2900:            // To convert the value of the href attribute to an IRI reference, the following characters must be escaped:
2901:            // space #x20
2902:            // the delimiters < #x3C, > #x3E and " #x22
2903:            // the unwise characters { #x7B, } #x7D, | #x7C, \ #x5C, ^ #x5E and ` #x60
2904:            //
2905:            // To convert an IRI reference to a URI reference, the following characters must also be escaped:
2906:            // the Unicode plane 0 characters #xA0 - #xD7FF, #xF900-#xFDCF, #xFDF0-#xFFEF
2907:            // the Unicode plane 1-14 characters #x10000-#x1FFFD ... #xE0000-#xEFFFD
2908:            //
2909:            private String escapeHref(String href) {
2910:                int len = href.length();
2911:                int ch;
2912:                StringBuffer buffer = new StringBuffer(len * 3);
2913:
2914:                // for each character in the href
2915:                int i = 0;
2916:                for (; i < len; i++) {
2917:                    ch = href.charAt(i);
2918:                    // if it's not an ASCII character (excluding 0x7F), break here, and use UTF-8 encoding
2919:                    if (ch > 0x7E) {
2920:                        break;
2921:                    }
2922:                    // abort: href does not allow this character
2923:                    if (ch < 0x20) {
2924:                        return href;
2925:                    }
2926:                    if (gNeedEscaping[ch]) {
2927:                        buffer.append('%');
2928:                        buffer.append(gAfterEscaping1[ch]);
2929:                        buffer.append(gAfterEscaping2[ch]);
2930:                    } else {
2931:                        buffer.append((char) ch);
2932:                    }
2933:                }
2934:
2935:                // we saw some non-ascii character
2936:                if (i < len) {
2937:                    // check if remainder of href contains any illegal characters before proceeding
2938:                    for (int j = i; j < len; ++j) {
2939:                        ch = href.charAt(j);
2940:                        if ((ch >= 0x20 && ch <= 0x7E)
2941:                                || (ch >= 0xA0 && ch <= 0xD7FF)
2942:                                || (ch >= 0xF900 && ch <= 0xFDCF)
2943:                                || (ch >= 0xFDF0 && ch <= 0xFFEF)) {
2944:                            continue;
2945:                        }
2946:                        if (XMLChar.isHighSurrogate(ch) && ++j < len) {
2947:                            int ch2 = href.charAt(j);
2948:                            if (XMLChar.isLowSurrogate(ch2)) {
2949:                                ch2 = XMLChar.supplemental((char) ch,
2950:                                        (char) ch2);
2951:                                if (ch2 < 0xF0000 && (ch2 & 0xFFFF) <= 0xFFFD) {
2952:                                    continue;
2953:                                }
2954:                            }
2955:                        }
2956:                        // abort: href does not allow this character
2957:                        return href;
2958:                    }
2959:
2960:                    // get UTF-8 bytes for the remaining sub-string
2961:                    byte[] bytes = null;
2962:                    byte b;
2963:                    try {
2964:                        bytes = href.substring(i).getBytes("UTF-8");
2965:                    } catch (java.io.UnsupportedEncodingException e) {
2966:                        // should never happen
2967:                        return href;
2968:                    }
2969:                    len = bytes.length;
2970:
2971:                    // for each byte
2972:                    for (i = 0; i < len; i++) {
2973:                        b = bytes[i];
2974:                        // for non-ASCII character: make it positive, then escape
2975:                        if (b < 0) {
2976:                            ch = b + 256;
2977:                            buffer.append('%');
2978:                            buffer.append(gHexChs[ch >> 4]);
2979:                            buffer.append(gHexChs[ch & 0xf]);
2980:                        } else if (gNeedEscaping[b]) {
2981:                            buffer.append('%');
2982:                            buffer.append(gAfterEscaping1[b]);
2983:                            buffer.append(gAfterEscaping2[b]);
2984:                        } else {
2985:                            buffer.append((char) b);
2986:                        }
2987:                    }
2988:                }
2989:
2990:                // If escaping happened, create a new string;
2991:                // otherwise, return the original one.
2992:                if (buffer.length() != len) {
2993:                    return buffer.toString();
2994:                } else {
2995:                    return href;
2996:                }
2997:            }
2998:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.