FactoryFinder.java revision d21d78fd49a2d798218e8c8aefbddb26a0e71bbb
1320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson/* 2320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one or more 3320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * contributor license agreements. See the NOTICE file distributed with 4320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * this work for additional information regarding copyright ownership. 5320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * The ASF licenses this file to You under the Apache License, Version 2.0 6320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * (the "License"); you may not use this file except in compliance with 7320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * the License. You may obtain a copy of the License at 8320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * 9320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 10320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * 11320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * Unless required by applicable law or agreed to in writing, software 12320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 13320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * See the License for the specific language governing permissions and 15320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * limitations under the License. 16320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson */ 17320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 18320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson// $Id: FactoryFinder.java 670432 2008-06-23 02:02:08Z mrglavas $ 19320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 20320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilsonpackage javax.xml.datatype; 21320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 22320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilsonimport java.io.BufferedReader; 23320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilsonimport java.io.File; 24320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilsonimport java.io.IOException; 25320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilsonimport java.io.InputStream; 26320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilsonimport java.io.InputStreamReader; 27320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilsonimport java.net.URL; 28320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilsonimport java.util.Properties; 29320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 30320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson/** 31320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * <p>Implement pluggabile Datatypes.</p> 32320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * 33320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * <p>This class is duplicated for each JAXP subpackage so keep it in 34320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * sync. It is package private for secure class loading.</p> 35320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * 36320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * @author <a href="mailto:Jeff.Suttor@Sun.com">Jeff Suttor</a> 37320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * @version $Revision: 670432 $, $Date: 2008-06-22 19:02:08 -0700 (Sun, 22 Jun 2008) $ 38320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * @since 1.5 39320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson */ 40320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilsonfinal class FactoryFinder { 41d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes 42d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes /** 43d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes * <p>Name of class to display in output messages.</p> 44d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes */ 45d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes private static final String CLASS_NAME = "javax.xml.datatype.FactoryFinder"; 46d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes 47320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson /** 48320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * <p>Debug flag to trace loading process.</p> 49320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson */ 50320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson private static boolean debug = false; 51320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 52320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson /** 53320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * <p>Cache properties for performance.</p> 54320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson */ 55d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes private static Properties cacheProps = new Properties(); 56d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes 57d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes /** 58d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes * <p>First time requires initialization overhead.</p> 59d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes */ 60d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes private static boolean firstTime = true; 61320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 62320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson /** 63320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * Default columns per line. 64320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson */ 65320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson private static final int DEFAULT_LINE_LENGTH = 80; 66d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes 67d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes /** 68d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes * <p>Check to see if debugging enabled by property.</p> 69d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes * 70d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes * <p>Use try/catch block to support applets, which throws 71320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * SecurityException out of this code.</p> 72d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes * 73d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes */ 74320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson static { 75320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson try { 76320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson String val = SecuritySupport.getSystemProperty("jaxp.debug"); 77320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // Allow simply setting the prop to turn on debug 78320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson debug = val != null && (! "false".equals(val)); 79320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } catch (Exception x) { 80320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson debug = false; 81320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 82320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 83320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 84320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson private FactoryFinder() {} 85320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 86d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes /** 87d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes * <p>Output debugging messages.</p> 88d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes * 89d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes * @param msg <code>String</code> to print to <code>stderr</code>. 90d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes */ 91320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson private static void debugPrintln(String msg) { 92320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (debug) { 93320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson System.err.println( 94d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes CLASS_NAME 95d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes + ":" 96d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes + msg); 97320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 98320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 99320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 100320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson /** 101320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * <p>Find the appropriate <code>ClassLoader</code> to use.</p> 102320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * 103320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * <p>The context ClassLoader is prefered.</p> 104320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * 105320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * @return <code>ClassLoader</code> to use. 106320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * 107320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * @throws ConfigurationError If a valid <code>ClassLoader</code> cannot be identified. 108320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson */ 109320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson private static ClassLoader findClassLoader() 110320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson throws ConfigurationError { 111320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson ClassLoader classLoader; 112320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 113320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // Figure out which ClassLoader to use for loading the provider 114320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // class. If there is a Context ClassLoader then use it. 115320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 116320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson classLoader = SecuritySupport.getContextClassLoader(); 117320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 118320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (debug) debugPrintln( 119320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson "Using context class loader: " 120320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson + classLoader); 121320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 122320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (classLoader == null) { 123320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // if we have no Context ClassLoader 124320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // so use the current ClassLoader 125320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson classLoader = FactoryFinder.class.getClassLoader(); 126320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (debug) debugPrintln( 127320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson "Using the class loader of FactoryFinder: " 128320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson + classLoader); 129320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 130320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 131320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson return classLoader; 132320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 133320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 134320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson /** 135320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * <p>Create an instance of a class using the specified ClassLoader.</p> 136320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * 137320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * @param className Name of class to create. 138320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * @param classLoader ClassLoader to use to create named class. 139320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * 140320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * @return New instance of specified class created using the specified ClassLoader. 141320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * 142320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * @throws ConfigurationError If class could not be created. 143320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson */ 144320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson static Object newInstance( 145d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes String className, 146320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson ClassLoader classLoader) 147320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson throws ConfigurationError { 148d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes 149320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson try { 150320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson Class spiClass; 151320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (classLoader == null) { 152320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson spiClass = Class.forName(className); 153320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } else { 154320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson spiClass = classLoader.loadClass(className); 155320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 156320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 157320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (debug) { 158d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes debugPrintln("Loaded " + className + " from " + which(spiClass)); 159320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 160320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 161320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson return spiClass.newInstance(); 162320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } catch (ClassNotFoundException x) { 163320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson throw new ConfigurationError( 164320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson "Provider " + className + " not found", x); 165320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } catch (Exception x) { 166320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson throw new ConfigurationError( 167320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson "Provider " + className + " could not be instantiated: " + x, 168320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson x); 169320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 170320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 171320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 172320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson /** 173320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * Finds the implementation Class object in the specified order. Main 174320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * entry point. 175320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * Package private so this code can be shared. 176320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * 177320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * @param factoryId Name of the factory to find, same as a property name 178320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * @param fallbackClassName Implementation class name, if nothing else is found. Use null to mean no fallback. 179320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * 180320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * @return Class Object of factory, never null 181320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * 182320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * @throws ConfigurationError If Class cannot be found. 183320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson */ 184320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson static Object find(String factoryId, String fallbackClassName) 185320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson throws ConfigurationError { 186d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes 187320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson ClassLoader classLoader = findClassLoader(); 188320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 189320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // Use the system property first 190320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson try { 191320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson String systemProp = SecuritySupport.getSystemProperty(factoryId); 192320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (systemProp != null && systemProp.length() > 0) { 193320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (debug) debugPrintln("found " + systemProp + " in the system property " + factoryId); 194320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson return newInstance(systemProp, classLoader); 195320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 196320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } catch (SecurityException se) { 197d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes ; // NOP, explicitly ignore SecurityException 198320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 199320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 200320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // try to read from $java.home/lib/jaxp.properties 201320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson try { 202320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson String javah = SecuritySupport.getSystemProperty("java.home"); 203320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson String configFile = javah + File.separator + "lib" + File.separator + "jaxp.properties"; 204d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes String factoryClassName = null; 205d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes if (firstTime) { 206d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes synchronized (cacheProps) { 207d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes if (firstTime) { 208d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes File f = new File(configFile); 209d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes firstTime = false; 210d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes if (SecuritySupport.doesFileExist(f)) { 211d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes if (debug) debugPrintln("Read properties file " + f); 212d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes cacheProps.load(SecuritySupport.getFileInputStream(f)); 213d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes } 214d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes } 215d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes } 216d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes } 217d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes factoryClassName = cacheProps.getProperty(factoryId); 218320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (debug) debugPrintln("found " + factoryClassName + " in $java.home/jaxp.properties"); 219d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes 220d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes if (factoryClassName != null) { 221d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes return newInstance(factoryClassName, classLoader); 222d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes } 223320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } catch (Exception ex) { 224320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (debug) { 225d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes ex.printStackTrace(); 226320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 227320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 228320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 229320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // Try Jar Service Provider Mechanism 230320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson Object provider = findJarServiceProvider(factoryId); 231320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (provider != null) { 232320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson return provider; 233320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 234320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 235320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (fallbackClassName == null) { 236320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson throw new ConfigurationError( 237320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson "Provider for " + factoryId + " cannot be found", null); 238320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 239320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 240320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (debug) debugPrintln("loaded from fallback value: " + fallbackClassName); 241320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson return newInstance(fallbackClassName, classLoader); 242320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 243320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 244320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson /* 245320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * Try to find provider using Jar Service Provider Mechanism 246320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * 247320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * @return instance of provider class if found or null 248320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson */ 249320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson private static Object findJarServiceProvider(String factoryId) 250320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson throws ConfigurationError 251320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson { 252320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 253320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson String serviceId = "META-INF/services/" + factoryId; 254320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson InputStream is = null; 255320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 256320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // First try the Context ClassLoader 257320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson ClassLoader cl = SecuritySupport.getContextClassLoader(); 258320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (cl != null) { 259320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson is = SecuritySupport.getResourceAsStream(cl, serviceId); 260320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 261320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // If no provider found then try the current ClassLoader 262320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (is == null) { 263320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson cl = FactoryFinder.class.getClassLoader(); 264320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson is = SecuritySupport.getResourceAsStream(cl, serviceId); 265320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 266320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } else { 267320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // No Context ClassLoader, try the current 268320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // ClassLoader 269320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson cl = FactoryFinder.class.getClassLoader(); 270320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson is = SecuritySupport.getResourceAsStream(cl, serviceId); 271320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 272320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 273320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (is == null) { 274320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // No provider found 275320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson return null; 276320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 277320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 278320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (debug) debugPrintln("found jar resource=" + serviceId + 279320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson " using ClassLoader: " + cl); 280320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 281320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson BufferedReader rd; 282320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson try { 283320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson rd = new BufferedReader(new InputStreamReader(is, "UTF-8"), DEFAULT_LINE_LENGTH); 284320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } catch (java.io.UnsupportedEncodingException e) { 285320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson rd = new BufferedReader(new InputStreamReader(is), DEFAULT_LINE_LENGTH); 286320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 287320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 288320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson String factoryClassName = null; 289320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson try { 290320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // XXX Does not handle all possible input as specified by the 291320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // Jar Service Provider specification 292320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson factoryClassName = rd.readLine(); 293320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 294320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson catch (IOException x) { 295320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // No provider found 296320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson return null; 297320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 298320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson finally { 299320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson try { 300320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // try to close the reader. 301320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson rd.close(); 302320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 303320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // Ignore the exception. 304320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson catch (IOException exc) {} 305320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 306320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 307320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (factoryClassName != null && 308320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson ! "".equals(factoryClassName)) { 309320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (debug) debugPrintln("found in resource, value=" 310320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson + factoryClassName); 311320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 312320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson return newInstance(factoryClassName, cl); 313320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 314320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 315320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // No provider found 316320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson return null; 317320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 318320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 319d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes /** 320d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes * <p>Configuration Error.</p> 321d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes */ 322320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson static class ConfigurationError extends Error { 323320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 324320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson private static final long serialVersionUID = -3644413026244211347L; 325d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes 326d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes /** 327d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes * <p>Exception that caused the error.</p> 328d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes */ 329320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson private Exception exception; 330320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 331320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson /** 332320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * <p>Construct a new instance with the specified detail string and 333320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * exception.</p> 334320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * 335320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * @param msg Detail message for this error. 336320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * @param x Exception that caused the error. 337320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson */ 338320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson ConfigurationError(String msg, Exception x) { 339320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson super(msg); 340320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson this.exception = x; 341320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 342320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 343d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes /** 344d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes * <p>Get the Exception that caused the error.</p> 345d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes * 346d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes * @return Exception that caused the error. 347d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes */ 348320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson Exception getException() { 349320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson return exception; 350320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 351320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 352320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 353320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 354320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 355320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson /** 356320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * Returns the location where the given Class is loaded from. 357320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * 358320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * @param clazz Class to find load location. 359320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * 360320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson * @return Location where class would be loaded from. 361320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson */ 362320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson private static String which(Class clazz) { 363320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson try { 364320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson String classnameAsResource = clazz.getName().replace('.', '/') + ".class"; 365320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 366320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson ClassLoader loader = clazz.getClassLoader(); 367320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 368320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson URL it; 369320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 370320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (loader != null) { 371d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes it = loader.getResource(classnameAsResource); 372320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } else { 373d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes it = ClassLoader.getSystemResource(classnameAsResource); 374320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 375320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson 376320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (it != null) { 377d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes return it.toString(); 378320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 379320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 380320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // The VM ran out of memory or there was some other serious problem. Re-throw. 381320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson catch (VirtualMachineError vme) { 382320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson throw vme; 383320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 384320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // ThreadDeath should always be re-thrown 385320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson catch (ThreadDeath td) { 386320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson throw td; 387320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 388320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson catch (Throwable t) { 389320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson // work defensively. 390320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson if (debug) { 391d21d78fd49a2d798218e8c8aefbddb26a0e71bbbElliott Hughes t.printStackTrace(); 392320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 393320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 394320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson return "unknown location"; 395320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson } 396320c9890e8241fb0ad05de6fa5e6c3eb3aece159Jesse Wilson} 397