KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xerces > internal > impl > XMLNamespaceBinder


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2000-2002 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) 1999, 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.impl;
59
60 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
61 import com.sun.org.apache.xerces.internal.util.SymbolTable;
62 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
63 import com.sun.org.apache.xerces.internal.xni.Augmentations;
64 import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
65 import com.sun.org.apache.xerces.internal.xni.QName;
66 import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
67 import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
68 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
69 import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
70 import com.sun.org.apache.xerces.internal.xni.XMLString;
71 import com.sun.org.apache.xerces.internal.xni.XNIException;
72 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
73 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
74 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
75 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentFilter;
76 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
77
78 /**
79  * This class performs namespace binding on the startElement and endElement
80  * method calls and passes all other methods through to the registered
81  * document handler. This class can be configured to only pass the
82  * start and end prefix mappings (start/endPrefixMapping).
83  * <p>
84  * This component requires the following features and properties from the
85  * component manager that uses it:
86  * <ul>
87  * <li>http://xml.org/sax/features/namespaces</li>
88  * <li>http://apache.org/xml/properties/internal/symbol-table</li>
89  * <li>http://apache.org/xml/properties/internal/error-reporter</li>
90  * </ul>
91  *
92  * @author Andy Clark, IBM
93  *
94  * @version $Id: XMLNamespaceBinder.java,v 1.33 2004/02/24 23:03:46 mrglavas Exp $
95  */

96 public class XMLNamespaceBinder
97     implements XMLComponent, XMLDocumentFilter {
98
99     //
100
// Constants
101
//
102

103     // feature identifiers
104

105     /** Feature identifier: namespaces. */
106     protected static final String JavaDoc NAMESPACES =
107         Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
108
109     // property identifiers
110

111     /** Property identifier: symbol table. */
112     protected static final String JavaDoc SYMBOL_TABLE =
113         Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
114
115     /** Property identifier: error reporter. */
116     protected static final String JavaDoc ERROR_REPORTER =
117         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
118
119     // recognized features and properties
120

121     /** Recognized features. */
122     private static final String JavaDoc[] RECOGNIZED_FEATURES = {
123         NAMESPACES,
124     };
125
126     /** Feature defaults. */
127     private static final Boolean JavaDoc[] FEATURE_DEFAULTS = {
128         null,
129     };
130
131     /** Recognized properties. */
132     private static final String JavaDoc[] RECOGNIZED_PROPERTIES = {
133         SYMBOL_TABLE,
134         ERROR_REPORTER,
135     };
136
137     /** Property defaults. */
138     private static final Object JavaDoc[] PROPERTY_DEFAULTS = {
139         null,
140         null,
141     };
142
143     //
144
// Data
145
//
146

147     // features
148

149     /** Namespaces. */
150     protected boolean fNamespaces;
151
152     // properties
153

154     /** Symbol table. */
155     protected SymbolTable fSymbolTable;
156
157     /** Error reporter. */
158     protected XMLErrorReporter fErrorReporter;
159
160     // handlers
161

162     /** Document handler. */
163     protected XMLDocumentHandler fDocumentHandler;
164
165     protected XMLDocumentSource fDocumentSource;
166
167     // settings
168

169     /** Only pass start and end prefix mapping events. */
170     protected boolean fOnlyPassPrefixMappingEvents;
171
172     // shared context
173

174     /** Namespace context. */
175     private NamespaceContext fNamespaceContext;
176
177     // temp vars
178

179     /** Attribute QName. */
180     private QName fAttributeQName = new QName();
181
182     //
183
// Constructors
184
//
185

186     /** Default constructor. */
187     public XMLNamespaceBinder() {
188     } // <init>()
189

190     //
191
// Public methods
192
//
193

194     // settings
195

196     /**
197      * Sets whether the namespace binder only passes the prefix mapping
198      * events to the registered document handler or passes all document
199      * events.
200      *
201      * @param onlyPassPrefixMappingEvents True to pass only the prefix
202      * mapping events; false to pass
203      * all events.
204      */

205     public void setOnlyPassPrefixMappingEvents(boolean onlyPassPrefixMappingEvents) {
206         fOnlyPassPrefixMappingEvents = onlyPassPrefixMappingEvents;
207     } // setOnlyPassPrefixMappingEvents(boolean)
208

209     /**
210      * Returns true if the namespace binder only passes the prefix mapping
211      * events to the registered document handler; false if the namespace
212      * binder passes all document events.
213      */

214     public boolean getOnlyPassPrefixMappingEvents() {
215         return fOnlyPassPrefixMappingEvents;
216     } // getOnlyPassPrefixMappingEvents():boolean
217

218     //
219
// XMLComponent methods
220
//
221

222     /**
223      * Resets the component. The component can query the component manager
224      * about any features and properties that affect the operation of the
225      * component.
226      *
227      * @param componentManager The component manager.
228      *
229      * @throws SAXException Thrown by component on initialization error.
230      * For example, if a feature or property is
231      * required for the operation of the component, the
232      * component manager may throw a
233      * SAXNotRecognizedException or a
234      * SAXNotSupportedException.
235      */

236     public void reset(XMLComponentManager componentManager)
237         throws XNIException {
238
239         // features
240
try {
241             fNamespaces = componentManager.getFeature(NAMESPACES);
242         }
243         catch (XMLConfigurationException e) {
244             fNamespaces = true;
245         }
246
247         // Xerces properties
248
fSymbolTable = (SymbolTable)componentManager.getProperty(SYMBOL_TABLE);
249         fErrorReporter = (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER);
250
251     } // reset(XMLComponentManager)
252

253     /**
254      * Returns a list of feature identifiers that are recognized by
255      * this component. This method may return null if no features
256      * are recognized by this component.
257      */

258     public String JavaDoc[] getRecognizedFeatures() {
259         return (String JavaDoc[])(RECOGNIZED_FEATURES.clone());
260     } // getRecognizedFeatures():String[]
261

262     /**
263      * Sets the state of a feature. This method is called by the component
264      * manager any time after reset when a feature changes state.
265      * <p>
266      * <strong>Note:</strong> Components should silently ignore features
267      * that do not affect the operation of the component.
268      *
269      * @param featureId The feature identifier.
270      * @param state The state of the feature.
271      *
272      * @throws SAXNotRecognizedException The component should not throw
273      * this exception.
274      * @throws SAXNotSupportedException The component should not throw
275      * this exception.
276      */

277     public void setFeature(String JavaDoc featureId, boolean state)
278         throws XMLConfigurationException {
279     } // setFeature(String,boolean)
280

281     /**
282      * Returns a list of property identifiers that are recognized by
283      * this component. This method may return null if no properties
284      * are recognized by this component.
285      */

286     public String JavaDoc[] getRecognizedProperties() {
287         return (String JavaDoc[])(RECOGNIZED_PROPERTIES.clone());
288     } // getRecognizedProperties():String[]
289

290     /**
291      * Sets the value of a property during parsing.
292      *
293      * @param propertyId
294      * @param value
295      */

296     public void setProperty(String JavaDoc propertyId, Object JavaDoc value)
297         throws XMLConfigurationException {
298
299         // Xerces properties
300
if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
301             final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
302             
303             if (suffixLength == Constants.SYMBOL_TABLE_PROPERTY.length() &&
304                 propertyId.endsWith(Constants.SYMBOL_TABLE_PROPERTY)) {
305                 fSymbolTable = (SymbolTable)value;
306             }
307             else if (suffixLength == Constants.ERROR_REPORTER_PROPERTY.length() &&
308                 propertyId.endsWith(Constants.ERROR_REPORTER_PROPERTY)) {
309                 fErrorReporter = (XMLErrorReporter)value;
310             }
311             return;
312         }
313
314     } // setProperty(String,Object)
315

316     /**
317      * Returns the default state for a feature, or null if this
318      * component does not want to report a default value for this
319      * feature.
320      *
321      * @param featureId The feature identifier.
322      *
323      * @since Xerces 2.2.0
324      */

325     public Boolean JavaDoc getFeatureDefault(String JavaDoc featureId) {
326         for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
327             if (RECOGNIZED_FEATURES[i].equals(featureId)) {
328                 return FEATURE_DEFAULTS[i];
329             }
330         }
331         return null;
332     } // getFeatureDefault(String):Boolean
333

334     /**
335      * Returns the default state for a property, or null if this
336      * component does not want to report a default value for this
337      * property.
338      *
339      * @param propertyId The property identifier.
340      *
341      * @since Xerces 2.2.0
342      */

343     public Object JavaDoc getPropertyDefault(String JavaDoc propertyId) {
344         for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
345             if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
346                 return PROPERTY_DEFAULTS[i];
347             }
348         }
349         return null;
350     } // getPropertyDefault(String):Object
351

352     //
353
// XMLDocumentSource methods
354
//
355

356     /** Sets the document handler to receive information about the document. */
357     public void setDocumentHandler(XMLDocumentHandler documentHandler) {
358         fDocumentHandler = documentHandler;
359     } // setDocumentHandler(XMLDocumentHandler)
360

361     /** Returns the document handler */
362     public XMLDocumentHandler getDocumentHandler() {
363         return fDocumentHandler;
364     } // setDocumentHandler(XMLDocumentHandler)
365

366
367     //
368
// XMLDocumentHandler methods
369
//
370

371     /** Sets the document source */
372     public void setDocumentSource(XMLDocumentSource source){
373         fDocumentSource = source;
374     } // setDocumentSource
375

376     /** Returns the document source */
377     public XMLDocumentSource getDocumentSource (){
378         return fDocumentSource;
379     } // getDocumentSource
380

381
382     /**
383      * This method notifies the start of a general entity.
384      * <p>
385      * <strong>Note:</strong> This method is not called for entity references
386      * appearing as part of attribute values.
387      *
388      * @param name The name of the general entity.
389      * @param identifier The resource identifier.
390      * @param encoding The auto-detected IANA encoding name of the entity
391      * stream. This value will be null in those situations
392      * where the entity encoding is not auto-detected (e.g.
393      * internal entities or a document entity that is
394      * parsed from a java.io.Reader).
395      * @param augs Additional information that may include infoset augmentations
396      *
397      * @exception XNIException Thrown by handler to signal an error.
398      */

399     public void startGeneralEntity(String JavaDoc name,
400                                    XMLResourceIdentifier identifier,
401                                    String JavaDoc encoding, Augmentations augs)
402         throws XNIException {
403         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
404             fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
405         }
406     } // startEntity(String,String,String,String,String)
407

408     /**
409      * Notifies of the presence of a TextDecl line in an entity. If present,
410      * this method will be called immediately following the startEntity call.
411      * <p>
412      * <strong>Note:</strong> This method will never be called for the
413      * document entity; it is only called for external general entities
414      * referenced in document content.
415      * <p>
416      * <strong>Note:</strong> This method is not called for entity references
417      * appearing as part of attribute values.
418      *
419      * @param version The XML version, or null if not specified.
420      * @param encoding The IANA encoding name of the entity.
421      * @param augs Additional information that may include infoset augmentations
422      *
423      * @throws XNIException Thrown by handler to signal an error.
424      */

425     public void textDecl(String JavaDoc version, String JavaDoc encoding, Augmentations augs)
426         throws XNIException {
427         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
428             fDocumentHandler.textDecl(version, encoding, augs);
429         }
430     } // textDecl(String,String)
431

432     /**
433      * The start of the document.
434      *
435      * @param locator The system identifier of the entity if the entity
436      * is external, null otherwise.
437      * @param encoding The auto-detected IANA encoding name of the entity
438      * stream. This value will be null in those situations
439      * where the entity encoding is not auto-detected (e.g.
440      * internal entities or a document entity that is
441      * parsed from a java.io.Reader).
442      * @param namespaceContext
443      * The namespace context in effect at the
444      * start of this document.
445      * This object represents the current context.
446      * Implementors of this class are responsible
447      * for copying the namespace bindings from the
448      * the current context (and its parent contexts)
449      * if that information is important.
450      * @param augs Additional information that may include infoset augmentations
451      *
452      * @throws XNIException Thrown by handler to signal an error.
453      */

454     public void startDocument(XMLLocator locator, String JavaDoc encoding,
455                                 NamespaceContext namespaceContext, Augmentations augs)
456                               throws XNIException {
457         fNamespaceContext = namespaceContext;
458
459         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
460             fDocumentHandler.startDocument(locator, encoding, namespaceContext, augs);
461         }
462     } // startDocument(XMLLocator,String)
463

464     /**
465      * Notifies of the presence of an XMLDecl line in the document. If
466      * present, this method will be called immediately following the
467      * startDocument call.
468      *
469      * @param version The XML version.
470      * @param encoding The IANA encoding name of the document, or null if
471      * not specified.
472      * @param standalone The standalone value, or null if not specified.
473      * @param augs Additional information that may include infoset augmentations
474      *
475      * @throws XNIException Thrown by handler to signal an error.
476      */

477     public void xmlDecl(String JavaDoc version, String JavaDoc encoding, String JavaDoc standalone, Augmentations augs)
478         throws XNIException {
479         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
480             fDocumentHandler.xmlDecl(version, encoding, standalone, augs);
481         }
482     } // xmlDecl(String,String,String)
483

484     /**
485      * Notifies of the presence of the DOCTYPE line in the document.
486      *
487      * @param rootElement The name of the root element.
488      * @param publicId The public identifier if an external DTD or null
489      * if the external DTD is specified using SYSTEM.
490      * @param systemId The system identifier if an external DTD, null
491      * otherwise.
492      * @param augs Additional information that may include infoset augmentations
493      *
494      * @throws XNIException Thrown by handler to signal an error.
495      */

496     public void doctypeDecl(String JavaDoc rootElement,
497                             String JavaDoc publicId, String JavaDoc systemId, Augmentations augs)
498         throws XNIException {
499         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
500             fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
501         }
502     } // doctypeDecl(String,String,String)
503

504     /**
505      * A comment.
506      *
507      * @param text The text in the comment.
508      * @param augs Additional information that may include infoset augmentations
509      *
510      * @throws XNIException Thrown by application to signal an error.
511      */

512     public void comment(XMLString text, Augmentations augs) throws XNIException {
513         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
514             fDocumentHandler.comment(text, augs);
515         }
516     } // comment(XMLString)
517

518     /**
519      * A processing instruction. Processing instructions consist of a
520      * target name and, optionally, text data. The data is only meaningful
521      * to the application.
522      * <p>
523      * Typically, a processing instruction's data will contain a series
524      * of pseudo-attributes. These pseudo-attributes follow the form of
525      * element attributes but are <strong>not</strong> parsed or presented
526      * to the application as anything other than text. The application is
527      * responsible for parsing the data.
528      *
529      * @param target The target.
530      * @param data The data or null if none specified.
531      * @param augs Additional information that may include infoset augmentations
532      *
533      * @throws XNIException Thrown by handler to signal an error.
534      */

535     public void processingInstruction(String JavaDoc target, XMLString data, Augmentations augs)
536         throws XNIException {
537         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
538             fDocumentHandler.processingInstruction(target, data, augs);
539         }
540     } // processingInstruction(String,XMLString)
541

542
543     /**
544      * Binds the namespaces. This method will handle calling the
545      * document handler to start the prefix mappings.
546      * <p>
547      * <strong>Note:</strong> This method makes use of the
548      * fAttributeQName variable. Any contents of the variable will
549      * be destroyed. Caller should copy the values out of this
550      * temporary variable before calling this method.
551      *
552      * @param element The name of the element.
553      * @param attributes The element attributes.
554      * @param augs Additional information that may include infoset augmentations
555      *
556      * @throws XNIException Thrown by handler to signal an error.
557      */

558     public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
559         throws XNIException {
560
561         if (fNamespaces) {
562             handleStartElement(element, attributes, augs, false);
563         }
564         else if (fDocumentHandler != null) {
565             fDocumentHandler.startElement(element, attributes, augs);
566         }
567
568
569     } // startElement(QName,XMLAttributes)
570

571     /**
572      * An empty element.
573      *
574      * @param element The name of the element.
575      * @param attributes The element attributes.
576      * @param augs Additional information that may include infoset augmentations
577      *
578      * @throws XNIException Thrown by handler to signal an error.
579      */

580     public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs)
581         throws XNIException {
582
583         if (fNamespaces) {
584             handleStartElement(element, attributes, augs, true);
585             handleEndElement(element, augs, true);
586         }
587         else if (fDocumentHandler != null) {
588             fDocumentHandler.emptyElement(element, attributes, augs);
589         }
590
591     } // emptyElement(QName,XMLAttributes)
592

593     /**
594      * Character content.
595      *
596      * @param text The content.
597      * @param augs Additional information that may include infoset augmentations
598      *
599      * @throws XNIException Thrown by handler to signal an error.
600      */

601     public void characters(XMLString text, Augmentations augs) throws XNIException {
602         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
603             fDocumentHandler.characters(text, augs);
604         }
605     } // characters(XMLString)
606

607     /**
608      * Ignorable whitespace. For this method to be called, the document
609      * source must have some way of determining that the text containing
610      * only whitespace characters should be considered ignorable. For
611      * example, the validator can determine if a length of whitespace
612      * characters in the document are ignorable based on the element
613      * content model.
614      *
615      * @param text The ignorable whitespace.
616      * @param augs Additional information that may include infoset augmentations
617      *
618      * @throws XNIException Thrown by handler to signal an error.
619      */

620     public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
621         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
622             fDocumentHandler.ignorableWhitespace(text, augs);
623         }
624     } // ignorableWhitespace(XMLString)
625

626     /**
627      * The end of an element.
628      *
629      * @param element The name of the element.
630      * @param augs Additional information that may include infoset augmentations
631      *
632      * @throws XNIException Thrown by handler to signal an error.
633      */

634     public void endElement(QName element, Augmentations augs) throws XNIException {
635
636         if (fNamespaces) {
637             handleEndElement(element, augs, false);
638         }
639         else if (fDocumentHandler != null) {
640             fDocumentHandler.endElement(element, augs);
641         }
642
643     } // endElement(QName)
644

645     /**
646      * The start of a CDATA section.
647      * @param augs Additional information that may include infoset augmentations
648      *
649      * @throws XNIException Thrown by handler to signal an error.
650      */

651     public void startCDATA(Augmentations augs) throws XNIException {
652         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
653             fDocumentHandler.startCDATA(augs);
654         }
655     } // startCDATA()
656

657     /**
658      * The end of a CDATA section.
659      * @param augs Additional information that may include infoset augmentations
660      *
661      * @throws XNIException Thrown by handler to signal an error.
662      */

663     public void endCDATA(Augmentations augs) throws XNIException {
664         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
665             fDocumentHandler.endCDATA(augs);
666         }
667     } // endCDATA()
668

669     /**
670      * The end of the document.
671      * @param augs Additional information that may include infoset augmentations
672      *
673      * @throws XNIException Thrown by handler to signal an error.
674      */

675     public void endDocument(Augmentations augs) throws XNIException {
676         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
677             fDocumentHandler.endDocument(augs);
678         }
679     } // endDocument()
680

681     /**
682      * This method notifies the end of a general entity.
683      * <p>
684      * <strong>Note:</strong> This method is not called for entity references
685      * appearing as part of attribute values.
686      *
687      * @param name The name of the entity.
688      * @param augs Additional information that may include infoset augmentations
689      *
690      * @exception XNIException
691      * Thrown by handler to signal an error.
692      */

693     public void endGeneralEntity(String JavaDoc name, Augmentations augs) throws XNIException {
694         if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
695             fDocumentHandler.endGeneralEntity(name, augs);
696         }
697     } // endEntity(String)
698

699     //
700
// Protected methods
701
//
702

703     /** Handles start element. */
704     protected void handleStartElement(QName element, XMLAttributes attributes,
705                                       Augmentations augs,
706                                       boolean isEmpty) throws XNIException {
707
708         // add new namespace context
709
fNamespaceContext.pushContext();
710
711         if (element.prefix == XMLSymbols.PREFIX_XMLNS) {
712             fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
713                                        "ElementXMLNSPrefix",
714                                        new Object JavaDoc[]{element.rawname},
715                                        XMLErrorReporter.SEVERITY_FATAL_ERROR);
716         }
717         
718         // search for new namespace bindings
719
int length = attributes.getLength();
720         for (int i = 0; i < length; i++) {
721             String JavaDoc localpart = attributes.getLocalName(i);
722             String JavaDoc prefix = attributes.getPrefix(i);
723             // when it's of form xmlns="..." or xmlns:prefix="...",
724
// it's a namespace declaration. but prefix:xmlns="..." isn't.
725
if (prefix == XMLSymbols.PREFIX_XMLNS ||
726                 prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS) {
727
728                 // get the internalized value of this attribute
729
String JavaDoc uri = fSymbolTable.addSymbol(attributes.getValue(i));
730
731                 // 1. "xmlns" can't be bound to any namespace
732
if (prefix == XMLSymbols.PREFIX_XMLNS && localpart == XMLSymbols.PREFIX_XMLNS) {
733                     fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
734                                                "CantBindXMLNS",
735                                                new Object JavaDoc[]{attributes.getQName(i)},
736                                                XMLErrorReporter.SEVERITY_FATAL_ERROR);
737                 }
738                 
739                 // 2. the namespace for "xmlns" can't be bound to any prefix
740
if (uri == NamespaceContext.XMLNS_URI) {
741                     fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
742                                                "CantBindXMLNS",
743                                                new Object JavaDoc[]{attributes.getQName(i)},
744                                                XMLErrorReporter.SEVERITY_FATAL_ERROR);
745                 }
746                 
747                 // 3. "xml" can't be bound to any other namespace than it's own
748
if (localpart == XMLSymbols.PREFIX_XML) {
749                     if (uri != NamespaceContext.XML_URI) {
750                         fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
751                                                    "CantBindXML",
752                                                    new Object JavaDoc[]{attributes.getQName(i)},
753                                                    XMLErrorReporter.SEVERITY_FATAL_ERROR);
754                     }
755                 }
756                 // 4. the namespace for "xml" can't be bound to any other prefix
757
else {
758                     if (uri ==NamespaceContext.XML_URI) {
759                         fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
760                                                    "CantBindXML",
761                                                    new Object JavaDoc[]{attributes.getQName(i)},
762                                                    XMLErrorReporter.SEVERITY_FATAL_ERROR);
763                     }
764                 }
765
766                 prefix = localpart != XMLSymbols.PREFIX_XMLNS ? localpart : XMLSymbols.EMPTY_STRING;
767
768                 // http://www.w3.org/TR/1999/REC-xml-names-19990114/#dt-prefix
769
// We should only report an error if there is a prefix,
770
// that is, the local part is not "xmlns". -SG
771
// Since this is an error condition in XML 1.0,
772
// and should be relatively uncommon in XML 1.1,
773
// making this test into a method call to reuse code
774
// should be acceptable. - NG
775
if(prefixBoundToNullURI(uri, localpart)) {
776                     fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
777                                                "EmptyPrefixedAttName",
778                                                new Object JavaDoc[]{attributes.getQName(i)},
779                                                XMLErrorReporter.SEVERITY_FATAL_ERROR);
780                     continue;
781                 }
782
783                 // declare prefix in context
784
fNamespaceContext.declarePrefix(prefix, uri.length() != 0 ? uri : null);
785
786             }
787         }
788
789         // bind the element
790
String JavaDoc prefix = element.prefix != null
791                       ? element.prefix : XMLSymbols.EMPTY_STRING;
792         element.uri = fNamespaceContext.getURI(prefix);
793         if (element.prefix == null && element.uri != null) {
794             element.prefix = XMLSymbols.EMPTY_STRING;
795         }
796         if (element.prefix != null && element.uri == null) {
797             fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
798                                        "ElementPrefixUnbound",
799                                        new Object JavaDoc[]{element.prefix, element.rawname},
800                                        XMLErrorReporter.SEVERITY_FATAL_ERROR);
801         }
802
803         // bind the attributes
804
for (int i = 0; i < length; i++) {
805             attributes.getName(i, fAttributeQName);
806             String JavaDoc aprefix = fAttributeQName.prefix != null
807                            ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING;
808             String JavaDoc arawname = fAttributeQName.rawname;
809             if (arawname == XMLSymbols.PREFIX_XMLNS) {
810                 fAttributeQName.uri = fNamespaceContext.getURI(XMLSymbols.PREFIX_XMLNS);
811                 attributes.setName(i, fAttributeQName);
812             }
813             else if (aprefix != XMLSymbols.EMPTY_STRING) {
814                 fAttributeQName.uri = fNamespaceContext.getURI(aprefix);
815                 if (fAttributeQName.uri == null) {
816                     fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
817                                                "AttributePrefixUnbound",
818                                                new Object JavaDoc[]{element.rawname,arawname,aprefix},
819                                                XMLErrorReporter.SEVERITY_FATAL_ERROR);
820                 }
821                 attributes.setName(i, fAttributeQName);
822             }
823         }
824
825         // verify that duplicate attributes don't exist
826
// Example: <foo xmlns:a='NS' xmlns:b='NS' a:attr='v1' b:attr='v2'/>
827
int attrCount = attributes.getLength();
828         for (int i = 0; i < attrCount - 1; i++) {
829             String JavaDoc auri = attributes.getURI(i);
830             if (auri == null || auri == NamespaceContext.XMLNS_URI) {
831                 continue;
832             }
833             String JavaDoc alocalpart = attributes.getLocalName(i);
834             for (int j = i + 1; j < attrCount; j++) {
835                 String JavaDoc blocalpart = attributes.getLocalName(j);
836                 String JavaDoc buri = attributes.getURI(j);
837                 if (alocalpart == blocalpart && auri == buri) {
838                     fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
839                                                "AttributeNSNotUnique",
840                                                new Object JavaDoc[]{element.rawname,alocalpart, auri},
841                                                XMLErrorReporter.SEVERITY_FATAL_ERROR);
842                 }
843             }
844         }
845
846         // call handler
847
if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
848             if (isEmpty) {
849                 fDocumentHandler.emptyElement(element, attributes, augs);
850             }
851             else {
852                 fDocumentHandler.startElement(element, attributes, augs);
853             }
854         }
855
856
857     } // handleStartElement(QName,XMLAttributes,boolean)
858

859     /** Handles end element. */
860     protected void handleEndElement(QName element, Augmentations augs, boolean isEmpty)
861         throws XNIException {
862
863         // bind element
864
String JavaDoc eprefix = element.prefix != null ? element.prefix : XMLSymbols.EMPTY_STRING;
865         element.uri = fNamespaceContext.getURI(eprefix);
866         if (element.uri != null) {
867             element.prefix = eprefix;
868         }
869
870         // call handlers
871
if (fDocumentHandler != null && !fOnlyPassPrefixMappingEvents) {
872             if (!isEmpty) {
873                 fDocumentHandler.endElement(element, augs);
874             }
875         }
876
877         // pop context
878
fNamespaceContext.popContext();
879
880     } // handleEndElement(QName,boolean)
881

882     // returns true iff the given prefix is bound to "" *and*
883
// this is disallowed by the version of XML namespaces in use.
884
protected boolean prefixBoundToNullURI(String JavaDoc uri, String JavaDoc localpart) {
885         return (uri == XMLSymbols.EMPTY_STRING && localpart != XMLSymbols.PREFIX_XMLNS);
886     } // prefixBoundToNullURI(String, String): boolean
887

888 } // class XMLNamespaceBinder
889
Popular Tags