content: /*
   * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Oracle in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   */
  
  // XMLReaderFactory.java - factory for creating a new reader.
  // http://www.saxproject.org
  // Written by David Megginson
  // and by David Brownell
  // NO WARRANTY!  This class is in the Public Domain.
  // $Id: XMLReaderFactory.java,v 1.2.2.1 2005/07/31 22:48:08 jeffsuttor Exp $
  
  package org.xml.sax.helpers;
  import java.io.BufferedReader;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import org.xml.sax.XMLReader;
  import org.xml.sax.SAXException;
  
  
  /**
   * Factory for creating an XML reader.
   *
   * <blockquote>
   * <em>This module, both source code and documentation, is in the
   * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
   * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
   * for further information.
   * </blockquote>
   *
   * <p>This class contains static methods for creating an XML reader
   * from an explicit class name, or based on runtime defaults:</p>
   *
   * <pre>
   * try {
   *   XMLReader myReader = XMLReaderFactory.createXMLReader();
   * } catch (SAXException e) {
   *   System.err.println(e.getMessage());
   * }
   * </pre>
   *
   * <p><strong>Note to Distributions bundled with parsers:</strong>
   * You should modify the implementation of the no-arguments
   * <em>createXMLReader</em> to handle cases where the external
   * configuration mechanisms aren't set up.  That method should do its
   * best to return a parser when one is in the class path, even when
   * nothing bound its class name to <code>org.xml.sax.driver</code> so
   * those configuration mechanisms would see it.</p>
   *
   * @since SAX 2.0
   * @author David Megginson, David Brownell
   * @version 2.0.1 (sax2r2)
   */
  final public class XMLReaderFactory
  {
      /**
       * Private constructor.
       *
       * <p>This constructor prevents the class from being instantiated.</p>
       */
      private XMLReaderFactory ()
      {
      }
  
      private static final String property = "org.xml.sax.driver";
      private static SecuritySupport ss = new SecuritySupport();
  
      private static String _clsFromJar = null;
      private static boolean _jarread = false;
      /**
       * Attempt to create an XMLReader from system defaults.
       * In environments which can support it, the name of the XMLReader
       * class is determined by trying each these options in order, and
       * using the first one which succeeds:</p> <ul>
       *
       * <li>If the system property <code>org.xml.sax.driver</code>
       * has a value, that is used as an XMLReader class name. </li>
       *
       * <li>The JAR "Services API" is used to look for a class name
       * in the <em>META-INF/services/org.xml.sax.driver</em> file in
       * jarfiles available to the runtime.</li>
       *
       * <li> SAX parser distributions are strongly encouraged to provide
       * a default XMLReader class name that will take effect only when
       * previous options (on this list) are not successful.</li>
       *
       * <li>Finally, if {@link org.xml.sax.helpers.ParserFactory#makeParser()} can
       * return a system default SAX1 parser, that parser is wrapped in
       * a {@link org.xml.sax.helpers.ParserAdapter}.  (This is a migration aid for SAX1
       * environments, where the <code>org.xml.sax.parser</code> system
       * property will often be usable.) </li>
       *
       * </ul>
       *
       * <p> In environments such as small embedded systems, which can not
       * support that flexibility, other mechanisms to determine the default
       * may be used. </p>
       *
       * <p>Note that many Java environments allow system properties to be
       * initialized on a command line.  This means that <em>in most cases</em>
       * setting a good value for that property ensures that calls to this
       * method will succeed, except when security policies intervene.
       * This will also maximize application portability to older SAX
       * environments, with less robust implementations of this method.
       * </p>
       *
       * @return A new XMLReader.
       * @exception org.xml.sax.SAXException If no default XMLReader class
       *            can be identified and instantiated.
       * @see #createXMLReader(java.lang.String)
       */
      public static XMLReader createXMLReader ()
          throws SAXException
      {
          String          className = null;
          ClassLoader     cl = ss.getContextClassLoader();
  
          // 1. try the JVM-instance-wide system property
          try {
              className = ss.getSystemProperty(property);
          }
          catch (RuntimeException e) { /* continue searching */ }
  
          // 2. if that fails, try META-INF/services/
          if (className == null) {
              if (!_jarread) {
                  _jarread = true;
                  String      service = "META-INF/services/" + property;
                  InputStream in;
                  BufferedReader      reader;
  
                  try {
                      if (cl != null) {
                          in = ss.getResourceAsStream(cl, service);
  
                          // If no provider found then try the current ClassLoader
                          if (in == null) {
                              cl = null;
                              in = ss.getResourceAsStream(cl, service);
                          }
                      } else {
                          // No Context ClassLoader, try the current ClassLoader
                          in = ss.getResourceAsStream(cl, service);
                      }
  
                      if (in != null) {
                          reader = new BufferedReader (new InputStreamReader (in, "UTF8"));
                          _clsFromJar = reader.readLine ();
                          in.close ();
                      }
                  } catch (Exception e) {
                  }
              }
              className = _clsFromJar;
          }
  
          // 3. Distro-specific fallback
          if (className == null) {
  // BEGIN DISTRIBUTION-SPECIFIC
  
              // EXAMPLE:
              // className = "com.example.sax.XmlReader";
              // or a $JAVA_HOME/jre/lib/*properties setting...
              className = "com.sun.org.apache.xerces.internal.parsers.SAXParser";
  
  // END DISTRIBUTION-SPECIFIC
          }
  
          // do we know the XMLReader implementation class yet?
          if (className != null)
              return loadClass (cl, className);
  
          // 4. panic -- adapt any SAX1 parser
          try {
              return new ParserAdapter(ParserFactory.makeParser ());
          } catch (Exception e) {
              throw new SAXException ("Can't create default XMLReader; "
                      + "is system property org.xml.sax.driver set?");
          }
      }
  
  
      /**
       * Attempt to create an XML reader from a class name.
       *
       * <p>Given a class name, this method attempts to load
       * and instantiate the class as an XML reader.</p>
       *
       * <p>Note that this method will not be usable in environments where
       * the caller (perhaps an applet) is not permitted to load classes
       * dynamically.</p>
       *
       * @return A new XML reader.
       * @exception org.xml.sax.SAXException If the class cannot be
       *            loaded, instantiated, and cast to XMLReader.
       * @see #createXMLReader()
       */
      public static XMLReader createXMLReader (String className)
          throws SAXException
      {
          return loadClass (ss.getContextClassLoader(), className);
      }
  
      private static XMLReader loadClass (ClassLoader loader, String className)
      throws SAXException
      {
          try {
              return (XMLReader) NewInstance.newInstance (loader, className);
          } catch (ClassNotFoundException e1) {
              throw new SAXException("SAX2 driver class " + className +
                                     " not found", e1);
          } catch (IllegalAccessException e2) {
              throw new SAXException("SAX2 driver class " + className +
                                     " found but cannot be loaded", e2);
          } catch (InstantiationException e3) {
              throw new SAXException("SAX2 driver class " + className +
             " loaded but cannot be instantiated (no empty public constructor?)",
                                     e3);
          } catch (ClassCastException e4) {
              throw new SAXException("SAX2 driver class " + className +
                                     " does not implement XMLReader", e4);
          }
      }
  }
  