0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: package org.apache.xerces.parsers;
0019:
0020: import java.io.CharConversionException;
0021: import java.io.IOException;
0022: import java.util.Locale;
0023:
0024: import org.apache.xerces.impl.Constants;
0025: import org.apache.xerces.util.EntityResolver2Wrapper;
0026: import org.apache.xerces.util.EntityResolverWrapper;
0027: import org.apache.xerces.util.ErrorHandlerWrapper;
0028: import org.apache.xerces.util.SAXMessageFormatter;
0029: import org.apache.xerces.util.SymbolHash;
0030: import org.apache.xerces.util.XMLSymbols;
0031: import org.apache.xerces.xni.Augmentations;
0032: import org.apache.xerces.xni.NamespaceContext;
0033: import org.apache.xerces.xni.QName;
0034: import org.apache.xerces.xni.XMLAttributes;
0035: import org.apache.xerces.xni.XMLLocator;
0036: import org.apache.xerces.xni.XMLResourceIdentifier;
0037: import org.apache.xerces.xni.XMLString;
0038: import org.apache.xerces.xni.XNIException;
0039: import org.apache.xerces.xni.parser.XMLConfigurationException;
0040: import org.apache.xerces.xni.parser.XMLEntityResolver;
0041: import org.apache.xerces.xni.parser.XMLErrorHandler;
0042: import org.apache.xerces.xni.parser.XMLInputSource;
0043: import org.apache.xerces.xni.parser.XMLParseException;
0044: import org.apache.xerces.xni.parser.XMLParserConfiguration;
0045: import org.apache.xerces.xs.AttributePSVI;
0046: import org.apache.xerces.xs.ElementPSVI;
0047: import org.apache.xerces.xs.PSVIProvider;
0048: import org.xml.sax.AttributeList;
0049: import org.xml.sax.ContentHandler;
0050: import org.xml.sax.DTDHandler;
0051: import org.xml.sax.DocumentHandler;
0052: import org.xml.sax.EntityResolver;
0053: import org.xml.sax.ErrorHandler;
0054: import org.xml.sax.InputSource;
0055: import org.xml.sax.Parser;
0056: import org.xml.sax.SAXException;
0057: import org.xml.sax.SAXNotRecognizedException;
0058: import org.xml.sax.SAXNotSupportedException;
0059: import org.xml.sax.SAXParseException;
0060: import org.xml.sax.XMLReader;
0061: import org.xml.sax.ext.Attributes2;
0062: import org.xml.sax.ext.DeclHandler;
0063: import org.xml.sax.ext.EntityResolver2;
0064: import org.xml.sax.ext.LexicalHandler;
0065: import org.xml.sax.ext.Locator2;
0066: import org.xml.sax.ext.Locator2Impl;
0067:
0068: /**
0069: * This is the base class of all SAX parsers. It implements both the
0070: * SAX1 and SAX2 parser functionality, while the actual pipeline is
0071: * defined in the parser configuration.
0072: *
0073: * @author Arnaud Le Hors, IBM
0074: * @author Andy Clark, IBM
0075: *
0076: * @version $Id: AbstractSAXParser.java 548086 2007-06-17 18:17:43Z mrglavas $
0077: */
0078: public abstract class AbstractSAXParser extends
0079: AbstractXMLDocumentParser implements PSVIProvider, // PSVI
0080: Parser, XMLReader // SAX1, SAX2
0081: {
0082:
0083: //
0084: // Constants
0085: //
0086:
0087: // features
0088:
0089: /** Feature identifier: namespaces. */
0090: protected static final String NAMESPACES = Constants.SAX_FEATURE_PREFIX
0091: + Constants.NAMESPACES_FEATURE;
0092:
0093: /** Feature id: string interning. */
0094: protected static final String STRING_INTERNING = Constants.SAX_FEATURE_PREFIX
0095: + Constants.STRING_INTERNING_FEATURE;
0096:
0097: /** Feature identifier: allow notation and unparsed entity events to be sent out of order. */
0098: // this is not meant to be a recognized feature, but we need it here to use
0099: // if it is already a recognized feature for the pipeline
0100: protected static final String ALLOW_UE_AND_NOTATION_EVENTS = Constants.SAX_FEATURE_PREFIX
0101: + Constants.ALLOW_DTD_EVENTS_AFTER_ENDDTD_FEATURE;
0102:
0103: /** Recognized features. */
0104: private static final String[] RECOGNIZED_FEATURES = { NAMESPACES,
0105: STRING_INTERNING, };
0106:
0107: // properties
0108:
0109: /** Property id: lexical handler. */
0110: protected static final String LEXICAL_HANDLER = Constants.SAX_PROPERTY_PREFIX
0111: + Constants.LEXICAL_HANDLER_PROPERTY;
0112:
0113: /** Property id: declaration handler. */
0114: protected static final String DECLARATION_HANDLER = Constants.SAX_PROPERTY_PREFIX
0115: + Constants.DECLARATION_HANDLER_PROPERTY;
0116:
0117: /** Property id: DOM node. */
0118: protected static final String DOM_NODE = Constants.SAX_PROPERTY_PREFIX
0119: + Constants.DOM_NODE_PROPERTY;
0120:
0121: /** Recognized properties. */
0122: private static final String[] RECOGNIZED_PROPERTIES = {
0123: LEXICAL_HANDLER, DECLARATION_HANDLER, DOM_NODE, };
0124:
0125: //
0126: // Data
0127: //
0128:
0129: // features
0130:
0131: /** Namespaces. */
0132: protected boolean fNamespaces;
0133:
0134: /** Namespace prefixes. */
0135: protected boolean fNamespacePrefixes = false;
0136:
0137: /** Lexical handler parameter entities. */
0138: protected boolean fLexicalHandlerParameterEntities = true;
0139:
0140: /** Standalone document declaration. */
0141: protected boolean fStandalone;
0142:
0143: /** Resolve DTD URIs. */
0144: protected boolean fResolveDTDURIs = true;
0145:
0146: /** Use EntityResolver2. */
0147: protected boolean fUseEntityResolver2 = true;
0148:
0149: /**
0150: * XMLNS URIs: Namespace declarations in the
0151: * http://www.w3.org/2000/xmlns/ namespace.
0152: */
0153: protected boolean fXMLNSURIs = false;
0154:
0155: // parser handlers
0156:
0157: /** Content handler. */
0158: protected ContentHandler fContentHandler;
0159:
0160: /** Document handler. */
0161: protected DocumentHandler fDocumentHandler;
0162:
0163: /** Namespace context */
0164: protected NamespaceContext fNamespaceContext;
0165:
0166: /** DTD handler. */
0167: protected org.xml.sax.DTDHandler fDTDHandler;
0168:
0169: /** Decl handler. */
0170: protected DeclHandler fDeclHandler;
0171:
0172: /** Lexical handler. */
0173: protected LexicalHandler fLexicalHandler;
0174:
0175: protected QName fQName = new QName();
0176:
0177: // state
0178:
0179: /**
0180: * True if a parse is in progress. This state is needed because
0181: * some features/properties cannot be set while parsing (e.g.
0182: * validation and namespaces).
0183: */
0184: protected boolean fParseInProgress = false;
0185:
0186: // track the version of the document being parsed
0187: protected String fVersion;
0188:
0189: // temp vars
0190: private final AttributesProxy fAttributesProxy = new AttributesProxy();
0191: private Augmentations fAugmentations = null;
0192:
0193: // temporary buffer for sending normalized values
0194: // REVISIT: what should be the size of the buffer?
0195: private static final int BUFFER_SIZE = 20;
0196: private char[] fCharBuffer = new char[BUFFER_SIZE];
0197:
0198: // allows us to keep track of whether an attribute has
0199: // been declared twice, so that we can avoid exposing the
0200: // second declaration to any registered DeclHandler
0201: protected SymbolHash fDeclaredAttrs = null;
0202:
0203: //
0204: // Constructors
0205: //
0206:
0207: /** Default constructor. */
0208: protected AbstractSAXParser(XMLParserConfiguration config) {
0209: super (config);
0210:
0211: config.addRecognizedFeatures(RECOGNIZED_FEATURES);
0212: config.addRecognizedProperties(RECOGNIZED_PROPERTIES);
0213:
0214: try {
0215: config.setFeature(ALLOW_UE_AND_NOTATION_EVENTS, false);
0216: } catch (XMLConfigurationException e) {
0217: // it wasn't a recognized feature, so we don't worry about it
0218: }
0219: } // <init>(XMLParserConfiguration)
0220:
0221: //
0222: // XMLDocumentHandler methods
0223: //
0224:
0225: /**
0226: * The start of the document.
0227: *
0228: * @param locator The document locator, or null if the document
0229: * location cannot be reported during the parsing
0230: * of this document. However, it is <em>strongly</em>
0231: * recommended that a locator be supplied that can
0232: * at least report the system identifier of the
0233: * document.
0234: * @param encoding The auto-detected IANA encoding name of the entity
0235: * stream. This value will be null in those situations
0236: * where the entity encoding is not auto-detected (e.g.
0237: * internal entities or a document entity that is
0238: * parsed from a java.io.Reader).
0239: * @param namespaceContext
0240: * The namespace context in effect at the
0241: * start of this document.
0242: * This object represents the current context.
0243: * Implementors of this class are responsible
0244: * for copying the namespace bindings from the
0245: * the current context (and its parent contexts)
0246: * if that information is important.
0247: * @param augs Additional information that may include infoset augmentations
0248: *
0249: * @throws XNIException Thrown by handler to signal an error.
0250: */
0251: public void startDocument(XMLLocator locator, String encoding,
0252: NamespaceContext namespaceContext, Augmentations augs)
0253: throws XNIException {
0254:
0255: fNamespaceContext = namespaceContext;
0256:
0257: try {
0258: // SAX1
0259: if (fDocumentHandler != null) {
0260: if (locator != null) {
0261: fDocumentHandler
0262: .setDocumentLocator(new LocatorProxy(
0263: locator));
0264: }
0265: fDocumentHandler.startDocument();
0266: }
0267:
0268: // SAX2
0269: if (fContentHandler != null) {
0270: if (locator != null) {
0271: fContentHandler
0272: .setDocumentLocator(new LocatorProxy(
0273: locator));
0274: }
0275: fContentHandler.startDocument();
0276: }
0277: } catch (SAXException e) {
0278: throw new XNIException(e);
0279: }
0280:
0281: } // startDocument(locator,encoding,augs)
0282:
0283: /**
0284: * Notifies of the presence of an XMLDecl line in the document. If
0285: * present, this method will be called immediately following the
0286: * startDocument call.
0287: *
0288: * @param version The XML version.
0289: * @param encoding The IANA encoding name of the document, or null if
0290: * not specified.
0291: * @param standalone The standalone value, or null if not specified.
0292: * @param augs Additional information that may include infoset augmentations
0293: *
0294: * @throws XNIException Thrown by handler to signal an error.
0295: */
0296: public void xmlDecl(String version, String encoding,
0297: String standalone, Augmentations augs) throws XNIException {
0298: // the version need only be set once; if
0299: // document's XML 1.0|1.1, that's how it'll stay
0300: fVersion = version;
0301: fStandalone = "yes".equals(standalone);
0302: } // xmlDecl(String,String,String)
0303:
0304: /**
0305: * Notifies of the presence of the DOCTYPE line in the document.
0306: *
0307: * @param rootElement The name of the root element.
0308: * @param publicId The public identifier if an external DTD or null
0309: * if the external DTD is specified using SYSTEM.
0310: * @param systemId The system identifier if an external DTD, null
0311: * otherwise.
0312: * @param augs Additional information that may include infoset augmentations
0313: *
0314: * @throws XNIException Thrown by handler to signal an error.
0315: */
0316: public void doctypeDecl(String rootElement, String publicId,
0317: String systemId, Augmentations augs) throws XNIException {
0318: fInDTD = true;
0319:
0320: try {
0321: // SAX2 extension
0322: if (fLexicalHandler != null) {
0323: fLexicalHandler.startDTD(rootElement, publicId,
0324: systemId);
0325: }
0326: } catch (SAXException e) {
0327: throw new XNIException(e);
0328: }
0329:
0330: // is there a DeclHandler?
0331: if (fDeclHandler != null) {
0332: fDeclaredAttrs = new SymbolHash();
0333: }
0334:
0335: } // doctypeDecl(String,String,String)
0336:
0337: /**
0338: * This method notifies of the start of an entity. The DTD has the
0339: * pseudo-name of "[dtd]" parameter entity names start with '%'; and
0340: * general entity names are just the entity name.
0341: * <p>
0342: * <strong>Note:</strong> Since the document is an entity, the handler
0343: * will be notified of the start of the document entity by calling the
0344: * startEntity method with the entity name "[xml]" <em>before</em> calling
0345: * the startDocument method. When exposing entity boundaries through the
0346: * SAX API, the document entity is never reported, however.
0347: * <p>
0348: * <strong>Note:</strong> This method is not called for entity references
0349: * appearing as part of attribute values.
0350: *
0351: * @param name The name of the entity.
0352: * @param identifier The resource identifier.
0353: * @param encoding The auto-detected IANA encoding name of the entity
0354: * stream. This value will be null in those situations
0355: * where the entity encoding is not auto-detected (e.g.
0356: * internal parameter entities).
0357: * @param augs Additional information that may include infoset augmentations
0358: *
0359: * @throws XNIException Thrown by handler to signal an error.
0360: */
0361: public void startGeneralEntity(String name,
0362: XMLResourceIdentifier identifier, String encoding,
0363: Augmentations augs) throws XNIException {
0364:
0365: try {
0366: // Only report startEntity if this entity was actually read.
0367: if (augs != null
0368: && Boolean.TRUE.equals(augs
0369: .getItem(Constants.ENTITY_SKIPPED))) {
0370: // report skipped entity to content handler
0371: if (fContentHandler != null) {
0372: fContentHandler.skippedEntity(name);
0373: }
0374: } else {
0375: // SAX2 extension
0376: if (fLexicalHandler != null) {
0377: fLexicalHandler.startEntity(name);
0378: }
0379: }
0380: } catch (SAXException e) {
0381: throw new XNIException(e);
0382: }
0383:
0384: } // startGeneralEntity(String,String,String,String,String)
0385:
0386: /**
0387: * This method notifies the end of an entity. The DTD has the pseudo-name
0388: * of "[dtd]" parameter entity names start with '%'; and general entity
0389: * names are just the entity name.
0390: * <p>
0391: * <strong>Note:</strong> Since the document is an entity, the handler
0392: * will be notified of the end of the document entity by calling the
0393: * endEntity method with the entity name "[xml]" <em>after</em> calling
0394: * the endDocument method. When exposing entity boundaries through the
0395: * SAX API, the document entity is never reported, however.
0396: * <p>
0397: * <strong>Note:</strong> This method is not called for entity references
0398: * appearing as part of attribute values.
0399: *
0400: * @param name The name of the entity.
0401: * @param augs Additional information that may include infoset augmentations
0402: *
0403: * @throws XNIException Thrown by handler to signal an error.
0404: */
0405: public void endGeneralEntity(String name, Augmentations augs)
0406: throws XNIException {
0407:
0408: try {
0409: // Only report endEntity if this entity was actually read.
0410: if (augs == null
0411: || !Boolean.TRUE.equals(augs
0412: .getItem(Constants.ENTITY_SKIPPED))) {
0413: // SAX2 extension
0414: if (fLexicalHandler != null) {
0415: fLexicalHandler.endEntity(name);
0416: }
0417: }
0418: } catch (SAXException e) {
0419: throw new XNIException(e);
0420: }
0421:
0422: } // endEntity(String)
0423:
0424: /**
0425: * The start of an element. If the document specifies the start element
0426: * by using an empty tag, then the startElement method will immediately
0427: * be followed by the endElement method, with no intervening methods.
0428: *
0429: * @param element The name of the element.
0430: * @param attributes The element attributes.
0431: * @param augs Additional information that may include infoset augmentations
0432: *
0433: * @throws XNIException Thrown by handler to signal an error.
0434: */
0435: public void startElement(QName element, XMLAttributes attributes,
0436: Augmentations augs) throws XNIException {
0437:
0438: try {
0439: // SAX1
0440: if (fDocumentHandler != null) {
0441: // REVISIT: should we support schema-normalized-value for SAX1 events
0442: //
0443: fAttributesProxy.setAttributes(attributes);
0444: fDocumentHandler.startElement(element.rawname,
0445: fAttributesProxy);
0446: }
0447:
0448: // SAX2
0449: if (fContentHandler != null) {
0450:
0451: if (fNamespaces) {
0452: // send prefix mapping events
0453: startNamespaceMapping();
0454:
0455: // REVISIT: It should not be necessary to iterate over the attribute
0456: // list when the set of [namespace attributes] is empty for this
0457: // element. This should be computable from the NamespaceContext, but
0458: // since we currently don't report the mappings for the xml prefix
0459: // we cannot use the declared prefix count for the current context
0460: // to skip this section. -- mrglavas
0461: int len = attributes.getLength();
0462: if (!fNamespacePrefixes) {
0463: for (int i = len - 1; i >= 0; --i) {
0464: attributes.getName(i, fQName);
0465: if ((fQName.prefix == XMLSymbols.PREFIX_XMLNS)
0466: || (fQName.rawname == XMLSymbols.PREFIX_XMLNS)) {
0467: // remove namespace declaration attributes
0468: attributes.removeAttributeAt(i);
0469: }
0470: }
0471: } else if (!fXMLNSURIs) {
0472: for (int i = len - 1; i >= 0; --i) {
0473: attributes.getName(i, fQName);
0474: if ((fQName.prefix == XMLSymbols.PREFIX_XMLNS)
0475: || (fQName.rawname == XMLSymbols.PREFIX_XMLNS)) {
0476: // localpart should be empty string as per SAX documentation:
0477: // http://www.saxproject.org/?selected=namespaces
0478: fQName.prefix = "";
0479: fQName.uri = "";
0480: fQName.localpart = "";
0481: attributes.setName(i, fQName);
0482: }
0483: }
0484: }
0485: }
0486:
0487: fAugmentations = augs;
0488:
0489: String uri = element.uri != null ? element.uri : "";
0490: String localpart = fNamespaces ? element.localpart : "";
0491: fAttributesProxy.setAttributes(attributes);
0492: fContentHandler.startElement(uri, localpart,
0493: element.rawname, fAttributesProxy);
0494: }
0495: } catch (SAXException e) {
0496: throw new XNIException(e);
0497: }
0498:
0499: } // startElement(QName,XMLAttributes)
0500:
0501: /**
0502: * Character content.
0503: *
0504: * @param text The content.
0505: * @param augs Additional information that may include infoset augmentations
0506: *
0507: * @throws XNIException Thrown by handler to signal an error.
0508: */
0509: public void characters(XMLString text, Augmentations augs)
0510: throws XNIException {
0511:
0512: // if type is union (XML Schema) it is possible that we receive
0513: // character call with empty data
0514: if (text.length == 0) {
0515: return;
0516: }
0517:
0518: try {
0519: // SAX1
0520: if (fDocumentHandler != null) {
0521: // REVISIT: should we support schema-normalized-value for SAX1 events
0522: //
0523: fDocumentHandler.characters(text.ch, text.offset,
0524: text.length);
0525: }
0526:
0527: // SAX2
0528: if (fContentHandler != null) {
0529: fContentHandler.characters(text.ch, text.offset,
0530: text.length);
0531: }
0532: } catch (SAXException e) {
0533: throw new XNIException(e);
0534: }
0535:
0536: } // characters(XMLString)
0537:
0538: /**
0539: * Ignorable whitespace. For this method to be called, the document
0540: * source must have some way of determining that the text containing
0541: * only whitespace characters should be considered ignorable. For
0542: * example, the validator can determine if a length of whitespace
0543: * characters in the document are ignorable based on the element
0544: * content model.
0545: *
0546: * @param text The ignorable whitespace.
0547: * @param augs Additional information that may include infoset augmentations
0548: *
0549: * @throws XNIException Thrown by handler to signal an error.
0550: */
0551: public void ignorableWhitespace(XMLString text, Augmentations augs)
0552: throws XNIException {
0553:
0554: try {
0555: // SAX1
0556: if (fDocumentHandler != null) {
0557: fDocumentHandler.ignorableWhitespace(text.ch,
0558: text.offset, text.length);
0559: }
0560:
0561: // SAX2
0562: if (fContentHandler != null) {
0563: fContentHandler.ignorableWhitespace(text.ch,
0564: text.offset, text.length);
0565: }
0566: } catch (SAXException e) {
0567: throw new XNIException(e);
0568: }
0569:
0570: } // ignorableWhitespace(XMLString)
0571:
0572: /**
0573: * The end of an element.
0574: *
0575: * @param element The name of the element.
0576: * @param augs Additional information that may include infoset augmentations
0577: *
0578: * @throws XNIException Thrown by handler to signal an error.
0579: */
0580: public void endElement(QName element, Augmentations augs)
0581: throws XNIException {
0582:
0583: try {
0584: // SAX1
0585: if (fDocumentHandler != null) {
0586: fDocumentHandler.endElement(element.rawname);
0587: }
0588:
0589: // SAX2
0590: if (fContentHandler != null) {
0591: fAugmentations = augs;
0592: String uri = element.uri != null ? element.uri : "";
0593: String localpart = fNamespaces ? element.localpart : "";
0594: fContentHandler.endElement(uri, localpart,
0595: element.rawname);
0596: if (fNamespaces) {
0597: endNamespaceMapping();
0598: }
0599: }
0600: } catch (SAXException e) {
0601: throw new XNIException(e);
0602: }
0603:
0604: } // endElement(QName)
0605:
0606: /**
0607: * The start of a CDATA section.
0608: * @param augs Additional information that may include infoset augmentations
0609: *
0610: * @throws XNIException Thrown by handler to signal an error.
0611: */
0612: public void startCDATA(Augmentations augs) throws XNIException {
0613:
0614: try {
0615: // SAX2 extension
0616: if (fLexicalHandler != null) {
0617: fLexicalHandler.startCDATA();
0618: }
0619: } catch (SAXException e) {
0620: throw new XNIException(e);
0621: }
0622:
0623: } // startCDATA()
0624:
0625: /**
0626: * The end of a CDATA section.
0627: * @param augs Additional information that may include infoset augmentations
0628: *
0629: * @throws XNIException Thrown by handler to signal an error.
0630: */
0631: public void endCDATA(Augmentations augs) throws XNIException {
0632:
0633: try {
0634: // SAX2 extension
0635: if (fLexicalHandler != null) {
0636: fLexicalHandler.endCDATA();
0637: }
0638: } catch (SAXException e) {
0639: throw new XNIException(e);
0640: }
0641:
0642: } // endCDATA()
0643:
0644: /**
0645: * A comment.
0646: *
0647: * @param text The text in the comment.
0648: * @param augs Additional information that may include infoset augmentations
0649: *
0650: * @throws XNIException Thrown by application to signal an error.
0651: */
0652: public void comment(XMLString text, Augmentations augs)
0653: throws XNIException {
0654:
0655: try {
0656: // SAX2 extension
0657: if (fLexicalHandler != null) {
0658: fLexicalHandler.comment(text.ch, 0, text.length);
0659: }
0660: } catch (SAXException e) {
0661: throw new XNIException(e);
0662: }
0663:
0664: } // comment(XMLString)
0665:
0666: /**
0667: * A processing instruction. Processing instructions consist of a
0668: * target name and, optionally, text data. The data is only meaningful
0669: * to the application.
0670: * <p>
0671: * Typically, a processing instruction's data will contain a series
0672: * of pseudo-attributes. These pseudo-attributes follow the form of
0673: * element attributes but are <strong>not</strong> parsed or presented
0674: * to the application as anything other than text. The application is
0675: * responsible for parsing the data.
0676: *
0677: * @param target The target.
0678: * @param data The data or null if none specified.
0679: * @param augs Additional information that may include infoset augmentations
0680: *
0681: * @throws XNIException Thrown by handler to signal an error.
0682: */
0683: public void processingInstruction(String target, XMLString data,
0684: Augmentations augs) throws XNIException {
0685:
0686: //
0687: // REVISIT - I keep running into SAX apps that expect
0688: // null data to be an empty string, which is contrary
0689: // to the comment for this method in the SAX API.
0690: //
0691:
0692: try {
0693: // SAX1
0694: if (fDocumentHandler != null) {
0695: fDocumentHandler.processingInstruction(target, data
0696: .toString());
0697: }
0698:
0699: // SAX2
0700: if (fContentHandler != null) {
0701: fContentHandler.processingInstruction(target, data
0702: .toString());
0703: }
0704: } catch (SAXException e) {
0705: throw new XNIException(e);
0706: }
0707:
0708: } // processingInstruction(String,XMLString)
0709:
0710: /**
0711: * The end of the document.
0712: * @param augs Additional information that may include infoset augmentations
0713: *
0714: * @throws XNIException Thrown by handler to signal an error.
0715: */
0716: public void endDocument(Augmentations augs) throws XNIException {
0717:
0718: try {
0719: // SAX1
0720: if (fDocumentHandler != null) {
0721: fDocumentHandler.endDocument();
0722: }
0723:
0724: // SAX2
0725: if (fContentHandler != null) {
0726: fContentHandler.endDocument();
0727: }
0728: } catch (SAXException e) {
0729: throw new XNIException(e);
0730: }
0731:
0732: } // endDocument()
0733:
0734: //
0735: // XMLDTDHandler methods
0736: //
0737:
0738: /**
0739: * The start of the DTD external subset.
0740: *
0741: * @param augs Additional information that may include infoset
0742: * augmentations.
0743: *
0744: * @throws XNIException Thrown by handler to signal an error.
0745: */
0746: public void startExternalSubset(XMLResourceIdentifier identifier,
0747: Augmentations augs) throws XNIException {
0748: startParameterEntity("[dtd]", null, null, augs);
0749: }
0750:
0751: /**
0752: * The end of the DTD external subset.
0753: *
0754: * @param augs Additional information that may include infoset
0755: * augmentations.
0756: *
0757: * @throws XNIException Thrown by handler to signal an error.
0758: */
0759: public void endExternalSubset(Augmentations augs)
0760: throws XNIException {
0761: endParameterEntity("[dtd]", augs);
0762: }
0763:
0764: /**
0765: * This method notifies of the start of parameter entity. The DTD has the
0766: * pseudo-name of "[dtd]" parameter entity names start with '%'; and
0767: * general entity names are just the entity name.
0768: * <p>
0769: * <strong>Note:</strong> Since the document is an entity, the handler
0770: * will be notified of the start of the document entity by calling the
0771: * startEntity method with the entity name "[xml]" <em>before</em> calling
0772: * the startDocument method. When exposing entity boundaries through the
0773: * SAX API, the document entity is never reported, however.
0774: * <p>
0775: * <strong>Note:</strong> This method is not called for entity references
0776: * appearing as part of attribute values.
0777: *
0778: * @param name The name of the parameter entity.
0779: * @param identifier The resource identifier.
0780: * @param encoding The auto-detected IANA encoding name of the entity
0781: * stream. This value will be null in those situations
0782: * where the entity encoding is not auto-detected (e.g.
0783: * internal parameter entities).
0784: * @param augs Additional information that may include infoset
0785: * augmentations.
0786: *
0787: * @throws XNIException Thrown by handler to signal an error.
0788: */
0789: public void startParameterEntity(String name,
0790: XMLResourceIdentifier identifier, String encoding,
0791: Augmentations augs) throws XNIException {
0792:
0793: try {
0794: // Only report startEntity if this entity was actually read.
0795: if (augs != null
0796: && Boolean.TRUE.equals(augs
0797: .getItem(Constants.ENTITY_SKIPPED))) {
0798: // report skipped entity to content handler
0799: if (fContentHandler != null) {
0800: fContentHandler.skippedEntity(name);
0801: }
0802: } else {
0803: // SAX2 extension
0804: if (fLexicalHandler != null
0805: && fLexicalHandlerParameterEntities) {
0806: fLexicalHandler.startEntity(name);
0807: }
0808: }
0809: } catch (SAXException e) {
0810: throw new XNIException(e);
0811: }
0812:
0813: } // startParameterEntity(String,identifier,String,Augmentation)
0814:
0815: /**
0816: * This method notifies the end of an entity. The DTD has the pseudo-name
0817: * of "[dtd]" parameter entity names start with '%'; and general entity
0818: * names are just the entity name.
0819: * <p>
0820: * <strong>Note:</strong> Since the document is an entity, the handler
0821: * will be notified of the end of the document entity by calling the
0822: * endEntity method with the entity name "[xml]" <em>after</em> calling
0823: * the endDocument method. When exposing entity boundaries through the
0824: * SAX API, the document entity is never reported, however.
0825: * <p>
0826: * <strong>Note:</strong> This method is not called for entity references
0827: * appearing as part of attribute values.
0828: *
0829: * @param name The name of the parameter entity.
0830: * @param augs Additional information that may include infoset
0831: * augmentations.
0832: *
0833: * @throws XNIException Thrown by handler to signal an error.
0834: */
0835: public void endParameterEntity(String name, Augmentations augs)
0836: throws XNIException {
0837:
0838: try {
0839: // Only report endEntity if this entity was actually read.
0840: if (augs == null
0841: || !Boolean.TRUE.equals(augs
0842: .getItem(Constants.ENTITY_SKIPPED))) {
0843: // SAX2 extension
0844: if (fLexicalHandler != null
0845: && fLexicalHandlerParameterEntities) {
0846: fLexicalHandler.endEntity(name);
0847: }
0848: }
0849: } catch (SAXException e) {
0850: throw new XNIException(e);
0851: }
0852:
0853: } // endEntity(String)
0854:
0855: /**
0856: * An element declaration.
0857: *
0858: * @param name The name of the element.
0859: * @param contentModel The element content model.
0860: *
0861: * @param augs Additional information that may include infoset
0862: * augmentations.
0863: *
0864: * @throws XNIException Thrown by handler to signal an error.
0865: */
0866: public void elementDecl(String name, String contentModel,
0867: Augmentations augs) throws XNIException {
0868:
0869: try {
0870: // SAX2 extension
0871: if (fDeclHandler != null) {
0872: fDeclHandler.elementDecl(name, contentModel);
0873: }
0874: } catch (SAXException e) {
0875: throw new XNIException(e);
0876: }
0877:
0878: } // elementDecl(String,String, Augmentations)
0879:
0880: /**
0881: * An attribute declaration.
0882: *
0883: * @param elementName The name of the element that this attribute
0884: * is associated with.
0885: * @param attributeName The name of the attribute.
0886: * @param type The attribute type. This value will be one of
0887: * the following: "CDATA", "ENTITY", "ENTITIES",
0888: * "ENUMERATION", "ID", "IDREF", "IDREFS",
0889: * "NMTOKEN", "NMTOKENS", or "NOTATION".
0890: * @param enumeration If the type has the value "ENUMERATION" or
0891: * "NOTATION", this array holds the allowed attribute
0892: * values; otherwise, this array is null.
0893: * @param defaultType The attribute default type. This value will be
0894: * one of the following: "#FIXED", "#IMPLIED",
0895: * "#REQUIRED", or null.
0896: * @param defaultValue The attribute default value, or null if no
0897: * default value is specified.
0898: *
0899: * @param nonNormalizedDefaultValue The attribute default value with no normalization
0900: * performed, or null if no default value is specified.
0901: * @param augs Additional information that may include infoset
0902: * augmentations.
0903: *
0904: * @throws XNIException Thrown by handler to signal an error.
0905: */
0906: public void attributeDecl(String elementName, String attributeName,
0907: String type, String[] enumeration, String defaultType,
0908: XMLString defaultValue,
0909: XMLString nonNormalizedDefaultValue, Augmentations augs)
0910: throws XNIException {
0911:
0912: try {
0913: // SAX2 extension
0914: if (fDeclHandler != null) {
0915: // used as a key to detect duplicate attribute definitions.
0916: String elemAttr = new StringBuffer(elementName).append(
0917: "<").append(attributeName).toString();
0918: if (fDeclaredAttrs.get(elemAttr) != null) {
0919: // we aren't permitted to return duplicate attribute definitions
0920: return;
0921: }
0922: fDeclaredAttrs.put(elemAttr, Boolean.TRUE);
0923: if (type.equals("NOTATION")
0924: || type.equals("ENUMERATION")) {
0925:
0926: StringBuffer str = new StringBuffer();
0927: if (type.equals("NOTATION")) {
0928: str.append(type);
0929: str.append(" (");
0930: } else {
0931: str.append("(");
0932: }
0933: for (int i = 0; i < enumeration.length; i++) {
0934: str.append(enumeration[i]);
0935: if (i < enumeration.length - 1) {
0936: str.append('|');
0937: }
0938: }
0939: str.append(')');
0940: type = str.toString();
0941: }
0942: String value = (defaultValue == null) ? null
0943: : defaultValue.toString();
0944: fDeclHandler.attributeDecl(elementName, attributeName,
0945: type, defaultType, value);
0946: }
0947: } catch (SAXException e) {
0948: throw new XNIException(e);
0949: }
0950:
0951: } // attributeDecl(String,String,String,String[],String,XMLString, XMLString, Augmentations)
0952:
0953: /**
0954: * An internal entity declaration.
0955: *
0956: * @param name The name of the entity. Parameter entity names start with
0957: * '%', whereas the name of a general entity is just the
0958: * entity name.
0959: * @param text The value of the entity.
0960: * @param nonNormalizedText The non-normalized value of the entity. This
0961: * value contains the same sequence of characters that was in
0962: * the internal entity declaration, without any entity
0963: * references expanded.
0964: *
0965: * @param augs Additional information that may include infoset
0966: * augmentations.
0967: *
0968: * @throws XNIException Thrown by handler to signal an error.
0969: */
0970: public void internalEntityDecl(String name, XMLString text,
0971: XMLString nonNormalizedText, Augmentations augs)
0972: throws XNIException {
0973:
0974: try {
0975: // SAX2 extensions
0976: if (fDeclHandler != null) {
0977: fDeclHandler.internalEntityDecl(name, text.toString());
0978: }
0979: } catch (SAXException e) {
0980: throw new XNIException(e);
0981: }
0982:
0983: } // internalEntityDecl(String,XMLString,XMLString)
0984:
0985: /**
0986: * An external entity declaration.
0987: *
0988: * @param name The name of the entity. Parameter entity names start
0989: * with '%', whereas the name of a general entity is just
0990: * the entity name.
0991: * @param identifier An object containing all location information
0992: * pertinent to this entity.
0993: * @param augs Additional information that may include infoset
0994: * augmentations.
0995: *
0996: * @throws XNIException Thrown by handler to signal an error.
0997: */
0998: public void externalEntityDecl(String name,
0999: XMLResourceIdentifier identifier, Augmentations augs)
1000: throws XNIException {
1001: try {
1002: // SAX2 extension
1003: if (fDeclHandler != null) {
1004: String publicId = identifier.getPublicId();
1005: String systemId = fResolveDTDURIs ? identifier
1006: .getExpandedSystemId() : identifier
1007: .getLiteralSystemId();
1008: fDeclHandler.externalEntityDecl(name, publicId,
1009: systemId);
1010: }
1011: } catch (SAXException e) {
1012: throw new XNIException(e);
1013: }
1014:
1015: } // externalEntityDecl(String,,XMLResourceIdentifier, Augmentations)
1016:
1017: /**
1018: * An unparsed entity declaration.
1019: *
1020: * @param name The name of the entity.
1021: * @param identifier An object containing all location information
1022: * pertinent to this entity.
1023: * @param notation The name of the notation.
1024: *
1025: * @param augs Additional information that may include infoset
1026: * augmentations.
1027: *
1028: * @throws XNIException Thrown by handler to signal an error.
1029: */
1030: public void unparsedEntityDecl(String name,
1031: XMLResourceIdentifier identifier, String notation,
1032: Augmentations augs) throws XNIException {
1033: try {
1034: // SAX2 extension
1035: if (fDTDHandler != null) {
1036: String publicId = identifier.getPublicId();
1037: String systemId = fResolveDTDURIs ? identifier
1038: .getExpandedSystemId() : identifier
1039: .getLiteralSystemId();
1040: fDTDHandler.unparsedEntityDecl(name, publicId,
1041: systemId, notation);
1042: }
1043: } catch (SAXException e) {
1044: throw new XNIException(e);
1045: }
1046:
1047: } // unparsedEntityDecl(String,XMLResourceIdentifier, String, Augmentations)
1048:
1049: /**
1050: * A notation declaration
1051: *
1052: * @param name The name of the notation.
1053: * @param identifier An object containing all location information
1054: * pertinent to this notation.
1055: * @param augs Additional information that may include infoset
1056: * augmentations.
1057: *
1058: * @throws XNIException Thrown by handler to signal an error.
1059: */
1060: public void notationDecl(String name,
1061: XMLResourceIdentifier identifier, Augmentations augs)
1062: throws XNIException {
1063: try {
1064: // SAX1 and SAX2
1065: if (fDTDHandler != null) {
1066: String publicId = identifier.getPublicId();
1067: String systemId = fResolveDTDURIs ? identifier
1068: .getExpandedSystemId() : identifier
1069: .getLiteralSystemId();
1070: fDTDHandler.notationDecl(name, publicId, systemId);
1071: }
1072: } catch (SAXException e) {
1073: throw new XNIException(e);
1074: }
1075:
1076: } // notationDecl(String,XMLResourceIdentifier, Augmentations)
1077:
1078: /**
1079: * The end of the DTD.
1080: *
1081: * @param augs Additional information that may include infoset
1082: * augmentations.
1083: *
1084: * @throws XNIException Thrown by handler to signal an error.
1085: */
1086: public void endDTD(Augmentations augs) throws XNIException {
1087: fInDTD = false;
1088:
1089: try {
1090: // SAX2 extension
1091: if (fLexicalHandler != null) {
1092: fLexicalHandler.endDTD();
1093: }
1094: } catch (SAXException e) {
1095: throw new XNIException(e);
1096: }
1097: if (fDeclaredAttrs != null) {
1098: // help out the GC
1099: fDeclaredAttrs.clear();
1100: }
1101:
1102: } // endDTD()
1103:
1104: //
1105: // Parser and XMLReader methods
1106: //
1107:
1108: /**
1109: * Parses the input source specified by the given system identifier.
1110: * <p>
1111: * This method is equivalent to the following:
1112: * <pre>
1113: * parse(new InputSource(systemId));
1114: * </pre>
1115: *
1116: * @param systemId The system identifier (URI).
1117: *
1118: * @exception org.xml.sax.SAXException Throws exception on SAX error.
1119: * @exception java.io.IOException Throws exception on i/o error.
1120: */
1121: public void parse(String systemId) throws SAXException, IOException {
1122:
1123: // parse document
1124: XMLInputSource source = new XMLInputSource(null, systemId, null);
1125: try {
1126: parse(source);
1127: }
1128:
1129: // wrap XNI exceptions as SAX exceptions
1130: catch (XMLParseException e) {
1131: Exception ex = e.getException();
1132: if (ex == null || ex instanceof CharConversionException) {
1133: // must be a parser exception; mine it for locator info
1134: // and throw a SAXParseException
1135: Locator2Impl locatorImpl = new Locator2Impl();
1136: // since XMLParseExceptions know nothing about encoding,
1137: // we cannot return anything meaningful in this context.
1138: // We *could* consult the LocatorProxy, but the
1139: // application can do this itself if it wishes to possibly
1140: // be mislead.
1141: locatorImpl.setXMLVersion(fVersion);
1142: locatorImpl.setPublicId(e.getPublicId());
1143: locatorImpl.setSystemId(e.getExpandedSystemId());
1144: locatorImpl.setLineNumber(e.getLineNumber());
1145: locatorImpl.setColumnNumber(e.getColumnNumber());
1146: throw (ex == null) ? new SAXParseException(e
1147: .getMessage(), locatorImpl)
1148: : new SAXParseException(e.getMessage(),
1149: locatorImpl, ex);
1150: }
1151: if (ex instanceof SAXException) {
1152: // why did we create an XMLParseException?
1153: throw (SAXException) ex;
1154: }
1155: if (ex instanceof IOException) {
1156: throw (IOException) ex;
1157: }
1158: throw new SAXException(ex);
1159: } catch (XNIException e) {
1160: Exception ex = e.getException();
1161: if (ex == null) {
1162: throw new SAXException(e.getMessage());
1163: }
1164: if (ex instanceof SAXException) {
1165: throw (SAXException) ex;
1166: }
1167: if (ex instanceof IOException) {
1168: throw (IOException) ex;
1169: }
1170: throw new SAXException(ex);
1171: }
1172:
1173: } // parse(String)
1174:
1175: /**
1176: * parse
1177: *
1178: * @param inputSource
1179: *
1180: * @exception org.xml.sax.SAXException
1181: * @exception java.io.IOException
1182: */
1183: public void parse(InputSource inputSource) throws SAXException,
1184: IOException {
1185:
1186: // parse document
1187: try {
1188: XMLInputSource xmlInputSource = new XMLInputSource(
1189: inputSource.getPublicId(), inputSource
1190: .getSystemId(), null);
1191: xmlInputSource.setByteStream(inputSource.getByteStream());
1192: xmlInputSource.setCharacterStream(inputSource
1193: .getCharacterStream());
1194: xmlInputSource.setEncoding(inputSource.getEncoding());
1195: parse(xmlInputSource);
1196: }
1197:
1198: // wrap XNI exceptions as SAX exceptions
1199: catch (XMLParseException e) {
1200: Exception ex = e.getException();
1201: if (ex == null || ex instanceof CharConversionException) {
1202: // must be a parser exception; mine it for locator info
1203: // and throw a SAXParseException
1204: Locator2Impl locatorImpl = new Locator2Impl();
1205: // since XMLParseExceptions know nothing about encoding,
1206: // we cannot return anything meaningful in this context.
1207: // We *could* consult the LocatorProxy, but the
1208: // application can do this itself if it wishes to possibly
1209: // be mislead.
1210: locatorImpl.setXMLVersion(fVersion);
1211: locatorImpl.setPublicId(e.getPublicId());
1212: locatorImpl.setSystemId(e.getExpandedSystemId());
1213: locatorImpl.setLineNumber(e.getLineNumber());
1214: locatorImpl.setColumnNumber(e.getColumnNumber());
1215: throw (ex == null) ? new SAXParseException(e
1216: .getMessage(), locatorImpl)
1217: : new SAXParseException(e.getMessage(),
1218: locatorImpl, ex);
1219: }
1220: if (ex instanceof SAXException) {
1221: // why did we create an XMLParseException?
1222: throw (SAXException) ex;
1223: }
1224: if (ex instanceof IOException) {
1225: throw (IOException) ex;
1226: }
1227: throw new SAXException(ex);
1228: } catch (XNIException e) {
1229: Exception ex = e.getException();
1230: if (ex == null) {
1231: throw new SAXException(e.getMessage());
1232: }
1233: if (ex instanceof SAXException) {
1234: throw (SAXException) ex;
1235: }
1236: if (ex instanceof IOException) {
1237: throw (IOException) ex;
1238: }
1239: throw new SAXException(ex);
1240: }
1241:
1242: } // parse(InputSource)
1243:
1244: /**
1245: * Sets the resolver used to resolve external entities. The EntityResolver
1246: * interface supports resolution of public and system identifiers.
1247: *
1248: * @param resolver The new entity resolver. Passing a null value will
1249: * uninstall the currently installed resolver.
1250: */
1251: public void setEntityResolver(EntityResolver resolver) {
1252:
1253: try {
1254: XMLEntityResolver xer = (XMLEntityResolver) fConfiguration
1255: .getProperty(ENTITY_RESOLVER);
1256: if (fUseEntityResolver2
1257: && resolver instanceof EntityResolver2) {
1258: if (xer instanceof EntityResolver2Wrapper) {
1259: EntityResolver2Wrapper er2w = (EntityResolver2Wrapper) xer;
1260: er2w.setEntityResolver((EntityResolver2) resolver);
1261: } else {
1262: fConfiguration.setProperty(ENTITY_RESOLVER,
1263: new EntityResolver2Wrapper(
1264: (EntityResolver2) resolver));
1265: }
1266: } else {
1267: if (xer instanceof EntityResolverWrapper) {
1268: EntityResolverWrapper erw = (EntityResolverWrapper) xer;
1269: erw.setEntityResolver(resolver);
1270: } else {
1271: fConfiguration.setProperty(ENTITY_RESOLVER,
1272: new EntityResolverWrapper(resolver));
1273: }
1274: }
1275: } catch (XMLConfigurationException e) {
1276: // do nothing
1277: }
1278:
1279: } // setEntityResolver(EntityResolver)
1280:
1281: /**
1282: * Return the current entity resolver.
1283: *
1284: * @return The current entity resolver, or null if none
1285: * has been registered.
1286: * @see #setEntityResolver
1287: */
1288: public EntityResolver getEntityResolver() {
1289:
1290: EntityResolver entityResolver = null;
1291: try {
1292: XMLEntityResolver xmlEntityResolver = (XMLEntityResolver) fConfiguration
1293: .getProperty(ENTITY_RESOLVER);
1294: if (xmlEntityResolver != null) {
1295: if (xmlEntityResolver instanceof EntityResolverWrapper) {
1296: entityResolver = ((EntityResolverWrapper) xmlEntityResolver)
1297: .getEntityResolver();
1298: } else if (xmlEntityResolver instanceof EntityResolver2Wrapper) {
1299: entityResolver = ((EntityResolver2Wrapper) xmlEntityResolver)
1300: .getEntityResolver();
1301: }
1302: }
1303: } catch (XMLConfigurationException e) {
1304: // do nothing
1305: }
1306: return entityResolver;
1307:
1308: } // getEntityResolver():EntityResolver
1309:
1310: /**
1311: * Allow an application to register an error event handler.
1312: *
1313: * <p>If the application does not register an error handler, all
1314: * error events reported by the SAX parser will be silently
1315: * ignored; however, normal processing may not continue. It is
1316: * highly recommended that all SAX applications implement an
1317: * error handler to avoid unexpected bugs.</p>
1318: *
1319: * <p>Applications may register a new or different handler in the
1320: * middle of a parse, and the SAX parser must begin using the new
1321: * handler immediately.</p>
1322: *
1323: * @param errorHandler The error handler.
1324: * @see #getErrorHandler
1325: */
1326: public void setErrorHandler(ErrorHandler errorHandler) {
1327:
1328: try {
1329: XMLErrorHandler xeh = (XMLErrorHandler) fConfiguration
1330: .getProperty(ERROR_HANDLER);
1331: if (xeh instanceof ErrorHandlerWrapper) {
1332: ErrorHandlerWrapper ehw = (ErrorHandlerWrapper) xeh;
1333: ehw.setErrorHandler(errorHandler);
1334: } else {
1335: fConfiguration.setProperty(ERROR_HANDLER,
1336: new ErrorHandlerWrapper(errorHandler));
1337: }
1338: } catch (XMLConfigurationException e) {
1339: // do nothing
1340: }
1341:
1342: } // setErrorHandler(ErrorHandler)
1343:
1344: /**
1345: * Return the current error handler.
1346: *
1347: * @return The current error handler, or null if none
1348: * has been registered.
1349: * @see #setErrorHandler
1350: */
1351: public ErrorHandler getErrorHandler() {
1352:
1353: ErrorHandler errorHandler = null;
1354: try {
1355: XMLErrorHandler xmlErrorHandler = (XMLErrorHandler) fConfiguration
1356: .getProperty(ERROR_HANDLER);
1357: if (xmlErrorHandler != null
1358: && xmlErrorHandler instanceof ErrorHandlerWrapper) {
1359: errorHandler = ((ErrorHandlerWrapper) xmlErrorHandler)
1360: .getErrorHandler();
1361: }
1362: } catch (XMLConfigurationException e) {
1363: // do nothing
1364: }
1365: return errorHandler;
1366:
1367: } // getErrorHandler():ErrorHandler
1368:
1369: /**
1370: * Set the locale to use for messages.
1371: *
1372: * @param locale The locale object to use for localization of messages.
1373: *
1374: * @exception SAXException An exception thrown if the parser does not
1375: * support the specified locale.
1376: *
1377: * @see org.xml.sax.Parser
1378: */
1379: public void setLocale(Locale locale) throws SAXException {
1380: //REVISIT:this methods is not part of SAX2 interfaces, we should throw exception
1381: //if any application uses SAX2 and sets locale also. -nb
1382: fConfiguration.setLocale(locale);
1383:
1384: } // setLocale(Locale)
1385:
1386: /**
1387: * Allow an application to register a DTD event handler.
1388: * <p>
1389: * If the application does not register a DTD handler, all DTD
1390: * events reported by the SAX parser will be silently ignored.
1391: * <p>
1392: * Applications may register a new or different handler in the
1393: * middle of a parse, and the SAX parser must begin using the new
1394: * handler immediately.
1395: *
1396: * @param dtdHandler The DTD handler.
1397: *
1398:
1399: * @see #getDTDHandler
1400: */
1401: public void setDTDHandler(DTDHandler dtdHandler) {
1402: fDTDHandler = dtdHandler;
1403: } // setDTDHandler(DTDHandler)
1404:
1405: //
1406: // Parser methods
1407: //
1408:
1409: /**
1410: * Allow an application to register a document event handler.
1411: * <p>
1412: * If the application does not register a document handler, all
1413: * document events reported by the SAX parser will be silently
1414: * ignored (this is the default behaviour implemented by
1415: * HandlerBase).
1416: * <p>
1417: * Applications may register a new or different handler in the
1418: * middle of a parse, and the SAX parser must begin using the new
1419: * handler immediately.
1420: *
1421: * @param documentHandler The document handler.
1422: */
1423: public void setDocumentHandler(DocumentHandler documentHandler) {
1424: fDocumentHandler = documentHandler;
1425: } // setDocumentHandler(DocumentHandler)
1426:
1427: //
1428: // XMLReader methods
1429: //
1430:
1431: /**
1432: * Allow an application to register a content event handler.
1433: * <p>
1434: * If the application does not register a content handler, all
1435: * content events reported by the SAX parser will be silently
1436: * ignored.
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 contentHandler The content handler.
1443: *
1444: * @see #getContentHandler
1445: */
1446: public void setContentHandler(ContentHandler contentHandler) {
1447: fContentHandler = contentHandler;
1448: } // setContentHandler(ContentHandler)
1449:
1450: /**
1451: * Return the current content handler.
1452: *
1453: * @return The current content handler, or null if none
1454: * has been registered.
1455: *
1456: * @see #setContentHandler
1457: */
1458: public ContentHandler getContentHandler() {
1459: return fContentHandler;
1460: } // getContentHandler():ContentHandler
1461:
1462: /**
1463: * Return the current DTD handler.
1464: *
1465: * @return The current DTD handler, or null if none
1466: * has been registered.
1467: * @see #setDTDHandler
1468: */
1469: public DTDHandler getDTDHandler() {
1470: return fDTDHandler;
1471: } // getDTDHandler():DTDHandler
1472:
1473: /**
1474: * Set the state of any feature in a SAX2 parser. The parser
1475: * might not recognize the feature, and if it does recognize
1476: * it, it might not be able to fulfill the request.
1477: *
1478: * @param featureId The unique identifier (URI) of the feature.
1479: * @param state The requested state of the feature (true or false).
1480: *
1481: * @exception SAXNotRecognizedException If the
1482: * requested feature is not known.
1483: * @exception SAXNotSupportedException If the
1484: * requested feature is known, but the requested
1485: * state is not supported.
1486: */
1487: public void setFeature(String featureId, boolean state)
1488: throws SAXNotRecognizedException, SAXNotSupportedException {
1489:
1490: try {
1491: //
1492: // SAX2 Features
1493: //
1494:
1495: if (featureId.startsWith(Constants.SAX_FEATURE_PREFIX)) {
1496: final int suffixLength = featureId.length()
1497: - Constants.SAX_FEATURE_PREFIX.length();
1498:
1499: // http://xml.org/sax/features/namespaces
1500: if (suffixLength == Constants.NAMESPACES_FEATURE
1501: .length()
1502: && featureId
1503: .endsWith(Constants.NAMESPACES_FEATURE)) {
1504: fConfiguration.setFeature(featureId, state);
1505: fNamespaces = state;
1506: return;
1507: }
1508:
1509: // http://xml.org/sax/features/namespace-prefixes
1510: // controls the reporting of raw prefixed names and Namespace
1511: // declarations (xmlns* attributes): when this feature is false
1512: // (the default), raw prefixed names may optionally be reported,
1513: // and xmlns* attributes must not be reported.
1514: //
1515: if (suffixLength == Constants.NAMESPACE_PREFIXES_FEATURE
1516: .length()
1517: && featureId
1518: .endsWith(Constants.NAMESPACE_PREFIXES_FEATURE)) {
1519: fNamespacePrefixes = state;
1520: return;
1521: }
1522:
1523: // http://xml.org/sax/features/string-interning
1524: // controls the use of java.lang.String#intern() for strings
1525: // passed to SAX handlers.
1526: //
1527: if (suffixLength == Constants.STRING_INTERNING_FEATURE
1528: .length()
1529: && featureId
1530: .endsWith(Constants.STRING_INTERNING_FEATURE)) {
1531: if (!state) {
1532: throw new SAXNotSupportedException(
1533: SAXMessageFormatter.formatMessage(
1534: fConfiguration.getLocale(),
1535: "false-not-supported",
1536: new Object[] { featureId }));
1537: }
1538: return;
1539: }
1540:
1541: // http://xml.org/sax/features/lexical-handler/parameter-entities
1542: // controls whether the beginning and end of parameter entities
1543: // will be reported to the LexicalHandler.
1544: //
1545: if (suffixLength == Constants.LEXICAL_HANDLER_PARAMETER_ENTITIES_FEATURE
1546: .length()
1547: && featureId
1548: .endsWith(Constants.LEXICAL_HANDLER_PARAMETER_ENTITIES_FEATURE)) {
1549: fLexicalHandlerParameterEntities = state;
1550: return;
1551: }
1552:
1553: // http://xml.org/sax/features/resolve-dtd-uris
1554: // controls whether system identifiers will be absolutized relative to
1555: // their base URIs before reporting.
1556: //
1557: if (suffixLength == Constants.RESOLVE_DTD_URIS_FEATURE
1558: .length()
1559: && featureId
1560: .endsWith(Constants.RESOLVE_DTD_URIS_FEATURE)) {
1561: fResolveDTDURIs = state;
1562: return;
1563: }
1564:
1565: // http://xml.org/sax/features/unicode-normalization-checking
1566: // controls whether Unicode normalization checking is performed
1567: // as per Appendix B of the XML 1.1 specification
1568: //
1569: if (suffixLength == Constants.UNICODE_NORMALIZATION_CHECKING_FEATURE
1570: .length()
1571: && featureId
1572: .endsWith(Constants.UNICODE_NORMALIZATION_CHECKING_FEATURE)) {
1573: // REVISIT: Allow this feature to be set once Unicode normalization
1574: // checking is supported -- mrglavas.
1575: if (state) {
1576: throw new SAXNotSupportedException(
1577: SAXMessageFormatter.formatMessage(
1578: fConfiguration.getLocale(),
1579: "true-not-supported",
1580: new Object[] { featureId }));
1581: }
1582: return;
1583: }
1584:
1585: // http://xml.org/sax/features/xmlns-uris
1586: // controls whether the parser reports that namespace declaration
1587: // attributes as being in the namespace: http://www.w3.org/2000/xmlns/
1588: //
1589: if (suffixLength == Constants.XMLNS_URIS_FEATURE
1590: .length()
1591: && featureId
1592: .endsWith(Constants.XMLNS_URIS_FEATURE)) {
1593: fXMLNSURIs = state;
1594: return;
1595: }
1596:
1597: // http://xml.org/sax/features/use-entity-resolver2
1598: // controls whether the methods of an object implementing
1599: // org.xml.sax.ext.EntityResolver2 will be used by the parser.
1600: //
1601: if (suffixLength == Constants.USE_ENTITY_RESOLVER2_FEATURE
1602: .length()
1603: && featureId
1604: .endsWith(Constants.USE_ENTITY_RESOLVER2_FEATURE)) {
1605: if (state != fUseEntityResolver2) {
1606: fUseEntityResolver2 = state;
1607: // Refresh EntityResolver wrapper.
1608: setEntityResolver(getEntityResolver());
1609: }
1610: return;
1611: }
1612:
1613: //
1614: // Read only features.
1615: //
1616:
1617: // http://xml.org/sax/features/is-standalone
1618: // reports whether the document specified a standalone document declaration.
1619: // http://xml.org/sax/features/use-attributes2
1620: // reports whether Attributes objects passed to startElement also implement
1621: // the org.xml.sax.ext.Attributes2 interface.
1622: // http://xml.org/sax/features/use-locator2
1623: // reports whether Locator objects passed to setDocumentLocator also implement
1624: // the org.xml.sax.ext.Locator2 interface.
1625: // http://xml.org/sax/features/xml-1.1
1626: // reports whether the parser supports both XML 1.1 and XML 1.0.
1627: if ((suffixLength == Constants.IS_STANDALONE_FEATURE
1628: .length() && featureId
1629: .endsWith(Constants.IS_STANDALONE_FEATURE))
1630: || (suffixLength == Constants.USE_ATTRIBUTES2_FEATURE
1631: .length() && featureId
1632: .endsWith(Constants.USE_ATTRIBUTES2_FEATURE))
1633: || (suffixLength == Constants.USE_LOCATOR2_FEATURE
1634: .length() && featureId
1635: .endsWith(Constants.USE_LOCATOR2_FEATURE))
1636: || (suffixLength == Constants.XML_11_FEATURE
1637: .length() && featureId
1638: .endsWith(Constants.XML_11_FEATURE))) {
1639: throw new SAXNotSupportedException(
1640: SAXMessageFormatter.formatMessage(
1641: fConfiguration.getLocale(),
1642: "feature-read-only",
1643: new Object[] { featureId }));
1644: }
1645:
1646: //
1647: // Drop through and perform default processing
1648: //
1649: }
1650:
1651: //
1652: // Xerces Features
1653: //
1654:
1655: /*
1656: else if (featureId.startsWith(XERCES_FEATURES_PREFIX)) {
1657: String feature = featureId.substring(XERCES_FEATURES_PREFIX.length());
1658: //
1659: // Drop through and perform default processing
1660: //
1661: }
1662: */
1663:
1664: //
1665: // Default handling
1666: //
1667: fConfiguration.setFeature(featureId, state);
1668: } catch (XMLConfigurationException e) {
1669: String identifier = e.getIdentifier();
1670: if (e.getType() == XMLConfigurationException.NOT_RECOGNIZED) {
1671: throw new SAXNotRecognizedException(SAXMessageFormatter
1672: .formatMessage(fConfiguration.getLocale(),
1673: "feature-not-recognized",
1674: new Object[] { identifier }));
1675: } else {
1676: throw new SAXNotSupportedException(SAXMessageFormatter
1677: .formatMessage(fConfiguration.getLocale(),
1678: "feature-not-supported",
1679: new Object[] { identifier }));
1680: }
1681: }
1682:
1683: } // setFeature(String,boolean)
1684:
1685: /**
1686: * Query the state of a feature.
1687: *
1688: * Query the current state of any feature in a SAX2 parser. The
1689: * parser might not recognize the feature.
1690: *
1691: * @param featureId The unique identifier (URI) of the feature
1692: * being set.
1693: * @return The current state of the feature.
1694: * @exception org.xml.sax.SAXNotRecognizedException If the
1695: * requested feature is not known.
1696: * @exception SAXNotSupportedException If the
1697: * requested feature is known but not supported.
1698: */
1699: public boolean getFeature(String featureId)
1700: throws SAXNotRecognizedException, SAXNotSupportedException {
1701:
1702: try {
1703: //
1704: // SAX2 Features
1705: //
1706:
1707: if (featureId.startsWith(Constants.SAX_FEATURE_PREFIX)) {
1708: final int suffixLength = featureId.length()
1709: - Constants.SAX_FEATURE_PREFIX.length();
1710:
1711: // http://xml.org/sax/features/namespace-prefixes
1712: // controls the reporting of raw prefixed names and Namespace
1713: // declarations (xmlns* attributes): when this feature is false
1714: // (the default), raw prefixed names may optionally be reported,
1715: // and xmlns* attributes must not be reported.
1716: //
1717: if (suffixLength == Constants.NAMESPACE_PREFIXES_FEATURE
1718: .length()
1719: && featureId
1720: .endsWith(Constants.NAMESPACE_PREFIXES_FEATURE)) {
1721: return fNamespacePrefixes;
1722: }
1723: // http://xml.org/sax/features/string-interning
1724: // controls the use of java.lang.String#intern() for strings
1725: // passed to SAX handlers.
1726: //
1727: if (suffixLength == Constants.STRING_INTERNING_FEATURE
1728: .length()
1729: && featureId
1730: .endsWith(Constants.STRING_INTERNING_FEATURE)) {
1731: return true;
1732: }
1733:
1734: // http://xml.org/sax/features/is-standalone
1735: // reports whether the document specified a standalone document declaration.
1736: //
1737: if (suffixLength == Constants.IS_STANDALONE_FEATURE
1738: .length()
1739: && featureId
1740: .endsWith(Constants.IS_STANDALONE_FEATURE)) {
1741: return fStandalone;
1742: }
1743:
1744: // http://xml.org/sax/features/xml-1.1
1745: // reports whether the parser supports both XML 1.1 and XML 1.0.
1746: //
1747: if (suffixLength == Constants.XML_11_FEATURE.length()
1748: && featureId.endsWith(Constants.XML_11_FEATURE)) {
1749: return (fConfiguration instanceof XML11Configurable);
1750: }
1751:
1752: // http://xml.org/sax/features/lexical-handler/parameter-entities
1753: // controls whether the beginning and end of parameter entities
1754: // will be reported to the LexicalHandler.
1755: //
1756: if (suffixLength == Constants.LEXICAL_HANDLER_PARAMETER_ENTITIES_FEATURE
1757: .length()
1758: && featureId
1759: .endsWith(Constants.LEXICAL_HANDLER_PARAMETER_ENTITIES_FEATURE)) {
1760: return fLexicalHandlerParameterEntities;
1761: }
1762:
1763: // http://xml.org/sax/features/resolve-dtd-uris
1764: // controls whether system identifiers will be absolutized relative to
1765: // their base URIs before reporting.
1766: if (suffixLength == Constants.RESOLVE_DTD_URIS_FEATURE
1767: .length()
1768: && featureId
1769: .endsWith(Constants.RESOLVE_DTD_URIS_FEATURE)) {
1770: return fResolveDTDURIs;
1771: }
1772:
1773: // http://xml.org/sax/features/xmlns-uris
1774: // controls whether the parser reports that namespace declaration
1775: // attributes as being in the namespace: http://www.w3.org/2000/xmlns/
1776: //
1777: if (suffixLength == Constants.XMLNS_URIS_FEATURE
1778: .length()
1779: && featureId
1780: .endsWith(Constants.XMLNS_URIS_FEATURE)) {
1781: return fXMLNSURIs;
1782: }
1783:
1784: // http://xml.org/sax/features/unicode-normalization-checking
1785: // controls whether Unicode normalization checking is performed
1786: // as per Appendix B of the XML 1.1 specification
1787: //
1788: if (suffixLength == Constants.UNICODE_NORMALIZATION_CHECKING_FEATURE
1789: .length()
1790: && featureId
1791: .endsWith(Constants.UNICODE_NORMALIZATION_CHECKING_FEATURE)) {
1792: // REVISIT: Allow this feature to be set once Unicode normalization
1793: // checking is supported -- mrglavas.
1794: return false;
1795: }
1796:
1797: // http://xml.org/sax/features/use-entity-resolver2
1798: // controls whether the methods of an object implementing
1799: // org.xml.sax.ext.EntityResolver2 will be used by the parser.
1800: //
1801: if (suffixLength == Constants.USE_ENTITY_RESOLVER2_FEATURE
1802: .length()
1803: && featureId
1804: .endsWith(Constants.USE_ENTITY_RESOLVER2_FEATURE)) {
1805: return fUseEntityResolver2;
1806: }
1807:
1808: // http://xml.org/sax/features/use-attributes2
1809: // reports whether Attributes objects passed to startElement also implement
1810: // the org.xml.sax.ext.Attributes2 interface.
1811: // http://xml.org/sax/features/use-locator2
1812: // reports whether Locator objects passed to setDocumentLocator also implement
1813: // the org.xml.sax.ext.Locator2 interface.
1814: //
1815: if ((suffixLength == Constants.USE_ATTRIBUTES2_FEATURE
1816: .length() && featureId
1817: .endsWith(Constants.USE_ATTRIBUTES2_FEATURE))
1818: || (suffixLength == Constants.USE_LOCATOR2_FEATURE
1819: .length() && featureId
1820: .endsWith(Constants.USE_LOCATOR2_FEATURE))) {
1821: return true;
1822: }
1823:
1824: //
1825: // Drop through and perform default processing
1826: //
1827: }
1828:
1829: //
1830: // Xerces Features
1831: //
1832:
1833: /*
1834: else if (featureId.startsWith(XERCES_FEATURES_PREFIX)) {
1835: //
1836: // Drop through and perform default processing
1837: //
1838: }
1839: */
1840:
1841: return fConfiguration.getFeature(featureId);
1842: } catch (XMLConfigurationException e) {
1843: String identifier = e.getIdentifier();
1844: if (e.getType() == XMLConfigurationException.NOT_RECOGNIZED) {
1845: throw new SAXNotRecognizedException(SAXMessageFormatter
1846: .formatMessage(fConfiguration.getLocale(),
1847: "feature-not-recognized",
1848: new Object[] { identifier }));
1849: } else {
1850: throw new SAXNotSupportedException(SAXMessageFormatter
1851: .formatMessage(fConfiguration.getLocale(),
1852: "feature-not-supported",
1853: new Object[] { identifier }));
1854: }
1855: }
1856:
1857: } // getFeature(String):boolean
1858:
1859: /**
1860: * Set the value of any property in a SAX2 parser. The parser
1861: * might not recognize the property, and if it does recognize
1862: * it, it might not support the requested value.
1863: *
1864: * @param propertyId The unique identifier (URI) of the property
1865: * being set.
1866: * @param value The value to which the property is being set.
1867: *
1868: * @exception SAXNotRecognizedException If the
1869: * requested property is not known.
1870: * @exception SAXNotSupportedException If the
1871: * requested property is known, but the requested
1872: * value is not supported.
1873: */
1874: public void setProperty(String propertyId, Object value)
1875: throws SAXNotRecognizedException, SAXNotSupportedException {
1876:
1877: try {
1878: //
1879: // SAX2 core properties
1880: //
1881:
1882: if (propertyId.startsWith(Constants.SAX_PROPERTY_PREFIX)) {
1883: final int suffixLength = propertyId.length()
1884: - Constants.SAX_PROPERTY_PREFIX.length();
1885:
1886: //
1887: // http://xml.org/sax/properties/lexical-handler
1888: // Value type: org.xml.sax.ext.LexicalHandler
1889: // Access: read/write, pre-parse only
1890: // Set the lexical event handler.
1891: //
1892: if (suffixLength == Constants.LEXICAL_HANDLER_PROPERTY
1893: .length()
1894: && propertyId
1895: .endsWith(Constants.LEXICAL_HANDLER_PROPERTY)) {
1896: try {
1897: setLexicalHandler((LexicalHandler) value);
1898: } catch (ClassCastException e) {
1899: throw new SAXNotSupportedException(
1900: SAXMessageFormatter
1901: .formatMessage(
1902: fConfiguration
1903: .getLocale(),
1904: "incompatible-class",
1905: new Object[] {
1906: propertyId,
1907: "org.xml.sax.ext.LexicalHandler" }));
1908: }
1909: return;
1910: }
1911: //
1912: // http://xml.org/sax/properties/declaration-handler
1913: // Value type: org.xml.sax.ext.DeclHandler
1914: // Access: read/write, pre-parse only
1915: // Set the DTD declaration event handler.
1916: //
1917: if (suffixLength == Constants.DECLARATION_HANDLER_PROPERTY
1918: .length()
1919: && propertyId
1920: .endsWith(Constants.DECLARATION_HANDLER_PROPERTY)) {
1921: try {
1922: setDeclHandler((DeclHandler) value);
1923: } catch (ClassCastException e) {
1924: throw new SAXNotSupportedException(
1925: SAXMessageFormatter
1926: .formatMessage(
1927: fConfiguration
1928: .getLocale(),
1929: "incompatible-class",
1930: new Object[] {
1931: propertyId,
1932: "org.xml.sax.ext.DeclHandler" }));
1933: }
1934: return;
1935: }
1936: //
1937: // http://xml.org/sax/properties/dom-node
1938: // Value type: DOM Node
1939: // Access: read-only
1940: // Get the DOM node currently being visited, if the SAX parser is
1941: // iterating over a DOM tree. If the parser recognises and
1942: // supports this property but is not currently visiting a DOM
1943: // node, it should return null (this is a good way to check for
1944: // availability before the parse begins).
1945: // http://xml.org/sax/properties/document-xml-version
1946: // Value type: java.lang.String
1947: // Access: read-only
1948: // The literal string describing the actual XML version of the document.
1949: //
1950: if ((suffixLength == Constants.DOM_NODE_PROPERTY
1951: .length() && propertyId
1952: .endsWith(Constants.DOM_NODE_PROPERTY))
1953: || (suffixLength == Constants.DOCUMENT_XML_VERSION_PROPERTY
1954: .length() && propertyId
1955: .endsWith(Constants.DOCUMENT_XML_VERSION_PROPERTY))) {
1956: throw new SAXNotSupportedException(
1957: SAXMessageFormatter.formatMessage(
1958: fConfiguration.getLocale(),
1959: "property-read-only",
1960: new Object[] { propertyId }));
1961: }
1962: //
1963: // Drop through and perform default processing
1964: //
1965: }
1966:
1967: //
1968: // Xerces Properties
1969: //
1970:
1971: /*
1972: else if (propertyId.startsWith(XERCES_PROPERTIES_PREFIX)) {
1973: //
1974: // Drop through and perform default processing
1975: //
1976: }
1977: */
1978:
1979: //
1980: // Perform default processing
1981: //
1982: fConfiguration.setProperty(propertyId, value);
1983: } catch (XMLConfigurationException e) {
1984: String identifier = e.getIdentifier();
1985: if (e.getType() == XMLConfigurationException.NOT_RECOGNIZED) {
1986: throw new SAXNotRecognizedException(SAXMessageFormatter
1987: .formatMessage(fConfiguration.getLocale(),
1988: "property-not-recognized",
1989: new Object[] { identifier }));
1990: } else {
1991: throw new SAXNotSupportedException(SAXMessageFormatter
1992: .formatMessage(fConfiguration.getLocale(),
1993: "property-not-supported",
1994: new Object[] { identifier }));
1995: }
1996: }
1997:
1998: } // setProperty(String,Object)
1999:
2000: /**
2001: * Query the value of a property.
2002: *
2003: * Return the current value of a property in a SAX2 parser.
2004: * The parser might not recognize the property.
2005: *
2006: * @param propertyId The unique identifier (URI) of the property
2007: * being set.
2008: * @return The current value of the property.
2009: * @exception org.xml.sax.SAXNotRecognizedException If the
2010: * requested property is not known.
2011: * @exception SAXNotSupportedException If the
2012: * requested property is known but not supported.
2013: */
2014: public Object getProperty(String propertyId)
2015: throws SAXNotRecognizedException, SAXNotSupportedException {
2016:
2017: try {
2018: //
2019: // SAX2 core properties
2020: //
2021:
2022: if (propertyId.startsWith(Constants.SAX_PROPERTY_PREFIX)) {
2023: final int suffixLength = propertyId.length()
2024: - Constants.SAX_PROPERTY_PREFIX.length();
2025:
2026: //
2027: // http://xml.org/sax/properties/document-xml-version
2028: // Value type: java.lang.String
2029: // Access: read-only
2030: // The literal string describing the actual XML version of the document.
2031: //
2032: if (suffixLength == Constants.DOCUMENT_XML_VERSION_PROPERTY
2033: .length()
2034: && propertyId
2035: .endsWith(Constants.DOCUMENT_XML_VERSION_PROPERTY)) {
2036: return fVersion;
2037: }
2038:
2039: //
2040: // http://xml.org/sax/properties/lexical-handler
2041: // Value type: org.xml.sax.ext.LexicalHandler
2042: // Access: read/write, pre-parse only
2043: // Set the lexical event handler.
2044: //
2045: if (suffixLength == Constants.LEXICAL_HANDLER_PROPERTY
2046: .length()
2047: && propertyId
2048: .endsWith(Constants.LEXICAL_HANDLER_PROPERTY)) {
2049: return getLexicalHandler();
2050: }
2051: //
2052: // http://xml.org/sax/properties/declaration-handler
2053: // Value type: org.xml.sax.ext.DeclHandler
2054: // Access: read/write, pre-parse only
2055: // Set the DTD declaration event handler.
2056: //
2057: if (suffixLength == Constants.DECLARATION_HANDLER_PROPERTY
2058: .length()
2059: && propertyId
2060: .endsWith(Constants.DECLARATION_HANDLER_PROPERTY)) {
2061: return getDeclHandler();
2062: }
2063:
2064: //
2065: // http://xml.org/sax/properties/dom-node
2066: // Value type: DOM Node
2067: // Access: read-only
2068: // Get the DOM node currently being visited, if the SAX parser is
2069: // iterating over a DOM tree. If the parser recognises and
2070: // supports this property but is not currently visiting a DOM
2071: // node, it should return null (this is a good way to check for
2072: // availability before the parse begins).
2073: //
2074: if (suffixLength == Constants.DOM_NODE_PROPERTY
2075: .length()
2076: && propertyId
2077: .endsWith(Constants.DOM_NODE_PROPERTY)) {
2078: // we are not iterating a DOM tree
2079: throw new SAXNotSupportedException(
2080: SAXMessageFormatter
2081: .formatMessage(
2082: fConfiguration.getLocale(),
2083: "dom-node-read-not-supported",
2084: null));
2085: }
2086:
2087: //
2088: // Drop through and perform default processing
2089: //
2090: }
2091:
2092: //
2093: // Xerces properties
2094: //
2095:
2096: /*
2097: else if (propertyId.startsWith(XERCES_PROPERTIES_PREFIX)) {
2098: //
2099: // Drop through and perform default processing
2100: //
2101: }
2102: */
2103:
2104: //
2105: // Perform default processing
2106: //
2107: return fConfiguration.getProperty(propertyId);
2108: } catch (XMLConfigurationException e) {
2109: String identifier = e.getIdentifier();
2110: if (e.getType() == XMLConfigurationException.NOT_RECOGNIZED) {
2111: throw new SAXNotRecognizedException(SAXMessageFormatter
2112: .formatMessage(fConfiguration.getLocale(),
2113: "property-not-recognized",
2114: new Object[] { identifier }));
2115: } else {
2116: throw new SAXNotSupportedException(SAXMessageFormatter
2117: .formatMessage(fConfiguration.getLocale(),
2118: "property-not-supported",
2119: new Object[] { identifier }));
2120: }
2121: }
2122:
2123: } // getProperty(String):Object
2124:
2125: //
2126: // Protected methods
2127: //
2128:
2129: // SAX2 core properties
2130:
2131: /**
2132: * Set the DTD declaration event handler.
2133: * <p>
2134: * This method is the equivalent to the property:
2135: * <pre>
2136: * http://xml.org/sax/properties/declaration-handler
2137: * </pre>
2138: *
2139: * @param handler The new handler.
2140: *
2141: * @see #getDeclHandler
2142: * @see #setProperty
2143: */
2144: protected void setDeclHandler(DeclHandler handler)
2145: throws SAXNotRecognizedException, SAXNotSupportedException {
2146:
2147: if (fParseInProgress) {
2148: throw new SAXNotSupportedException(
2149: SAXMessageFormatter
2150: .formatMessage(
2151: fConfiguration.getLocale(),
2152: "property-not-parsing-supported",
2153: new Object[] { "http://xml.org/sax/properties/declaration-handler" }));
2154: }
2155: fDeclHandler = handler;
2156:
2157: } // setDeclHandler(DeclHandler)
2158:
2159: /**
2160: * Returns the DTD declaration event handler.
2161: *
2162: * @see #setDeclHandler
2163: */
2164: protected DeclHandler getDeclHandler()
2165: throws SAXNotRecognizedException, SAXNotSupportedException {
2166: return fDeclHandler;
2167: } // getDeclHandler():DeclHandler
2168:
2169: /**
2170: * Set the lexical event handler.
2171: * <p>
2172: * This method is the equivalent to the property:
2173: * <pre>
2174: * http://xml.org/sax/properties/lexical-handler
2175: * </pre>
2176: *
2177: * @param handler lexical event handler
2178: *
2179: * @see #getLexicalHandler
2180: * @see #setProperty
2181: */
2182: protected void setLexicalHandler(LexicalHandler handler)
2183: throws SAXNotRecognizedException, SAXNotSupportedException {
2184:
2185: if (fParseInProgress) {
2186: throw new SAXNotSupportedException(
2187: SAXMessageFormatter
2188: .formatMessage(
2189: fConfiguration.getLocale(),
2190: "property-not-parsing-supported",
2191: new Object[] { "http://xml.org/sax/properties/lexical-handler" }));
2192: }
2193: fLexicalHandler = handler;
2194:
2195: } // setLexicalHandler(LexicalHandler)
2196:
2197: /**
2198: * Returns the lexical handler.
2199: *
2200: * @see #setLexicalHandler
2201: */
2202: protected LexicalHandler getLexicalHandler()
2203: throws SAXNotRecognizedException, SAXNotSupportedException {
2204: return fLexicalHandler;
2205: } // getLexicalHandler():LexicalHandler
2206:
2207: /**
2208: * Send startPrefixMapping events
2209: */
2210: protected final void startNamespaceMapping() throws SAXException {
2211: int count = fNamespaceContext.getDeclaredPrefixCount();
2212: if (count > 0) {
2213: String prefix = null;
2214: String uri = null;
2215: for (int i = 0; i < count; i++) {
2216: prefix = fNamespaceContext.getDeclaredPrefixAt(i);
2217: uri = fNamespaceContext.getURI(prefix);
2218: fContentHandler.startPrefixMapping(prefix,
2219: (uri == null) ? "" : uri);
2220: }
2221: }
2222: }
2223:
2224: /**
2225: * Send endPrefixMapping events
2226: */
2227: protected final void endNamespaceMapping() throws SAXException {
2228: int count = fNamespaceContext.getDeclaredPrefixCount();
2229: if (count > 0) {
2230: for (int i = 0; i < count; i++) {
2231: fContentHandler.endPrefixMapping(fNamespaceContext
2232: .getDeclaredPrefixAt(i));
2233: }
2234: }
2235: }
2236:
2237: //
2238: // XMLDocumentParser methods
2239: //
2240:
2241: /**
2242: * Reset all components before parsing.
2243: *
2244: * @throws XNIException Thrown if an error occurs during initialization.
2245: */
2246: public void reset() throws XNIException {
2247: super .reset();
2248:
2249: // reset state
2250: fInDTD = false;
2251: fVersion = "1.0";
2252: fStandalone = false;
2253:
2254: // features
2255: fNamespaces = fConfiguration.getFeature(NAMESPACES);
2256: fAugmentations = null;
2257: fDeclaredAttrs = null;
2258:
2259: } // reset()
2260:
2261: //
2262: // Classes
2263: //
2264:
2265: protected static final class LocatorProxy implements Locator2 {
2266:
2267: //
2268: // Data
2269: //
2270:
2271: /** XML locator. */
2272: protected XMLLocator fLocator;
2273:
2274: //
2275: // Constructors
2276: //
2277:
2278: /** Constructs an XML locator proxy. */
2279: public LocatorProxy(XMLLocator locator) {
2280: fLocator = locator;
2281: }
2282:
2283: //
2284: // Locator methods
2285: //
2286:
2287: /** Public identifier. */
2288: public String getPublicId() {
2289: return fLocator.getPublicId();
2290: }
2291:
2292: /** System identifier. */
2293: public String getSystemId() {
2294: return fLocator.getExpandedSystemId();
2295: }
2296:
2297: /** Line number. */
2298: public int getLineNumber() {
2299: return fLocator.getLineNumber();
2300: }
2301:
2302: /** Column number. */
2303: public int getColumnNumber() {
2304: return fLocator.getColumnNumber();
2305: }
2306:
2307: // Locator2 methods
2308: public String getXMLVersion() {
2309: return fLocator.getXMLVersion();
2310: }
2311:
2312: public String getEncoding() {
2313: return fLocator.getEncoding();
2314: }
2315:
2316: } // class LocatorProxy
2317:
2318: protected static final class AttributesProxy implements
2319: AttributeList, Attributes2 {
2320:
2321: //
2322: // Data
2323: //
2324:
2325: /** XML attributes. */
2326: protected XMLAttributes fAttributes;
2327:
2328: //
2329: // Public methods
2330: //
2331:
2332: /** Sets the XML attributes. */
2333: public void setAttributes(XMLAttributes attributes) {
2334: fAttributes = attributes;
2335: } // setAttributes(XMLAttributes)
2336:
2337: public int getLength() {
2338: return fAttributes.getLength();
2339: }
2340:
2341: public String getName(int i) {
2342: return fAttributes.getQName(i);
2343: }
2344:
2345: public String getQName(int index) {
2346: return fAttributes.getQName(index);
2347: }
2348:
2349: public String getURI(int index) {
2350: // REVISIT: this hides the fact that internally we use
2351: // null instead of empty string
2352: // SAX requires URI to be a string or an empty string
2353: String uri = fAttributes.getURI(index);
2354: return uri != null ? uri : "";
2355: }
2356:
2357: public String getLocalName(int index) {
2358: return fAttributes.getLocalName(index);
2359: }
2360:
2361: public String getType(int i) {
2362: return fAttributes.getType(i);
2363: }
2364:
2365: public String getType(String name) {
2366: return fAttributes.getType(name);
2367: }
2368:
2369: public String getType(String uri, String localName) {
2370: return uri.equals("") ? fAttributes
2371: .getType(null, localName) : fAttributes.getType(
2372: uri, localName);
2373: }
2374:
2375: public String getValue(int i) {
2376: return fAttributes.getValue(i);
2377: }
2378:
2379: public String getValue(String name) {
2380: return fAttributes.getValue(name);
2381: }
2382:
2383: public String getValue(String uri, String localName) {
2384: return uri.equals("") ? fAttributes.getValue(null,
2385: localName) : fAttributes.getValue(uri, localName);
2386: }
2387:
2388: public int getIndex(String qName) {
2389: return fAttributes.getIndex(qName);
2390: }
2391:
2392: public int getIndex(String uri, String localPart) {
2393: return uri.equals("") ? fAttributes.getIndex(null,
2394: localPart) : fAttributes.getIndex(uri, localPart);
2395: }
2396:
2397: // Attributes2 methods
2398: // REVISIT: Localize exception messages. -- mrglavas
2399: public boolean isDeclared(int index) {
2400: if (index < 0 || index >= fAttributes.getLength()) {
2401: throw new ArrayIndexOutOfBoundsException(index);
2402: }
2403: return Boolean.TRUE.equals(fAttributes.getAugmentations(
2404: index).getItem(Constants.ATTRIBUTE_DECLARED));
2405: }
2406:
2407: public boolean isDeclared(String qName) {
2408: int index = getIndex(qName);
2409: if (index == -1) {
2410: throw new IllegalArgumentException(qName);
2411: }
2412: return Boolean.TRUE.equals(fAttributes.getAugmentations(
2413: index).getItem(Constants.ATTRIBUTE_DECLARED));
2414: }
2415:
2416: public boolean isDeclared(String uri, String localName) {
2417: int index = getIndex(uri, localName);
2418: if (index == -1) {
2419: throw new IllegalArgumentException(localName);
2420: }
2421: return Boolean.TRUE.equals(fAttributes.getAugmentations(
2422: index).getItem(Constants.ATTRIBUTE_DECLARED));
2423: }
2424:
2425: public boolean isSpecified(int index) {
2426: if (index < 0 || index >= fAttributes.getLength()) {
2427: throw new ArrayIndexOutOfBoundsException(index);
2428: }
2429: return fAttributes.isSpecified(index);
2430: }
2431:
2432: public boolean isSpecified(String qName) {
2433: int index = getIndex(qName);
2434: if (index == -1) {
2435: throw new IllegalArgumentException(qName);
2436: }
2437: return fAttributes.isSpecified(index);
2438: }
2439:
2440: public boolean isSpecified(String uri, String localName) {
2441: int index = getIndex(uri, localName);
2442: if (index == -1) {
2443: throw new IllegalArgumentException(localName);
2444: }
2445: return fAttributes.isSpecified(index);
2446: }
2447:
2448: } // class AttributesProxy
2449:
2450: // PSVIProvider methods
2451:
2452: public ElementPSVI getElementPSVI() {
2453: return (fAugmentations != null) ? (ElementPSVI) fAugmentations
2454: .getItem(Constants.ELEMENT_PSVI) : null;
2455: }
2456:
2457: public AttributePSVI getAttributePSVI(int index) {
2458:
2459: return (AttributePSVI) fAttributesProxy.fAttributes
2460: .getAugmentations(index).getItem(
2461: Constants.ATTRIBUTE_PSVI);
2462: }
2463:
2464: public AttributePSVI getAttributePSVIByName(String uri,
2465: String localname) {
2466: return (AttributePSVI) fAttributesProxy.fAttributes
2467: .getAugmentations(uri, localname).getItem(
2468: Constants.ATTRIBUTE_PSVI);
2469: }
2470:
2471: } // class AbstractSAXParser
|