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