19f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/*
29f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one
39f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * or more contributor license agreements. See the NOTICE file
49f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed with this work for additional information
59f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * regarding copyright ownership. The ASF licenses this file
69f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * to you under the Apache License, Version 2.0 (the  "License");
79f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * you may not use this file except in compliance with the License.
89f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * You may obtain a copy of the License at
99f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *     http://www.apache.org/licenses/LICENSE-2.0
119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Unless required by applicable law or agreed to in writing, software
139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * See the License for the specific language governing permissions and
169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * limitations under the License.
179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/*
199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * $Id$
209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpackage org.apache.xml.utils;
239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport java.io.InputStream;
259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport java.io.IOException;
269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport java.io.File;
279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport java.io.FileInputStream;
289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport java.util.Properties;
309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport java.io.BufferedReader;
319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport java.io.InputStreamReader;
329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/**
349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * This class is duplicated for each JAXP subpackage so keep it in sync.
359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * It is package private and therefore is not exposed as part of the JAXP
369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * API.
379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * <p>
389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * This code is designed to implement the JAXP 1.1 spec pluggability
399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * feature and is designed to run on JDK version 1.1 and
409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * later, and to compile on JDK 1.2 and onward.
419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * The code also runs both as part of an unbundled jar file and
429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * when bundled as part of the JDK.
439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * <p>
449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * This class was moved from the <code>javax.xml.parsers.ObjectFactory</code>
459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * class and modified to be used as a general utility for creating objects
469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * dynamically.
479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @version $Id:  $
499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonclass ObjectFactory {
519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //
539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Constants
549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //
559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // name of default properties file to look for in JDK's jre/lib directory
579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    private static final String DEFAULT_PROPERTIES_FILENAME =
589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                                     "xalan.properties";
599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    private static final String SERVICES_PATH = "META-INF/services/";
619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /** Set to true for debugging */
639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    private static final boolean DEBUG = false;
649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /** cache the contents of the xalan.properties file.
669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  Until an attempt has been made to read this file, this will
679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * be null; if the file does not exist or we encounter some other error
689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * during the read, this will be empty.
699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     */
709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    private static Properties fXalanProperties = null;
719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /***
739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * Cache the time stamp of the xalan.properties file so
749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * that we know if it's been modified and can invalidate
759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * the cache when necessary.
769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     */
779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    private static long fLastModified = -1;
789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //
809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Public static methods
819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //
829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /**
849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * Finds the implementation Class object in the specified order.  The
859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * specified order is the following:
869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * <ol>
879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  <li>query the system property using <code>System.getProperty</code>
889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  <li>read <code>META-INF/services/<i>factoryId</i></code> file
899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  <li>use fallback classname
909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * </ol>
919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *
929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @return instance of factory, never null
939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *
949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @param factoryId             Name of the factory to find, same as
959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *                              a property name
969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @param fallbackClassName     Implementation class name, if nothing else
979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *                              is found.  Use null to mean no fallback.
989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *
999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @exception ObjectFactory.ConfigurationError
1009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     */
1019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    static Object createObject(String factoryId, String fallbackClassName)
1029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        throws ConfigurationError {
1039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        return createObject(factoryId, null, fallbackClassName);
1049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    } // createObject(String,String):Object
1059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /**
1079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * Finds the implementation Class object in the specified order.  The
1089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * specified order is the following:
1099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * <ol>
1109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  <li>query the system property using <code>System.getProperty</code>
1119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file
1129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  <li>read <code>META-INF/services/<i>factoryId</i></code> file
1139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  <li>use fallback classname
1149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * </ol>
1159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *
1169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @return instance of factory, never null
1179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *
1189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @param factoryId             Name of the factory to find, same as
1199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *                              a property name
1209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @param propertiesFilename The filename in the $java.home/lib directory
1219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *                           of the properties file.  If none specified,
1229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *                           ${java.home}/lib/xalan.properties will be used.
1239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @param fallbackClassName     Implementation class name, if nothing else
1249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *                              is found.  Use null to mean no fallback.
1259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *
1269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @exception ObjectFactory.ConfigurationError
1279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     */
1289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    static Object createObject(String factoryId,
1299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                      String propertiesFilename,
1309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                      String fallbackClassName)
1319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        throws ConfigurationError
1329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
1339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        Class factoryClass = lookUpFactoryClass(factoryId,
1349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                                propertiesFilename,
1359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                                fallbackClassName);
1369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (factoryClass == null) {
1389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            throw new ConfigurationError(
1399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                "Provider for " + factoryId + " cannot be found", null);
1409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
1419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        try{
1439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            Object instance = factoryClass.newInstance();
1449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            debugPrintln("created new instance of factory " + factoryId);
1459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            return instance;
1469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        } catch (Exception x) {
1479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            throw new ConfigurationError(
1489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                "Provider for factory " + factoryId
1499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    + " could not be instantiated: " + x, x);
1509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
1519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    } // createObject(String,String,String):Object
1529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /**
1549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * Finds the implementation Class object in the specified order.  The
1559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * specified order is the following:
1569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * <ol>
1579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  <li>query the system property using <code>System.getProperty</code>
1589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file
1599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  <li>read <code>META-INF/services/<i>factoryId</i></code> file
1609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  <li>use fallback classname
1619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * </ol>
1629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *
1639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @return Class object of factory, never null
1649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *
1659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @param factoryId             Name of the factory to find, same as
1669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *                              a property name
1679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @param propertiesFilename The filename in the $java.home/lib directory
1689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *                           of the properties file.  If none specified,
1699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *                           ${java.home}/lib/xalan.properties will be used.
1709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @param fallbackClassName     Implementation class name, if nothing else
1719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *                              is found.  Use null to mean no fallback.
1729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *
1739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @exception ObjectFactory.ConfigurationError
1749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     */
1759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    static Class lookUpFactoryClass(String factoryId)
1769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        throws ConfigurationError
1779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
1789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        return lookUpFactoryClass(factoryId, null, null);
1799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    } // lookUpFactoryClass(String):Class
1809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /**
1829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * Finds the implementation Class object in the specified order.  The
1839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * specified order is the following:
1849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * <ol>
1859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  <li>query the system property using <code>System.getProperty</code>
1869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file
1879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  <li>read <code>META-INF/services/<i>factoryId</i></code> file
1889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  <li>use fallback classname
1899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * </ol>
1909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *
1919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @return Class object that provides factory service, never null
1929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *
1939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @param factoryId             Name of the factory to find, same as
1949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *                              a property name
1959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @param propertiesFilename The filename in the $java.home/lib directory
1969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *                           of the properties file.  If none specified,
1979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *                           ${java.home}/lib/xalan.properties will be used.
1989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @param fallbackClassName     Implementation class name, if nothing else
1999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *                              is found.  Use null to mean no fallback.
2009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *
2019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @exception ObjectFactory.ConfigurationError
2029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     */
2039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    static Class lookUpFactoryClass(String factoryId,
2049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                           String propertiesFilename,
2059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                           String fallbackClassName)
2069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        throws ConfigurationError
2079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
2089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        String factoryClassName = lookUpFactoryClassName(factoryId,
2099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                                         propertiesFilename,
2109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                                         fallbackClassName);
2119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        ClassLoader cl = findClassLoader();
2129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (factoryClassName == null) {
2149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            factoryClassName = fallbackClassName;
2159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
2169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // assert(className != null);
2189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        try{
2199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            Class providerClass = findProviderClass(factoryClassName,
2209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                                    cl,
2219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                                    true);
2229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            debugPrintln("created new instance of " + providerClass +
2239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                   " using ClassLoader: " + cl);
2249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            return providerClass;
2259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        } catch (ClassNotFoundException x) {
2269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            throw new ConfigurationError(
2279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                "Provider " + factoryClassName + " not found", x);
2289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        } catch (Exception x) {
2299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            throw new ConfigurationError(
2309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                "Provider "+factoryClassName+" could not be instantiated: "+x,
2319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                x);
2329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
2339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    } // lookUpFactoryClass(String,String,String):Class
2349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /**
2369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * Finds the name of the required implementation class in the specified
2379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * order.  The specified order is the following:
2389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * <ol>
2399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  <li>query the system property using <code>System.getProperty</code>
2409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file
2419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  <li>read <code>META-INF/services/<i>factoryId</i></code> file
2429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *  <li>use fallback classname
2439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * </ol>
2449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *
2459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @return name of class that provides factory service, never null
2469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *
2479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @param factoryId             Name of the factory to find, same as
2489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *                              a property name
2499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @param propertiesFilename The filename in the $java.home/lib directory
2509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *                           of the properties file.  If none specified,
2519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *                           ${java.home}/lib/xalan.properties will be used.
2529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @param fallbackClassName     Implementation class name, if nothing else
2539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *                              is found.  Use null to mean no fallback.
2549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *
2559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @exception ObjectFactory.ConfigurationError
2569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     */
2579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    static String lookUpFactoryClassName(String factoryId,
2589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                                String propertiesFilename,
2599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                                String fallbackClassName)
2609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
2619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        SecuritySupport ss = SecuritySupport.getInstance();
2629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // Use the system property first
2649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        try {
2659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            String systemProp = ss.getSystemProperty(factoryId);
2669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            if (systemProp != null) {
2679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                debugPrintln("found system property, value=" + systemProp);
2689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                return systemProp;
2699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            }
2709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        } catch (SecurityException se) {
2719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // Ignore and continue w/ next location
2729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
2739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // Try to read from propertiesFilename, or
2759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // $java.home/lib/xalan.properties
2769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        String factoryClassName = null;
2779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // no properties file name specified; use
2789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // $JAVA_HOME/lib/xalan.properties:
2799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (propertiesFilename == null) {
2809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            File propertiesFile = null;
2819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            boolean propertiesFileExists = false;
2829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            try {
2839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                String javah = ss.getSystemProperty("java.home");
2849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                propertiesFilename = javah + File.separator +
2859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    "lib" + File.separator + DEFAULT_PROPERTIES_FILENAME;
2869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                propertiesFile = new File(propertiesFilename);
2879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                propertiesFileExists = ss.getFileExists(propertiesFile);
2889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            } catch (SecurityException e) {
2899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // try again...
2909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                fLastModified = -1;
2919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                fXalanProperties = null;
2929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            }
2939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            synchronized (ObjectFactory.class) {
2959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                boolean loadProperties = false;
2969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                FileInputStream fis = null;
2979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                try {
2989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    // file existed last time
2999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    if(fLastModified >= 0) {
3009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        if(propertiesFileExists &&
3019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                (fLastModified < (fLastModified = ss.getLastModified(propertiesFile)))) {
3029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                            loadProperties = true;
3039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        } else {
3049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                            // file has stopped existing...
3059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                            if(!propertiesFileExists) {
3069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                fLastModified = -1;
3079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                fXalanProperties = null;
3089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                            } // else, file wasn't modified!
3099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        }
3109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    } else {
3119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        // file has started to exist:
3129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        if(propertiesFileExists) {
3139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                            loadProperties = true;
3149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                            fLastModified = ss.getLastModified(propertiesFile);
3159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        } // else, nothing's changed
3169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    }
3179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    if(loadProperties) {
3189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        // must never have attempted to read xalan.properties
3199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        // before (or it's outdeated)
3209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        fXalanProperties = new Properties();
3219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        fis = ss.getFileInputStream(propertiesFile);
3229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        fXalanProperties.load(fis);
3239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    }
3249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	        } catch (Exception x) {
3259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	            fXalanProperties = null;
3269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	            fLastModified = -1;
3279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    // assert(x instanceof FileNotFoundException
3289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	            //        || x instanceof SecurityException)
3299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	            // In both cases, ignore and continue w/ next location
3309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson	        }
3319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                finally {
3329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    // try to close the input stream if one was opened.
3339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    if (fis != null) {
3349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        try {
3359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                            fis.close();
3369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        }
3379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        // Ignore the exception.
3389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        catch (IOException exc) {}
3399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    }
3409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                }
3419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            }
3429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            if(fXalanProperties != null) {
3439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                factoryClassName = fXalanProperties.getProperty(factoryId);
3449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            }
3459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        } else {
3469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            FileInputStream fis = null;
3479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            try {
3489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                fis = ss.getFileInputStream(new File(propertiesFilename));
3499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                Properties props = new Properties();
3509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                props.load(fis);
3519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                factoryClassName = props.getProperty(factoryId);
3529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            } catch (Exception x) {
3539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // assert(x instanceof FileNotFoundException
3549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                //        || x instanceof SecurityException)
3559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // In both cases, ignore and continue w/ next location
3569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            }
3579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            finally {
3589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // try to close the input stream if one was opened.
3599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                if (fis != null) {
3609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    try {
3619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        fis.close();
3629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    }
3639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    // Ignore the exception.
3649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    catch (IOException exc) {}
3659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                }
3669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            }
3679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
3689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (factoryClassName != null) {
3699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            debugPrintln("found in " + propertiesFilename + ", value="
3709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                          + factoryClassName);
3719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            return factoryClassName;
3729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
3739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // Try Jar Service Provider Mechanism
3759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        return findJarServiceProviderName(factoryId);
3769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    } // lookUpFactoryClass(String,String):String
3779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //
3799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Private static methods
3809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //
3819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /** Prints a message to standard error if debugging is enabled. */
3839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    private static void debugPrintln(String msg) {
3849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (DEBUG) {
3859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            System.err.println("JAXP: " + msg);
3869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
3879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    } // debugPrintln(String)
3889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /**
3909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * Figure out which ClassLoader to use.  For JDK 1.2 and later use
3919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * the context ClassLoader.
3929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     */
3939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    static ClassLoader findClassLoader()
3949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        throws ConfigurationError
3959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
3969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        SecuritySupport ss = SecuritySupport.getInstance();
3979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // Figure out which ClassLoader to use for loading the provider
3999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // class.  If there is a Context ClassLoader then use it.
4009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        ClassLoader context = ss.getContextClassLoader();
4019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        ClassLoader system = ss.getSystemClassLoader();
4029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        ClassLoader chain = system;
4049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        while (true) {
4059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            if (context == chain) {
4069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // Assert: we are on JDK 1.1 or we have no Context ClassLoader
4079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // or any Context ClassLoader in chain of system classloader
4089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // (including extension ClassLoader) so extend to widest
4099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // ClassLoader (always look in system ClassLoader if Xalan
4109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // is in boot/extension/system classpath and in current
4119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // ClassLoader otherwise); normal classloaders delegate
4129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // back to system ClassLoader first so this widening doesn't
4139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // change the fact that context ClassLoader will be consulted
4149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                ClassLoader current = ObjectFactory.class.getClassLoader();
4159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                chain = system;
4179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                while (true) {
4189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    if (current == chain) {
4199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        // Assert: Current ClassLoader in chain of
4209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        // boot/extension/system ClassLoaders
4219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        return system;
4229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    }
4239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    if (chain == null) {
4249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        break;
4259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    }
4269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    chain = ss.getParentClassLoader(chain);
4279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                }
4289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // Assert: Current ClassLoader not in chain of
4309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // boot/extension/system ClassLoaders
4319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                return current;
4329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            }
4339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            if (chain == null) {
4359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // boot ClassLoader reached
4369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                break;
4379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            }
4389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // Check for any extension ClassLoaders in chain up to
4409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // boot ClassLoader
4419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            chain = ss.getParentClassLoader(chain);
4429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        };
4439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // Assert: Context ClassLoader not in chain of
4459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // boot/extension/system ClassLoaders
4469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        return context;
4479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    } // findClassLoader():ClassLoader
4489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /**
4509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * Create an instance of a class using the specified ClassLoader
4519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     */
4529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    static Object newInstance(String className, ClassLoader cl,
4539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                      boolean doFallback)
4549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        throws ConfigurationError
4559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
4569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // assert(className != null);
4579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        try{
4589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            Class providerClass = findProviderClass(className, cl, doFallback);
4599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            Object instance = providerClass.newInstance();
4609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            debugPrintln("created new instance of " + providerClass +
4619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                   " using ClassLoader: " + cl);
4629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            return instance;
4639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        } catch (ClassNotFoundException x) {
4649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            throw new ConfigurationError(
4659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                "Provider " + className + " not found", x);
4669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        } catch (Exception x) {
4679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            throw new ConfigurationError(
4689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                "Provider " + className + " could not be instantiated: " + x,
4699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                x);
4709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
4719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
4729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /**
4749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * Find a Class using the specified ClassLoader
4759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     */
4769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    static Class findProviderClass(String className, ClassLoader cl,
4779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                           boolean doFallback)
4789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        throws ClassNotFoundException, ConfigurationError
4799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
4809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        //throw security exception if the calling thread is not allowed to access the
4819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        //class. Restrict the access to the package classes as specified in java.security policy.
4829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        SecurityManager security = System.getSecurityManager();
4839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        try{
4849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                if (security != null){
4859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    final int lastDot = className.lastIndexOf(".");
4869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    String packageName = className;
4879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    if (lastDot != -1) packageName = className.substring(0, lastDot);
4889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    security.checkPackageAccess(packageName);
4899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                 }
4909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }catch(SecurityException e){
4919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            throw e;
4929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
4939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        Class providerClass;
4959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (cl == null) {
4969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // XXX Use the bootstrap ClassLoader.  There is no way to
4979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // load a class using the bootstrap ClassLoader that works
4989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // in both JDK 1.1 and Java 2.  However, this should still
4999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // work b/c the following should be true:
5009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            //
5019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // (cl == null) iff current ClassLoader == null
5029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            //
5039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // Thus Class.forName(String) will use the current
5049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // ClassLoader which will be the bootstrap ClassLoader.
5059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            providerClass = Class.forName(className);
5069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        } else {
5079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            try {
5089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                providerClass = cl.loadClass(className);
5099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            } catch (ClassNotFoundException x) {
5109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                if (doFallback) {
5119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    // Fall back to current classloader
5129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    ClassLoader current = ObjectFactory.class.getClassLoader();
5139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    if (current == null) {
5149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        providerClass = Class.forName(className);
5159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    } else if (cl != current) {
5169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        cl = current;
5179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        providerClass = cl.loadClass(className);
5189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    } else {
5199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                        throw x;
5209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    }
5219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                } else {
5229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                    throw x;
5239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                }
5249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            }
5259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
5269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        return providerClass;
5289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
5299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /**
5319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * Find the name of service provider using Jar Service Provider Mechanism
5329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     *
5339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * @return instance of provider class if found or null
5349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     */
5359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    private static String findJarServiceProviderName(String factoryId)
5369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
5379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        SecuritySupport ss = SecuritySupport.getInstance();
5389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        String serviceId = SERVICES_PATH + factoryId;
5399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        InputStream is = null;
5409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // First try the Context ClassLoader
5429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        ClassLoader cl = findClassLoader();
5439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        is = ss.getResourceAsStream(cl, serviceId);
5459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // If no provider found then try the current ClassLoader
5479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (is == null) {
5489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            ClassLoader current = ObjectFactory.class.getClassLoader();
5499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            if (cl != current) {
5509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                cl = current;
5519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                is = ss.getResourceAsStream(cl, serviceId);
5529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            }
5539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
5549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (is == null) {
5569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // No provider found
5579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            return null;
5589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
5599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        debugPrintln("found jar resource=" + serviceId +
5619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson               " using ClassLoader: " + cl);
5629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // Read the service provider name in UTF-8 as specified in
5649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // the jar spec.  Unfortunately this fails in Microsoft
5659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // VJ++, which does not implement the UTF-8
5669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // encoding. Theoretically, we should simply let it fail in
5679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // that case, since the JVM is obviously broken if it
5689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // doesn't support such a basic standard.  But since there
5699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // are still some users attempting to use VJ++ for
5709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // development, we have dropped in a fallback which makes a
5719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // second attempt using the platform's default encoding. In
5729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // VJ++ this is apparently ASCII, which is a subset of
5739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // UTF-8... and since the strings we'll be reading here are
5749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // also primarily limited to the 7-bit ASCII range (at
5759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // least, in English versions), this should work well
5769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // enough to keep us on the air until we're ready to
5779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // officially decommit from VJ++. [Edited comment from
5789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // jkesselm]
5799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        BufferedReader rd;
5809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        try {
5819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
5829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        } catch (java.io.UnsupportedEncodingException e) {
5839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            rd = new BufferedReader(new InputStreamReader(is));
5849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
5859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        String factoryClassName = null;
5879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        try {
5889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // XXX Does not handle all possible input as specified by the
5899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // Jar Service Provider specification
5909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            factoryClassName = rd.readLine();
5919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        } catch (IOException x) {
5929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // No provider found
5939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            return null;
5949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
5959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        finally {
5969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            try {
5979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // try to close the reader.
5989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                rd.close();
5999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            }
6009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // Ignore the exception.
6019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            catch (IOException exc) {}
6029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
6039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (factoryClassName != null &&
6059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            ! "".equals(factoryClassName)) {
6069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            debugPrintln("found in resource, value="
6079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                   + factoryClassName);
6089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // Note: here we do not want to fall back to the current
6109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // ClassLoader because we want to avoid the case where the
6119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // resource file was found using one ClassLoader and the
6129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            // provider class was instantiated using a different one.
6139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            return factoryClassName;
6149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
6159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // No provider found
6179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        return null;
6189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
6199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //
6219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Classes
6229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    //
6239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /**
6259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     * A configuration error.
6269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson     */
6279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    static class ConfigurationError
6289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        extends Error {
6299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                static final long serialVersionUID = 2036619216663421552L;
6309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        //
6319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // Data
6329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        //
6339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        /** Exception. */
6359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        private Exception exception;
6369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        //
6389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // Constructors
6399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        //
6409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        /**
6429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson         * Construct a new instance with the specified detail string and
6439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson         * exception.
6449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson         */
6459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        ConfigurationError(String msg, Exception x) {
6469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            super(msg);
6479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            this.exception = x;
6489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        } // <init>(String,Exception)
6499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        //
6519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        // Public methods
6529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        //
6539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        /** Returns the exception associated to this error. */
6559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        Exception getException() {
6569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            return exception;
6579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        } // getException():Exception
6589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    } // class ConfigurationError
6609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
6619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} // class ObjectFactory
662