| /* |
| * reserved comment block |
| * DO NOT REMOVE OR ALTER! |
| */ |
| /* |
| * Copyright 2000-2005 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.sun.org.apache.xerces.internal.parsers; |
| |
| import java.io.IOException; |
| |
| import com.sun.org.apache.xerces.internal.impl.Constants; |
| import com.sun.org.apache.xerces.internal.util.EntityResolverWrapper; |
| import com.sun.org.apache.xerces.internal.util.EntityResolver2Wrapper; |
| import com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper; |
| import com.sun.org.apache.xerces.internal.util.SAXMessageFormatter; |
| import com.sun.org.apache.xerces.internal.util.Status; |
| import com.sun.org.apache.xerces.internal.util.SymbolTable; |
| import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; |
| import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; |
| import com.sun.org.apache.xerces.internal.xni.XNIException; |
| import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool; |
| import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; |
| import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver; |
| import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler; |
| import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; |
| import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException; |
| import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration; |
| import org.w3c.dom.Node; |
| import org.xml.sax.EntityResolver; |
| import org.xml.sax.ErrorHandler; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.SAXNotRecognizedException; |
| import org.xml.sax.SAXNotSupportedException; |
| import org.xml.sax.SAXParseException; |
| import org.xml.sax.ext.EntityResolver2; |
| import org.xml.sax.helpers.LocatorImpl; |
| |
| /** |
| * This is the main Xerces DOM parser class. It uses the abstract DOM |
| * parser with a document scanner, a dtd scanner, and a validator, as |
| * well as a grammar pool. |
| * |
| * @author Arnaud Le Hors, IBM |
| * @author Andy Clark, IBM |
| * |
| * @version $Id: DOMParser.java,v 1.7 2010-11-01 04:40:09 joehw Exp $ |
| */ |
| public class DOMParser |
| extends AbstractDOMParser { |
| |
| // |
| // Constants |
| // |
| |
| // features |
| |
| /** Feature identifier: EntityResolver2. */ |
| protected static final String USE_ENTITY_RESOLVER2 = |
| Constants.SAX_FEATURE_PREFIX + Constants.USE_ENTITY_RESOLVER2_FEATURE; |
| |
| protected static final String REPORT_WHITESPACE = |
| Constants.SUN_SCHEMA_FEATURE_PREFIX + Constants.SUN_REPORT_IGNORED_ELEMENT_CONTENT_WHITESPACE; |
| |
| /** Property identifier: Security property manager. */ |
| private static final String XML_SECURITY_PROPERTY_MANAGER = |
| Constants.XML_SECURITY_PROPERTY_MANAGER; |
| |
| // recognized features: |
| private static final String[] RECOGNIZED_FEATURES = { |
| REPORT_WHITESPACE |
| }; |
| |
| // properties |
| |
| /** Property identifier: symbol table. */ |
| protected static final String SYMBOL_TABLE = |
| Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY; |
| |
| /** Property identifier: XML grammar pool. */ |
| protected static final String XMLGRAMMAR_POOL = |
| Constants.XERCES_PROPERTY_PREFIX+Constants.XMLGRAMMAR_POOL_PROPERTY; |
| |
| /** Recognized properties. */ |
| private static final String[] RECOGNIZED_PROPERTIES = { |
| SYMBOL_TABLE, |
| XMLGRAMMAR_POOL, |
| }; |
| |
| // |
| // Data |
| // |
| |
| // features |
| |
| /** Use EntityResolver2. */ |
| protected boolean fUseEntityResolver2 = true; |
| |
| // |
| // Constructors |
| // |
| |
| /** |
| * Constructs a DOM parser using the specified parser configuration. |
| */ |
| public DOMParser(XMLParserConfiguration config) { |
| super(config); |
| } // <init>(XMLParserConfiguration) |
| |
| /** |
| * Constructs a DOM parser using the dtd/xml schema parser configuration. |
| */ |
| public DOMParser() { |
| this(null, null); |
| } // <init>() |
| |
| /** |
| * Constructs a DOM parser using the specified symbol table. |
| */ |
| public DOMParser(SymbolTable symbolTable) { |
| this(symbolTable, null); |
| } // <init>(SymbolTable) |
| |
| |
| /** |
| * Constructs a DOM parser using the specified symbol table and |
| * grammar pool. |
| */ |
| public DOMParser(SymbolTable symbolTable, XMLGrammarPool grammarPool) { |
| super(new XIncludeAwareParserConfiguration()); |
| |
| // set properties |
| fConfiguration.addRecognizedProperties(RECOGNIZED_PROPERTIES); |
| if (symbolTable != null) { |
| fConfiguration.setProperty(SYMBOL_TABLE, symbolTable); |
| } |
| if (grammarPool != null) { |
| fConfiguration.setProperty(XMLGRAMMAR_POOL, grammarPool); |
| } |
| |
| fConfiguration.addRecognizedFeatures(RECOGNIZED_FEATURES); |
| |
| } // <init>(SymbolTable,XMLGrammarPool) |
| |
| // |
| // XMLReader methods |
| // |
| |
| /** |
| * Parses the input source specified by the given system identifier. |
| * <p> |
| * This method is equivalent to the following: |
| * <pre> |
| * parse(new InputSource(systemId)); |
| * </pre> |
| * |
| * @param systemId The system identifier (URI). |
| * |
| * @exception org.xml.sax.SAXException Throws exception on SAX error. |
| * @exception java.io.IOException Throws exception on i/o error. |
| */ |
| public void parse(String systemId) throws SAXException, IOException { |
| |
| // parse document |
| XMLInputSource source = new XMLInputSource(null, systemId, null); |
| try { |
| parse(source); |
| } |
| |
| // wrap XNI exceptions as SAX exceptions |
| catch (XMLParseException e) { |
| Exception ex = e.getException(); |
| if (ex == null) { |
| // must be a parser exception; mine it for locator info and throw |
| // a SAXParseException |
| 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) { |
| // why did we create an XMLParseException? |
| throw (SAXException)ex; |
| } |
| if (ex instanceof IOException) { |
| throw (IOException)ex; |
| } |
| throw new SAXException(ex); |
| } |
| catch (XNIException e) { |
| e.printStackTrace(); |
| 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); |
| } |
| |
| } // parse(String) |
| |
| /** |
| * parse |
| * |
| * @param inputSource |
| * |
| * @exception org.xml.sax.SAXException |
| * @exception java.io.IOException |
| */ |
| public void parse(InputSource inputSource) |
| throws SAXException, IOException { |
| |
| // parse document |
| try { |
| XMLInputSource xmlInputSource = |
| new XMLInputSource(inputSource.getPublicId(), |
| inputSource.getSystemId(), |
| null); |
| xmlInputSource.setByteStream(inputSource.getByteStream()); |
| xmlInputSource.setCharacterStream(inputSource.getCharacterStream()); |
| xmlInputSource.setEncoding(inputSource.getEncoding()); |
| parse(xmlInputSource); |
| } |
| |
| // wrap XNI exceptions as SAX exceptions |
| catch (XMLParseException e) { |
| Exception ex = e.getException(); |
| if (ex == null) { |
| // must be a parser exception; mine it for locator info and throw |
| // a SAXParseException |
| 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) { |
| // why did we create an XMLParseException? |
| 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); |
| } |
| |
| } // parse(InputSource) |
| |
| /** |
| * Sets the resolver used to resolve external entities. The EntityResolver |
| * interface supports resolution of public and system identifiers. |
| * |
| * @param resolver The new entity resolver. Passing a null value will |
| * uninstall the currently installed resolver. |
| */ |
| public void setEntityResolver(EntityResolver resolver) { |
| |
| try { |
| XMLEntityResolver xer = (XMLEntityResolver) fConfiguration.getProperty(ENTITY_RESOLVER); |
| if (fUseEntityResolver2 && resolver instanceof EntityResolver2) { |
| if (xer instanceof EntityResolver2Wrapper) { |
| EntityResolver2Wrapper er2w = (EntityResolver2Wrapper) xer; |
| er2w.setEntityResolver((EntityResolver2) resolver); |
| } |
| else { |
| fConfiguration.setProperty(ENTITY_RESOLVER, |
| new EntityResolver2Wrapper((EntityResolver2) resolver)); |
| } |
| } |
| else { |
| if (xer instanceof EntityResolverWrapper) { |
| EntityResolverWrapper erw = (EntityResolverWrapper) xer; |
| erw.setEntityResolver(resolver); |
| } |
| else { |
| fConfiguration.setProperty(ENTITY_RESOLVER, |
| new EntityResolverWrapper(resolver)); |
| } |
| } |
| } |
| catch (XMLConfigurationException e) { |
| // do nothing |
| } |
| |
| } // setEntityResolver(EntityResolver) |
| |
| /** |
| * Return the current entity resolver. |
| * |
| * @return The current entity resolver, or null if none |
| * has been registered. |
| * @see #setEntityResolver |
| */ |
| public EntityResolver getEntityResolver() { |
| |
| EntityResolver entityResolver = null; |
| try { |
| XMLEntityResolver xmlEntityResolver = |
| (XMLEntityResolver)fConfiguration.getProperty(ENTITY_RESOLVER); |
| if (xmlEntityResolver != null) { |
| if (xmlEntityResolver instanceof EntityResolverWrapper) { |
| entityResolver = |
| ((EntityResolverWrapper) xmlEntityResolver).getEntityResolver(); |
| } |
| else if (xmlEntityResolver instanceof EntityResolver2Wrapper) { |
| entityResolver = |
| ((EntityResolver2Wrapper) xmlEntityResolver).getEntityResolver(); |
| } |
| } |
| } |
| catch (XMLConfigurationException e) { |
| // do nothing |
| } |
| return entityResolver; |
| |
| } // getEntityResolver():EntityResolver |
| |
| /** |
| * Allow an application to register an error event handler. |
| * |
| * <p>If the application does not register an error handler, all |
| * error events reported by the SAX parser will be silently |
| * ignored; however, normal processing may not continue. It is |
| * highly recommended that all SAX applications implement an |
| * error handler to avoid unexpected bugs.</p> |
| * |
| * <p>Applications may register a new or different handler in the |
| * middle of a parse, and the SAX parser must begin using the new |
| * handler immediately.</p> |
| * |
| * @param errorHandler The error handler. |
| * @exception java.lang.NullPointerException If the handler |
| * argument is null. |
| * @see #getErrorHandler |
| */ |
| public void setErrorHandler(ErrorHandler errorHandler) { |
| |
| try { |
| XMLErrorHandler xeh = (XMLErrorHandler) fConfiguration.getProperty(ERROR_HANDLER); |
| if (xeh instanceof ErrorHandlerWrapper) { |
| ErrorHandlerWrapper ehw = (ErrorHandlerWrapper) xeh; |
| ehw.setErrorHandler(errorHandler); |
| } |
| else { |
| fConfiguration.setProperty(ERROR_HANDLER, |
| new ErrorHandlerWrapper(errorHandler)); |
| } |
| } |
| catch (XMLConfigurationException e) { |
| // do nothing |
| } |
| |
| } // setErrorHandler(ErrorHandler) |
| |
| /** |
| * Return the current error handler. |
| * |
| * @return The current error handler, or null if none |
| * has been registered. |
| * @see #setErrorHandler |
| */ |
| public ErrorHandler getErrorHandler() { |
| |
| ErrorHandler errorHandler = null; |
| try { |
| XMLErrorHandler xmlErrorHandler = |
| (XMLErrorHandler)fConfiguration.getProperty(ERROR_HANDLER); |
| if (xmlErrorHandler != null && |
| xmlErrorHandler instanceof ErrorHandlerWrapper) { |
| errorHandler = ((ErrorHandlerWrapper)xmlErrorHandler).getErrorHandler(); |
| } |
| } |
| catch (XMLConfigurationException e) { |
| // do nothing |
| } |
| return errorHandler; |
| |
| } // getErrorHandler():ErrorHandler |
| |
| /** |
| * Set the state of any feature in a SAX2 parser. The parser |
| * might not recognize the feature, and if it does recognize |
| * it, it might not be able to fulfill the request. |
| * |
| * @param featureId The unique identifier (URI) of the feature. |
| * @param state The requested state of the feature (true or false). |
| * |
| * @exception SAXNotRecognizedException If the |
| * requested feature is not known. |
| * @exception SAXNotSupportedException If the |
| * requested feature is known, but the requested |
| * state is not supported. |
| */ |
| public void setFeature(String featureId, boolean state) |
| throws SAXNotRecognizedException, SAXNotSupportedException { |
| |
| try { |
| |
| // http://xml.org/sax/features/use-entity-resolver2 |
| // controls whether the methods of an object implementing |
| // org.xml.sax.ext.EntityResolver2 will be used by the parser. |
| // |
| if (featureId.equals(USE_ENTITY_RESOLVER2)) { |
| if (state != fUseEntityResolver2) { |
| fUseEntityResolver2 = state; |
| // Refresh EntityResolver wrapper. |
| setEntityResolver(getEntityResolver()); |
| } |
| return; |
| } |
| |
| // |
| // Default handling |
| // |
| |
| fConfiguration.setFeature(featureId, state); |
| } |
| catch (XMLConfigurationException e) { |
| String identifier = e.getIdentifier(); |
| if (e.getType() == Status.NOT_RECOGNIZED) { |
| throw new SAXNotRecognizedException( |
| SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), |
| "feature-not-recognized", new Object [] {identifier})); |
| } |
| else { |
| throw new SAXNotSupportedException( |
| SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), |
| "feature-not-supported", new Object [] {identifier})); |
| } |
| } |
| |
| } // setFeature(String,boolean) |
| |
| /** |
| * Query the state of a feature. |
| * |
| * Query the current state of any feature in a SAX2 parser. The |
| * parser might not recognize the feature. |
| * |
| * @param featureId The unique identifier (URI) of the feature |
| * being set. |
| * @return The current state of the feature. |
| * @exception org.xml.sax.SAXNotRecognizedException If the |
| * requested feature is not known. |
| * @exception SAXNotSupportedException If the |
| * requested feature is known but not supported. |
| */ |
| public boolean getFeature(String featureId) |
| throws SAXNotRecognizedException, SAXNotSupportedException { |
| |
| try { |
| |
| // http://xml.org/sax/features/use-entity-resolver2 |
| // controls whether the methods of an object implementing |
| // org.xml.sax.ext.EntityResolver2 will be used by the parser. |
| // |
| if (featureId.equals(USE_ENTITY_RESOLVER2)) { |
| return fUseEntityResolver2; |
| } |
| |
| // |
| // Default handling |
| // |
| |
| return fConfiguration.getFeature(featureId); |
| } |
| catch (XMLConfigurationException e) { |
| String identifier = e.getIdentifier(); |
| if (e.getType() == Status.NOT_RECOGNIZED) { |
| throw new SAXNotRecognizedException( |
| SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), |
| "feature-not-recognized", new Object [] {identifier})); |
| } |
| else { |
| throw new SAXNotSupportedException( |
| SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), |
| "feature-not-supported", new Object [] {identifier})); |
| } |
| } |
| |
| } // getFeature(String):boolean |
| |
| /** |
| * Set the value of any property in a SAX2 parser. The parser |
| * might not recognize the property, and if it does recognize |
| * it, it might not support the requested value. |
| * |
| * @param propertyId The unique identifier (URI) of the property |
| * being set. |
| * @param value The value to which the property is being set. |
| * |
| * @exception SAXNotRecognizedException If the |
| * requested property is not known. |
| * @exception SAXNotSupportedException If the |
| * requested property is known, but the requested |
| * value is not supported. |
| */ |
| public void setProperty(String propertyId, Object value) |
| throws SAXNotRecognizedException, SAXNotSupportedException { |
| /** |
| * It's possible for users to set a security manager through the interface. |
| * If it's the old SecurityManager, convert it to the new XMLSecurityManager |
| */ |
| if (propertyId.equals(Constants.SECURITY_MANAGER)) { |
| securityManager = XMLSecurityManager.convert(value, securityManager); |
| setProperty0(Constants.SECURITY_MANAGER, securityManager); |
| return; |
| } |
| if (propertyId.equals(Constants.XML_SECURITY_PROPERTY_MANAGER)) { |
| if (value == null) { |
| securityPropertyManager = new XMLSecurityPropertyManager(); |
| } else { |
| securityPropertyManager = (XMLSecurityPropertyManager)value; |
| } |
| setProperty0(Constants.XML_SECURITY_PROPERTY_MANAGER, securityPropertyManager); |
| return; |
| } |
| |
| if (securityManager == null) { |
| securityManager = new XMLSecurityManager(true); |
| setProperty0(Constants.SECURITY_MANAGER, securityManager); |
| } |
| |
| if (securityPropertyManager == null) { |
| securityPropertyManager = new XMLSecurityPropertyManager(); |
| setProperty0(Constants.XML_SECURITY_PROPERTY_MANAGER, securityPropertyManager); |
| } |
| int index = securityPropertyManager.getIndex(propertyId); |
| |
| if (index > -1) { |
| /** |
| * this is a direct call to this parser, not a subclass since |
| * internally the support of this property is done through |
| * XMLSecurityPropertyManager |
| */ |
| securityPropertyManager.setValue(index, XMLSecurityPropertyManager.State.APIPROPERTY, (String)value); |
| } else { |
| //check if the property is managed by security manager |
| if (!securityManager.setLimit(propertyId, XMLSecurityManager.State.APIPROPERTY, value)) { |
| //fall back to the default configuration to handle the property |
| setProperty0(propertyId, value); |
| } |
| } |
| } |
| |
| public void setProperty0(String propertyId, Object value) |
| throws SAXNotRecognizedException, SAXNotSupportedException { |
| try { |
| fConfiguration.setProperty(propertyId, value); |
| } |
| catch (XMLConfigurationException e) { |
| String identifier = e.getIdentifier(); |
| if (e.getType() == Status.NOT_RECOGNIZED) { |
| throw new SAXNotRecognizedException( |
| SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), |
| "property-not-recognized", new Object [] {identifier})); |
| } |
| else { |
| throw new SAXNotSupportedException( |
| SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), |
| "property-not-supported", new Object [] {identifier})); |
| } |
| } |
| |
| } // setProperty(String,Object) |
| |
| /** |
| * Query the value of a property. |
| * |
| * Return the current value of a property in a SAX2 parser. |
| * The parser might not recognize the property. |
| * |
| * @param propertyId The unique identifier (URI) of the property |
| * being set. |
| * @return The current value of the property. |
| * @exception org.xml.sax.SAXNotRecognizedException If the |
| * requested property is not known. |
| * @exception SAXNotSupportedException If the |
| * requested property is known but not supported. |
| */ |
| public Object getProperty(String propertyId) |
| throws SAXNotRecognizedException, SAXNotSupportedException { |
| |
| if (propertyId.equals(CURRENT_ELEMENT_NODE)) { |
| boolean deferred = false; |
| try { |
| deferred = getFeature(DEFER_NODE_EXPANSION); |
| } |
| catch (XMLConfigurationException e){ |
| // ignore |
| } |
| if (deferred) { |
| throw new SAXNotSupportedException("Current element node cannot be queried when node expansion is deferred."); |
| } |
| return (fCurrentNode!=null && |
| fCurrentNode.getNodeType() == Node.ELEMENT_NODE)? fCurrentNode:null; |
| } |
| |
| try { |
| XMLSecurityPropertyManager spm = (XMLSecurityPropertyManager) |
| fConfiguration.getProperty(XML_SECURITY_PROPERTY_MANAGER); |
| int index = spm.getIndex(propertyId); |
| if (index > -1) { |
| return spm.getValueByIndex(index); |
| } |
| |
| return fConfiguration.getProperty(propertyId); |
| } |
| catch (XMLConfigurationException e) { |
| String identifier = e.getIdentifier(); |
| if (e.getType() == Status.NOT_RECOGNIZED) { |
| throw new SAXNotRecognizedException( |
| SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), |
| "property-not-recognized", new Object [] {identifier})); |
| } |
| else { |
| throw new SAXNotSupportedException( |
| SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), |
| "property-not-supported", new Object [] {identifier})); |
| } |
| } |
| |
| } // getProperty(String):Object |
| |
| /** |
| * Returns this parser's XMLParserConfiguration. |
| */ |
| public XMLParserConfiguration getXMLParserConfiguration() { |
| return fConfiguration; |
| } // getXMLParserConfiguration():XMLParserConfiguration |
| |
| } // class DOMParser |