KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xerces > internal > xinclude > XIncludeHandler


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2001-2004 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 2003, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package com.sun.org.apache.xerces.internal.xinclude;
59
60 import java.io.CharConversionException JavaDoc;
61 import java.io.IOException JavaDoc;
62 import java.io.InputStream JavaDoc;
63 import java.io.Reader JavaDoc;
64 import java.net.HttpURLConnection JavaDoc;
65 import java.net.URL JavaDoc;
66 import java.net.URLConnection JavaDoc;
67 import java.util.Enumeration JavaDoc;
68 import java.util.Stack JavaDoc;
69 import java.util.StringTokenizer JavaDoc;
70 import java.util.Vector JavaDoc;
71
72 import com.sun.org.apache.xerces.internal.impl.Constants;
73 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
74 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
75 import com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException;
76 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
77 import com.sun.org.apache.xerces.internal.util.AugmentationsImpl;
78 import com.sun.org.apache.xerces.internal.util.IntStack;
79 import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings;
80 import com.sun.org.apache.xerces.internal.util.SecurityManager;
81 import com.sun.org.apache.xerces.internal.util.URI;
82 import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl;
83 import com.sun.org.apache.xerces.internal.util.XMLResourceIdentifierImpl;
84 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
85 import com.sun.org.apache.xerces.internal.util.URI.MalformedURIException;
86 import com.sun.org.apache.xerces.internal.xni.Augmentations;
87 import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
88 import com.sun.org.apache.xerces.internal.xni.QName;
89 import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
90 import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler;
91 import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
92 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
93 import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
94 import com.sun.org.apache.xerces.internal.xni.XMLString;
95 import com.sun.org.apache.xerces.internal.xni.XNIException;
96 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
97 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
98 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
99 import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDFilter;
100 import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDSource;
101 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentFilter;
102 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
103 import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
104 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
105 import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration;
106
107 /**
108  * <p>
109  * This is a pipeline component which performs XInclude handling, according to the
110  * W3C specification for XML Inclusions.
111  * </p>
112  * <p>
113  * This component analyzes each event in the pipeline, looking for &lt;include&gt;
114  * elements. An &lt;include&gt; element is one which has a namespace of
115  * <code>http://www.w3.org/2001/XInclude</code> and a localname of <code>include</code>.
116  * When it finds an &lt;include&gt; element, it attempts to include the file specified
117  * in the <code>href</code> attribute of the element. If inclusion succeeds, all
118  * children of the &lt;include&gt; element are ignored (with the exception of
119  * checking for invalid children as outlined in the specification). If the inclusion
120  * fails, the &lt;fallback&gt; child of the &lt;include&gt; element is processed.
121  * </p>
122  * <p>
123  * See the <a HREF="http://www.w3.org/TR/xinclude/">XInclude specification</a> for
124  * more information on how XInclude is to be used.
125  * </p>
126  * <p>
127  * This component requires the following features and properties from the
128  * component manager that uses it:
129  * <ul>
130  * <li>http://xml.org/sax/features/allow-dtd-events-after-endDTD</li>
131  * <li>http://apache.org/xml/properties/internal/error-reporter</li>
132  * <li>http://apache.org/xml/properties/internal/entity-resolver</li>
133  * </ul>
134  * Furthermore, the <code>NamespaceContext</code> used in the pipeline is required
135  * to be an instance of <code>XIncludeNamespaceSupport</code>.
136  * </p>
137  * <p>
138  * Currently, this implementation has only partial support for the XInclude specification.
139  * Specifically, it is missing support for XPointer document fragments. Thus, only whole
140  * documents can be included using this component in the pipeline.
141  * </p>
142  *
143  * @author Peter McCracken, IBM
144  *
145  * @version $Id: XIncludeHandler.java,v 1.26 2004/04/15 04:51:56 mrglavas Exp $
146  *
147  * @see XIncludeNamespaceSupport
148  */

149 public class XIncludeHandler
150 implements XMLComponent, XMLDocumentFilter, XMLDTDFilter {
151     
152     //Xpointer support
153
//START
154
public final static String JavaDoc XPOINTER_DEFAULT_CONFIGURATION =
155     "com.sun.org.apache.xerces.internal.parsers.XPointerParserConfiguration";
156     protected static final String JavaDoc XPOINTER_SCHEMA =
157     Constants.XERCES_PROPERTY_PREFIX + Constants.XPOINTER_SCHEMA_PROPERTY;
158     protected static final String JavaDoc XINCLUDE_AWARE =
159     Constants.XERCES_FEATURE_PREFIX + Constants.XINCLUDE_AWARE ;
160     
161     //END
162
public final static String JavaDoc XINCLUDE_DEFAULT_CONFIGURATION =
163     "com.sun.org.apache.xerces.internal.parsers.XIncludeParserConfiguration";
164     public final static String JavaDoc HTTP_ACCEPT = "Accept";
165     public final static String JavaDoc HTTP_ACCEPT_LANGUAGE = "Accept-Language";
166     public final static String JavaDoc HTTP_ACCEPT_CHARSET = "Accept-Charset";
167     public final static String JavaDoc XPOINTER = "xpointer";
168     
169     public final static String JavaDoc XINCLUDE_NS_URI =
170     "http://www.w3.org/2001/XInclude".intern();
171     public final static String JavaDoc XINCLUDE_INCLUDE = "include".intern();
172     public final static String JavaDoc XINCLUDE_FALLBACK = "fallback".intern();
173     public final static String JavaDoc XINCLUDE_PARSE_XML = "xml".intern();
174     public final static String JavaDoc XINCLUDE_PARSE_TEXT = "text".intern();
175     
176     public final static String JavaDoc XINCLUDE_ATTR_HREF = "href".intern();
177     public final static String JavaDoc XINCLUDE_ATTR_PARSE = "parse".intern();
178     public final static String JavaDoc XINCLUDE_ATTR_ENCODING = "encoding".intern();
179     public final static String JavaDoc XINCLUDE_ATTR_ACCEPT = "accept".intern();
180     public final static String JavaDoc XINCLUDE_ATTR_ACCEPT_LANGUAGE = "accept-language".intern();
181     public final static String JavaDoc XINCLUDE_ATTR_ACCEPT_CHARSET = "accept-charset".intern();
182     
183     // Top Level Information Items have [included] property in infoset
184
public final static String JavaDoc XINCLUDE_INCLUDED = "[included]".intern();
185     
186     /** The identifier for the Augmentation that contains the current base URI */
187     public final static String JavaDoc CURRENT_BASE_URI = "currentBaseURI";
188     
189     // used for adding [base URI] attributes
190
public final static String JavaDoc XINCLUDE_BASE = "base";
191     public final static QName XML_BASE_QNAME =
192     new QName(
193     XMLSymbols.PREFIX_XML,
194     XINCLUDE_BASE,
195     XMLSymbols.PREFIX_XML + ":" + XINCLUDE_BASE,
196     NamespaceContext.XML_URI);
197     
198     public final static QName NEW_NS_ATTR_QNAME =
199     new QName(
200     XMLSymbols.PREFIX_XMLNS,
201     "",
202     XMLSymbols.PREFIX_XMLNS + ":",
203     NamespaceContext.XMLNS_URI);
204     
205     // Processing States
206
private final static int STATE_NORMAL_PROCESSING = 1;
207     // we go into this state after a successful include (thus we ignore the children
208
// of the include) or after a fallback
209
private final static int STATE_IGNORE = 2;
210     // we go into this state after a failed include. If we don't encounter a fallback
211
// before we reach the end include tag, it's a fatal error
212
private final static int STATE_EXPECT_FALLBACK = 3;
213     
214     // recognized features and properties
215

216     /** Feature identifier: allow notation and unparsed entity events to be sent out of order. */
217     protected static final String JavaDoc ALLOW_UE_AND_NOTATION_EVENTS =
218     Constants.SAX_FEATURE_PREFIX
219     + Constants.ALLOW_DTD_EVENTS_AFTER_ENDDTD_FEATURE;
220     
221     /** Property identifier: error reporter. */
222     protected static final String JavaDoc ERROR_REPORTER =
223     Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
224     
225     /** Property identifier: entity resolver. */
226     protected static final String JavaDoc ENTITY_RESOLVER =
227     Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
228     
229     /** property identifier: security manager. */
230     protected static final String JavaDoc SECURITY_MANAGER =
231     Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
232     
233     /** Recognized features. */
234     private static final String JavaDoc[] RECOGNIZED_FEATURES =
235     { ALLOW_UE_AND_NOTATION_EVENTS };
236     
237     /** Feature defaults. */
238     private static final Boolean JavaDoc[] FEATURE_DEFAULTS = { Boolean.TRUE };
239     
240     /** Recognized properties. */
241     
242     private static final String JavaDoc[] RECOGNIZED_PROPERTIES =
243     { ERROR_REPORTER, ENTITY_RESOLVER, XPOINTER_SCHEMA };
244     /** Property defaults. */
245     private static final Object JavaDoc[] PROPERTY_DEFAULTS = { null, null, null };
246     
247     // instance variables
248

249     // for XMLDocumentFilter
250
protected XMLDocumentHandler fDocumentHandler;
251     protected XMLDocumentSource fDocumentSource;
252     
253     protected XPointerFramework fXPointerFramework = null;
254     protected XPointerSchema [] fXPointerSchema;
255     
256     // for XMLDTDFilter
257
protected XMLDTDHandler fDTDHandler;
258     protected XMLDTDSource fDTDSource;
259     
260     // for XIncludeHandler
261
protected XIncludeHandler fParentXIncludeHandler;
262     
263     // It's "feels wrong" to store this value here. However,
264
// calculating it can be time consuming, so we cache it.
265
// It's never going to change in the lifetime of this XIncludeHandler
266
protected String JavaDoc fParentRelativeURI;
267     
268     // we cache the child parser configuration, so we don't have to re-create
269
// the objects when the parser is re-used
270
protected XMLParserConfiguration fChildConfig;
271     
272     protected XMLLocator fDocLocation;
273     protected XIncludeNamespaceSupport fNamespaceContext;
274     protected XMLErrorReporter fErrorReporter;
275     protected XMLEntityResolver fEntityResolver;
276     protected SecurityManager JavaDoc fSecurityManager;
277     
278     // these are needed for XML Base processing
279
protected XMLResourceIdentifier fCurrentBaseURI;
280     protected IntStack baseURIScope;
281     protected Stack JavaDoc baseURI;
282     protected Stack JavaDoc literalSystemID;
283     protected Stack JavaDoc expandedSystemID;
284     
285     // used for passing features on to child XIncludeHandler objects
286
protected ParserConfigurationSettings fSettings;
287     
288     // The current element depth. We start at depth 0 (before we've reached any elements)
289
// The first element is at depth 1.
290
private int fDepth;
291     
292     // this value must be at least 1
293
private static final int INITIAL_SIZE = 8;
294     
295     // Used to ensure that fallbacks are always children of include elements,
296
// and that include elements are never children of other include elements.
297
// An index contains true if the ancestor of the current element which resides
298
// at that depth was an include element.
299
private boolean[] fSawInclude = new boolean[INITIAL_SIZE];
300     
301     // Ensures that only one fallback element can be at a single depth.
302
// An index contains true if we have seen any fallback elements at that depth,
303
// and it is only reset to false when the end tag of the parent is encountered.
304
private boolean[] fSawFallback = new boolean[INITIAL_SIZE];
305     
306     // The state of the processor at each given depth.
307
private int[] fState = new int[INITIAL_SIZE];
308     
309     // buffering the necessary DTD events
310
private Vector JavaDoc fNotations;
311     private Vector JavaDoc fUnparsedEntities;
312     
313     // for SAX compatibility.
314
// Has the value of the ALLOW_UE_AND_NOTATION_EVENTS feature
315
private boolean fSendUEAndNotationEvents;
316     
317     // track the version of the document being parsed
318
private boolean fIsXML11;
319     
320     // track whether a DTD is being parsed
321
private boolean fInDTD;
322     
323     // Constructors
324

325     public XIncludeHandler() {
326         fDepth = 0;
327         
328         fSawFallback[fDepth] = false;
329         fSawInclude[fDepth] = false;
330         fState[fDepth] = STATE_NORMAL_PROCESSING;
331         fNotations = new Vector JavaDoc();
332         fUnparsedEntities = new Vector JavaDoc();
333         
334         baseURIScope = new IntStack();
335         baseURI = new Stack JavaDoc();
336         literalSystemID = new Stack JavaDoc();
337         expandedSystemID = new Stack JavaDoc();
338         fCurrentBaseURI = new XMLResourceIdentifierImpl();
339     }
340     
341     // XMLComponent methods
342

343     public void reset(XMLComponentManager componentManager)
344     throws XNIException {
345         fNamespaceContext = null;
346         fDepth = 0;
347         fNotations = new Vector JavaDoc();
348         fUnparsedEntities = new Vector JavaDoc();
349         fParentRelativeURI = null;
350         fIsXML11 = false;
351         fInDTD = false;
352         
353         baseURIScope.clear();
354         baseURI.clear();
355         literalSystemID.clear();
356         expandedSystemID.clear();
357         
358         // REVISIT: Find a better method for maintaining
359
// the state of the XInclude processor. These arrays
360
// can potentially grow quite large. Cleaning them
361
// out on reset may be very time consuming. -- mrglavas
362
//
363
// clear the previous settings from the arrays
364
for (int i = 0; i < fState.length; ++i) {
365             fState[i] = STATE_NORMAL_PROCESSING;
366         }
367         for (int i = 0; i < fSawFallback.length; ++i) {
368             fSawFallback[i] = false;
369         }
370         for (int i = 0; i < fSawInclude.length; ++i) {
371             fSawInclude[i] = false;
372         }
373         
374         try {
375             fSendUEAndNotationEvents =
376             componentManager.getFeature(ALLOW_UE_AND_NOTATION_EVENTS);
377             if (fChildConfig != null) {
378                 fChildConfig.setFeature(
379                 ALLOW_UE_AND_NOTATION_EVENTS,
380                 fSendUEAndNotationEvents);
381             }
382         }
383         catch (XMLConfigurationException e) {
384         }
385         
386         // Get error reporter.
387
try {
388             XMLErrorReporter value =
389             (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER);
390             if (value != null) {
391                 setErrorReporter(value);
392                 if (fChildConfig != null) {
393                     fChildConfig.setProperty(ERROR_REPORTER, value);
394                 }
395             }
396             
397         }
398         catch (XMLConfigurationException e) {
399             fErrorReporter = null;
400         }
401         
402         // Get entity resolver.
403
try {
404             XMLEntityResolver value =
405             (XMLEntityResolver)componentManager.getProperty(
406             ENTITY_RESOLVER);
407             
408             if (value != null) {
409                 fEntityResolver = value;
410                 if (fChildConfig != null) {
411                     fChildConfig.setProperty(ENTITY_RESOLVER, value);
412                 }
413             }
414         }
415         catch (XMLConfigurationException e) {
416             fEntityResolver = null;
417         }
418         
419         try {
420             fXPointerSchema =
421             (XPointerSchema [])componentManager.getProperty(
422             XPOINTER_SCHEMA);
423         }
424         catch (XMLConfigurationException e) {
425             fXPointerSchema = null;
426         }
427         
428         // Get security manager.
429
try {
430             SecurityManager JavaDoc value =
431             (SecurityManager JavaDoc)componentManager.getProperty(
432             SECURITY_MANAGER);
433             
434             if (value != null) {
435                 fSecurityManager = value;
436                 if (fChildConfig != null) {
437                     fChildConfig.setProperty(SECURITY_MANAGER, value);
438                 }
439             }
440         }
441         catch (XMLConfigurationException e) {
442             fSecurityManager = null;
443         }
444         
445         fSettings = new ParserConfigurationSettings();
446         copyFeatures(componentManager, fSettings);
447         // Don't reset fChildConfig -- we don't want it to share the same components.
448
// It will be reset when it is actually used to parse something.
449
} // reset(XMLComponentManager)
450

451     /**
452      * Returns a list of feature identifiers that are recognized by
453      * this component. This method may return null if no features
454      * are recognized by this component.
455      */

456     public String JavaDoc[] getRecognizedFeatures() {
457         return RECOGNIZED_FEATURES;
458     } // getRecognizedFeatures():String[]
459

460     /**
461      * Sets the state of a feature. This method is called by the component
462      * manager any time after reset when a feature changes state.
463      * <p>
464      * <strong>Note:</strong> Components should silently ignore features
465      * that do not affect the operation of the component.
466      *
467      * @param featureId The feature identifier.
468      * @param state The state of the feature.
469      *
470      * @throws SAXNotRecognizedException The component should not throw
471      * this exception.
472      * @throws SAXNotSupportedException The component should not throw
473      * this exception.
474      */

475     public void setFeature(String JavaDoc featureId, boolean state)
476     throws XMLConfigurationException {
477         if (featureId.equals(ALLOW_UE_AND_NOTATION_EVENTS)) {
478             fSendUEAndNotationEvents = state;
479         }
480         if (fSettings != null) {
481             fSettings.setFeature(featureId, state);
482         }
483     } // setFeature(String,boolean)
484

485     /**
486      * Returns a list of property identifiers that are recognized by
487      * this component. This method may return null if no properties
488      * are recognized by this component.
489      */

490     public String JavaDoc[] getRecognizedProperties() {
491         return RECOGNIZED_PROPERTIES;
492     } // getRecognizedProperties():String[]
493

494     /**
495      * Sets the value of a property. This method is called by the component
496      * manager any time after reset when a property changes value.
497      * <p>
498      * <strong>Note:</strong> Components should silently ignore properties
499      * that do not affect the operation of the component.
500      *
501      * @param propertyId The property identifier.
502      * @param value The value of the property.
503      *
504      * @throws SAXNotRecognizedException The component should not throw
505      * this exception.
506      * @throws SAXNotSupportedException The component should not throw
507      * this exception.
508      */

509     public void setProperty(String JavaDoc propertyId, Object JavaDoc value)
510     throws XMLConfigurationException {
511         if (propertyId.equals(ERROR_REPORTER)) {
512             setErrorReporter((XMLErrorReporter)value);
513             if (fChildConfig != null) {
514                 fChildConfig.setProperty(propertyId, value);
515             }
516         }
517         if (propertyId.equals(ENTITY_RESOLVER)) {
518             fEntityResolver = (XMLEntityResolver)value;
519             if (fChildConfig != null) {
520                 fChildConfig.setProperty(propertyId, value);
521             }
522         }
523         if (propertyId.equals(SECURITY_MANAGER)) {
524             fSecurityManager = (SecurityManager JavaDoc)value;
525             if (fChildConfig != null) {
526                 fChildConfig.setProperty(propertyId, value);
527             }
528         }
529         
530     } // setProperty(String,Object)
531

532     /**
533      * Returns the default state for a feature, or null if this
534      * component does not want to report a default value for this
535      * feature.
536      *
537      * @param featureId The feature identifier.
538      *
539      * @since Xerces 2.2.0
540      */

541     public Boolean JavaDoc getFeatureDefault(String JavaDoc featureId) {
542         for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
543             if (RECOGNIZED_FEATURES[i].equals(featureId)) {
544                 return FEATURE_DEFAULTS[i];
545             }
546         }
547         return null;
548     } // getFeatureDefault(String):Boolean
549

550     /**
551      * Returns the default state for a property, or null if this
552      * component does not want to report a default value for this
553      * property.
554      *
555      * @param propertyId The property identifier.
556      *
557      * @since Xerces 2.2.0
558      */

559     public Object JavaDoc getPropertyDefault(String JavaDoc propertyId) {
560         for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
561             if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
562                 return PROPERTY_DEFAULTS[i];
563             }
564         }
565         return null;
566     } // getPropertyDefault(String):Object
567

568     public void setDocumentHandler(XMLDocumentHandler handler) {
569         fDocumentHandler = handler;
570     }
571     
572     public XMLDocumentHandler getDocumentHandler() {
573         return fDocumentHandler;
574     }
575     
576     // XMLDocumentHandler methods
577

578     /**
579      * Event sent at the start of the document.
580      *
581      * A fatal error will occur here, if it is detected that this document has been processed
582      * before.
583      *
584      * This event is only passed on to the document handler if this is the root document.
585      */

586     public void startDocument(
587     XMLLocator locator,
588     String JavaDoc encoding,
589     NamespaceContext namespaceContext,
590     Augmentations augs)
591     throws XNIException {
592         
593         // we do this to ensure that the proper location is reported in errors
594
// otherwise, the locator from the root document would always be used
595
if(fErrorReporter != null)
596             fErrorReporter.setDocumentLocator(locator);
597         if (!isRootDocument()
598         && fParentXIncludeHandler.searchForRecursiveIncludes(locator)) {
599             reportFatalError(
600             "RecursiveInclude",
601             new Object JavaDoc[] { locator.getExpandedSystemId()});
602         }
603         
604         if (!(namespaceContext instanceof XIncludeNamespaceSupport)) {
605             reportFatalError("IncompatibleNamespaceContext");
606         }
607         fNamespaceContext = (XIncludeNamespaceSupport)namespaceContext;
608         fDocLocation = locator;
609         
610         // initialize the current base URI
611
fCurrentBaseURI.setBaseSystemId(locator.getBaseSystemId());
612         fCurrentBaseURI.setExpandedSystemId(locator.getExpandedSystemId());
613         fCurrentBaseURI.setLiteralSystemId(locator.getLiteralSystemId());
614         saveBaseURI();
615         if (augs == null) {
616             augs = new AugmentationsImpl();
617         }
618         augs.putItem(CURRENT_BASE_URI, fCurrentBaseURI);
619         
620         if (isRootDocument() && fDocumentHandler != null) {
621             fDocumentHandler.startDocument(
622             locator,
623             encoding,
624             namespaceContext,
625             augs);
626         }
627     }
628     
629     public void xmlDecl(
630     String JavaDoc version,
631     String JavaDoc encoding,
632     String JavaDoc standalone,
633     Augmentations augs)
634     throws XNIException {
635         fIsXML11 = "1.1".equals(version);
636         if (isRootDocument() && fDocumentHandler != null) {
637             fDocumentHandler.xmlDecl(version, encoding, standalone, augs);
638         }
639     }
640     
641     public void doctypeDecl(
642     String JavaDoc rootElement,
643     String JavaDoc publicId,
644     String JavaDoc systemId,
645     Augmentations augs)
646     throws XNIException {
647         if (isRootDocument() && fDocumentHandler != null) {
648             fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
649         }
650     }
651     
652     public void comment(XMLString text, Augmentations augs)
653     throws XNIException {
654         if (!fInDTD) {
655             if (fDocumentHandler != null
656             && getState() == STATE_NORMAL_PROCESSING) {
657                 fDepth++;
658                 augs = modifyAugmentations(augs);
659                 fDocumentHandler.comment(text, augs);
660                 fDepth--;
661             }
662         }
663         else if (fDTDHandler != null) {
664             fDTDHandler.comment(text, augs);
665         }
666     }
667     
668     public void processingInstruction(
669     String JavaDoc target,
670     XMLString data,
671     Augmentations augs)
672     throws XNIException {
673         if (!fInDTD) {
674             if (fDocumentHandler != null
675             && getState() == STATE_NORMAL_PROCESSING) {
676                 // we need to change the depth like this so that modifyAugmentations() works
677
fDepth++;
678                 augs = modifyAugmentations(augs);
679                 fDocumentHandler.processingInstruction(target, data, augs);
680                 fDepth--;
681             }
682         }
683         else if (fDTDHandler != null) {
684             fDTDHandler.processingInstruction(target, data, augs);
685         }
686     }
687     
688     public void startElement(
689     QName element,
690     XMLAttributes attributes,
691     Augmentations augs)
692     throws XNIException {
693         fDepth++;
694         setState(getState(fDepth - 1));
695         // we process the xml:base attributes regardless of what type of element it is
696
processXMLBaseAttributes(attributes);
697         
698         if (isIncludeElement(element)) {
699             boolean success = this.handleIncludeElement(attributes);
700             if (success) {
701                 setState(STATE_IGNORE);
702             }
703             else {
704                 setState(STATE_EXPECT_FALLBACK);
705             }
706         }
707         else if (isFallbackElement(element)) {
708             this.handleFallbackElement();
709         }
710         else if (
711         fDocumentHandler != null
712         && getState() == STATE_NORMAL_PROCESSING) {
713             augs = modifyAugmentations(augs);
714             attributes = processAttributes(attributes);
715             fDocumentHandler.startElement(element, attributes, augs);
716         }
717     }
718     
719     public void emptyElement(
720     QName element,
721     XMLAttributes attributes,
722     Augmentations augs)
723     throws XNIException {
724         fDepth++;
725         setState(getState(fDepth - 1));
726         
727         // we process the xml:base attributes regardless of what type of element it is
728
processXMLBaseAttributes(attributes);
729         
730         if (isIncludeElement(element)) {
731             boolean success = this.handleIncludeElement(attributes);
732             if (success) {
733                 setState(STATE_IGNORE);
734             }
735             else {
736                 reportFatalError("NoFallback");
737             }
738         }
739         else if (isFallbackElement(element)) {
740             this.handleFallbackElement();
741         }
742         else if (hasXIncludeNamespace(element)) {
743             if (getSawInclude(fDepth - 1)) {
744                 reportFatalError(
745                 "IncludeChild",
746                 new Object JavaDoc[] { element.rawname });
747             }
748         }
749         else if (
750         fDocumentHandler != null
751         && getState() == STATE_NORMAL_PROCESSING) {
752             augs = modifyAugmentations(augs);
753             attributes = processAttributes(attributes);
754             fDocumentHandler.emptyElement(element, attributes, augs);
755         }
756         // reset the out of scope stack elements
757
setSawFallback(fDepth + 1, false);
758         setSawInclude(fDepth + 1, false);
759         
760         // check if an xml:base has gone out of scope
761
if (baseURIScope.size() > 0 && fDepth == baseURIScope.peek()) {
762             // pop the values from the stack
763
restoreBaseURI();
764         }
765         fDepth--;
766     }
767     
768     public void endElement(QName element, Augmentations augs)
769     throws XNIException {
770         
771         if (isIncludeElement(element)) {
772             // if we're ending an include element, and we were expecting a fallback
773
// we check to see if the children of this include element contained a fallback
774
if (getState() == STATE_EXPECT_FALLBACK
775             && !getSawFallback(fDepth + 1)) {
776                 reportFatalError("NoFallback");
777             }
778         }
779         if (isFallbackElement(element)) {
780             // the state would have been set to normal processing if we were expecting the fallback element
781
// now that we're done processing it, we should ignore all the other children of the include element
782
if (getState() == STATE_NORMAL_PROCESSING) {
783                 setState(STATE_IGNORE);
784             }
785         }
786         else if (
787         fDocumentHandler != null
788         && getState() == STATE_NORMAL_PROCESSING) {
789             fDocumentHandler.endElement(element, augs);
790         }
791         
792         // reset the out of scope stack elements
793
setSawFallback(fDepth + 1, false);
794         setSawInclude(fDepth + 1, false);
795         
796         // check if an xml:base has gone out of scope
797
if (baseURIScope.size() > 0 && fDepth == baseURIScope.peek()) {
798             // pop the values from the stack
799
restoreBaseURI();
800         }
801         fDepth--;
802     }
803     
804     public void startGeneralEntity(
805     String JavaDoc name,
806     XMLResourceIdentifier resId,
807     String JavaDoc encoding,
808     Augmentations augs)
809     throws XNIException {
810         if (fDocumentHandler != null
811         && getState() == STATE_NORMAL_PROCESSING) {
812             fDocumentHandler.startGeneralEntity(name, resId, encoding, augs);
813         }
814     }
815     
816     public void textDecl(String JavaDoc version, String JavaDoc encoding, Augmentations augs)
817     throws XNIException {
818         if (fDocumentHandler != null
819         && getState() == STATE_NORMAL_PROCESSING) {
820             fDocumentHandler.textDecl(version, encoding, augs);
821         }
822     }
823     
824     public void endGeneralEntity(String JavaDoc name, Augmentations augs)
825     throws XNIException {
826         if (fDocumentHandler != null
827         && getState() == STATE_NORMAL_PROCESSING) {
828             fDocumentHandler.endGeneralEntity(name, augs);
829         }
830     }
831     
832     public void characters(XMLString text, Augmentations augs)
833     throws XNIException {
834         if (fDocumentHandler != null
835         && getState() == STATE_NORMAL_PROCESSING) {
836             // we need to change the depth like this so that modifyAugmentations() works
837
fDepth++;
838             augs = modifyAugmentations(augs);
839             fDocumentHandler.characters(text, augs);
840             fDepth--;
841         }
842     }
843     
844     public void ignorableWhitespace(XMLString text, Augmentations augs)
845     throws XNIException {
846         if (fDocumentHandler != null
847         && getState() == STATE_NORMAL_PROCESSING) {
848             fDocumentHandler.ignorableWhitespace(text, augs);
849         }
850     }
851     
852     public void startCDATA(Augmentations augs) throws XNIException {
853         if (fDocumentHandler != null
854         && getState() == STATE_NORMAL_PROCESSING) {
855             fDocumentHandler.startCDATA(augs);
856         }
857     }
858     
859     public void endCDATA(Augmentations augs) throws XNIException {
860         if (fDocumentHandler != null
861         && getState() == STATE_NORMAL_PROCESSING) {
862             fDocumentHandler.endCDATA(augs);
863         }
864     }
865     
866     public void endDocument(Augmentations augs) throws XNIException {
867         if (isRootDocument() && fDocumentHandler != null) {
868             fDocumentHandler.endDocument(augs);
869         }
870     }
871     
872     public void setDocumentSource(XMLDocumentSource source) {
873         fDocumentSource = source;
874     }
875     
876     public XMLDocumentSource getDocumentSource() {
877         return fDocumentSource;
878     }
879     
880     // DTDHandler methods
881
// We are only interested in the notation and unparsed entity declarations,
882
// the rest we just pass on
883

884     /* (non-Javadoc)
885      * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#attributeDecl(java.lang.String, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, com.sun.org.apache.xerces.internal.xni.XMLString, com.sun.org.apache.xerces.internal.xni.XMLString, com.sun.org.apache.xerces.internal.xni.Augmentations)
886      */

887     public void attributeDecl(
888     String JavaDoc elementName,
889     String JavaDoc attributeName,
890     String JavaDoc type,
891     String JavaDoc[] enumeration,
892     String JavaDoc defaultType,
893     XMLString defaultValue,
894     XMLString nonNormalizedDefaultValue,
895     Augmentations augmentations)
896     throws XNIException {
897         if (fDTDHandler != null) {
898             fDTDHandler.attributeDecl(
899             elementName,
900             attributeName,
901             type,
902             enumeration,
903             defaultType,
904             defaultValue,
905             nonNormalizedDefaultValue,
906             augmentations);
907         }
908     }
909     
910     /* (non-Javadoc)
911      * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#elementDecl(java.lang.String, java.lang.String, com.sun.org.apache.xerces.internal.xni.Augmentations)
912      */

913     public void elementDecl(
914     String JavaDoc name,
915     String JavaDoc contentModel,
916     Augmentations augmentations)
917     throws XNIException {
918         if (fDTDHandler != null) {
919             fDTDHandler.elementDecl(name, contentModel, augmentations);
920         }
921     }
922     
923     /* (non-Javadoc)
924      * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#endAttlist(com.sun.org.apache.xerces.internal.xni.Augmentations)
925      */

926     public void endAttlist(Augmentations augmentations) throws XNIException {
927         if (fDTDHandler != null) {
928             fDTDHandler.endAttlist(augmentations);
929         }
930     }
931     
932     /* (non-Javadoc)
933      * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#endConditional(com.sun.org.apache.xerces.internal.xni.Augmentations)
934      */

935     public void endConditional(Augmentations augmentations)
936     throws XNIException {
937         if (fDTDHandler != null) {
938             fDTDHandler.endConditional(augmentations);
939         }
940     }
941     
942     /* (non-Javadoc)
943      * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#endDTD(com.sun.org.apache.xerces.internal.xni.Augmentations)
944      */

945     public void endDTD(Augmentations augmentations) throws XNIException {
946         if (fDTDHandler != null) {
947             fDTDHandler.endDTD(augmentations);
948         }
949         fInDTD = false;
950     }
951     
952     /* (non-Javadoc)
953      * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#endExternalSubset(com.sun.org.apache.xerces.internal.xni.Augmentations)
954      */

955     public void endExternalSubset(Augmentations augmentations)
956     throws XNIException {
957         if (fDTDHandler != null) {
958             fDTDHandler.endExternalSubset(augmentations);
959         }
960     }
961     
962     /* (non-Javadoc)
963      * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#endParameterEntity(java.lang.String, com.sun.org.apache.xerces.internal.xni.Augmentations)
964      */

965     public void endParameterEntity(String JavaDoc name, Augmentations augmentations)
966     throws XNIException {
967         if (fDTDHandler != null) {
968             fDTDHandler.endParameterEntity(name, augmentations);
969         }
970     }
971     
972     /* (non-Javadoc)
973      * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#externalEntityDecl(java.lang.String, com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier, com.sun.org.apache.xerces.internal.xni.Augmentations)
974      */

975     public void externalEntityDecl(
976     String JavaDoc name,
977     XMLResourceIdentifier identifier,
978     Augmentations augmentations)
979     throws XNIException {
980         if (fDTDHandler != null) {
981             fDTDHandler.externalEntityDecl(name, identifier, augmentations);
982         }
983     }
984     
985     /* (non-Javadoc)
986      * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#getDTDSource()
987      */

988     public XMLDTDSource getDTDSource() {
989         return fDTDSource;
990     }
991     
992     /* (non-Javadoc)
993      * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#ignoredCharacters(com.sun.org.apache.xerces.internal.xni.XMLString, com.sun.org.apache.xerces.internal.xni.Augmentations)
994      */

995     public void ignoredCharacters(XMLString text, Augmentations augmentations)
996     throws XNIException {
997         if (fDTDHandler != null) {
998             fDTDHandler.ignoredCharacters(text, augmentations);
999         }
1000    }
1001    
1002    /* (non-Javadoc)
1003     * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#internalEntityDecl(java.lang.String, com.sun.org.apache.xerces.internal.xni.XMLString, com.sun.org.apache.xerces.internal.xni.XMLString, com.sun.org.apache.xerces.internal.xni.Augmentations)
1004     */

1005    public void internalEntityDecl(
1006    String JavaDoc name,
1007    XMLString text,
1008    XMLString nonNormalizedText,
1009    Augmentations augmentations)
1010    throws XNIException {
1011        if (fDTDHandler != null) {
1012            fDTDHandler.internalEntityDecl(
1013            name,
1014            text,
1015            nonNormalizedText,
1016            augmentations);
1017        }
1018    }
1019    
1020    /* (non-Javadoc)
1021     * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#notationDecl(java.lang.String, com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier, com.sun.org.apache.xerces.internal.xni.Augmentations)
1022     */

1023    public void notationDecl(
1024    String JavaDoc name,
1025    XMLResourceIdentifier identifier,
1026    Augmentations augmentations)
1027    throws XNIException {
1028        this.addNotation(name, identifier, augmentations);
1029        if (fDTDHandler != null) {
1030            fDTDHandler.notationDecl(name, identifier, augmentations);
1031        }
1032    }
1033    
1034    /* (non-Javadoc)
1035     * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#setDTDSource(com.sun.org.apache.xerces.internal.xni.parser.XMLDTDSource)
1036     */

1037    public void setDTDSource(XMLDTDSource source) {
1038        fDTDSource = source;
1039    }
1040    
1041    /* (non-Javadoc)
1042     * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#startAttlist(java.lang.String, com.sun.org.apache.xerces.internal.xni.Augmentations)
1043     */

1044    public void startAttlist(String JavaDoc elementName, Augmentations augmentations)
1045    throws XNIException {
1046        if (fDTDHandler != null) {
1047            fDTDHandler.startAttlist(elementName, augmentations);
1048        }
1049    }
1050    
1051    /* (non-Javadoc)
1052     * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#startConditional(short, com.sun.org.apache.xerces.internal.xni.Augmentations)
1053     */

1054    public void startConditional(short type, Augmentations augmentations)
1055    throws XNIException {
1056        if (fDTDHandler != null) {
1057            fDTDHandler.startConditional(type, augmentations);
1058        }
1059    }
1060    
1061    /* (non-Javadoc)
1062     * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#startDTD(com.sun.org.apache.xerces.internal.xni.XMLLocator, com.sun.org.apache.xerces.internal.xni.Augmentations)
1063     */

1064    public void startDTD(XMLLocator locator, Augmentations augmentations)
1065    throws XNIException {
1066        fInDTD = true;
1067        if (fDTDHandler != null) {
1068            fDTDHandler.startDTD(locator, augmentations);
1069        }
1070    }
1071    
1072    /* (non-Javadoc)
1073     * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#startExternalSubset(com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier, com.sun.org.apache.xerces.internal.xni.Augmentations)
1074     */

1075    public void startExternalSubset(
1076    XMLResourceIdentifier identifier,
1077    Augmentations augmentations)
1078    throws XNIException {
1079        if (fDTDHandler != null) {
1080            fDTDHandler.startExternalSubset(identifier, augmentations);
1081        }
1082    }
1083    
1084    /* (non-Javadoc)
1085     * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#startParameterEntity(java.lang.String, com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier, java.lang.String, com.sun.org.apache.xerces.internal.xni.Augmentations)
1086     */

1087    public void startParameterEntity(
1088    String JavaDoc name,
1089    XMLResourceIdentifier identifier,
1090    String JavaDoc encoding,
1091    Augmentations augmentations)
1092    throws XNIException {
1093        if (fDTDHandler != null) {
1094            fDTDHandler.startParameterEntity(
1095            name,
1096            identifier,
1097            encoding,
1098            augmentations);
1099        }
1100    }
1101    
1102    /* (non-Javadoc)
1103     * @see com.sun.org.apache.xerces.internal.xni.XMLDTDHandler#unparsedEntityDecl(java.lang.String, com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier, java.lang.String, com.sun.org.apache.xerces.internal.xni.Augmentations)
1104     */

1105    public void unparsedEntityDecl(
1106    String JavaDoc name,
1107    XMLResourceIdentifier identifier,
1108    String JavaDoc notation,
1109    Augmentations augmentations)
1110    throws XNIException {
1111        this.addUnparsedEntity(name, identifier, notation, augmentations);
1112        if (fDTDHandler != null) {
1113            fDTDHandler.unparsedEntityDecl(
1114            name,
1115            identifier,
1116            notation,
1117            augmentations);
1118        }
1119    }
1120    
1121    /* (non-Javadoc)
1122     * @see com.sun.org.apache.xerces.internal.xni.parser.XMLDTDSource#getDTDHandler()
1123     */

1124    public XMLDTDHandler getDTDHandler() {
1125        return fDTDHandler;
1126    }
1127    
1128    /* (non-Javadoc)
1129     * @see com.sun.org.apache.xerces.internal.xni.parser.XMLDTDSource#setDTDHandler(com.sun.org.apache.xerces.internal.xni.XMLDTDHandler)
1130     */

1131    public void setDTDHandler(XMLDTDHandler handler) {
1132        fDTDHandler = handler;
1133    }
1134    
1135    // XIncludeHandler methods
1136

1137    private void setErrorReporter(XMLErrorReporter reporter) {
1138        fErrorReporter = reporter;
1139        if (fErrorReporter != null) {
1140            fErrorReporter.putMessageFormatter(
1141            XIncludeMessageFormatter.XINCLUDE_DOMAIN,
1142            new XIncludeMessageFormatter());
1143            // this ensures the proper location is displayed in error messages
1144
if (fDocLocation != null) {
1145                fErrorReporter.setDocumentLocator(fDocLocation);
1146            }
1147        }
1148    }
1149    
1150    protected void handleFallbackElement() {
1151        setSawInclude(fDepth, false);
1152        fNamespaceContext.setContextInvalid();
1153        if (!getSawInclude(fDepth - 1)) {
1154            reportFatalError("FallbackParent");
1155        }
1156        
1157        if (getSawFallback(fDepth)) {
1158            reportFatalError("MultipleFallbacks");
1159        }
1160        else {
1161            setSawFallback(fDepth, true);
1162        }
1163        
1164        // Either the state is STATE_EXPECT_FALLBACK or it's STATE_IGNORE.
1165
// If we're ignoring, we want to stay ignoring. But if we're expecting this fallback element,
1166
// we want to signal that we should process the children.
1167
if (getState() == STATE_EXPECT_FALLBACK) {
1168            setState(STATE_NORMAL_PROCESSING);
1169        }
1170    }
1171    
1172    protected boolean handleIncludeElement(XMLAttributes attributes)
1173    throws XNIException {
1174        setSawInclude(fDepth, true);
1175        fNamespaceContext.setContextInvalid();
1176        if (getSawInclude(fDepth - 1)) {
1177            reportFatalError("IncludeChild", new Object JavaDoc[] { XINCLUDE_INCLUDE });
1178        }
1179        if (getState() == STATE_IGNORE)
1180            return true;
1181        
1182        // TODO: does Java use IURIs by default?
1183
// [Definition: An internationalized URI reference, or IURI, is a URI reference that directly uses [Unicode] characters.]
1184
// TODO: figure out what section 4.1.1 of the XInclude spec is talking about
1185
// has to do with disallowed ASCII character escaping
1186
// this ties in with the above IURI section, but I suspect Java already does it
1187

1188        String JavaDoc href = attributes.getValue(XINCLUDE_ATTR_HREF);
1189        String JavaDoc parse = attributes.getValue(XINCLUDE_ATTR_PARSE);
1190        String JavaDoc xpointerPart = attributes.getValue(XPOINTER);
1191        String JavaDoc accept = attributes.getValue(XINCLUDE_ATTR_ACCEPT);
1192        String JavaDoc acceptLanguage = attributes.getValue(XINCLUDE_ATTR_ACCEPT_LANGUAGE);
1193        
1194        if (href == null && xpointerPart == null) {
1195            reportFatalError("XpointerMissing");
1196        }
1197        if (parse == null) {
1198            parse = XINCLUDE_PARSE_XML;
1199        }
1200        
1201        boolean xpointer = false;
1202        String JavaDoc parserName = null;
1203        
1204        //Ignore fragment identifiers, implementation specific as per spec.
1205

1206        if( href.indexOf("#")!=-1 )
1207            href = href.substring(0,href.indexOf("#"));
1208        
1209        if ( xpointerPart != null && parse.equals(XINCLUDE_PARSE_XML))
1210            xpointer = true;
1211        
1212        // Verify that if an accept and/or an accept-language attribute exist
1213
// that the value(s) don't contain disallowed characters.
1214
if (accept != null && !isValidInHTTPHeader(accept)) {
1215            reportFatalError("AcceptMalformed", null);
1216        }
1217        if (acceptLanguage != null && !isValidInHTTPHeader(acceptLanguage)) {
1218            reportFatalError("AcceptLanguageMalformed", null);
1219        }
1220        
1221        XMLInputSource includedSource = null;
1222        if (fEntityResolver != null) {
1223            try {
1224                XMLResourceIdentifier resourceIdentifier =
1225                new XMLResourceIdentifierImpl(
1226                null,
1227                href,
1228                fCurrentBaseURI.getExpandedSystemId(),
1229                XMLEntityManager.expandSystemId(
1230                href,
1231                fCurrentBaseURI.getExpandedSystemId(),
1232                false));
1233                
1234                includedSource =
1235                fEntityResolver.resolveEntity(resourceIdentifier);
1236            } catch (IOException JavaDoc e) {
1237                reportResourceError(
1238                "XMLResourceError",
1239                new Object JavaDoc[] { href, e.getMessage()});
1240                return false;
1241            }
1242        }
1243        
1244        if (includedSource == null) {
1245            includedSource =
1246            new XIncludeInputSource(
1247            null,
1248            href,
1249            fCurrentBaseURI.getExpandedSystemId());
1250        }
1251        
1252        if(parse.equals(XINCLUDE_PARSE_XML) && xpointer ){
1253            if(fXPointerFramework == null){
1254                fXPointerFramework = new XPointerFramework();
1255                fXPointerFramework.setXPointerSchema(fXPointerSchema);
1256            }else{
1257                fXPointerFramework.reset();
1258                fXPointerFramework.setXPointerSchema(fXPointerSchema);
1259            }
1260            parserName = XPOINTER_DEFAULT_CONFIGURATION;
1261            fChildConfig = createXPointerParser();
1262            fXPointerFramework.setSchemaPointer(xpointerPart);
1263            // we don't want a schema validator on the new pipeline,
1264
// so we set it to false, regardless of what was copied above
1265
/* fChildConfig.setFeature(
1266            Constants.XERCES_FEATURE_PREFIX
1267            + Constants.SCHEMA_VALIDATION_FEATURE,
1268            false);*/

1269            //-Revisit and clean up this piece of unclean code.
1270
XPointerSchema fXPointerSchemaS;
1271            
1272            if((fXPointerSchemaS = fXPointerFramework.getNextXPointerSchema()) == null && fXPointerFramework.getSchemaCount() == 0){
1273                fNamespaceContext.pushScope();
1274                fXPointerSchemaS = fXPointerFramework.getDefaultSchema();
1275                fXPointerSchemaS.setXPointerSchemaPointer(xpointerPart);
1276                processSchema(fXPointerSchemaS,includedSource);
1277                /*
1278                 Object sch = null;
1279                if(!fXPointerFramework.fSchemaNotAvailable.empty())
1280                    sch = fXPointerFramework.fSchemaNotAvailable.pop();
1281                reportFatalError("NO_XPointerSchema", new Object[] {sch});
1282                 */

1283            }else {
1284                try {
1285                    fNamespaceContext.pushScope();
1286                    if(fXPointerSchemaS != null && processSchema(fXPointerSchemaS,includedSource)){
1287                        ;
1288                    }else{
1289                        for (int i=fXPointerFramework.getCurrentPointer(); i <=fXPointerFramework.getSchemaCount();i++){
1290                            fXPointerSchemaS = fXPointerFramework.getNextXPointerSchema();
1291                            if(fXPointerSchemaS != null && processSchema(fXPointerSchemaS,includedSource)){
1292                                break;
1293                            }
1294                        }
1295                    }
1296                }
1297                catch (XNIException e) {
1298                    reportFatalError("XMLParseError");
1299                }
1300                finally {
1301                    fNamespaceContext.popScope();
1302                }
1303            }
1304            
1305        }
1306        else if (parse.equals(XINCLUDE_PARSE_XML)) {
1307            // Instead of always creating a new configuration, the first one can be reused
1308
//if (fChildConfig == null) {
1309
parserName = XINCLUDE_DEFAULT_CONFIGURATION;
1310            
1311            fChildConfig =
1312            (XMLParserConfiguration)ObjectFactory.newInstance(
1313            parserName,
1314            ObjectFactory.findClassLoader(),
1315            true);
1316            // use the same error reporter, entity resolver, and security manager.
1317
if (fErrorReporter != null) fChildConfig.setProperty(ERROR_REPORTER, fErrorReporter);
1318            if (fEntityResolver != null) fChildConfig.setProperty(ENTITY_RESOLVER, fEntityResolver);
1319            if (fSecurityManager != null) fChildConfig.setProperty(SECURITY_MANAGER, fSecurityManager);
1320            
1321            // use the same namespace context
1322
fChildConfig.setProperty(
1323            Constants.XERCES_PROPERTY_PREFIX
1324            + Constants.NAMESPACE_CONTEXT_PROPERTY,
1325            fNamespaceContext);
1326            
1327            XIncludeHandler newHandler =
1328            (XIncludeHandler)fChildConfig.getProperty(
1329            Constants.XERCES_PROPERTY_PREFIX
1330            + Constants.XINCLUDE_HANDLER_PROPERTY);
1331            newHandler.setParent(this);
1332            newHandler.setDocumentHandler(this.getDocumentHandler());
1333            //}
1334

1335            // set all features on parserConfig to match this parser configuration
1336
copyFeatures(fSettings, fChildConfig);
1337            // we don't want a schema validator on the new pipeline,
1338
// so we set it to false, regardless of what was copied above
1339
fChildConfig.setFeature(
1340            Constants.XERCES_FEATURE_PREFIX
1341            + Constants.SCHEMA_VALIDATION_FEATURE,
1342            false);
1343            fChildConfig.setFeature(
1344            Constants.XERCES_FEATURE_PREFIX
1345            + Constants.XINCLUDE_AWARE,
1346            true);
1347            
1348            try {
1349                fNamespaceContext.pushScope();
1350                includedSource = setHttpProperties(includedSource,attributes);
1351                fChildConfig.parse(includedSource);
1352                // necessary to make sure proper location is reported in errors
1353
if (fErrorReporter != null) {
1354                    fErrorReporter.setDocumentLocator(fDocLocation);
1355                }
1356            }
1357            catch (XNIException e) {
1358                // necessary to make sure proper location is reported in errors
1359
if (fErrorReporter != null) {
1360                    fErrorReporter.setDocumentLocator(fDocLocation);
1361                }
1362                reportFatalError("XMLParseError", new Object JavaDoc[] { href });
1363            }
1364            catch (IOException JavaDoc e) {
1365                // necessary to make sure proper location is reported in errors
1366
if (fErrorReporter != null) {
1367                    fErrorReporter.setDocumentLocator(fDocLocation);
1368                }
1369                // An IOException indicates that we had trouble reading the file, not
1370
// that it was an invalid XML file. So we send a resource error, not a
1371
// fatal error.
1372
reportResourceError(
1373                "XMLResourceError",
1374                new Object JavaDoc[] { href, e.getMessage()});
1375                return false;
1376            }
1377            finally {
1378                fNamespaceContext.popScope();
1379            }
1380        }
1381        else if (parse.equals(XINCLUDE_PARSE_TEXT)) {
1382            // we only care about encoding for parse="text"
1383
String JavaDoc encoding = attributes.getValue(XINCLUDE_ATTR_ENCODING);
1384            includedSource.setEncoding(encoding);
1385            
1386            XIncludeTextReader reader = null;
1387            try {
1388                if (fIsXML11) {
1389                    reader = new XInclude11TextReader(includedSource, this);
1390                }
1391                else {
1392                    reader = new XIncludeTextReader(includedSource, this);
1393                }
1394                if (includedSource.getCharacterStream() == null
1395                && includedSource.getByteStream() == null) {
1396                    reader.setHttpProperties(accept, acceptLanguage);
1397                }
1398                reader.setErrorReporter(fErrorReporter);
1399                reader.parse();
1400            }
1401            // encoding errors
1402
catch (MalformedByteSequenceException ex) {
1403                fErrorReporter.reportError(ex.getDomain(), ex.getKey(),
1404                ex.getArguments(), XMLErrorReporter.SEVERITY_FATAL_ERROR);
1405            }
1406            catch (CharConversionException JavaDoc e) {
1407                fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
1408                "CharConversionFailure", null, XMLErrorReporter.SEVERITY_FATAL_ERROR);
1409            }
1410            catch (IOException JavaDoc e) {
1411                reportResourceError(
1412                "TextResourceError",
1413                new Object JavaDoc[] { href, e.getMessage()});
1414                return false;
1415            }
1416            finally {
1417                if (reader != null) {
1418                    try {
1419                        reader.close();
1420                    }
1421                    catch (IOException JavaDoc e) {
1422                        reportResourceError(
1423                        "TextResourceError",
1424                        new Object JavaDoc[] { href, e.getMessage()});
1425                        return false;
1426                    }
1427                }
1428            }
1429        }
1430        else {
1431            reportFatalError("InvalidParseValue", new Object JavaDoc[] { parse });
1432        }
1433        return true;
1434    }
1435    
1436    /**
1437     * Returns true if the element has the namespace "http://www.w3.org/2001/XInclude"
1438     * @param element the element to check
1439     * @return true if the element has the namespace "http://www.w3.org/2001/XInclude"
1440     */

1441    protected boolean hasXIncludeNamespace(QName element) {
1442        // REVISIT: The namespace of this element should be bound
1443
// already. Why are we looking it up from the namespace
1444
// context? -- mrglavas
1445
return element.uri == XINCLUDE_NS_URI
1446        || fNamespaceContext.getURI(element.prefix) == XINCLUDE_NS_URI;
1447    }
1448    
1449    /**
1450     * Checks if the element is an &lt;include&gt; element. The element must have
1451     * the XInclude namespace, and a local name of "include".
1452     *
1453     * @param element the element to check
1454     * @return true if the element is an &lt;include&gt; element
1455     * @see #hasXIncludeNamespace(QName)
1456     */

1457    protected boolean isIncludeElement(QName element) {
1458        return element.localpart.equals(XINCLUDE_INCLUDE) &&
1459        hasXIncludeNamespace(element);
1460    }
1461    
1462    /**
1463     * Checks if the element is an &lt;fallback&gt; element. The element must have
1464     * the XInclude namespace, and a local name of "fallback".
1465     *
1466     * @param element the element to check
1467     * @return true if the element is an &lt;fallback; element
1468     * @see #hasXIncludeNamespace(QName)
1469     */

1470    protected boolean isFallbackElement(QName element) {
1471        return element.localpart.equals(XINCLUDE_FALLBACK) &&
1472        hasXIncludeNamespace(element);
1473    }
1474    
1475    /**
1476     * Returns true if the current [base URI] is the same as the [base URI] that
1477     * was in effect on the include parent. This method should <em>only</em> be called
1478     * when the current element is a top level included element, i.e. the direct child
1479     * of a fallback element, or the root elements in an included document.
1480     * The "include parent" is the element which, in the result infoset, will be the
1481     * direct parent of the current element.
1482     * @return true if the [base URIs] are the same string
1483     */

1484    protected boolean sameBaseURIAsIncludeParent() {
1485        String JavaDoc parentBaseURI = getIncludeParentBaseURI();
1486        String JavaDoc baseURI = fCurrentBaseURI.getExpandedSystemId();
1487        // REVISIT: should we use File#sameFile() ?
1488
// I think the benefit of using it is that it resolves host names
1489
// instead of just doing a string comparison.
1490
// TODO: [base URI] is still an open issue with the working group.
1491
// They're deciding if xml:base should be added if the [base URI] is different in terms
1492
// of resolving relative references, or if it should be added if they are different at all.
1493
// Revisit this after a final decision has been made.
1494
// The decision also affects whether we output the file name of the URI, or just the path.
1495
return parentBaseURI != null && parentBaseURI.equals(baseURI);
1496    }
1497    
1498    /**
1499     * Checks if the file indicated by the given XMLLocator has already been included
1500     * in the current stack.
1501     * @param includedSource the source to check for inclusion
1502     * @return true if the source has already been included
1503     */

1504    protected boolean searchForRecursiveIncludes(XMLLocator includedSource) {
1505        String JavaDoc includedSystemId = includedSource.getExpandedSystemId();
1506        
1507        if (includedSystemId == null) {
1508            try {
1509                includedSystemId =
1510                XMLEntityManager.expandSystemId(
1511                includedSource.getLiteralSystemId(),
1512                includedSource.getBaseSystemId(),
1513                false);
1514            }
1515            catch (MalformedURIException e) {
1516                reportFatalError("ExpandedSystemId");
1517            }
1518        }
1519        
1520        if (includedSystemId.equals(fCurrentBaseURI.getExpandedSystemId())) {
1521            return true;
1522        }
1523        
1524        if (fParentXIncludeHandler == null) {
1525            return false;
1526        }
1527        return fParentXIncludeHandler.searchForRecursiveIncludes(
1528        includedSource);
1529    }
1530    
1531    /**
1532     * Returns true if the current element is a top level included item. This means
1533     * it's either the child of a fallback element, or the top level item in an
1534     * included document
1535     * @return true if the current element is a top level included item
1536     */

1537    protected boolean isTopLevelIncludedItem() {
1538        return isTopLevelIncludedItemViaInclude()
1539        || isTopLevelIncludedItemViaFallback();
1540    }
1541    
1542    protected boolean isTopLevelIncludedItemViaInclude() {
1543        return fDepth == 1 && !isRootDocument();
1544    }
1545    
1546    protected boolean isTopLevelIncludedItemViaFallback() {
1547        // Technically, this doesn't check if the parent was a fallback, it also
1548
// would return true if any of the parent's sibling elements were fallbacks.
1549
// However, this doesn't matter, since we will always be ignoring elements
1550
// whose parent's siblings were fallbacks.
1551
return getSawFallback(fDepth - 1);
1552    }
1553    
1554    /**
1555     * Processes the XMLAttributes object of startElement() calls. Performs the following tasks:
1556     * <ul>
1557     * <li> If the element is a top level included item whose [base URI] is different from the
1558     * [base URI] of the include parent, then an xml:base attribute is added to specify the
1559     * true [base URI]
1560     * <li> For all namespace prefixes which are in-scope in an included item, but not in scope
1561     * in the include parent, a xmlns:prefix attribute is added
1562     * <li> For all attributes with a type of ENTITY, ENTITIES or NOTATIONS, the notations and
1563     * unparsed entities are processed as described in the spec, sections 4.5.1 and 4.5.2
1564     * </ul>
1565     * @param attributes
1566     * @return
1567     */

1568    protected XMLAttributes processAttributes(XMLAttributes attributes) {
1569        if (isTopLevelIncludedItem()) {
1570            // Modify attributes to fix the base URI (spec 4.5.5).
1571
// We only do it to top level included elements, which have a different
1572
// base URI than their include parent.
1573
if (!sameBaseURIAsIncludeParent()) {
1574                if (attributes == null) {
1575                    attributes = new XMLAttributesImpl();
1576                }
1577                
1578                // This causes errors with schema validation, if the schema doesn't
1579
// specify that these elements can have an xml:base attribute
1580
// TODO: add a user option to turn this off?
1581
String JavaDoc uri = null;
1582                try {
1583                    uri = this.getRelativeBaseURI();
1584                }
1585                catch (MalformedURIException e) {
1586                    // this shouldn't ever happen, since by definition, we had to traverse
1587
// the same URIs to even get to this place
1588
uri = fCurrentBaseURI.getExpandedSystemId();
1589                }
1590                int index =
1591                attributes.addAttribute(
1592                XML_BASE_QNAME,
1593                XMLSymbols.fCDATASymbol,
1594                uri);
1595                attributes.setSpecified(index, true);
1596            }
1597            
1598            // Modify attributes of included items to do namespace-fixup. (spec 4.5.4)
1599
Enumeration JavaDoc inscopeNS = fNamespaceContext.getAllPrefixes();
1600            while (inscopeNS.hasMoreElements()) {
1601                String JavaDoc prefix = (String JavaDoc)inscopeNS.nextElement();
1602                String JavaDoc parentURI =
1603                fNamespaceContext.getURIFromIncludeParent(prefix);
1604                String JavaDoc uri = fNamespaceContext.getURI(prefix);
1605                if (parentURI != uri && attributes != null) {
1606                    if (prefix == XMLSymbols.EMPTY_STRING) {
1607                        if (attributes
1608                        .getValue(
1609                        NamespaceContext.XMLNS_URI,
1610                        XMLSymbols.PREFIX_XMLNS)
1611                        == null) {
1612                            if (attributes == null) {
1613                                attributes = new XMLAttributesImpl();
1614                            }
1615                            
1616                            QName ns = (QName)NEW_NS_ATTR_QNAME.clone();
1617                            ns.localpart = XMLSymbols.PREFIX_XMLNS;
1618                            ns.rawname = XMLSymbols.PREFIX_XMLNS;
1619                            attributes.addAttribute(
1620                            ns,
1621                            XMLSymbols.fCDATASymbol,
1622                            uri);
1623                        }
1624                    }
1625                    else if (
1626                    attributes.getValue(NamespaceContext.XMLNS_URI, prefix)
1627                    == null) {
1628                        if (attributes == null) {
1629                            attributes = new XMLAttributesImpl();
1630                        }
1631                        
1632                        QName ns = (QName)NEW_NS_ATTR_QNAME.clone();
1633                        ns.localpart = prefix;
1634                        ns.rawname += prefix;
1635                        attributes.addAttribute(
1636                        ns,
1637                        XMLSymbols.fCDATASymbol,
1638                        uri);
1639                    }
1640                }
1641            }
1642        }
1643        
1644        if (attributes != null) {
1645            int length = attributes.getLength();
1646            for (int i = 0; i < length; i++) {
1647                String JavaDoc type = attributes.getType(i);
1648                String JavaDoc value = attributes.getValue(i);
1649                if (type == XMLSymbols.fENTITYSymbol) {
1650                    this.checkUnparsedEntity(value);
1651                }
1652                if (type == XMLSymbols.fENTITIESSymbol) {
1653                    // 4.5.1 - Unparsed Entities
1654
StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(value);
1655                    while (st.hasMoreTokens()) {
1656                        String JavaDoc entName = st.nextToken();
1657                        this.checkUnparsedEntity(entName);
1658                    }
1659                }
1660                else if (type == XMLSymbols.fNOTATIONSymbol) {
1661                    // 4.5.2 - Notations
1662
this.checkNotation(value);
1663                }
1664                /* We actually don't need to do anything for 4.5.3, because at this stage the
1665                 * value of the attribute is just a string. It will be taken care of later
1666                 * in the pipeline, when the IDREFs are actually resolved against IDs.
1667                 *
1668                 * if (type == XMLSymbols.fIDREFSymbol || type == XMLSymbols.fIDREFSSymbol) { }
1669                 */

1670            }
1671        }
1672        
1673        return attributes;
1674    }
1675    
1676    /**
1677     * Returns a URI, relative to the include parent's base URI, of the current
1678     * [base URI]. For instance, if the current [base URI] was "dir1/dir2/file.xml"
1679     * and the include parent's [base URI] was "dir/", this would return "dir2/file.xml".
1680     * @return the relative URI
1681     */

1682    protected String JavaDoc getRelativeBaseURI() throws MalformedURIException {
1683        int includeParentDepth = getIncludeParentDepth();
1684        String JavaDoc relativeURI = this.getRelativeURI(includeParentDepth);
1685        if (isRootDocument()) {
1686            return relativeURI;
1687        }
1688        else {
1689            if (relativeURI.equals("")) {
1690                relativeURI = fCurrentBaseURI.getLiteralSystemId();
1691            }
1692            
1693            if (includeParentDepth == 0) {
1694                if (fParentRelativeURI == null) {
1695                    fParentRelativeURI =
1696                    fParentXIncludeHandler.getRelativeBaseURI();
1697                }
1698                if (fParentRelativeURI.equals("")) {
1699                    return relativeURI;
1700                }
1701                URI uri = new URI("file", fParentRelativeURI);
1702                uri = new URI(uri, relativeURI);
1703                return uri.getPath();
1704            }
1705            else {
1706                return relativeURI;
1707            }
1708        }
1709    }
1710    
1711    /**
1712     * Returns the [base URI] of the include parent.
1713     * @return the base URI of the include parent.
1714     */

1715    private String JavaDoc getIncludeParentBaseURI() {
1716        int depth = getIncludeParentDepth();
1717        if (!isRootDocument() && depth == 0) {
1718            return fParentXIncludeHandler.getIncludeParentBaseURI();
1719        }
1720        else {
1721            return this.getBaseURI(depth);
1722        }
1723    }
1724    
1725    /**
1726     * Returns the depth of the include parent. Here, the include parent is
1727     * calculated as the last non-include or non-fallback element. It is assumed
1728     * this method is called when the current element is a top level included item.
1729     * Returning 0 indicates that the top level element in this document
1730     * was an include element.
1731     * @return the depth of the top level include element
1732     */

1733    private int getIncludeParentDepth() {
1734        // We don't start at fDepth, since it is either the top level included item,
1735
// or an include element, when this method is called.
1736
for (int i = fDepth - 1; i >= 0; i--) {
1737            // This technically might not always return the first non-include/fallback
1738
// element that it comes to, since sawFallback() returns true if a fallback
1739
// was ever encountered at that depth. However, if a fallback was encountered
1740
// at that depth, and it wasn't the direct descendant of the current element
1741
// then we can't be in a situation where we're calling this method (because
1742
// we'll always be in STATE_IGNORE)
1743
if (!getSawInclude(i) && !getSawFallback(i)) {
1744                return i;
1745            }
1746        }
1747        // shouldn't get here, since depth 0 should never have an include element or
1748
// a fallback element
1749
return 0;
1750    }
1751    
1752    /**
1753     * Modify the augmentations. Add an [included] infoset item, if the current
1754     * element is a top level included item.
1755     * @param augs the Augmentations to modify.
1756     * @return the modified Augmentations
1757     */

1758    protected Augmentations modifyAugmentations(Augmentations augs) {
1759        return modifyAugmentations(augs, false);
1760    }
1761    
1762    /**
1763     * Modify the augmentations. Add an [included] infoset item, if <code>force</code>
1764     * is true, or if the current element is a top level included item.
1765     * @param augs the Augmentations to modify.
1766     * @param force whether to force modification
1767     * @return the modified Augmentations
1768     */

1769    protected Augmentations modifyAugmentations(
1770    Augmentations augs,
1771    boolean force) {
1772        if (force || isTopLevelIncludedItem()) {
1773            if (augs == null) {
1774                augs = new AugmentationsImpl();
1775            }
1776            augs.putItem(XINCLUDE_INCLUDED, Boolean.TRUE);
1777        }
1778        return augs;
1779    }
1780    
1781    protected int getState(int depth) {
1782        return fState[depth];
1783    }
1784    
1785    protected int getState() {
1786        return fState[fDepth];
1787    }
1788    
1789    protected void setState(int state) {
1790        if (fDepth >= fState.length) {
1791            int[] newarray = new int[fDepth * 2];
1792            System.arraycopy(fState, 0, newarray, 0, fState.length);
1793            fState = newarray;
1794        }
1795        fState[fDepth] = state;
1796    }
1797    
1798    /**
1799     * Records that an &lt;fallback&gt; was encountered at the specified depth,
1800     * as an ancestor of the current element, or as a sibling of an ancestor of the
1801     * current element.
1802     *
1803     * @param depth
1804     * @param val
1805     */

1806    protected void setSawFallback(int depth, boolean val) {
1807        if (depth >= fSawFallback.length) {
1808            boolean[] newarray = new boolean[depth * 2];
1809            System.arraycopy(fSawFallback, 0, newarray, 0, fSawFallback.length);
1810            fSawFallback = newarray;
1811        }
1812        fSawFallback[depth] = val;
1813    }
1814    
1815    /**
1816     * Returns whether an &lt;fallback&gt; was encountered at the specified depth,
1817     * as an ancestor of the current element, or as a sibling of an ancestor of the
1818     * current element.
1819     *
1820     * @param depth
1821     */

1822    protected boolean getSawFallback(int depth) {
1823        if (depth >= fSawFallback.length) {
1824            return false;
1825        }
1826        return fSawFallback[depth];
1827    }
1828    
1829    /**
1830     * Records that an &lt;include&gt; was encountered at the specified depth,
1831     * as an ancestor of the current item.
1832     *
1833     * @param depth
1834     * @param val
1835     */

1836    protected void setSawInclude(int depth, boolean val) {
1837        if (depth >= fSawInclude.length) {
1838            boolean[] newarray = new boolean[depth * 2];
1839            System.arraycopy(fSawInclude, 0, newarray, 0, fSawInclude.length);
1840            fSawInclude = newarray;
1841        }
1842        fSawInclude[depth] = val;
1843    }
1844    
1845    /**
1846     * Return whether an &lt;include&gt; was encountered at the specified depth,
1847     * as an ancestor of the current item.
1848     *
1849     * @param depth
1850     * @return
1851     */

1852    protected boolean getSawInclude(int depth) {
1853        if (depth >= fSawInclude.length) {
1854            return false;
1855        }
1856        return fSawInclude[depth];
1857    }
1858    
1859    protected void reportResourceError(String JavaDoc key) {
1860        this.reportFatalError(key, null);
1861    }
1862    
1863    protected void reportResourceError(String JavaDoc key, Object JavaDoc[] args) {
1864        this.reportError(key, args, XMLErrorReporter.SEVERITY_WARNING);
1865    }
1866    
1867    protected void reportFatalError(String JavaDoc key) {
1868        this.reportFatalError(key, null);
1869    }
1870    
1871    protected void reportFatalError(String JavaDoc key, Object JavaDoc[] args) {
1872        this.reportError(key, args, XMLErrorReporter.SEVERITY_FATAL_ERROR);
1873    }
1874    
1875    private void reportError(String JavaDoc key, Object JavaDoc[] args, short severity) {
1876        if (fErrorReporter != null) {
1877            fErrorReporter.reportError(
1878            XIncludeMessageFormatter.XINCLUDE_DOMAIN,
1879            key,
1880            args,
1881            severity);
1882        }
1883        // we won't worry about when error reporter is null, since there should always be
1884
// at least the default error reporter
1885
}
1886    
1887    /**
1888     * Set the parent of this XIncludeHandler in the tree
1889     * @param parent
1890     */

1891    protected void setParent(XIncludeHandler parent) {
1892        fParentXIncludeHandler = parent;
1893    }
1894    
1895    // used to know whether to pass declarations to the document handler
1896
protected boolean isRootDocument() {
1897        return fParentXIncludeHandler == null;
1898    }
1899    
1900    /**
1901     * Caches an unparsed entity.
1902     * @param name the name of the unparsed entity
1903     * @param identifier the location of the unparsed entity
1904     * @param augmentations any Augmentations that were on the original unparsed entity declaration
1905     */

1906    protected void addUnparsedEntity(
1907    String JavaDoc name,
1908    XMLResourceIdentifier identifier,
1909    String JavaDoc notation,
1910    Augmentations augmentations) {
1911        UnparsedEntity ent = new UnparsedEntity();
1912        ent.name = name;
1913        ent.systemId = identifier.getLiteralSystemId();
1914        ent.publicId = identifier.getPublicId();
1915        ent.baseURI = identifier.getBaseSystemId();
1916        ent.notation = notation;
1917        ent.augmentations = augmentations;
1918        fUnparsedEntities.add(ent);
1919    }
1920    
1921    /**
1922     * Caches a notation.
1923     * @param name the name of the notation
1924     * @param identifier the location of the notation
1925     * @param augmentations any Augmentations that were on the original notation declaration
1926     */

1927    protected void addNotation(
1928    String JavaDoc name,
1929    XMLResourceIdentifier identifier,
1930    Augmentations augmentations) {
1931        Notation not = new Notation();
1932        not.name = name;
1933        not.systemId = identifier.getLiteralSystemId();
1934        not.publicId = identifier.getPublicId();
1935        not.baseURI = identifier.getBaseSystemId();
1936        not.augmentations = augmentations;
1937        fNotations.add(not);
1938    }
1939    
1940    /**
1941     * Checks if an UnparsedEntity with the given name was declared in the DTD of the document
1942     * for the current pipeline. If so, then the notation for the UnparsedEntity is checked.
1943     * If that turns out okay, then the UnparsedEntity is passed to the root pipeline to
1944     * be checked for conflicts, and sent to the root DTDHandler.
1945     *
1946     * @param entName the name of the UnparsedEntity to check
1947     */

1948    protected void checkUnparsedEntity(String JavaDoc entName) {
1949        UnparsedEntity ent = new UnparsedEntity();
1950        ent.name = entName;
1951        int index = fUnparsedEntities.indexOf(ent);
1952        if (index != -1) {
1953            ent = (UnparsedEntity)fUnparsedEntities.get(index);
1954            // first check the notation of the unparsed entity
1955
checkNotation(ent.notation);
1956            checkAndSendUnparsedEntity(ent);
1957        }
1958    }
1959    
1960    /**
1961     * Checks if a Notation with the given name was declared in the DTD of the document
1962     * for the current pipeline. If so, that Notation is passed to the root pipeline to
1963     * be checked for conflicts, and sent to the root DTDHandler
1964     *
1965     * @param notName the name of the Notation to check
1966     */

1967    protected void checkNotation(String JavaDoc notName) {
1968        Notation not = new Notation();
1969        not.name = notName;
1970        int index = fNotations.indexOf(not);
1971        if (index != -1) {
1972            not = (Notation)fNotations.get(index);
1973            checkAndSendNotation(not);
1974        }
1975    }
1976    
1977    /**
1978     * The purpose of this method is to check if an UnparsedEntity conflicts with a previously
1979     * declared entity in the current pipeline stack. If there is no conflict, the
1980     * UnparsedEntity is sent by the root pipeline.
1981     *
1982     * @param ent the UnparsedEntity to check for conflicts
1983     */

1984    protected void checkAndSendUnparsedEntity(UnparsedEntity ent) {
1985        if (isRootDocument()) {
1986            int index = fUnparsedEntities.indexOf(ent);
1987            if (index == -1) {
1988                // There is no unparsed entity with the same name that we have sent.
1989
// Calling unparsedEntityDecl() will add the entity to our local store,
1990
// and also send the unparsed entity to the DTDHandler
1991
XMLResourceIdentifier id =
1992                new XMLResourceIdentifierImpl(
1993                ent.publicId,
1994                ent.systemId,
1995                ent.baseURI,
1996                null);
1997                this.addUnparsedEntity(
1998                ent.name,
1999                id,
2000                ent.notation,
2001                ent.augmentations);
2002                if (fSendUEAndNotationEvents && fDTDHandler != null) {
2003                    fDTDHandler.unparsedEntityDecl(
2004                    ent.name,
2005                    id,
2006                    ent.notation,
2007                    ent.augmentations);
2008                }
2009            }
2010            else {
2011                UnparsedEntity localEntity =
2012                (UnparsedEntity)fUnparsedEntities.get(index);
2013                if (!ent.isDuplicate(localEntity)) {
2014                    reportFatalError(
2015                    "NonDuplicateUnparsedEntity",
2016                    new Object JavaDoc[] { ent.name });
2017                }
2018            }
2019        }
2020        else {
2021            fParentXIncludeHandler.checkAndSendUnparsedEntity(ent);
2022        }
2023    }
2024    
2025    /**
2026     * The purpose of this method is to check if a Notation conflicts with a previously
2027     * declared notation in the current pipeline stack. If there is no conflict, the
2028     * Notation is sent by the root pipeline.
2029     *
2030     * @param not the Notation to check for conflicts
2031     */

2032    protected void checkAndSendNotation(Notation not) {
2033        if (isRootDocument()) {
2034            int index = fNotations.indexOf(not);
2035            if (index == -1) {
2036                // There is no notation with the same name that we have sent.
2037
XMLResourceIdentifier id =
2038                new XMLResourceIdentifierImpl(
2039                not.publicId,
2040                not.systemId,
2041                not.baseURI,
2042                null);
2043                this.addNotation(not.name, id, not.augmentations);
2044                if (fSendUEAndNotationEvents && fDTDHandler != null) {
2045                    fDTDHandler.notationDecl(not.name, id, not.augmentations);
2046                }
2047            }
2048            else {
2049                Notation localNotation = (Notation)fNotations.get(index);
2050                if (!not.isDuplicate(localNotation)) {
2051                    reportFatalError(
2052                    "NonDuplicateNotation",
2053                    new Object JavaDoc[] { not.name });
2054                }
2055            }
2056        }
2057        else {
2058            fParentXIncludeHandler.checkAndSendNotation(not);
2059        }
2060    }
2061    
2062    // It would be nice if we didn't have to repeat code like this, but there's no interface that has
2063
// setFeature() and addRecognizedFeatures() that the objects have in common.
2064
protected void copyFeatures(
2065    XMLComponentManager from,
2066    ParserConfigurationSettings to) {
2067        Enumeration JavaDoc features = Constants.getXercesFeatures();
2068        copyFeatures1(features, Constants.XERCES_FEATURE_PREFIX, from, to);
2069        features = Constants.getSAXFeatures();
2070        copyFeatures1(features, Constants.SAX_FEATURE_PREFIX, from, to);
2071    }
2072    
2073    protected void copyFeatures(
2074    XMLComponentManager from,
2075    XMLParserConfiguration to) {
2076        Enumeration JavaDoc features = Constants.getXercesFeatures();
2077        copyFeatures1(features, Constants.XERCES_FEATURE_PREFIX, from, to);
2078        features = Constants.getSAXFeatures();
2079        copyFeatures1(features, Constants.SAX_FEATURE_PREFIX, from, to);
2080    }
2081    
2082    private void copyFeatures1(
2083    Enumeration JavaDoc features,
2084    String JavaDoc featurePrefix,
2085    XMLComponentManager from,
2086    ParserConfigurationSettings to) {
2087        while (features.hasMoreElements()) {
2088            String JavaDoc featureId = featurePrefix + (String JavaDoc)features.nextElement();
2089            
2090            to.addRecognizedFeatures(new String JavaDoc[] { featureId });
2091            
2092            try {
2093                to.setFeature(featureId, from.getFeature(featureId));
2094            }
2095            catch (XMLConfigurationException e) {
2096                // componentManager doesn't support this feature,
2097
// so we won't worry about it
2098
}
2099        }
2100    }
2101    
2102    private void copyFeatures1(
2103    Enumeration JavaDoc features,
2104    String JavaDoc featurePrefix,
2105    XMLComponentManager from,
2106    XMLParserConfiguration to) {
2107        while (features.hasMoreElements()) {
2108            String JavaDoc featureId = featurePrefix + (String JavaDoc)features.nextElement();
2109            boolean value = from.getFeature(featureId);
2110            
2111            try {
2112                to.setFeature(featureId, value);
2113            }
2114            catch (XMLConfigurationException e) {
2115                // componentManager doesn't support this feature,
2116
// so we won't worry about it
2117
}
2118        }
2119    }
2120    
2121    // This is a storage class to hold information about the notations.
2122
// We're not using XMLNotationDecl because we don't want to lose the augmentations.
2123
protected class Notation {
2124        public String JavaDoc name;
2125        public String JavaDoc systemId;
2126        public String JavaDoc baseURI;
2127        public String JavaDoc publicId;
2128        public Augmentations augmentations;
2129        
2130        // equals() returns true if two Notations have the same name.
2131
// Useful for searching Vectors for notations with the same name
2132
public boolean equals(Object JavaDoc obj) {
2133            if (obj == null) {
2134                return false;
2135            }
2136            if (obj instanceof Notation) {
2137                Notation other = (Notation)obj;
2138                return name.equals(other.name);
2139            }
2140            return false;
2141        }
2142        
2143        // from 4.5.2
2144
// Notation items with the same [name], [system identifier],
2145
// [public identifier], and [declaration base URI] are considered
2146
// to be duplicate
2147
public boolean isDuplicate(Object JavaDoc obj) {
2148            if (obj != null && obj instanceof Notation) {
2149                Notation other = (Notation)obj;
2150                return name.equals(other.name)
2151                && (systemId == other.systemId
2152                || (systemId != null && systemId.equals(other.systemId)))
2153                && (publicId == other.publicId
2154                || (publicId != null && publicId.equals(other.publicId)))
2155                && (baseURI == other.baseURI
2156                || (baseURI != null && baseURI.equals(other.baseURI)));
2157            }
2158            return false;
2159        }
2160    }
2161    
2162    // This is a storage class to hold information about the unparsed entities.
2163
// We're not using XMLEntityDecl because we don't want to lose the augmentations.
2164
protected class UnparsedEntity {
2165        public String JavaDoc name;
2166        public String JavaDoc systemId;
2167        public String JavaDoc baseURI;
2168        public String JavaDoc publicId;
2169        public String JavaDoc notation;
2170        public Augmentations augmentations;
2171        
2172        // equals() returns true if two UnparsedEntities have the same name.
2173
// Useful for searching Vectors for entities with the same name
2174
public boolean equals(Object JavaDoc obj) {
2175            if (obj == null) {
2176                return false;
2177            }
2178            if (obj instanceof UnparsedEntity) {
2179                UnparsedEntity other = (UnparsedEntity)obj;
2180                return name.equals(other.name);
2181            }
2182            return false;
2183        }
2184        
2185        // from 4.5.1:
2186
// Unparsed entity items with the same [name], [system identifier],
2187
// [public identifier], [declaration base URI], [notation name], and
2188
// [notation] are considered to be duplicate
2189
public boolean isDuplicate(Object JavaDoc obj) {
2190            if (obj != null && obj instanceof UnparsedEntity) {
2191                UnparsedEntity other = (UnparsedEntity)obj;
2192                return name.equals(other.name)
2193                && (systemId == other.systemId
2194                || (systemId != null && systemId.equals(other.systemId)))
2195                && (publicId == other.publicId
2196                || (publicId != null && publicId.equals(other.publicId)))
2197                && (baseURI == other.baseURI
2198                || (baseURI != null && baseURI.equals(other.baseURI)))
2199                && (notation == other.notation
2200                || (notation != null && notation.equals(other.notation)));
2201            }
2202            return false;
2203        }
2204    }
2205    
2206    // The following methods are used for XML Base processing
2207

2208    /**
2209     * Saves the current base URI to the top of the stack.
2210     */

2211    protected void saveBaseURI() {
2212        baseURIScope.push(fDepth);
2213        baseURI.push(fCurrentBaseURI.getBaseSystemId());
2214        literalSystemID.push(fCurrentBaseURI.getLiteralSystemId());
2215        expandedSystemID.push(fCurrentBaseURI.getExpandedSystemId());
2216    }
2217    
2218    /**
2219     * Discards the URIs at the top of the stack, and restores the ones beneath it.
2220     */

2221    protected void restoreBaseURI() {
2222        baseURI.pop();
2223        literalSystemID.pop();
2224        expandedSystemID.pop();
2225        baseURIScope.pop();
2226        fCurrentBaseURI.setBaseSystemId((String JavaDoc)baseURI.peek());
2227        fCurrentBaseURI.setLiteralSystemId((String JavaDoc)literalSystemID.peek());
2228        fCurrentBaseURI.setExpandedSystemId((String JavaDoc)expandedSystemID.peek());
2229    }
2230    
2231    /**
2232     * Gets the base URI that was in use at that depth
2233     * @param depth
2234     * @return the base URI
2235     */

2236    public String JavaDoc getBaseURI(int depth) {
2237        int scope = scopeOf(depth);
2238        return (String JavaDoc)expandedSystemID.elementAt(scope);
2239    }
2240    
2241    /**
2242     * Returns a relative URI, which when resolved against the base URI at the
2243     * specified depth, will create the current base URI.
2244     * This is accomplished by merged the literal system IDs.
2245     * @param depth the depth at which to start creating the relative URI
2246     * @return a relative URI to convert the base URI at the given depth to the current
2247     * base URI
2248     */

2249    public String JavaDoc getRelativeURI(int depth) throws MalformedURIException {
2250        // The literal system id at the location given by "start" is *in focus* at
2251
// the given depth. So we need to adjust it to the next scope, so that we
2252
// only process out of focus literal system ids
2253
int start = scopeOf(depth) + 1;
2254        if (start == baseURIScope.size()) {
2255            // If that is the last system id, then we don't need a relative URI
2256
return "";
2257        }
2258        URI uri = new URI("file", (String JavaDoc)literalSystemID.elementAt(start));
2259        for (int i = start + 1; i < baseURIScope.size(); i++) {
2260            uri = new URI(uri, (String JavaDoc)literalSystemID.elementAt(i));
2261        }
2262        return uri.getPath();
2263    }
2264    
2265    // We need to find two consecutive elements in the scope stack,
2266
// such that the first is lower than 'depth' (or equal), and the
2267
// second is higher.
2268
private int scopeOf(int depth) {
2269        for (int i = baseURIScope.size() - 1; i >= 0; i--) {
2270            if (baseURIScope.elementAt(i) <= depth)
2271                return i;
2272        }
2273        
2274        // we should never get here, because 0 was put on the stack in startDocument()
2275
return -1;
2276    }
2277    
2278    /**
2279     * Search for a xml:base attribute, and if one is found, put the new base URI into
2280     * effect.
2281     */

2282    protected void processXMLBaseAttributes(XMLAttributes attributes) {
2283        String JavaDoc baseURIValue =
2284        attributes.getValue(NamespaceContext.XML_URI, "base");
2285        if (baseURIValue != null) {
2286            try {
2287                String JavaDoc expandedValue =
2288                XMLEntityManager.expandSystemId(
2289                baseURIValue,
2290                fCurrentBaseURI.getExpandedSystemId(),
2291                false);
2292                fCurrentBaseURI.setLiteralSystemId(baseURIValue);
2293                fCurrentBaseURI.setBaseSystemId(
2294                fCurrentBaseURI.getExpandedSystemId());
2295                fCurrentBaseURI.setExpandedSystemId(expandedValue);
2296                
2297                // push the new values on the stack
2298
saveBaseURI();
2299            }
2300            catch (MalformedURIException e) {
2301                // REVISIT: throw error here
2302
}
2303        }
2304    }
2305    
2306    /**
2307     * Set the Accept,Accept-Language,Accept-CharSet
2308     */

2309    protected XMLInputSource setHttpProperties(XMLInputSource source,XMLAttributes attributes) throws IOException JavaDoc{
2310        String JavaDoc httpAcceptLang = attributes.getValue(HTTP_ACCEPT_LANGUAGE);
2311        String JavaDoc httpAccept = attributes.getValue(HTTP_ACCEPT);
2312        String JavaDoc httpAcceptchar = attributes.getValue(HTTP_ACCEPT_CHARSET);
2313        if (source.getCharacterStream() == null && source.getByteStream() == null) {
2314            XIncludeInputSource includeSource = new XIncludeInputSource(source.getPublicId(),source.getSystemId(),source.getBaseSystemId(), source.getByteStream(),source.getEncoding());
2315            includeSource.setProperty(XINCLUDE_ATTR_ACCEPT,attributes.getValue(XINCLUDE_ATTR_ACCEPT));
2316            includeSource.setProperty(XINCLUDE_ATTR_ACCEPT_CHARSET,attributes.getValue(XINCLUDE_ATTR_ACCEPT_CHARSET));
2317            includeSource.setProperty(XINCLUDE_ATTR_ACCEPT_LANGUAGE,attributes.getValue(XINCLUDE_ATTR_ACCEPT_LANGUAGE));
2318        }
2319        return source;
2320    }
2321    
2322    public boolean processSchema(XPointerSchema fXPointerSchemaS,
2323    XMLInputSource includedSource){
2324        try{
2325            fChildConfig = createXPointerParser();//for now -Revisit and change this.
2326
fChildConfig.setProperty(Constants.XERCES_PROPERTY_PREFIX
2327            + Constants.XINCLUDE_HANDLER_PROPERTY,
2328            fXPointerSchemaS);
2329            fXPointerSchemaS.setParent(this);
2330            fXPointerSchemaS.setDocumentHandler(this.getDocumentHandler());
2331            fChildConfig.parse(includedSource);
2332        }
2333        catch (Exception JavaDoc e) {
2334            //Venu For now do this.
2335
reportResourceError(
2336            "XMLResourceError",
2337            new Object JavaDoc[] { null, e.getMessage()});
2338        }
2339        return fXPointerSchemaS.isSubResourceIndentified();
2340    }
2341    
2342    /**
2343     * Returns <code>true</code> if the given string
2344     * would be valid in an HTTP header.
2345     *
2346     * @param value string to check
2347     * @return <code>true</code> if the given string
2348     * would be valid in an HTTP header
2349     */

2350    private boolean isValidInHTTPHeader(String JavaDoc value) {
2351        char ch;
2352        for (int i = value.length() - 1; i >= 0; --i) {
2353            ch = value.charAt(i);
2354            if (ch < 0x20 || ch > 0x7E) {
2355                return false;
2356            }
2357        }
2358        return true;
2359    }
2360    
2361    protected XMLParserConfiguration createXPointerParser(){
2362        XMLParserConfiguration childConfig =
2363        (XMLParserConfiguration)ObjectFactory.newInstance(
2364        XPOINTER_DEFAULT_CONFIGURATION,
2365        ObjectFactory.findClassLoader(),
2366        true);
2367        childConfig.setProperty(ERROR_REPORTER, fErrorReporter);
2368        childConfig.setProperty(
2369        Constants.XERCES_PROPERTY_PREFIX
2370        + Constants.NAMESPACE_CONTEXT_PROPERTY,
2371        fNamespaceContext);
2372        copyFeatures(fSettings, childConfig);
2373        return childConfig;
2374    }
2375}
2376
Popular Tags