1 /*
2 * reserved comment block
3 * DO NOT REMOVE OR ALTER!
4 */
5 /*
6 * Copyright 2001-2005 The Apache Software Foundation.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21 package com.sun.org.apache.xerces.internal.parsers;
22
23 import java.io.IOException;
24 import java.util.Locale;
25
26 import com.sun.org.apache.xerces.internal.impl.Constants;
27 import com.sun.org.apache.xerces.internal.xs.PSVIProvider;
28 import com.sun.org.apache.xerces.internal.util.EntityResolverWrapper;
29 import com.sun.org.apache.xerces.internal.util.EntityResolver2Wrapper;
30 import com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper;
31 import com.sun.org.apache.xerces.internal.util.SAXMessageFormatter;
32 import com.sun.org.apache.xerces.internal.util.SymbolHash;
33 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
34 import com.sun.org.apache.xerces.internal.xni.Augmentations;
35 import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
36 import com.sun.org.apache.xerces.internal.xni.QName;
37 import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
38 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
39 import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
40 import com.sun.org.apache.xerces.internal.xni.XMLString;
41 import com.sun.org.apache.xerces.internal.xni.XNIException;
42 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
43 import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
44 import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler;
45 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
46 import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException;
47 import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration;
48 import com.sun.org.apache.xerces.internal.xs.AttributePSVI;
49 import com.sun.org.apache.xerces.internal.xs.ElementPSVI;
50 import org.xml.sax.AttributeList;
51 import org.xml.sax.Attributes;
52 import org.xml.sax.ContentHandler;
53 import org.xml.sax.DTDHandler;
54 import org.xml.sax.DocumentHandler;
55 import org.xml.sax.EntityResolver;
56 import org.xml.sax.ErrorHandler;
57 import org.xml.sax.InputSource;
58 import org.xml.sax.Locator;
59 import org.xml.sax.Parser;
60 import org.xml.sax.SAXException;
61 import org.xml.sax.SAXNotRecognizedException;
62 import org.xml.sax.SAXNotSupportedException;
63 import org.xml.sax.SAXParseException;
64 import org.xml.sax.XMLReader;
65 import org.xml.sax.ext.Attributes2;
66 import org.xml.sax.ext.DeclHandler;
67 import org.xml.sax.ext.EntityResolver2;
68 import org.xml.sax.ext.LexicalHandler;
69 import org.xml.sax.ext.Locator2;
70 import org.xml.sax.helpers.LocatorImpl;
71
72 /**
73 * This is the base class of all SAX parsers. It implements both the
74 * SAX1 and SAX2 parser functionality, while the actual pipeline is
75 * defined in the parser configuration.
76 *
77 * @author Arnaud Le Hors, IBM
78 * @author Andy Clark, IBM
79 *
80 */
81 public abstract class AbstractSAXParser
82 extends AbstractXMLDocumentParser
83 implements PSVIProvider, // PSVI
84 Parser, XMLReader // SAX1, SAX2
85 {
86
87 //
88 // Constants
89 //
90
91 // features
92
93 /** Feature identifier: namespaces. */
94 protected static final String NAMESPACES =
95 Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
96
97 /** Feature identifier: namespace prefixes. */
98 protected static final String NAMESPACE_PREFIXES =
99 Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACE_PREFIXES_FEATURE;
100
101 /** Feature id: string interning. */
102 protected static final String STRING_INTERNING =
103 Constants.SAX_FEATURE_PREFIX + Constants.STRING_INTERNING_FEATURE;
104
105 /** Feature identifier: allow notation and unparsed entity events to be sent out of order. */
106 // this is not meant to be a recognized feature, but we need it here to use
107 // if it is already a recognized feature for the pipeline
108 protected static final String ALLOW_UE_AND_NOTATION_EVENTS =
109 Constants.SAX_FEATURE_PREFIX + Constants.ALLOW_DTD_EVENTS_AFTER_ENDDTD_FEATURE;
110
111 /** Recognized features. */
112 private static final String[] RECOGNIZED_FEATURES = {
113 NAMESPACES,
114 NAMESPACE_PREFIXES,
115 STRING_INTERNING,
116 };
117
118 // properties
119
120 /** Property id: lexical handler. */
121 protected static final String LEXICAL_HANDLER =
122 Constants.SAX_PROPERTY_PREFIX + Constants.LEXICAL_HANDLER_PROPERTY;
123
124 /** Property id: declaration handler. */
125 protected static final String DECLARATION_HANDLER =
126 Constants.SAX_PROPERTY_PREFIX + Constants.DECLARATION_HANDLER_PROPERTY;
127
128 /** Property id: DOM node. */
129 protected static final String DOM_NODE =
130 Constants.SAX_PROPERTY_PREFIX + Constants.DOM_NODE_PROPERTY;
131
132 /** Recognized properties. */
133 private static final String[] RECOGNIZED_PROPERTIES = {
134 LEXICAL_HANDLER,
135 DECLARATION_HANDLER,
136 DOM_NODE,
137 };
138
139 //
140 // Data
141 //
142
143 // features
144
145 /** Namespaces. */
146 protected boolean fNamespaces;
147
148 /** Namespace prefixes. */
149 protected boolean fNamespacePrefixes = false;
150
151 /** Lexical handler parameter entities. */
152 protected boolean fLexicalHandlerParameterEntities = true;
153
154 /** Standalone document declaration. */
155 protected boolean fStandalone;
156
157 /** Resolve DTD URIs. */
158 protected boolean fResolveDTDURIs = true;
159
160 /** Use EntityResolver2. */
161 protected boolean fUseEntityResolver2 = true;
162
163 /**
164 * XMLNS URIs: Namespace declarations in the
165 * http://www.w3.org/2000/xmlns/ namespace.
166 */
167 protected boolean fXMLNSURIs = false;
168
169 // parser handlers
170
171 /** Content handler. */
172 protected ContentHandler fContentHandler;
173
174 /** Document handler. */
175 protected DocumentHandler fDocumentHandler;
176
177 /** Namespace context */
178 protected NamespaceContext fNamespaceContext;
179
180 /** DTD handler. */
181 protected org.xml.sax.DTDHandler fDTDHandler;
182
183 /** Decl handler. */
184 protected DeclHandler fDeclHandler;
185
186 /** Lexical handler. */
187 protected LexicalHandler fLexicalHandler;
188
189 protected QName fQName = new QName();
190
191 // state
192
193 /**
194 * True if a parse is in progress. This state is needed because
195 * some features/properties cannot be set while parsing (e.g.
196 * validation and namespaces).
197 */
198 protected boolean fParseInProgress = false;
199
200 // track the version of the document being parsed
201 protected String fVersion;
202
203 // temp vars
204 private final AttributesProxy fAttributesProxy = new AttributesProxy();
205 private Augmentations fAugmentations = null;
206
207
208 // temporary buffer for sending normalized values
209 // REVISIT: what should be the size of the buffer?
210 private static final int BUFFER_SIZE = 20;
211 private char[] fCharBuffer = new char[BUFFER_SIZE];
212
213 // allows us to keep track of whether an attribute has
214 // been declared twice, so that we can avoid exposing the
215 // second declaration to any registered DeclHandler
216 protected SymbolHash fDeclaredAttrs = null;
217
218 //
219 // Constructors
220 //
221
222 /** Default constructor. */
223 protected AbstractSAXParser(XMLParserConfiguration config) {
224 super(config);
225
226 config.addRecognizedFeatures(RECOGNIZED_FEATURES);
227 config.addRecognizedProperties(RECOGNIZED_PROPERTIES);
228
229 try {
230 config.setFeature(ALLOW_UE_AND_NOTATION_EVENTS, false);
231 }
232 catch (XMLConfigurationException e) {
233 // it wasn't a recognized feature, so we don't worry about it
234 }
235 } // <init>(XMLParserConfiguration)
236
237 //
238 // XMLDocumentHandler methods
239 //
240
241 /**
242 * The start of the document.
243 *
244 * @param locator The document locator, or null if the document
245 * location cannot be reported during the parsing
246 * of this document. However, it is <em>strongly</em>
247 * recommended that a locator be supplied that can
248 * at least report the system identifier of the
249 * document.
250 * @param encoding The auto-detected IANA encoding name of the entity
251 * stream. This value will be null in those situations
252 * where the entity encoding is not auto-detected (e.g.
253 * internal entities or a document entity that is
254 * parsed from a java.io.Reader).
255 * @param namespaceContext
256 * The namespace context in effect at the
257 * start of this document.
258 * This object represents the current context.
259 * Implementors of this class are responsible
260 * for copying the namespace bindings from the
261 * the current context (and its parent contexts)
262 * if that information is important.
263 * @param augs Additional information that may include infoset augmentations
264 *
265 * @throws XNIException Thrown by handler to signal an error.
266 */
267 public void startDocument(XMLLocator locator, String encoding,
268 NamespaceContext namespaceContext, Augmentations augs)
269 throws XNIException {
270
271 fNamespaceContext = namespaceContext;
272
273 try {
274 // SAX1
275 if (fDocumentHandler != null) {
276 if (locator != null) {
277 fDocumentHandler.setDocumentLocator(new LocatorProxy(locator));
278 }
279 fDocumentHandler.startDocument();
280 }
281
282 // SAX2
283 if (fContentHandler != null) {
284 if (locator != null) {
285 fContentHandler.setDocumentLocator(new LocatorProxy(locator));
286 }
287 fContentHandler.startDocument();
288 }
289 }
290 catch (SAXException e) {
291 throw new XNIException(e);
292 }
293
294 } // startDocument(locator,encoding,augs)
295
296 /**
297 * Notifies of the presence of an XMLDecl line in the document. If
298 * present, this method will be called immediately following the
299 * startDocument call.
300 *
301 * @param version The XML version.
302 * @param encoding The IANA encoding name of the document, or null if
303 * not specified.
304 * @param standalone The standalone value, or null if not specified.
305 * @param augs Additional information that may include infoset augmentations
306 *
307 * @throws XNIException Thrown by handler to signal an error.
308 */
309 public void xmlDecl(String version, String encoding, String standalone, Augmentations augs)
310 throws XNIException {
311 // the version need only be set once; if
312 // document's XML 1.0|1.1, that's how it'll stay
313 fVersion = version;
314 fStandalone = "yes".equals(standalone);
315 } // xmlDecl(String,String,String)
316
317 /**
318 * Notifies of the presence of the DOCTYPE line in the document.
319 *
320 * @param rootElement The name of the root element.
321 * @param publicId The public identifier if an external DTD or null
322 * if the external DTD is specified using SYSTEM.
323 * @param systemId The system identifier if an external DTD, null
324 * otherwise.
325 * @param augs Additional information that may include infoset augmentations
326 *
327 * @throws XNIException Thrown by handler to signal an error.
328 */
329 public void doctypeDecl(String rootElement,
330 String publicId, String systemId, Augmentations augs)
331 throws XNIException {
332 fInDTD = true;
333
334 try {
335 // SAX2 extension
336 if (fLexicalHandler != null) {
337 fLexicalHandler.startDTD(rootElement, publicId, systemId);
338 }
339 }
340 catch (SAXException e) {
341 throw new XNIException(e);
342 }
343
344 // is there a DeclHandler?
345 if(fDeclHandler != null) {
346 fDeclaredAttrs = new SymbolHash();
347 }
348
349 } // doctypeDecl(String,String,String)
350
351 /**
352 * This method notifies of the start of an entity. The DTD has the
353 * pseudo-name of "[dtd]" parameter entity names start with '%'; and
354 * general entity names are just the entity name.
355 * <p>
356 * <strong>Note:</strong> Since the document is an entity, the handler
357 * will be notified of the start of the document entity by calling the
358 * startEntity method with the entity name "[xml]" <em>before</em> calling
359 * the startDocument method. When exposing entity boundaries through the
360 * SAX API, the document entity is never reported, however.
361 * <p>
362 * <strong>Note:</strong> This method is not called for entity references
363 * appearing as part of attribute values.
364 *
365 * @param name The name of the entity.
366 * @param identifier The resource identifier.
367 * @param encoding The auto-detected IANA encoding name of the entity
368 * stream. This value will be null in those situations
369 * where the entity encoding is not auto-detected (e.g.
370 * internal parameter entities).
371 * @param augs Additional information that may include infoset augmentations
372 *
373 * @throws XNIException Thrown by handler to signal an error.
374 */
375 public void startGeneralEntity(String name, XMLResourceIdentifier identifier,
376 String encoding, Augmentations augs)
377 throws XNIException {
378
379 try {
380 // Only report startEntity if this entity was actually read.
381 if (augs != null && Boolean.TRUE.equals(augs.getItem(Constants.ENTITY_SKIPPED))) {
382 // report skipped entity to content handler
383 if (fContentHandler != null) {
384 fContentHandler.skippedEntity(name);
385 }
386 }
387 else {
388 // SAX2 extension
389 if (fLexicalHandler != null) {
390 fLexicalHandler.startEntity(name);
391 }
392 }
393 }
394 catch (SAXException e) {
395 throw new XNIException(e);
396 }
397
398 } // startGeneralEntity(String,String,String,String,String)
399
400 /**
401 * This method notifies the end of an entity. The DTD has the pseudo-name
402 * of "[dtd]" parameter entity names start with '%'; and general entity
403 * names are just the entity name.
404 * <p>
405 * <strong>Note:</strong> Since the document is an entity, the handler
406 * will be notified of the end of the document entity by calling the
407 * endEntity method with the entity name "[xml]" <em>after</em> calling
408 * the endDocument method. When exposing entity boundaries through the
409 * SAX API, the document entity is never reported, however.
410 * <p>
411 * <strong>Note:</strong> This method is not called for entity references
412 * appearing as part of attribute values.
413 *
414 * @param name The name of the entity.
415 * @param augs Additional information that may include infoset augmentations
416 *
417 * @throws XNIException Thrown by handler to signal an error.
418 */
419 public void endGeneralEntity(String name, Augmentations augs) throws XNIException {
420
421 try {
422 // Only report endEntity if this entity was actually read.
423 if (augs == null || !Boolean.TRUE.equals(augs.getItem(Constants.ENTITY_SKIPPED))) {
424 // SAX2 extension
425 if (fLexicalHandler != null) {
426 fLexicalHandler.endEntity(name);
427 }
428 }
429 }
430 catch (SAXException e) {
431 throw new XNIException(e);
432 }
433
434 } // endEntity(String)
435
436 /**
437 * The start of an element. If the document specifies the start element
438 * by using an empty tag, then the startElement method will immediately
439 * be followed by the endElement method, with no intervening methods.
440 *
441 * @param element The name of the element.
442 * @param attributes The element attributes.
443 * @param augs Additional information that may include infoset augmentations
444 *
445 * @throws XNIException Thrown by handler to signal an error.
446 */
447 public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
448 throws XNIException {
449
450 try {
451 // SAX1
452 if (fDocumentHandler != null) {
453 // REVISIT: should we support schema-normalized-value for SAX1 events
454 //
455 fAttributesProxy.setAttributes(attributes);
456 fDocumentHandler.startElement(element.rawname, fAttributesProxy);
457 }
458
459 // SAX2
460 if (fContentHandler != null) {
461
462 if (fNamespaces) {
463 // send prefix mapping events
464 startNamespaceMapping();
465
466 // REVISIT: It should not be necessary to iterate over the attribute
467 // list when the set of [namespace attributes] is empty for this
468 // element. This should be computable from the NamespaceContext, but
469 // since we currently don't report the mappings for the xml prefix
470 // we cannot use the declared prefix count for the current context
471 // to skip this section. -- mrglavas
472 int len = attributes.getLength();
473 if (!fNamespacePrefixes) {
474 for (int i = len - 1; i >= 0; --i) {
475 attributes.getName(i, fQName);
476 if ((fQName.prefix == XMLSymbols.PREFIX_XMLNS) ||
477 (fQName.rawname == XMLSymbols.PREFIX_XMLNS)) {
478 // remove namespace declaration attributes
479 attributes.removeAttributeAt(i);
480 }
481 }
482 }
483 else if (!fXMLNSURIs) {
484 for (int i = len - 1; i >= 0; --i) {
485 attributes.getName(i, fQName);
486 if ((fQName.prefix == XMLSymbols.PREFIX_XMLNS) ||
487 (fQName.rawname == XMLSymbols.PREFIX_XMLNS)) {
488 // localpart should be empty string as per SAX documentation:
489 // http://www.saxproject.org/?selected=namespaces
490 fQName.prefix = "";
491 fQName.uri = "";
492 fQName.localpart = "";
493 attributes.setName(i, fQName);
494 }
495 }
496 }
497 }
498
499 fAugmentations = augs;
500
501 String uri = element.uri != null ? element.uri : "";
502 String localpart = fNamespaces ? element.localpart : "";
503 fAttributesProxy.setAttributes(attributes);
504 fContentHandler.startElement(uri, localpart, element.rawname,
505 fAttributesProxy);
506 }
507 }
508 catch (SAXException e) {
509 throw new XNIException(e);
510 }
511
512 } // startElement(QName,XMLAttributes)
513
514 /**
515 * Character content.
516 *
517 * @param text The content.
518 * @param augs Additional information that may include infoset augmentations
519 *
520 * @throws XNIException Thrown by handler to signal an error.
521 */
522 public void characters(XMLString text, Augmentations augs) throws XNIException {
523
524 // if type is union (XML Schema) it is possible that we receive
525 // character call with empty data
526 if (text.length == 0) {
527 return;
528 }
529
530
531 try {
532 // SAX1
533 if (fDocumentHandler != null) {
534 // REVISIT: should we support schema-normalized-value for SAX1 events
535 //
536 fDocumentHandler.characters(text.ch, text.offset, text.length);
537 }
538
539 // SAX2
540 if (fContentHandler != null) {
541 fContentHandler.characters(text.ch, text.offset, text.length);
542 }
543 }
544 catch (SAXException e) {
545 throw new XNIException(e);
546 }
547
548 } // characters(XMLString)
549
550 /**
551 * Ignorable whitespace. For this method to be called, the document
552 * source must have some way of determining that the text containing
553 * only whitespace characters should be considered ignorable. For
554 * example, the validator can determine if a length of whitespace
555 * characters in the document are ignorable based on the element
556 * content model.
557 *
558 * @param text The ignorable whitespace.
559 * @param augs Additional information that may include infoset augmentations
560 *
561 * @throws XNIException Thrown by handler to signal an error.
562 */
563 public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
564
565 try {
566 // SAX1
567 if (fDocumentHandler != null) {
568 fDocumentHandler.ignorableWhitespace(text.ch, text.offset, text.length);
569 }
570
571 // SAX2
572 if (fContentHandler != null) {
573 fContentHandler.ignorableWhitespace(text.ch, text.offset, text.length);
574 }
575 }
576 catch (SAXException e) {
577 throw new XNIException(e);
578 }
579
580 } // ignorableWhitespace(XMLString)
581
582 /**
583 * The end of an element.
584 *
585 * @param element The name of the element.
586 * @param augs Additional information that may include infoset augmentations
587 *
588 * @throws XNIException Thrown by handler to signal an error.
589 */
590 public void endElement(QName element, Augmentations augs) throws XNIException {
591
592
593 try {
594 // SAX1
595 if (fDocumentHandler != null) {
596 fDocumentHandler.endElement(element.rawname);
597 }
598
599 // SAX2
600 if (fContentHandler != null) {
601 fAugmentations = augs;
602 String uri = element.uri != null ? element.uri : "";
603 String localpart = fNamespaces ? element.localpart : "";
604 fContentHandler.endElement(uri, localpart,
605 element.rawname);
606 if (fNamespaces) {
607 endNamespaceMapping();
608 }
609 }
610 }
611 catch (SAXException e) {
612 throw new XNIException(e);
613 }
614
615 } // endElement(QName)
616
617 /**
618 * The start of a CDATA section.
619 * @param augs Additional information that may include infoset augmentations
620 *
621 * @throws XNIException Thrown by handler to signal an error.
622 */
623 public void startCDATA(Augmentations augs) throws XNIException {
624
625 try {
626 // SAX2 extension
627 if (fLexicalHandler != null) {
628 fLexicalHandler.startCDATA();
629 }
630 }
631 catch (SAXException e) {
632 throw new XNIException(e);
633 }
634
635 } // startCDATA()
636
637 /**
638 * The end of a CDATA section.
639 * @param augs Additional information that may include infoset augmentations
640 *
641 * @throws XNIException Thrown by handler to signal an error.
642 */
643 public void endCDATA(Augmentations augs) throws XNIException {
644
645 try {
646 // SAX2 extension
647 if (fLexicalHandler != null) {
648 fLexicalHandler.endCDATA();
649 }
650 }
651 catch (SAXException e) {
652 throw new XNIException(e);
653 }
654
655 } // endCDATA()
656
657 /**
658 * A comment.
659 *
660 * @param text The text in the comment.
661 * @param augs Additional information that may include infoset augmentations
662 *
663 * @throws XNIException Thrown by application to signal an error.
664 */
665 public void comment(XMLString text, Augmentations augs) throws XNIException {
666
667 try {
668 // SAX2 extension
669 if (fLexicalHandler != null) {
670 fLexicalHandler.comment(text.ch, 0, text.length);
671 }
672 }
673 catch (SAXException e) {
674 throw new XNIException(e);
675 }
676
677 } // comment(XMLString)
678
679 /**
680 * A processing instruction. Processing instructions consist of a
681 * target name and, optionally, text data. The data is only meaningful
682 * to the application.
683 * <p>
684 * Typically, a processing instruction's data will contain a series
685 * of pseudo-attributes. These pseudo-attributes follow the form of
686 * element attributes but are <strong>not</strong> parsed or presented
687 * to the application as anything other than text. The application is
688 * responsible for parsing the data.
689 *
690 * @param target The target.
691 * @param data The data or null if none specified.
692 * @param augs Additional information that may include infoset augmentations
693 *
694 * @throws XNIException Thrown by handler to signal an error.
695 */
696 public void processingInstruction(String target, XMLString data, Augmentations augs)
697 throws XNIException {
698
699 //
700 // REVISIT - I keep running into SAX apps that expect
701 // null data to be an empty string, which is contrary
702 // to the comment for this method in the SAX API.
703 //
704
705 try {
706 // SAX1
707 if (fDocumentHandler != null) {
708 fDocumentHandler.processingInstruction(target,
709 data.toString());
710 }
711
712 // SAX2
713 if (fContentHandler != null) {
714 fContentHandler.processingInstruction(target, data.toString());
715 }
716 }
717 catch (SAXException e) {
718 throw new XNIException(e);
719 }
720
721 } // processingInstruction(String,XMLString)
722
723
724 /**
725 * The end of the document.
726 * @param augs Additional information that may include infoset augmentations
727 *
728 * @throws XNIException Thrown by handler to signal an error.
729 */
730 public void endDocument(Augmentations augs) throws XNIException {
731
732 try {
733 // SAX1
734 if (fDocumentHandler != null) {
735 fDocumentHandler.endDocument();
736 }
737
738 // SAX2
739 if (fContentHandler != null) {
740 fContentHandler.endDocument();
741 }
742 }
743 catch (SAXException e) {
744 throw new XNIException(e);
745 }
746
747 } // endDocument()
748
749 //
750 // XMLDTDHandler methods
751 //
752
753 /**
754 * The start of the DTD external subset.
755 *
756 * @param augs Additional information that may include infoset
757 * augmentations.
758 *
759 * @throws XNIException Thrown by handler to signal an error.
760 */
761 public void startExternalSubset(XMLResourceIdentifier identifier,
762 Augmentations augs) throws XNIException {
763 startParameterEntity("[dtd]", null, null, augs);
764 }
765
766 /**
767 * The end of the DTD external subset.
768 *
769 * @param augs Additional information that may include infoset
770 * augmentations.
771 *
772 * @throws XNIException Thrown by handler to signal an error.
773 */
774 public void endExternalSubset(Augmentations augs) throws XNIException {
775 endParameterEntity("[dtd]", augs);
776 }
777
778 /**
779 * This method notifies of the start of parameter entity. The DTD has the
780 * pseudo-name of "[dtd]" parameter entity names start with '%'; and
781 * general entity names are just the entity name.
782 * <p>
783 * <strong>Note:</strong> Since the document is an entity, the handler
784 * will be notified of the start of the document entity by calling the
785 * startEntity method with the entity name "[xml]" <em>before</em> calling
786 * the startDocument method. When exposing entity boundaries through the
787 * SAX API, the document entity is never reported, however.
788 * <p>
789 * <strong>Note:</strong> This method is not called for entity references
790 * appearing as part of attribute values.
791 *
792 * @param name The name of the parameter entity.
793 * @param identifier The resource identifier.
794 * @param encoding The auto-detected IANA encoding name of the entity
795 * stream. This value will be null in those situations
796 * where the entity encoding is not auto-detected (e.g.
797 * internal parameter entities).
798 * @param augs Additional information that may include infoset
799 * augmentations.
800 *
801 * @throws XNIException Thrown by handler to signal an error.
802 */
803 public void startParameterEntity(String name,
804 XMLResourceIdentifier identifier,
805 String encoding, Augmentations augs)
806 throws XNIException {
807
808 try {
809 // Only report startEntity if this entity was actually read.
810 if (augs != null && Boolean.TRUE.equals(augs.getItem(Constants.ENTITY_SKIPPED))) {
811 // report skipped entity to content handler
812 if (fContentHandler != null) {
813 fContentHandler.skippedEntity(name);
814 }
815 }
816 else {
817 // SAX2 extension
818 if (fLexicalHandler != null && fLexicalHandlerParameterEntities) {
819 fLexicalHandler.startEntity(name);
820 }
821 }
822 }
823 catch (SAXException e) {
824 throw new XNIException(e);
825 }
826
827 } // startParameterEntity(String,identifier,String,Augmentation)
828
829 /**
830 * This method notifies the end of an entity. The DTD has the pseudo-name
831 * of "[dtd]" parameter entity names start with '%'; and general entity
832 * names are just the entity name.
833 * <p>
834 * <strong>Note:</strong> Since the document is an entity, the handler
835 * will be notified of the end of the document entity by calling the
836 * endEntity method with the entity name "[xml]" <em>after</em> calling
837 * the endDocument method. When exposing entity boundaries through the
838 * SAX API, the document entity is never reported, however.
839 * <p>
840 * <strong>Note:</strong> This method is not called for entity references
841 * appearing as part of attribute values.
842 *
843 * @param name The name of the parameter entity.
844 * @param augs Additional information that may include infoset
845 * augmentations.
846 *
847 * @throws XNIException Thrown by handler to signal an error.
848 */
849 public void endParameterEntity(String name, Augmentations augs) throws XNIException {
850
851 try {
852 // Only report endEntity if this entity was actually read.
853 if (augs == null || !Boolean.TRUE.equals(augs.getItem(Constants.ENTITY_SKIPPED))) {
854 // SAX2 extension
855 if (fLexicalHandler != null && fLexicalHandlerParameterEntities) {
856 fLexicalHandler.endEntity(name);
857 }
858 }
859 }
860 catch (SAXException e) {
861 throw new XNIException(e);
862 }
863
864 } // endEntity(String)
865
866 /**
867 * An element declaration.
868 *
869 * @param name The name of the element.
870 * @param contentModel The element content model.
871 *
872 * @param augs Additional information that may include infoset
873 * augmentations.
874 *
875 * @throws XNIException Thrown by handler to signal an error.
876 */
877 public void elementDecl(String name, String contentModel, Augmentations augs)
878 throws XNIException {
879
880 try {
881 // SAX2 extension
882 if (fDeclHandler != null) {
883 fDeclHandler.elementDecl(name, contentModel);
884 }
885 }
886 catch (SAXException e) {
887 throw new XNIException(e);
888 }
889
890 } // elementDecl(String,String, Augmentations)
891
892 /**
893 * An attribute declaration.
894 *
895 * @param elementName The name of the element that this attribute
896 * is associated with.
897 * @param attributeName The name of the attribute.
898 * @param type The attribute type. This value will be one of
899 * the following: "CDATA", "ENTITY", "ENTITIES",
900 * "ENUMERATION", "ID", "IDREF", "IDREFS",
901 * "NMTOKEN", "NMTOKENS", or "NOTATION".
902 * @param enumeration If the type has the value "ENUMERATION" or
903 * "NOTATION", this array holds the allowed attribute
904 * values; otherwise, this array is null.
905 * @param defaultType The attribute default type. This value will be
906 * one of the following: "#FIXED", "#IMPLIED",
907 * "#REQUIRED", or null.
908 * @param defaultValue The attribute default value, or null if no
909 * default value is specified.
910 *
911 * @param nonNormalizedDefaultValue The attribute default value with no normalization
912 * performed, or null if no default value is specified.
913 * @param augs Additional information that may include infoset
914 * augmentations.
915 *
916 * @throws XNIException Thrown by handler to signal an error.
917 */
918 public void attributeDecl(String elementName, String attributeName,
919 String type, String[] enumeration,
920 String defaultType, XMLString defaultValue,
921 XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException {
922
923 try {
924 // SAX2 extension
925 if (fDeclHandler != null) {
926 // used as a key to detect duplicate attribute definitions.
927 String elemAttr = new StringBuffer(elementName).append("<").append(attributeName).toString();
928 if(fDeclaredAttrs.get(elemAttr) != null) {
929 // we aren't permitted to return duplicate attribute definitions
930 return;
931 }
932 fDeclaredAttrs.put(elemAttr, Boolean.TRUE);
933 if (type.equals("NOTATION") ||
934 type.equals("ENUMERATION")) {
935
936 StringBuffer str = new StringBuffer();
937 if (type.equals("NOTATION")) {
938 str.append(type);
939 str.append(" (");
940 }
941 else {
942 str.append("(");
943 }
944 for (int i = 0; i < enumeration.length; i++) {
945 str.append(enumeration[i]);
946 if (i < enumeration.length - 1) {
947 str.append('|');
948 }
949 }
950 str.append(')');
951 type = str.toString();
952 }
953 String value = (defaultValue==null) ? null : defaultValue.toString();
954 fDeclHandler.attributeDecl(elementName, attributeName,
955 type, defaultType, value);
956 }
957 }
958 catch (SAXException e) {
959 throw new XNIException(e);
960 }
961
962 } // attributeDecl(String,String,String,String[],String,XMLString, XMLString, Augmentations)
963
964 /**
965 * An internal entity declaration.
966 *
967 * @param name The name of the entity. Parameter entity names start with
968 * '%', whereas the name of a general entity is just the
969 * entity name.
970 * @param text The value of the entity.
971 * @param nonNormalizedText The non-normalized value of the entity. This
972 * value contains the same sequence of characters that was in
973 * the internal entity declaration, without any entity
974 * references expanded.
975 *
976 * @param augs Additional information that may include infoset
977 * augmentations.
978 *
979 * @throws XNIException Thrown by handler to signal an error.
980 */
981 public void internalEntityDecl(String name, XMLString text,
982 XMLString nonNormalizedText,
983 Augmentations augs) throws XNIException {
984
985 try {
986 // SAX2 extensions
987 if (fDeclHandler != null) {
988 fDeclHandler.internalEntityDecl(name, text.toString());
989 }
990 }
991 catch (SAXException e) {
992 throw new XNIException(e);
993 }
994
995 } // internalEntityDecl(String,XMLString,XMLString)
996
997 /**
998 * An external entity declaration.
999 *
1000 * @param name The name of the entity. Parameter entity names start
1001 * with '%', whereas the name of a general entity is just
1002 * the entity name.
1003 * @param identifier An object containing all location information
1004 * pertinent to this entity.
1005 * @param augs Additional information that may include infoset
1006 * augmentations.
1007 *
1008 * @throws XNIException Thrown by handler to signal an error.
1009 */
1010 public void externalEntityDecl(String name, XMLResourceIdentifier identifier,
1011 Augmentations augs) throws XNIException {
1012 try {
1013 // SAX2 extension
1014 if (fDeclHandler != null) {
1015 String publicId = identifier.getPublicId();
1016 String systemId = fResolveDTDURIs ?
1017 identifier.getExpandedSystemId() : identifier.getLiteralSystemId();
1018 fDeclHandler.externalEntityDecl(name, publicId, systemId);
1019 }
1020 }
1021 catch (SAXException e) {
1022 throw new XNIException(e);
1023 }
1024
1025 } // externalEntityDecl(String,,XMLResourceIdentifier, Augmentations)
1026
1027 /**
1028 * An unparsed entity declaration.
1029 *
1030 * @param name The name of the entity.
1031 * @param identifier An object containing all location information
1032 * pertinent to this entity.
1033 * @param notation The name of the notation.
1034 *
1035 * @param augs Additional information that may include infoset
1036 * augmentations.
1037 *
1038 * @throws XNIException Thrown by handler to signal an error.
1039 */
1040 public void unparsedEntityDecl(String name, XMLResourceIdentifier identifier,
1041 String notation,
1042 Augmentations augs) throws XNIException {
1043 try {
1044 // SAX2 extension
1045 if (fDTDHandler != null) {
1046 String publicId = identifier.getPublicId();
1047 String systemId = fResolveDTDURIs ?
1048 identifier.getExpandedSystemId() : identifier.getLiteralSystemId();
1049 fDTDHandler.unparsedEntityDecl(name, publicId, systemId, notation);
1050 }
1051 }
1052 catch (SAXException e) {
1053 throw new XNIException(e);
1054 }
1055
1056 } // unparsedEntityDecl(String,XMLResourceIdentifier, String, Augmentations)
1057
1058 /**
1059 * A notation declaration
1060 *
1061 * @param name The name of the notation.
1062 * @param identifier An object containing all location information
1063 * pertinent to this notation.
1064 * @param augs Additional information that may include infoset
1065 * augmentations.
1066 *
1067 * @throws XNIException Thrown by handler to signal an error.
1068 */
1069 public void notationDecl(String name, XMLResourceIdentifier identifier,
1070 Augmentations augs) throws XNIException {
1071 try {
1072 // SAX1 and SAX2
1073 if (fDTDHandler != null) {
1074 String publicId = identifier.getPublicId();
1075 String systemId = fResolveDTDURIs ?
1076 identifier.getExpandedSystemId() : identifier.getLiteralSystemId();
1077 fDTDHandler.notationDecl(name, publicId, systemId);
1078 }
1079 }
1080 catch (SAXException e) {
1081 throw new XNIException(e);
1082 }
1083
1084 } // notationDecl(String,XMLResourceIdentifier, Augmentations)
1085
1086 /**
1087 * The end of the DTD.
1088 *
1089 * @param augs Additional information that may include infoset
1090 * augmentations.
1091 *
1092 * @throws XNIException Thrown by handler to signal an error.
1093 */
1094 public void endDTD(Augmentations augs) throws XNIException {
1095 fInDTD = false;
1096
1097 try {
1098 // SAX2 extension
1099 if (fLexicalHandler != null) {
1100 fLexicalHandler.endDTD();
1101 }
1102 }
1103 catch (SAXException e) {
1104 throw new XNIException(e);
1105 }
1106 if(fDeclaredAttrs != null) {
1107 // help out the GC
1108 fDeclaredAttrs.clear();
1109 }
1110
1111 } // endDTD()
1112
1113 //
1114 // Parser and XMLReader methods
1115 //
1116
1117 /**
1118 * Parses the input source specified by the given system identifier.
1119 * <p>
1120 * This method is equivalent to the following:
1121 * <pre>
1122 * parse(new InputSource(systemId));
1123 * </pre>
1124 *
1125 * @param systemId The system identifier (URI).
1126 *
1127 * @exception org.xml.sax.SAXException Throws exception on SAX error.
1128 * @exception java.io.IOException Throws exception on i/o error.
1129 */
1130 public void parse(String systemId) throws SAXException, IOException {
1131
1132 // parse document
1133 XMLInputSource source = new XMLInputSource(null, systemId, null);
1134 try {
1135 parse(source);
1136 }
1137
1138 // wrap XNI exceptions as SAX exceptions
1139 catch (XMLParseException e) {
1140 Exception ex = e.getException();
1141 if (ex == null) {
1142 // must be a parser exception; mine it for locator info and throw
1143 // a SAXParseException
1144 LocatorImpl locatorImpl = new LocatorImpl(){
1145 public String getXMLVersion() {
1146 return fVersion;
1147 }
1148 // since XMLParseExceptions know nothing about encoding,
1149 // we cannot return anything meaningful in this context.
1150 // We *could* consult the LocatorProxy, but the
1151 // application can do this itself if it wishes to possibly
1152 // be mislead.
1153 public String getEncoding() {
1154 return null;
1155 }
1156 };
1157 locatorImpl.setPublicId(e.getPublicId());
1158 locatorImpl.setSystemId(e.getExpandedSystemId());
1159 locatorImpl.setLineNumber(e.getLineNumber());
1160 locatorImpl.setColumnNumber(e.getColumnNumber());
1161 throw new SAXParseException(e.getMessage(), locatorImpl);
1162 }
1163 if (ex instanceof SAXException) {
1164 // why did we create an XMLParseException?
1165 throw (SAXException)ex;
1166 }
1167 if (ex instanceof IOException) {
1168 throw (IOException)ex;
1169 }
1170 throw new SAXException(ex);
1171 }
1172 catch (XNIException e) {
1173 Exception ex = e.getException();
1174 if (ex == null) {
1175 throw new SAXException(e.getMessage());
1176 }
1177 if (ex instanceof SAXException) {
1178 throw (SAXException)ex;
1179 }
1180 if (ex instanceof IOException) {
1181 throw (IOException)ex;
1182 }
1183 throw new SAXException(ex);
1184 }
1185
1186 } // parse(String)
1187
1188 /**
1189 * parse
1190 *
1191 * @param inputSource
1192 *
1193 * @exception org.xml.sax.SAXException
1194 * @exception java.io.IOException
1195 */
1196 public void parse(InputSource inputSource)
1197 throws SAXException, IOException {
1198
1199 // parse document
1200 try {
1201 XMLInputSource xmlInputSource =
1202 new XMLInputSource(inputSource.getPublicId(),
1203 inputSource.getSystemId(),
1204 null);
1205 xmlInputSource.setByteStream(inputSource.getByteStream());
1206 xmlInputSource.setCharacterStream(inputSource.getCharacterStream());
1207 xmlInputSource.setEncoding(inputSource.getEncoding());
1208 parse(xmlInputSource);
1209 }
1210
1211 // wrap XNI exceptions as SAX exceptions
1212 catch (XMLParseException e) {
1213 Exception ex = e.getException();
1214 if (ex == null) {
1215 // must be a parser exception; mine it for locator info and throw
1216 // a SAXParseException
1217 LocatorImpl locatorImpl = new LocatorImpl() {
1218 public String getXMLVersion() {
1219 return fVersion;
1220 }
1221 // since XMLParseExceptions know nothing about encoding,
1222 // we cannot return anything meaningful in this context.
1223 // We *could* consult the LocatorProxy, but the
1224 // application can do this itself if it wishes to possibly
1225 // be mislead.
1226 public String getEncoding() {
1227 return null;
1228 }
1229 };
1230 locatorImpl.setPublicId(e.getPublicId());
1231 locatorImpl.setSystemId(e.getExpandedSystemId());
1232 locatorImpl.setLineNumber(e.getLineNumber());
1233 locatorImpl.setColumnNumber(e.getColumnNumber());
1234 throw new SAXParseException(e.getMessage(), locatorImpl);
1235 }
1236 if (ex instanceof SAXException) {
1237 // why did we create an XMLParseException?
1238 throw (SAXException)ex;
1239 }
1240 if (ex instanceof IOException) {
1241 throw (IOException)ex;
1242 }
1243 throw new SAXException(ex);
1244 }
1245 catch (XNIException e) {
1246 Exception ex = e.getException();
1247 if (ex == null) {
1248 throw new SAXException(e.getMessage());
1249 }
1250 if (ex instanceof SAXException) {
1251 throw (SAXException)ex;
1252 }
1253 if (ex instanceof IOException) {
1254 throw (IOException)ex;
1255 }
1256 throw new SAXException(ex);
1257 }
1258
1259 } // parse(InputSource)
1260
1261 /**
1262 * Sets the resolver used to resolve external entities. The EntityResolver
1263 * interface supports resolution of public and system identifiers.
1264 *
1265 * @param resolver The new entity resolver. Passing a null value will
1266 * uninstall the currently installed resolver.
1267 */
1268 public void setEntityResolver(EntityResolver resolver) {
1269
1270 try {
1271 XMLEntityResolver xer = (XMLEntityResolver) fConfiguration.getProperty(ENTITY_RESOLVER);
1272 if (fUseEntityResolver2 && resolver instanceof EntityResolver2) {
1273 if (xer instanceof EntityResolver2Wrapper) {
1274 EntityResolver2Wrapper er2w = (EntityResolver2Wrapper) xer;
1275 er2w.setEntityResolver((EntityResolver2) resolver);
1276 }
1277 else {
1278 fConfiguration.setProperty(ENTITY_RESOLVER,
1279 new EntityResolver2Wrapper((EntityResolver2) resolver));
1280 }
1281 }
1282 else {
1283 if (xer instanceof EntityResolverWrapper) {
1284 EntityResolverWrapper erw = (EntityResolverWrapper) xer;
1285 erw.setEntityResolver(resolver);
1286 }
1287 else {
1288 fConfiguration.setProperty(ENTITY_RESOLVER,
1289 new EntityResolverWrapper(resolver));
1290 }
1291 }
1292 }
1293 catch (XMLConfigurationException e) {
1294 // do nothing
1295 }
1296
1297 } // setEntityResolver(EntityResolver)
1298
1299 /**
1300 * Return the current entity resolver.
1301 *
1302 * @return The current entity resolver, or null if none
1303 * has been registered.
1304 * @see #setEntityResolver
1305 */
1306 public EntityResolver getEntityResolver() {
1307
1308 EntityResolver entityResolver = null;
1309 try {
1310 XMLEntityResolver xmlEntityResolver =
1311 (XMLEntityResolver)fConfiguration.getProperty(ENTITY_RESOLVER);
1312 if (xmlEntityResolver != null) {
1313 if (xmlEntityResolver instanceof EntityResolverWrapper) {
1314 entityResolver =
1315 ((EntityResolverWrapper) xmlEntityResolver).getEntityResolver();
1316 }
1317 else if (xmlEntityResolver instanceof EntityResolver2Wrapper) {
1318 entityResolver =
1319 ((EntityResolver2Wrapper) xmlEntityResolver).getEntityResolver();
1320 }
1321 }
1322 }
1323 catch (XMLConfigurationException e) {
1324 // do nothing
1325 }
1326 return entityResolver;
1327
1328 } // getEntityResolver():EntityResolver
1329
1330 /**
1331 * Allow an application to register an error event handler.
1332 *
1333 * <p>If the application does not register an error handler, all
1334 * error events reported by the SAX parser will be silently
1335 * ignored; however, normal processing may not continue. It is
1336 * highly recommended that all SAX applications implement an
1337 * error handler to avoid unexpected bugs.</p>
1338 *
1339 * <p>Applications may register a new or different handler in the
1340 * middle of a parse, and the SAX parser must begin using the new
1341 * handler immediately.</p>
1342 *
1343 * @param errorHandler The error handler.
1344 * @see #getErrorHandler
1345 */
1346 public void setErrorHandler(ErrorHandler errorHandler) {
1347
1348 try {
1349 XMLErrorHandler xeh = (XMLErrorHandler) fConfiguration.getProperty(ERROR_HANDLER);
1350 if (xeh instanceof ErrorHandlerWrapper) {
1351 ErrorHandlerWrapper ehw = (ErrorHandlerWrapper) xeh;
1352 ehw.setErrorHandler(errorHandler);
1353 }
1354 else {
1355 fConfiguration.setProperty(ERROR_HANDLER,
1356 new ErrorHandlerWrapper(errorHandler));
1357 }
1358 }
1359 catch (XMLConfigurationException e) {
1360 // do nothing
1361 }
1362
1363 } // setErrorHandler(ErrorHandler)
1364
1365 /**
1366 * Return the current error handler.
1367 *
1368 * @return The current error handler, or null if none
1369 * has been registered.
1370 * @see #setErrorHandler
1371 */
1372 public ErrorHandler getErrorHandler() {
1373
1374 ErrorHandler errorHandler = null;
1375 try {
1376 XMLErrorHandler xmlErrorHandler =
1377 (XMLErrorHandler)fConfiguration.getProperty(ERROR_HANDLER);
1378 if (xmlErrorHandler != null &&
1379 xmlErrorHandler instanceof ErrorHandlerWrapper) {
1380 errorHandler = ((ErrorHandlerWrapper)xmlErrorHandler).getErrorHandler();
1381 }
1382 }
1383 catch (XMLConfigurationException e) {
1384 // do nothing
1385 }
1386 return errorHandler;
1387
1388 } // getErrorHandler():ErrorHandler
1389
1390 /**
1391 * Set the locale to use for messages.
1392 *
1393 * @param locale The locale object to use for localization of messages.
1394 *
1395 * @exception SAXException An exception thrown if the parser does not
1396 * support the specified locale.
1397 *
1398 * @see org.xml.sax.Parser
1399 */
1400 public void setLocale(Locale locale) throws SAXException {
1401 //REVISIT:this methods is not part of SAX2 interfaces, we should throw exception
1402 //if any application uses SAX2 and sets locale also. -nb
1403 fConfiguration.setLocale(locale);
1404
1405 } // setLocale(Locale)
1406
1407 /**
1408 * Allow an application to register a DTD event handler.
1409 * <p>
1410 * If the application does not register a DTD handler, all DTD
1411 * events reported by the SAX parser will be silently ignored.
1412 * <p>
1413 * Applications may register a new or different handler in the
1414 * middle of a parse, and the SAX parser must begin using the new
1415 * handler immediately.
1416 *
1417 * @param dtdHandler The DTD handler.
1418 *
1419
1420 * @see #getDTDHandler
1421 */
1422 public void setDTDHandler(DTDHandler dtdHandler) {
1423 fDTDHandler = dtdHandler;
1424 } // setDTDHandler(DTDHandler)
1425
1426 //
1427 // Parser methods
1428 //
1429
1430 /**
1431 * Allow an application to register a document event handler.
1432 * <p>
1433 * If the application does not register a document handler, all
1434 * document events reported by the SAX parser will be silently
1435 * ignored (this is the default behaviour implemented by
1436 * HandlerBase).
1437 * <p>
1438 * Applications may register a new or different handler in the
1439 * middle of a parse, and the SAX parser must begin using the new
1440 * handler immediately.
1441 *
1442 * @param documentHandler The document handler.
1443 */
1444 public void setDocumentHandler(DocumentHandler documentHandler) {
1445 fDocumentHandler = documentHandler;
1446 } // setDocumentHandler(DocumentHandler)
1447
1448 //
1449 // XMLReader methods
1450 //
1451
1452 /**
1453 * Allow an application to register a content event handler.
1454 * <p>
1455 * If the application does not register a content handler, all
1456 * content events reported by the SAX parser will be silently
1457 * ignored.
1458 * <p>
1459 * Applications may register a new or different handler in the
1460 * middle of a parse, and the SAX parser must begin using the new
1461 * handler immediately.
1462 *
1463 * @param contentHandler The content handler.
1464 *
1465 * @see #getContentHandler
1466 */
1467 public void setContentHandler(ContentHandler contentHandler) {
1468 fContentHandler = contentHandler;
1469 } // setContentHandler(ContentHandler)
1470
1471 /**
1472 * Return the current content handler.
1473 *
1474 * @return The current content handler, or null if none
1475 * has been registered.
1476 *
1477 * @see #setContentHandler
1478 */
1479 public ContentHandler getContentHandler() {
1480 return fContentHandler;
1481 } // getContentHandler():ContentHandler
1482
1483 /**
1484 * Return the current DTD handler.
1485 *
1486 * @return The current DTD handler, or null if none
1487 * has been registered.
1488 * @see #setDTDHandler
1489 */
1490 public DTDHandler getDTDHandler() {
1491 return fDTDHandler;
1492 } // getDTDHandler():DTDHandler
1493
1494 /**
1495 * Set the state of any feature in a SAX2 parser. The parser
1496 * might not recognize the feature, and if it does recognize
1497 * it, it might not be able to fulfill the request.
1498 *
1499 * @param featureId The unique identifier (URI) of the feature.
1500 * @param state The requested state of the feature (true or false).
1501 *
1502 * @exception SAXNotRecognizedException If the
1503 * requested feature is not known.
1504 * @exception SAXNotSupportedException If the
1505 * requested feature is known, but the requested
1506 * state is not supported.
1507 */
1508 public void setFeature(String featureId, boolean state)
1509 throws SAXNotRecognizedException, SAXNotSupportedException {
1510
1511 try {
1512 //
1513 // SAX2 Features
1514 //
1515
1516 if (featureId.startsWith(Constants.SAX_FEATURE_PREFIX)) {
1517 final int suffixLength = featureId.length() - Constants.SAX_FEATURE_PREFIX.length();
1518
1519 // http://xml.org/sax/features/namespaces
1520 if (suffixLength == Constants.NAMESPACES_FEATURE.length() &&
1521 featureId.endsWith(Constants.NAMESPACES_FEATURE)) {
1522 fConfiguration.setFeature(featureId, state);
1523 fNamespaces = state;
1524 return;
1525 }
1526
1527 // http://xml.org/sax/features/namespace-prefixes
1528 // controls the reporting of raw prefixed names and Namespace
1529 // declarations (xmlns* attributes): when this feature is false
1530 // (the default), raw prefixed names may optionally be reported,
1531 // and xmlns* attributes must not be reported.
1532 //
1533 if (suffixLength == Constants.NAMESPACE_PREFIXES_FEATURE.length() &&
1534 featureId.endsWith(Constants.NAMESPACE_PREFIXES_FEATURE)) {
1535 fConfiguration.setFeature(featureId, state);
1536 fNamespacePrefixes = state;
1537 return;
1538 }
1539
1540 // http://xml.org/sax/features/string-interning
1541 // controls the use of java.lang.String#intern() for strings
1542 // passed to SAX handlers.
1543 //
1544 if (suffixLength == Constants.STRING_INTERNING_FEATURE.length() &&
1545 featureId.endsWith(Constants.STRING_INTERNING_FEATURE)) {
1546 if (!state) {
1547 throw new SAXNotSupportedException(
1548 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
1549 "false-not-supported", new Object [] {featureId}));
1550 }
1551 return;
1552 }
1553
1554 // http://xml.org/sax/features/lexical-handler/parameter-entities
1555 // controls whether the beginning and end of parameter entities
1556 // will be reported to the LexicalHandler.
1557 //
1558 if (suffixLength == Constants.LEXICAL_HANDLER_PARAMETER_ENTITIES_FEATURE.length() &&
1559 featureId.endsWith(Constants.LEXICAL_HANDLER_PARAMETER_ENTITIES_FEATURE)) {
1560 fLexicalHandlerParameterEntities = state;
1561 return;
1562 }
1563
1564 // http://xml.org/sax/features/resolve-dtd-uris
1565 // controls whether system identifiers will be absolutized relative to
1566 // their base URIs before reporting.
1567 //
1568 if (suffixLength == Constants.RESOLVE_DTD_URIS_FEATURE.length() &&
1569 featureId.endsWith(Constants.RESOLVE_DTD_URIS_FEATURE)) {
1570 fResolveDTDURIs = state;
1571 return;
1572 }
1573
1574 // http://xml.org/sax/features/unicode-normalization-checking
1575 // controls whether Unicode normalization checking is performed
1576 // as per Appendix B of the XML 1.1 specification
1577 //
1578 if (suffixLength == Constants.UNICODE_NORMALIZATION_CHECKING_FEATURE.length() &&
1579 featureId.endsWith(Constants.UNICODE_NORMALIZATION_CHECKING_FEATURE)) {
1580 // REVISIT: Allow this feature to be set once Unicode normalization
1581 // checking is supported -- mrglavas.
1582 if (state) {
1583 throw new SAXNotSupportedException(
1584 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
1585 "true-not-supported", new Object [] {featureId}));
1586 }
1587 return;
1588 }
1589
1590 // http://xml.org/sax/features/xmlns-uris
1591 // controls whether the parser reports that namespace declaration
1592 // attributes as being in the namespace: http://www.w3.org/2000/xmlns/
1593 //
1594 if (suffixLength == Constants.XMLNS_URIS_FEATURE.length() &&
1595 featureId.endsWith(Constants.XMLNS_URIS_FEATURE)) {
1596 fXMLNSURIs = state;
1597 return;
1598 }
1599
1600 // http://xml.org/sax/features/use-entity-resolver2
1601 // controls whether the methods of an object implementing
1602 // org.xml.sax.ext.EntityResolver2 will be used by the parser.
1603 //
1604 if (suffixLength == Constants.USE_ENTITY_RESOLVER2_FEATURE.length() &&
1605 featureId.endsWith(Constants.USE_ENTITY_RESOLVER2_FEATURE)) {
1606 if (state != fUseEntityResolver2) {
1607 fUseEntityResolver2 = state;
1608 // Refresh EntityResolver wrapper.
1609 setEntityResolver(getEntityResolver());
1610 }
1611 return;
1612 }
1613
1614 //
1615 // Read only features.
1616 //
1617
1618 // http://xml.org/sax/features/is-standalone
1619 // reports whether the document specified a standalone document declaration.
1620 // http://xml.org/sax/features/use-attributes2
1621 // reports whether Attributes objects passed to startElement also implement
1622 // the org.xml.sax.ext.Attributes2 interface.
1623 // http://xml.org/sax/features/use-locator2
1624 // reports whether Locator objects passed to setDocumentLocator also implement
1625 // the org.xml.sax.ext.Locator2 interface.
1626 // http://xml.org/sax/features/xml-1.1
1627 // reports whether the parser supports both XML 1.1 and XML 1.0.
1628 if ((suffixLength == Constants.IS_STANDALONE_FEATURE.length() &&
1629 featureId.endsWith(Constants.IS_STANDALONE_FEATURE)) ||
1630 (suffixLength == Constants.USE_ATTRIBUTES2_FEATURE.length() &&
1631 featureId.endsWith(Constants.USE_ATTRIBUTES2_FEATURE)) ||
1632 (suffixLength == Constants.USE_LOCATOR2_FEATURE.length() &&
1633 featureId.endsWith(Constants.USE_LOCATOR2_FEATURE)) ||
1634 (suffixLength == Constants.XML_11_FEATURE.length() &&
1635 featureId.endsWith(Constants.XML_11_FEATURE))) {
1636 throw new SAXNotSupportedException(
1637 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
1638 "feature-read-only", new Object [] {featureId}));
1639 }
1640
1641
1642 //
1643 // Drop through and perform default processing
1644 //
1645 }
1646
1647 //
1648 // Xerces Features
1649 //
1650
1651 /*
1652 else if (featureId.startsWith(XERCES_FEATURES_PREFIX)) {
1653 String feature = featureId.substring(XERCES_FEATURES_PREFIX.length());
1654 //
1655 // Drop through and perform default processing
1656 //
1657 }
1658 */
1659
1660 //
1661 // Default handling
1662 //
1663
1664 fConfiguration.setFeature(featureId, state);
1665 }
1666 catch (XMLConfigurationException e) {
1667 String identifier = e.getIdentifier();
1668 if (e.getType() == XMLConfigurationException.NOT_RECOGNIZED) {
1669 throw new SAXNotRecognizedException(
1670 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
1671 "feature-not-recognized", new Object [] {identifier}));
1672 }
1673 else {
1674 throw new SAXNotSupportedException(
1675 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
1676 "feature-not-supported", new Object [] {identifier}));
1677 }
1678 }
1679
1680 } // setFeature(String,boolean)
1681
1682 /**
1683 * Query the state of a feature.
1684 *
1685 * Query the current state of any feature in a SAX2 parser. The
1686 * parser might not recognize the feature.
1687 *
1688 * @param featureId The unique identifier (URI) of the feature
1689 * being set.
1690 * @return The current state of the feature.
1691 * @exception org.xml.sax.SAXNotRecognizedException If the
1692 * requested feature is not known.
1693 * @exception SAXNotSupportedException If the
1694 * requested feature is known but not supported.
1695 */
1696 public boolean getFeature(String featureId)
1697 throws SAXNotRecognizedException, SAXNotSupportedException {
1698
1699 try {
1700 //
1701 // SAX2 Features
1702 //
1703
1704 if (featureId.startsWith(Constants.SAX_FEATURE_PREFIX)) {
1705 final int suffixLength = featureId.length() - Constants.SAX_FEATURE_PREFIX.length();
1706
1707 // http://xml.org/sax/features/namespace-prefixes
1708 // controls the reporting of raw prefixed names and Namespace
1709 // declarations (xmlns* attributes): when this feature is false
1710 // (the default), raw prefixed names may optionally be reported,
1711 // and xmlns* attributes must not be reported.
1712 //
1713 if (suffixLength == Constants.NAMESPACE_PREFIXES_FEATURE.length() &&
1714 featureId.endsWith(Constants.NAMESPACE_PREFIXES_FEATURE)) {
1715 boolean state = fConfiguration.getFeature(featureId);
1716 return state;
1717 }
1718 // http://xml.org/sax/features/string-interning
1719 // controls the use of java.lang.String#intern() for strings
1720 // passed to SAX handlers.
1721 //
1722 if (suffixLength == Constants.STRING_INTERNING_FEATURE.length() &&
1723 featureId.endsWith(Constants.STRING_INTERNING_FEATURE)) {
1724 return true;
1725 }
1726
1727 // http://xml.org/sax/features/is-standalone
1728 // reports whether the document specified a standalone document declaration.
1729 //
1730 if (suffixLength == Constants.IS_STANDALONE_FEATURE.length() &&
1731 featureId.endsWith(Constants.IS_STANDALONE_FEATURE)) {
1732 return fStandalone;
1733 }
1734
1735 // http://xml.org/sax/features/xml-1.1
1736 // reports whether the parser supports both XML 1.1 and XML 1.0.
1737 //
1738 if (suffixLength == Constants.XML_11_FEATURE.length() &&
1739 featureId.endsWith(Constants.XML_11_FEATURE)) {
1740 return (fConfiguration instanceof XML11Configurable);
1741 }
1742
1743 // http://xml.org/sax/features/lexical-handler/parameter-entities
1744 // controls whether the beginning and end of parameter entities
1745 // will be reported to the LexicalHandler.
1746 //
1747 if (suffixLength == Constants.LEXICAL_HANDLER_PARAMETER_ENTITIES_FEATURE.length() &&
1748 featureId.endsWith(Constants.LEXICAL_HANDLER_PARAMETER_ENTITIES_FEATURE)) {
1749 return fLexicalHandlerParameterEntities;
1750 }
1751
1752 // http://xml.org/sax/features/resolve-dtd-uris
1753 // controls whether system identifiers will be absolutized relative to
1754 // their base URIs before reporting.
1755 if (suffixLength == Constants.RESOLVE_DTD_URIS_FEATURE.length() &&
1756 featureId.endsWith(Constants.RESOLVE_DTD_URIS_FEATURE)) {
1757 return fResolveDTDURIs;
1758 }
1759
1760 // http://xml.org/sax/features/xmlns-uris
1761 // controls whether the parser reports that namespace declaration
1762 // attributes as being in the namespace: http://www.w3.org/2000/xmlns/
1763 //
1764 if (suffixLength == Constants.XMLNS_URIS_FEATURE.length() &&
1765 featureId.endsWith(Constants.XMLNS_URIS_FEATURE)) {
1766 return fXMLNSURIs;
1767 }
1768
1769 // http://xml.org/sax/features/unicode-normalization-checking
1770 // controls whether Unicode normalization checking is performed
1771 // as per Appendix B of the XML 1.1 specification
1772 //
1773 if (suffixLength == Constants.UNICODE_NORMALIZATION_CHECKING_FEATURE.length() &&
1774 featureId.endsWith(Constants.UNICODE_NORMALIZATION_CHECKING_FEATURE)) {
1775 // REVISIT: Allow this feature to be set once Unicode normalization
1776 // checking is supported -- mrglavas.
1777 return false;
1778 }
1779
1780 // http://xml.org/sax/features/use-entity-resolver2
1781 // controls whether the methods of an object implementing
1782 // org.xml.sax.ext.EntityResolver2 will be used by the parser.
1783 //
1784 if (suffixLength == Constants.USE_ENTITY_RESOLVER2_FEATURE.length() &&
1785 featureId.endsWith(Constants.USE_ENTITY_RESOLVER2_FEATURE)) {
1786 return fUseEntityResolver2;
1787 }
1788
1789 // http://xml.org/sax/features/use-attributes2
1790 // reports whether Attributes objects passed to startElement also implement
1791 // the org.xml.sax.ext.Attributes2 interface.
1792 // http://xml.org/sax/features/use-locator2
1793 // reports whether Locator objects passed to setDocumentLocator also implement
1794 // the org.xml.sax.ext.Locator2 interface.
1795 //
1796 if ((suffixLength == Constants.USE_ATTRIBUTES2_FEATURE.length() &&
1797 featureId.endsWith(Constants.USE_ATTRIBUTES2_FEATURE)) ||
1798 (suffixLength == Constants.USE_LOCATOR2_FEATURE.length() &&
1799 featureId.endsWith(Constants.USE_LOCATOR2_FEATURE))) {
1800 return true;
1801 }
1802
1803
1804 //
1805 // Drop through and perform default processing
1806 //
1807 }
1808
1809 //
1810 // Xerces Features
1811 //
1812
1813 /*
1814 else if (featureId.startsWith(XERCES_FEATURES_PREFIX)) {
1815 //
1816 // Drop through and perform default processing
1817 //
1818 }
1819 */
1820
1821 return fConfiguration.getFeature(featureId);
1822 }
1823 catch (XMLConfigurationException e) {
1824 String identifier = e.getIdentifier();
1825 if (e.getType() == XMLConfigurationException.NOT_RECOGNIZED) {
1826 throw new SAXNotRecognizedException(
1827 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
1828 "feature-not-recognized", new Object [] {identifier}));
1829 }
1830 else {
1831 throw new SAXNotSupportedException(
1832 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
1833 "feature-not-supported", new Object [] {identifier}));
1834 }
1835 }
1836
1837 } // getFeature(String):boolean
1838
1839 /**
1840 * Set the value of any property in a SAX2 parser. The parser
1841 * might not recognize the property, and if it does recognize
1842 * it, it might not support the requested value.
1843 *
1844 * @param propertyId The unique identifier (URI) of the property
1845 * being set.
1846 * @param value The value to which the property is being set.
1847 *
1848 * @exception SAXNotRecognizedException If the
1849 * requested property is not known.
1850 * @exception SAXNotSupportedException If the
1851 * requested property is known, but the requested
1852 * value is not supported.
1853 */
1854 public void setProperty(String propertyId, Object value)
1855 throws SAXNotRecognizedException, SAXNotSupportedException {
1856
1857 try {
1858 //
1859 // SAX2 core properties
1860 //
1861
1862 if (propertyId.startsWith(Constants.SAX_PROPERTY_PREFIX)) {
1863 final int suffixLength = propertyId.length() - Constants.SAX_PROPERTY_PREFIX.length();
1864
1865 //
1866 // http://xml.org/sax/properties/lexical-handler
1867 // Value type: org.xml.sax.ext.LexicalHandler
1868 // Access: read/write, pre-parse only
1869 // Set the lexical event handler.
1870 //
1871 if (suffixLength == Constants.LEXICAL_HANDLER_PROPERTY.length() &&
1872 propertyId.endsWith(Constants.LEXICAL_HANDLER_PROPERTY)) {
1873 try {
1874 setLexicalHandler((LexicalHandler)value);
1875 }
1876 catch (ClassCastException e) {
1877 throw new SAXNotSupportedException(
1878 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
1879 "incompatible-class", new Object [] {propertyId, "org.xml.sax.ext.LexicalHandler"}));
1880 }
1881 return;
1882 }
1883 //
1884 // http://xml.org/sax/properties/declaration-handler
1885 // Value type: org.xml.sax.ext.DeclHandler
1886 // Access: read/write, pre-parse only
1887 // Set the DTD declaration event handler.
1888 //
1889 if (suffixLength == Constants.DECLARATION_HANDLER_PROPERTY.length() &&
1890 propertyId.endsWith(Constants.DECLARATION_HANDLER_PROPERTY)) {
1891 try {
1892 setDeclHandler((DeclHandler)value);
1893 }
1894 catch (ClassCastException e) {
1895 throw new SAXNotSupportedException(
1896 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
1897 "incompatible-class", new Object [] {propertyId, "org.xml.sax.ext.DeclHandler"}));
1898 }
1899 return;
1900 }
1901 //
1902 // http://xml.org/sax/properties/dom-node
1903 // Value type: DOM Node
1904 // Access: read-only
1905 // Get the DOM node currently being visited, if the SAX parser is
1906 // iterating over a DOM tree. If the parser recognises and
1907 // supports this property but is not currently visiting a DOM
1908 // node, it should return null (this is a good way to check for
1909 // availability before the parse begins).
1910 // http://xml.org/sax/properties/document-xml-version
1911 // Value type: java.lang.String
1912 // Access: read-only
1913 // The literal string describing the actual XML version of the document.
1914 //
1915 if ((suffixLength == Constants.DOM_NODE_PROPERTY.length() &&
1916 propertyId.endsWith(Constants.DOM_NODE_PROPERTY)) ||
1917 (suffixLength == Constants.DOCUMENT_XML_VERSION_PROPERTY.length() &&
1918 propertyId.endsWith(Constants.DOCUMENT_XML_VERSION_PROPERTY))) {
1919 throw new SAXNotSupportedException(
1920 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
1921 "property-read-only", new Object [] {propertyId}));
1922 }
1923 //
1924 // Drop through and perform default processing
1925 //
1926 }
1927
1928 //
1929 // Xerces Properties
1930 //
1931
1932 /*
1933 else if (propertyId.startsWith(XERCES_PROPERTIES_PREFIX)) {
1934 //
1935 // Drop through and perform default processing
1936 //
1937 }
1938 */
1939
1940 //
1941 // Perform default processing
1942 //
1943
1944 fConfiguration.setProperty(propertyId, value);
1945 }
1946 catch (XMLConfigurationException e) {
1947 String identifier = e.getIdentifier();
1948 if (e.getType() == XMLConfigurationException.NOT_RECOGNIZED) {
1949 throw new SAXNotRecognizedException(
1950 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
1951 "property-not-recognized", new Object [] {identifier}));
1952 }
1953 else {
1954 throw new SAXNotSupportedException(
1955 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
1956 "property-not-supported", new Object [] {identifier}));
1957 }
1958 }
1959
1960 } // setProperty(String,Object)
1961
1962 /**
1963 * Query the value of a property.
1964 *
1965 * Return the current value of a property in a SAX2 parser.
1966 * The parser might not recognize the property.
1967 *
1968 * @param propertyId The unique identifier (URI) of the property
1969 * being set.
1970 * @return The current value of the property.
1971 * @exception org.xml.sax.SAXNotRecognizedException If the
1972 * requested property is not known.
1973 * @exception SAXNotSupportedException If the
1974 * requested property is known but not supported.
1975 */
1976 public Object getProperty(String propertyId)
1977 throws SAXNotRecognizedException, SAXNotSupportedException {
1978
1979 try {
1980 //
1981 // SAX2 core properties
1982 //
1983
1984 if (propertyId.startsWith(Constants.SAX_PROPERTY_PREFIX)) {
1985 final int suffixLength = propertyId.length() - Constants.SAX_PROPERTY_PREFIX.length();
1986
1987 //
1988 // http://xml.org/sax/properties/document-xml-version
1989 // Value type: java.lang.String
1990 // Access: read-only
1991 // The literal string describing the actual XML version of the document.
1992 //
1993 if (suffixLength == Constants.DOCUMENT_XML_VERSION_PROPERTY.length() &&
1994 propertyId.endsWith(Constants.DOCUMENT_XML_VERSION_PROPERTY)) {
1995 return fVersion;
1996 }
1997
1998 //
1999 // http://xml.org/sax/properties/lexical-handler
2000 // Value type: org.xml.sax.ext.LexicalHandler
2001 // Access: read/write, pre-parse only
2002 // Set the lexical event handler.
2003 //
2004 if (suffixLength == Constants.LEXICAL_HANDLER_PROPERTY.length() &&
2005 propertyId.endsWith(Constants.LEXICAL_HANDLER_PROPERTY)) {
2006 return getLexicalHandler();
2007 }
2008 //
2009 // http://xml.org/sax/properties/declaration-handler
2010 // Value type: org.xml.sax.ext.DeclHandler
2011 // Access: read/write, pre-parse only
2012 // Set the DTD declaration event handler.
2013 //
2014 if (suffixLength == Constants.DECLARATION_HANDLER_PROPERTY.length() &&
2015 propertyId.endsWith(Constants.DECLARATION_HANDLER_PROPERTY)) {
2016 return getDeclHandler();
2017 }
2018
2019 //
2020 // http://xml.org/sax/properties/dom-node
2021 // Value type: DOM Node
2022 // Access: read-only
2023 // Get the DOM node currently being visited, if the SAX parser is
2024 // iterating over a DOM tree. If the parser recognises and
2025 // supports this property but is not currently visiting a DOM
2026 // node, it should return null (this is a good way to check for
2027 // availability before the parse begins).
2028 //
2029 if (suffixLength == Constants.DOM_NODE_PROPERTY.length() &&
2030 propertyId.endsWith(Constants.DOM_NODE_PROPERTY)) {
2031 // we are not iterating a DOM tree
2032 throw new SAXNotSupportedException(
2033 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
2034 "dom-node-read-not-supported", null));
2035 }
2036
2037 //
2038 // Drop through and perform default processing
2039 //
2040 }
2041
2042 //
2043 // Xerces properties
2044 //
2045
2046 /*
2047 else if (propertyId.startsWith(XERCES_PROPERTIES_PREFIX)) {
2048 //
2049 // Drop through and perform default processing
2050 //
2051 }
2052 */
2053
2054 //
2055 // Perform default processing
2056 //
2057
2058 return fConfiguration.getProperty(propertyId);
2059 }
2060 catch (XMLConfigurationException e) {
2061 String identifier = e.getIdentifier();
2062 if (e.getType() == XMLConfigurationException.NOT_RECOGNIZED) {
2063 throw new SAXNotRecognizedException(
2064 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
2065 "property-not-recognized", new Object [] {identifier}));
2066 }
2067 else {
2068 throw new SAXNotSupportedException(
2069 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
2070 "property-not-supported", new Object [] {identifier}));
2071 }
2072 }
2073
2074 } // getProperty(String):Object
2075
2076 //
2077 // Protected methods
2078 //
2079
2080 // SAX2 core properties
2081
2082 /**
2083 * Set the DTD declaration event handler.
2084 * <p>
2085 * This method is the equivalent to the property:
2086 * <pre>
2087 * http://xml.org/sax/properties/declaration-handler
2088 * </pre>
2089 *
2090 * @param handler The new handler.
2091 *
2092 * @see #getDeclHandler
2093 * @see #setProperty
2094 */
2095 protected void setDeclHandler(DeclHandler handler)
2096 throws SAXNotRecognizedException, SAXNotSupportedException {
2097
2098 if (fParseInProgress) {
2099 throw new SAXNotSupportedException(
2100 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
2101 "property-not-parsing-supported",
2102 new Object [] {"http://xml.org/sax/properties/declaration-handler"}));
2103 }
2104 fDeclHandler = handler;
2105
2106 } // setDeclHandler(DeclHandler)
2107
2108 /**
2109 * Returns the DTD declaration event handler.
2110 *
2111 * @see #setDeclHandler
2112 */
2113 protected DeclHandler getDeclHandler()
2114 throws SAXNotRecognizedException, SAXNotSupportedException {
2115 return fDeclHandler;
2116 } // getDeclHandler():DeclHandler
2117
2118 /**
2119 * Set the lexical event handler.
2120 * <p>
2121 * This method is the equivalent to the property:
2122 * <pre>
2123 * http://xml.org/sax/properties/lexical-handler
2124 * </pre>
2125 *
2126 * @param handler lexical event handler
2127 *
2128 * @see #getLexicalHandler
2129 * @see #setProperty
2130 */
2131 protected void setLexicalHandler(LexicalHandler handler)
2132 throws SAXNotRecognizedException, SAXNotSupportedException {
2133
2134 if (fParseInProgress) {
2135 throw new SAXNotSupportedException(
2136 SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
2137 "property-not-parsing-supported",
2138 new Object [] {"http://xml.org/sax/properties/lexical-handler"}));
2139 }
2140 fLexicalHandler = handler;
2141
2142 } // setLexicalHandler(LexicalHandler)
2143
2144 /**
2145 * Returns the lexical handler.
2146 *
2147 * @see #setLexicalHandler
2148 */
2149 protected LexicalHandler getLexicalHandler()
2150 throws SAXNotRecognizedException, SAXNotSupportedException {
2151 return fLexicalHandler;
2152 } // getLexicalHandler():LexicalHandler
2153
2154 /**
2155 * Send startPrefixMapping events
2156 */
2157 protected final void startNamespaceMapping() throws SAXException{
2158 int count = fNamespaceContext.getDeclaredPrefixCount();
2159 if (count > 0) {
2160 String prefix = null;
2161 String uri = null;
2162 for (int i = 0; i < count; i++) {
2163 prefix = fNamespaceContext.getDeclaredPrefixAt(i);
2164 uri = fNamespaceContext.getURI(prefix);
2165 fContentHandler.startPrefixMapping(prefix,
2166 (uri == null) ? "" : uri);
2167 }
2168 }
2169 }
2170
2171 /**
2172 * Send endPrefixMapping events
2173 */
2174 protected final void endNamespaceMapping() throws SAXException {
2175 int count = fNamespaceContext.getDeclaredPrefixCount();
2176 if (count > 0) {
2177 for (int i = 0; i < count; i++) {
2178 fContentHandler.endPrefixMapping(fNamespaceContext.getDeclaredPrefixAt(i));
2179 }
2180 }
2181 }
2182
2183 //
2184 // XMLDocumentParser methods
2185 //
2186
2187 /**
2188 * Reset all components before parsing.
2189 *
2190 * @throws XNIException Thrown if an error occurs during initialization.
2191 */
2192 public void reset() throws XNIException {
2193 super.reset();
2194
2195 // reset state
2196 fInDTD = false;
2197 fVersion = "1.0";
2198 fStandalone = false;
2199
2200 // features
2201 fNamespaces = fConfiguration.getFeature(NAMESPACES);
2202 fNamespacePrefixes = fConfiguration.getFeature(NAMESPACE_PREFIXES);
2203 fAugmentations = null;
2204 fDeclaredAttrs = null;
2205
2206 } // reset()
2207
2208 //
2209 // Classes
2210 //
2211
2212 protected class LocatorProxy
2213 implements Locator2 {
2214
2215 //
2216 // Data
2217 //
2218
2219 /** XML locator. */
2220 protected XMLLocator fLocator;
2221
2222 //
2223 // Constructors
2224 //
2225
2226 /** Constructs an XML locator proxy. */
2227 public LocatorProxy(XMLLocator locator) {
2228 fLocator = locator;
2229 }
2230
2231 //
2232 // Locator methods
2233 //
2234
2235 /** Public identifier. */
2236 public String getPublicId() {
2237 return fLocator.getPublicId();
2238 }
2239
2240 /** System identifier. */
2241 public String getSystemId() {
2242 return fLocator.getExpandedSystemId();
2243 }
2244 /** Line number. */
2245 public int getLineNumber() {
2246 return fLocator.getLineNumber();
2247 }
2248
2249 /** Column number. */
2250 public int getColumnNumber() {
2251 return fLocator.getColumnNumber();
2252 }
2253
2254 // Locator2 methods
2255 public String getXMLVersion() {
2256 return fLocator.getXMLVersion();
2257 }
2258
2259 public String getEncoding() {
2260 return fLocator.getEncoding();
2261 }
2262
2263 } // class LocatorProxy
2264
2265 protected static final class AttributesProxy
2266 implements AttributeList, Attributes2 {
2267
2268 //
2269 // Data
2270 //
2271
2272 /** XML attributes. */
2273 protected XMLAttributes fAttributes;
2274
2275 //
2276 // Public methods
2277 //
2278
2279 /** Sets the XML attributes. */
2280 public void setAttributes(XMLAttributes attributes) {
2281 fAttributes = attributes;
2282 } // setAttributes(XMLAttributes)
2283
2284 public int getLength() {
2285 return fAttributes.getLength();
2286 }
2287
2288 public String getName(int i) {
2289 return fAttributes.getQName(i);
2290 }
2291
2292 public String getQName(int index) {
2293 return fAttributes.getQName(index);
2294 }
2295
2296 public String getURI(int index) {
2297 // REVISIT: this hides the fact that internally we use
2298 // null instead of empty string
2299 // SAX requires URI to be a string or an empty string
2300 String uri= fAttributes.getURI(index);
2301 return uri != null ? uri : "";
2302 }
2303
2304 public String getLocalName(int index) {
2305 return fAttributes.getLocalName(index);
2306 }
2307
2308 public String getType(int i) {
2309 return fAttributes.getType(i);
2310 }
2311
2312 public String getType(String name) {
2313 return fAttributes.getType(name);
2314 }
2315
2316 public String getType(String uri, String localName) {
2317 return uri.equals("") ? fAttributes.getType(null, localName) :
2318 fAttributes.getType(uri, localName);
2319 }
2320
2321 public String getValue(int i) {
2322 return fAttributes.getValue(i);
2323 }
2324
2325 public String getValue(String name) {
2326 return fAttributes.getValue(name);
2327 }
2328
2329 public String getValue(String uri, String localName) {
2330