content: /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You 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 mf.org.apache.xerces.parsers;
  
  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;
  
  import java.io.CharConversionException;
  import java.io.IOException;
  
  import mf.org.apache.xerces.dom.DOMMessageFormatter;
  import mf.org.apache.xerces.impl.Constants;
  import mf.org.apache.xerces.util.EntityResolver2Wrapper;
  import mf.org.apache.xerces.util.EntityResolverWrapper;
  import mf.org.apache.xerces.util.ErrorHandlerWrapper;
  import mf.org.apache.xerces.util.SAXMessageFormatter;
  import mf.org.apache.xerces.util.SymbolTable;
  import mf.org.apache.xerces.xni.XNIException;
  import mf.org.apache.xerces.xni.grammars.XMLGrammarPool;
  import mf.org.apache.xerces.xni.parser.XMLConfigurationException;
  import mf.org.apache.xerces.xni.parser.XMLEntityResolver;
  import mf.org.apache.xerces.xni.parser.XMLErrorHandler;
  import mf.org.apache.xerces.xni.parser.XMLInputSource;
  import mf.org.apache.xerces.xni.parser.XMLParseException;
  import mf.org.apache.xerces.xni.parser.XMLParserConfiguration;
  import mf.org.w3c.dom.Node;
  
  /**
   * 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 699892 2008-09-28 21:08:27Z mrglavas $
   */
  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;
  
      // 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.
       */
      //MF
      public DOMParser(SymbolTable symbolTable, XMLGrammarPool grammarPool) {
          super((XMLParserConfiguration) ObjectFactory.createObject(
                  "mf.org.apache.xerces.xni.parser.XMLParserConfiguration",
                  "mf.org.apache.xerces.parsers.XIncludeAwareParserConfiguration"
          ));
  
          // set properties
          fConfiguration.addRecognizedProperties(RECOGNIZED_PROPERTIES);
          if (symbolTable != null) {
              fConfiguration.setProperty(SYMBOL_TABLE, symbolTable);
          }
          if (grammarPool != null) {
              fConfiguration.setProperty(XMLGRAMMAR_POOL, grammarPool);
          }
  
      } // <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).
       * @throws org.xml.sax.SAXException Throws exception on SAX error.
       * @throws 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 || ex instanceof CharConversionException) {
                  // 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 (ex == null) ?
                          new SAXParseException(e.getMessage(), locatorImpl) :
                          new SAXParseException(e.getMessage(), locatorImpl, ex);
              }
              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
       * @throws org.xml.sax.SAXException
       * @throws 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 || ex instanceof CharConversionException) {
                  // 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 (ex == null) ?
                          new SAXParseException(e.getMessage(), locatorImpl) :
                          new SAXParseException(e.getMessage(), locatorImpl, ex);
              }
              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)
  
      /**
       * 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
  
      /**
       * 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 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
  
      /**
       * Allow an application to register an error event handler.
       * <p/>
       * <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/>
       * <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.
       * @throws 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)
  
      /**
       * 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).
       * @throws SAXNotRecognizedException If the
       *                                   requested feature is not known.
       * @throws 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() == XMLConfigurationException.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.
       * <p/>
       * 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.
       * @throws org.xml.sax.SAXNotRecognizedException If the
       *                                               requested feature is not known.
       * @throws 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() == XMLConfigurationException.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.
       * @throws SAXNotRecognizedException If the
       *                                   requested property is not known.
       * @throws SAXNotSupportedException  If the
       *                                   requested property is known, but the requested
       *                                   value is not supported.
       */
      public void setProperty(String propertyId, Object value)
              throws SAXNotRecognizedException, SAXNotSupportedException {
  
          try {
              fConfiguration.setProperty(propertyId, value);
          } catch (XMLConfigurationException e) {
              String identifier = e.getIdentifier();
              if (e.getType() == XMLConfigurationException.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.
       * <p/>
       * 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.
       * @throws org.xml.sax.SAXNotRecognizedException If the
       *                                               requested property is not known.
       * @throws 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(
                          DOMMessageFormatter.formatMessage(
                                  DOMMessageFormatter.DOM_DOMAIN,
                                  "CannotQueryDeferredNode", null));
              }
              return (fCurrentNode != null &&
                      fCurrentNode.getNodeType() == Node.ELEMENT_NODE) ? fCurrentNode : null;
          }
  
          try {
              return fConfiguration.getProperty(propertyId);
          } catch (XMLConfigurationException e) {
              String identifier = e.getIdentifier();
              if (e.getType() == XMLConfigurationException.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
  