package org.apache.xerces.parsers; import java.io.IOException; import java.util.Locale; import org.apache.xerces.impl.xs.psvi.PSVIProvider; import org.apache.xerces.util.EntityResolverWrapper; import org.apache.xerces.util.ErrorHandlerWrapper; import org.apache.xerces.util.SymbolHash; import org.apache.xerces.xni.Augmentations; import org.apache.xerces.xni.NamespaceContext; import org.apache.xerces.xni.QName; import org.apache.xerces.xni.XMLAttributes; import org.apache.xerces.xni.XMLLocator; import org.apache.xerces.xni.XMLResourceIdentifier; import org.apache.xerces.xni.XMLString; import org.apache.xerces.xni.XNIException; import org.apache.xerces.xni.parser.XMLConfigurationException; import org.apache.xerces.xni.parser.XMLEntityResolver; import org.apache.xerces.xni.parser.XMLErrorHandler; import org.apache.xerces.xni.parser.XMLInputSource; import org.apache.xerces.xni.parser.XMLParseException; import org.apache.xerces.xni.parser.XMLParserConfiguration; import org.apache.xerces.xni.psvi.AttributePSVI; import org.apache.xerces.xni.psvi.ElementPSVI; import org.xml.sax.AttributeList; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.DTDHandler; import org.xml.sax.DocumentHandler; import org.xml.sax.EntityResolver; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.Locator; import org.xml.sax.Parser; import org.xml.sax.SAXException; import org.xml.sax.SAXNotRecognizedException; import org.xml.sax.SAXNotSupportedException; import org.xml.sax.SAXParseException; import org.xml.sax.XMLReader; import org.xml.sax.ext.DeclHandler; import org.xml.sax.ext.LexicalHandler; import org.xml.sax.helpers.LocatorImpl; public abstract class AbstractSAXParser extends AbstractXMLDocumentParser implements PSVIProvider, Parser, XMLReader { protected static final String NAMESPACES = "http://xml.org/sax/features/namespaces"; protected static final String NAMESPACE_PREFIXES = "http://xml.org/sax/features/namespace-prefixes"; protected static final String STRING_INTERNING = "http://xml.org/sax/features/string-interning"; private static final String[] RECOGNIZED_FEATURES = new String[] { "http://xml.org/sax/features/namespaces", "http://xml.org/sax/features/namespace-prefixes", "http://xml.org/sax/features/string-interning" }; protected static final String LEXICAL_HANDLER = "http://xml.org/sax/properties/lexical-handler"; protected static final String DECLARATION_HANDLER = "http://xml.org/sax/properties/declaration-handler"; protected static final String DOM_NODE = "http://xml.org/sax/properties/dom-node"; private static final String[] RECOGNIZED_PROPERTIES = new String[] { "http://xml.org/sax/properties/lexical-handler", "http://xml.org/sax/properties/declaration-handler", "http://xml.org/sax/properties/dom-node" }; protected boolean fNamespaces; protected boolean fNamespacePrefixes = false; protected ContentHandler fContentHandler; protected DocumentHandler fDocumentHandler; protected NamespaceContext fNamespaceContext; protected DTDHandler fDTDHandler; protected DeclHandler fDeclHandler; protected LexicalHandler fLexicalHandler; protected QName fQName = new QName(); protected boolean fParseInProgress = false; private final AttributesProxy fAttributesProxy = new AttributesProxy(); private Augmentations fAugmentations = null; private static final int BUFFER_SIZE = 20; private char[] fCharBuffer = new char[20]; protected SymbolHash fDeclaredAttrs = null; protected AbstractSAXParser(XMLParserConfiguration config) { super(config); config.addRecognizedFeatures(RECOGNIZED_FEATURES); config.addRecognizedProperties(RECOGNIZED_PROPERTIES); } public void startDocument(XMLLocator locator, String encoding, NamespaceContext namespaceContext, Augmentations augs) throws XNIException { this.fNamespaceContext = namespaceContext; try { if (this.fDocumentHandler != null) { if (locator != null) this.fDocumentHandler.setDocumentLocator(new LocatorProxy(locator)); this.fDocumentHandler.startDocument(); } if (this.fContentHandler != null) { if (locator != null) this.fContentHandler.setDocumentLocator(new LocatorProxy(locator)); this.fContentHandler.startDocument(); } } catch (SAXException e) { throw new XNIException(e); } } public void doctypeDecl(String rootElement, String publicId, String systemId, Augmentations augs) throws XNIException { this.fInDTD = true; try { if (this.fLexicalHandler != null) this.fLexicalHandler.startDTD(rootElement, publicId, systemId); } catch (SAXException e) { throw new XNIException(e); } if (this.fDeclHandler != null) this.fDeclaredAttrs = new SymbolHash(); } public void startGeneralEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augs) throws XNIException { startParameterEntity(name, identifier, encoding, augs); } public void endGeneralEntity(String name, Augmentations augs) throws XNIException { endParameterEntity(name, augs); } public void startElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException { try { if (this.fDocumentHandler != null) { this.fAttributesProxy.setAttributes(attributes); this.fDocumentHandler.startElement(element.rawname, this.fAttributesProxy); } if (this.fContentHandler != null) { startNamespaceMapping(); this.fAugmentations = augs; int len = attributes.getLength(); for (int i = len - 1; i >= 0; i--) { attributes.getName(i, this.fQName); if ((this.fQName.prefix != null && this.fQName.prefix.equals("xmlns")) || this.fQName.rawname.equals("xmlns")) { if (!this.fNamespacePrefixes) attributes.removeAttributeAt(i); if (this.fNamespaces && this.fNamespacePrefixes) { this.fQName.prefix = ""; this.fQName.uri = ""; this.fQName.localpart = ""; attributes.setName(i, this.fQName); } } } String uri = (element.uri != null) ? element.uri : ""; String localpart = this.fNamespaces ? element.localpart : ""; this.fAttributesProxy.setAttributes(attributes); this.fContentHandler.startElement(uri, localpart, element.rawname, this.fAttributesProxy); } } catch (SAXException e) { throw new XNIException(e); } } public void characters(XMLString text, Augmentations augs) throws XNIException { if (text.length == 0) return; try { if (this.fDocumentHandler != null) this.fDocumentHandler.characters(text.ch, text.offset, text.length); if (this.fContentHandler != null) this.fContentHandler.characters(text.ch, text.offset, text.length); } catch (SAXException e) { throw new XNIException(e); } } public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException { try { if (this.fDocumentHandler != null) this.fDocumentHandler.ignorableWhitespace(text.ch, text.offset, text.length); if (this.fContentHandler != null) this.fContentHandler.ignorableWhitespace(text.ch, text.offset, text.length); } catch (SAXException e) { throw new XNIException(e); } } public void endElement(QName element, Augmentations augs) throws XNIException { try { if (this.fDocumentHandler != null) this.fDocumentHandler.endElement(element.rawname); if (this.fContentHandler != null) { this.fAugmentations = augs; String uri = (element.uri != null) ? element.uri : ""; String localpart = this.fNamespaces ? element.localpart : ""; this.fContentHandler.endElement(uri, localpart, element.rawname); endNamespaceMapping(); } } catch (SAXException e) { throw new XNIException(e); } } public void startCDATA(Augmentations augs) throws XNIException { try { if (this.fLexicalHandler != null) this.fLexicalHandler.startCDATA(); } catch (SAXException e) { throw new XNIException(e); } } public void endCDATA(Augmentations augs) throws XNIException { try { if (this.fLexicalHandler != null) this.fLexicalHandler.endCDATA(); } catch (SAXException e) { throw new XNIException(e); } } public void comment(XMLString text, Augmentations augs) throws XNIException { try { if (this.fLexicalHandler != null) this.fLexicalHandler.comment(text.ch, 0, text.length); } catch (SAXException e) { throw new XNIException(e); } } public void processingInstruction(String target, XMLString data, Augmentations augs) throws XNIException { try { if (this.fDocumentHandler != null) this.fDocumentHandler.processingInstruction(target, data.toString()); if (this.fContentHandler != null) this.fContentHandler.processingInstruction(target, data.toString()); } catch (SAXException e) { throw new XNIException(e); } } public void endDocument(Augmentations augs) throws XNIException { try { if (this.fDocumentHandler != null) this.fDocumentHandler.endDocument(); if (this.fContentHandler != null) this.fContentHandler.endDocument(); } catch (SAXException e) { throw new XNIException(e); } } public void startExternalSubset(XMLResourceIdentifier identifier, Augmentations augs) throws XNIException { startParameterEntity("[dtd]", (XMLResourceIdentifier)null, (String)null, augs); } public void endExternalSubset(Augmentations augs) throws XNIException { endParameterEntity("[dtd]", augs); } public void startParameterEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augs) throws XNIException { try { if (this.fLexicalHandler != null) this.fLexicalHandler.startEntity(name); } catch (SAXException e) { throw new XNIException(e); } } public void endParameterEntity(String name, Augmentations augs) throws XNIException { try { if (this.fLexicalHandler != null) this.fLexicalHandler.endEntity(name); } catch (SAXException e) { throw new XNIException(e); } } public void elementDecl(String name, String contentModel, Augmentations augs) throws XNIException { try { if (this.fDeclHandler != null) this.fDeclHandler.elementDecl(name, contentModel); } catch (SAXException e) { throw new XNIException(e); } } public void attributeDecl(String elementName, String attributeName, String type, String[] enumeration, String defaultType, XMLString defaultValue, XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException { try { if (this.fDeclHandler != null) { String elemAttr = elementName + "<" + attributeName; if (this.fDeclaredAttrs.get(elemAttr) != null) return; this.fDeclaredAttrs.put(elemAttr, Boolean.TRUE); if (type.equals("NOTATION") || type.equals("ENUMERATION")) { StringBuffer str = new StringBuffer(); if (type.equals("NOTATION")) { str.append(type); str.append(" ("); } else { str.append("("); } for (int i = 0; i < enumeration.length; i++) { str.append(enumeration[i]); if (i < enumeration.length - 1) str.append('|'); } str.append(')'); type = str.toString(); } String value = (defaultValue == null) ? null : defaultValue.toString(); this.fDeclHandler.attributeDecl(elementName, attributeName, type, defaultType, value); } } catch (SAXException e) { throw new XNIException(e); } } public void internalEntityDecl(String name, XMLString text, XMLString nonNormalizedText, Augmentations augs) throws XNIException { try { if (this.fDeclHandler != null) this.fDeclHandler.internalEntityDecl(name, text.toString()); } catch (SAXException e) { throw new XNIException(e); } } public void externalEntityDecl(String name, XMLResourceIdentifier identifier, Augmentations augs) throws XNIException { String publicId = identifier.getPublicId(); String literalSystemId = identifier.getLiteralSystemId(); try { if (this.fDeclHandler != null) this.fDeclHandler.externalEntityDecl(name, publicId, literalSystemId); } catch (SAXException e) { throw new XNIException(e); } } public void unparsedEntityDecl(String name, XMLResourceIdentifier identifier, String notation, Augmentations augs) throws XNIException { String publicId = identifier.getPublicId(); String expandedSystemId = identifier.getExpandedSystemId(); try { if (this.fDTDHandler != null) this.fDTDHandler.unparsedEntityDecl(name, publicId, expandedSystemId, notation); } catch (SAXException e) { throw new XNIException(e); } } public void notationDecl(String name, XMLResourceIdentifier identifier, Augmentations augs) throws XNIException { String publicId = identifier.getPublicId(); String expandedSystemId = identifier.getExpandedSystemId(); try { if (this.fDTDHandler != null) this.fDTDHandler.notationDecl(name, publicId, expandedSystemId); } catch (SAXException e) { throw new XNIException(e); } } public void endDTD(Augmentations augs) throws XNIException { this.fInDTD = false; try { if (this.fLexicalHandler != null) this.fLexicalHandler.endDTD(); } catch (SAXException e) { throw new XNIException(e); } if (this.fDeclaredAttrs != null) this.fDeclaredAttrs.clear(); } public void parse(String systemId) throws SAXException, IOException { XMLInputSource source = new XMLInputSource(null, systemId, null); try { parse(source); } catch (XMLParseException e) { Exception ex = e.getException(); if (ex == null) { LocatorImpl locatorImpl = new LocatorImpl(); locatorImpl.setPublicId(e.getPublicId()); locatorImpl.setSystemId(e.getExpandedSystemId()); locatorImpl.setLineNumber(e.getLineNumber()); locatorImpl.setColumnNumber(e.getColumnNumber()); throw new SAXParseException(e.getMessage(), locatorImpl); } if (ex instanceof SAXException) throw (SAXException)ex; if (ex instanceof IOException) throw (IOException)ex; throw new SAXException(ex); } catch (XNIException e) { Exception ex = e.getException(); if (ex == null) throw new SAXException(e.getMessage()); if (ex instanceof SAXException) throw (SAXException)ex; if (ex instanceof IOException) throw (IOException)ex; throw new SAXException(ex); } } public void parse(InputSource inputSource) throws SAXException, IOException { try { XMLInputSource xmlInputSource = new XMLInputSource(inputSource.getPublicId(), inputSource.getSystemId(), null); xmlInputSource.setByteStream(inputSource.getByteStream()); xmlInputSource.setCharacterStream(inputSource.getCharacterStream()); xmlInputSource.setEncoding(inputSource.getEncoding()); parse(xmlInputSource); } catch (XMLParseException e) { Exception ex = e.getException(); if (ex == null) { LocatorImpl locatorImpl = new LocatorImpl(); locatorImpl.setPublicId(e.getPublicId()); locatorImpl.setSystemId(e.getExpandedSystemId()); locatorImpl.setLineNumber(e.getLineNumber()); locatorImpl.setColumnNumber(e.getColumnNumber()); throw new SAXParseException(e.getMessage(), locatorImpl); } if (ex instanceof SAXException) throw (SAXException)ex; if (ex instanceof IOException) throw (IOException)ex; throw new SAXException(ex); } catch (XNIException e) { Exception ex = e.getException(); if (ex == null) throw new SAXException(e.getMessage()); if (ex instanceof SAXException) throw (SAXException)ex; if (ex instanceof IOException) throw (IOException)ex; throw new SAXException(ex); } } public void setEntityResolver(EntityResolver resolver) { if (resolver == null) throw new NullPointerException(); try { this.fConfiguration.setProperty("http://apache.org/xml/properties/internal/entity-resolver", new EntityResolverWrapper(resolver)); } catch (XMLConfigurationException e) {} } public EntityResolver getEntityResolver() { EntityResolver entityResolver = null; try { XMLEntityResolver xmlEntityResolver = (XMLEntityResolver)this.fConfiguration.getProperty("http://apache.org/xml/properties/internal/entity-resolver"); if (xmlEntityResolver != null && xmlEntityResolver instanceof EntityResolverWrapper) entityResolver = ((EntityResolverWrapper)xmlEntityResolver).getEntityResolver(); } catch (XMLConfigurationException e) {} return entityResolver; } public void setErrorHandler(ErrorHandler errorHandler) { if (errorHandler == null) throw new NullPointerException(); try { this.fConfiguration.setProperty("http://apache.org/xml/properties/internal/error-handler", new ErrorHandlerWrapper(errorHandler)); } catch (XMLConfigurationException e) {} } public ErrorHandler getErrorHandler() { ErrorHandler errorHandler = null; try { XMLErrorHandler xmlErrorHandler = (XMLErrorHandler)this.fConfiguration.getProperty("http://apache.org/xml/properties/internal/error-handler"); if (xmlErrorHandler != null && xmlErrorHandler instanceof ErrorHandlerWrapper) errorHandler = ((ErrorHandlerWrapper)xmlErrorHandler).getErrorHandler(); } catch (XMLConfigurationException e) {} return errorHandler; } public void setLocale(Locale locale) throws SAXException { this.fConfiguration.setLocale(locale); } public void setDTDHandler(DTDHandler dtdHandler) { if (dtdHandler == null) throw new NullPointerException(); this.fDTDHandler = dtdHandler; } public void setDocumentHandler(DocumentHandler documentHandler) { this.fDocumentHandler = documentHandler; } public void setContentHandler(ContentHandler contentHandler) { if (contentHandler == null) throw new NullPointerException(); this.fContentHandler = contentHandler; } public ContentHandler getContentHandler() { return this.fContentHandler; } public DTDHandler getDTDHandler() { return this.fDTDHandler; } public void setFeature(String featureId, boolean state) throws SAXNotRecognizedException, SAXNotSupportedException { try { if (featureId.startsWith("http://xml.org/sax/features/")) { String feature = featureId.substring("http://xml.org/sax/features/".length()); if (feature.equals("namespaces")) { this.fConfiguration.setFeature(featureId, state); this.fNamespaces = state; return; } if (feature.equals("namespace-prefixes")) { this.fConfiguration.setFeature(featureId, state); this.fNamespacePrefixes = state; return; } if (feature.equals("string-interning")) { if (!state) throw new SAXNotSupportedException("PAR018 " + state + " state for feature \"" + featureId + "\" is not supported.\n" + state + '\t' + featureId); return; } } this.fConfiguration.setFeature(featureId, state); } catch (XMLConfigurationException e) { String message = e.getMessage(); if (e.getType() == 0) throw new SAXNotRecognizedException(message); throw new SAXNotSupportedException(message); } } public boolean getFeature(String featureId) throws SAXNotRecognizedException, SAXNotSupportedException { try { if (featureId.startsWith("http://xml.org/sax/features/")) { String feature = featureId.substring("http://xml.org/sax/features/".length()); if (feature.equals("namespace-prefixes")) { boolean state = this.fConfiguration.getFeature(featureId); return state; } if (feature.equals("string-interning")) return true; } return this.fConfiguration.getFeature(featureId); } catch (XMLConfigurationException e) { String message = e.getMessage(); if (e.getType() == 0) throw new SAXNotRecognizedException(message); throw new SAXNotSupportedException(message); } } public void setProperty(String propertyId, Object value) throws SAXNotRecognizedException, SAXNotSupportedException { try { if (propertyId.startsWith("http://xml.org/sax/properties/")) { String property = propertyId.substring("http://xml.org/sax/properties/".length()); if (property.equals("lexical-handler")) { try { setLexicalHandler((LexicalHandler)value); } catch (ClassCastException e) { throw new SAXNotSupportedException("PAR012 For propertyID \"" + propertyId + "\", the value \"" + value + "\" cannot be cast to LexicalHandler." + '\n' + propertyId + '\t' + value + "\tLexicalHandler"); } return; } if (property.equals("declaration-handler")) { try { setDeclHandler((DeclHandler)value); } catch (ClassCastException e) { throw new SAXNotSupportedException("PAR012 For propertyID \"" + propertyId + "\", the value \"" + value + "\" cannot be cast to DeclHandler." + '\n' + propertyId + '\t' + value + "\tDeclHandler"); } return; } if (property.equals("dom-node")) throw new SAXNotSupportedException("PAR013 Property \"" + propertyId + "\" is read only." + '\n' + propertyId); } this.fConfiguration.setProperty(propertyId, value); } catch (XMLConfigurationException e) { String message = e.getMessage(); if (e.getType() == 0) throw new SAXNotRecognizedException(message); throw new SAXNotSupportedException(message); } } public Object getProperty(String propertyId) throws SAXNotRecognizedException, SAXNotSupportedException { try { if (propertyId.startsWith("http://xml.org/sax/properties/")) { String property = propertyId.substring("http://xml.org/sax/properties/".length()); if (property.equals("lexical-handler")) return getLexicalHandler(); if (property.equals("declaration-handler")) return getDeclHandler(); if (property.equals("dom-node")) throw new SAXNotSupportedException("PAR014 Cannot getProperty(\"" + propertyId + "\". No DOM Tree exists.\n" + propertyId); } return this.fConfiguration.getProperty(propertyId); } catch (XMLConfigurationException e) { String message = e.getMessage(); if (e.getType() == 0) throw new SAXNotRecognizedException(message); throw new SAXNotSupportedException(message); } } protected void setDeclHandler(DeclHandler handler) throws SAXNotRecognizedException, SAXNotSupportedException { if (this.fParseInProgress) throw new SAXNotSupportedException("PAR011 Feature: http://xml.org/sax/properties/declaration-handler is not supported during parse.\nhttp://xml.org/sax/properties/declaration-handler"); this.fDeclHandler = handler; } protected DeclHandler getDeclHandler() throws SAXNotRecognizedException, SAXNotSupportedException { return this.fDeclHandler; } protected void setLexicalHandler(LexicalHandler handler) throws SAXNotRecognizedException, SAXNotSupportedException { if (this.fParseInProgress) throw new SAXNotSupportedException("PAR011 Feature: http://xml.org/sax/properties/lexical-handler is not supported during parse.\nhttp://xml.org/sax/properties/lexical-handler"); this.fLexicalHandler = handler; } protected LexicalHandler getLexicalHandler() throws SAXNotRecognizedException, SAXNotSupportedException { return this.fLexicalHandler; } protected final void startNamespaceMapping() throws SAXException { int count = this.fNamespaceContext.getDeclaredPrefixCount(); if (count > 0) { String prefix = null; String uri = null; for (int i = 0; i < count; i++) { prefix = this.fNamespaceContext.getDeclaredPrefixAt(i); uri = this.fNamespaceContext.getURI(prefix); this.fContentHandler.startPrefixMapping(prefix, (uri == null) ? "" : uri); } } } protected final void endNamespaceMapping() throws SAXException { int count = this.fNamespaceContext.getDeclaredPrefixCount(); if (count > 0) for (int i = 0; i < count; i++) this.fContentHandler.endPrefixMapping(this.fNamespaceContext.getDeclaredPrefixAt(i)); } public void reset() throws XNIException { super.reset(); this.fInDTD = false; this.fNamespaces = this.fConfiguration.getFeature("http://xml.org/sax/features/namespaces"); this.fNamespacePrefixes = this.fConfiguration.getFeature("http://xml.org/sax/features/namespace-prefixes"); this.fAugmentations = null; this.fDeclaredAttrs = null; } protected static class LocatorProxy implements Locator { protected XMLLocator fLocator; public LocatorProxy(XMLLocator locator) { this.fLocator = locator; } public String getPublicId() { return this.fLocator.getPublicId(); } public String getSystemId() { return this.fLocator.getExpandedSystemId(); } public int getLineNumber() { return this.fLocator.getLineNumber(); } public int getColumnNumber() { return this.fLocator.getColumnNumber(); } } protected static final class AttributesProxy implements AttributeList, Attributes { protected XMLAttributes fAttributes; public void setAttributes(XMLAttributes attributes) { this.fAttributes = attributes; } public int getLength() { return this.fAttributes.getLength(); } public String getName(int i) { return this.fAttributes.getQName(i); } public String getQName(int index) { return this.fAttributes.getQName(index); } public String getURI(int index) { String uri = this.fAttributes.getURI(index); return (uri != null) ? uri : ""; } public String getLocalName(int index) { return this.fAttributes.getLocalName(index); } public String getType(int i) { return this.fAttributes.getType(i); } public String getType(String name) { return this.fAttributes.getType(name); } public String getType(String uri, String localName) { return uri.equals("") ? this.fAttributes.getType(null, localName) : this.fAttributes.getType(uri, localName); } public String getValue(int i) { return this.fAttributes.getValue(i); } public String getValue(String name) { return this.fAttributes.getValue(name); } public String getValue(String uri, String localName) { return uri.equals("") ? this.fAttributes.getValue(null, localName) : this.fAttributes.getValue(uri, localName); } public int getIndex(String qName) { return this.fAttributes.getIndex(qName); } public int getIndex(String uri, String localPart) { return uri.equals("") ? this.fAttributes.getIndex(null, localPart) : this.fAttributes.getIndex(uri, localPart); } } public ElementPSVI getElementPSVI() { return (this.fAugmentations != null) ? (ElementPSVI)this.fAugmentations.getItem("ELEMENT_PSVI") : null; } public AttributePSVI getAttributePSVI(int index) { return (AttributePSVI)this.fAttributesProxy.fAttributes.getAugmentations(index).getItem("ATTRIBUTE_PSVI"); } public AttributePSVI getAttributePSVIByName(String uri, String localname) { return (AttributePSVI)this.fAttributesProxy.fAttributes.getAugmentations(uri, localname).getItem("ATTRIBUTE_PSVI"); } }