6 * Copyright 2001-2004 The Apache Software Foundation. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 /* 21 * $Id: ObjectFactory.java,v 1.2.4.1 2005/09/15 02:39:54 jeffsuttor Exp $ 22 */ 23 24 package com.sun.org.apache.xalan.internal.utils; 25 26 import java.io.InputStream; 27 import java.io.IOException; 28 import java.io.File; 29 import java.io.FileInputStream; 30 31 import java.util.Properties; 32 import java.io.BufferedReader; 33 import java.io.InputStreamReader; 34 35 /** 36 * This class is duplicated for each JAXP subpackage so keep it in sync. 37 * It is package private and therefore is not exposed as part of the JAXP 38 * API. 39 * <p> 40 * This code is designed to implement the JAXP 1.1 spec pluggability 41 * feature and is designed to run on JDK version 1.1 and 42 * later, and to compile on JDK 1.2 and onward. 43 * The code also runs both as part of an unbundled jar file and 44 * when bundled as part of the JDK. 45 * <p> 46 * This class was moved from the <code>javax.xml.parsers.ObjectFactory</code> 47 * class and modified to be used as a general utility for creating objects 48 * dynamically. 49 * 50 * @version $Id: ObjectFactory.java,v 1.11 2010-11-01 04:34:25 joehw Exp $ 51 */ 52 public class ObjectFactory { 53 54 // 55 // Constants 56 // 57 private static final String XALAN_INTERNAL = "com.sun.org.apache.xalan.internal"; 58 private static final String XERCES_INTERNAL = "com.sun.org.apache.xerces.internal"; 59 60 // name of default properties file to look for in JDK's jre/lib directory 61 private static final String DEFAULT_PROPERTIES_FILENAME = 62 "xalan.properties"; 63 64 private static final String SERVICES_PATH = "META-INF/services/"; 65 66 /** Set to true for debugging */ 67 private static final boolean DEBUG = false; 68 69 /** cache the contents of the xalan.properties file. 70 * Until an attempt has been made to read this file, this will 71 * be null; if the file does not exist or we encounter some other error 72 * during the read, this will be empty. 73 */ 74 private static Properties fXalanProperties = null; 75 76 /*** 77 * Cache the time stamp of the xalan.properties file so 78 * that we know if it's been modified and can invalidate 79 * the cache when necessary. 80 */ 81 private static long fLastModified = -1; 82 83 // 84 // Public static methods 85 // 86 87 /** 88 * Finds the implementation Class object in the specified order. The 89 * specified order is the following: 90 * <ol> 91 * <li>query the system property using <code>System.getProperty</code> 92 * <li>read <code>META-INF/services/<i>factoryId</i></code> file 93 * <li>use fallback classname 94 * </ol> 95 * 96 * @return instance of factory, never null 97 * 98 * @param factoryId Name of the factory to find, same as 99 * a property name 100 * @param fallbackClassName Implementation class name, if nothing else 101 * is found. Use null to mean no fallback. 102 * 103 * @exception ObjectFactory.ConfigurationError 104 */ 105 public static Object createObject(String factoryId, String fallbackClassName) 106 throws ConfigurationError { 107 return createObject(factoryId, null, fallbackClassName); 108 } // createObject(String,String):Object 109 110 /** 111 * Finds the implementation Class object in the specified order. The 112 * specified order is the following: 113 * <ol> 114 * <li>query the system property using <code>System.getProperty</code> 115 * <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file 116 * <li>read <code>META-INF/services/<i>factoryId</i></code> file 117 * <li>use fallback classname 118 * </ol> 119 * 120 * @return instance of factory, never null 121 * 122 * @param factoryId Name of the factory to find, same as 123 * a property name 124 * @param propertiesFilename The filename in the $java.home/lib directory 125 * of the properties file. If none specified, 126 * ${java.home}/lib/xalan.properties will be used. 127 * @param fallbackClassName Implementation class name, if nothing else 128 * is found. Use null to mean no fallback. 129 * 130 * @exception ObjectFactory.ConfigurationError 131 */ 132 static Object createObject(String factoryId, 133 String propertiesFilename, 134 String fallbackClassName) 135 throws ConfigurationError 136 { 137 Class factoryClass = lookUpFactoryClass(factoryId, 138 propertiesFilename, 139 fallbackClassName); 140 141 if (factoryClass == null) { 142 throw new ConfigurationError( 143 "Provider for " + factoryId + " cannot be found", null); 144 } 145 146 try{ 147 Object instance = factoryClass.newInstance(); 148 if (DEBUG) debugPrintln("created new instance of factory " + factoryId); 149 return instance; 150 } catch (Exception x) { 151 throw new ConfigurationError( 152 "Provider for factory " + factoryId 153 + " could not be instantiated: " + x, x); 154 } 155 } // createObject(String,String,String):Object 156 157 /** 158 * Finds the implementation Class object in the specified order. The 159 * specified order is the following: 160 * <ol> 161 * <li>query the system property using <code>System.getProperty</code> 162 * <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file 163 * <li>read <code>META-INF/services/<i>factoryId</i></code> file 164 * <li>use fallback classname 165 * </ol> 166 * 167 * @return Class object of factory, never null 168 * 169 * @param factoryId Name of the factory to find, same as 170 * a property name 171 * @param propertiesFilename The filename in the $java.home/lib directory 172 * of the properties file. If none specified, 173 * ${java.home}/lib/xalan.properties will be used. 174 * @param fallbackClassName Implementation class name, if nothing else 175 * is found. Use null to mean no fallback. 176 * 177 * @exception ObjectFactory.ConfigurationError 178 */ 179 public static Class lookUpFactoryClass(String factoryId) 180 throws ConfigurationError 181 { 182 return lookUpFactoryClass(factoryId, null, null); 183 } // lookUpFactoryClass(String):Class 184 185 /** 186 * Finds the implementation Class object in the specified order. The 187 * specified order is the following: 188 * <ol> 189 * <li>query the system property using <code>System.getProperty</code> 190 * <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file 191 * <li>read <code>META-INF/services/<i>factoryId</i></code> file 192 * <li>use fallback classname 193 * </ol> 194 * 195 * @return Class object that provides factory service, never null 196 * 197 * @param factoryId Name of the factory to find, same as 198 * a property name 199 * @param propertiesFilename The filename in the $java.home/lib directory 200 * of the properties file. If none specified, 201 * ${java.home}/lib/xalan.properties will be used. 202 * @param fallbackClassName Implementation class name, if nothing else 203 * is found. Use null to mean no fallback. 204 * 205 * @exception ObjectFactory.ConfigurationError 206 */ 207 public static Class lookUpFactoryClass(String factoryId, 208 String propertiesFilename, 209 String fallbackClassName) 210 throws ConfigurationError 211 { 212 String factoryClassName = lookUpFactoryClassName(factoryId, 213 propertiesFilename, 214 fallbackClassName); 215 ClassLoader cl = findClassLoader(); 216 217 if (factoryClassName == null) { 218 factoryClassName = fallbackClassName; 219 } 220 221 // assert(className != null); 222 try{ 223 Class providerClass = findProviderClass(factoryClassName, 224 cl, 225 true); 226 if (DEBUG) debugPrintln("created new instance of " + providerClass + 227 " using ClassLoader: " + cl); 228 return providerClass; 229 } catch (ClassNotFoundException x) { 230 throw new ConfigurationError( 231 "Provider " + factoryClassName + " not found", x); 232 } catch (Exception x) { 233 throw new ConfigurationError( 234 "Provider "+factoryClassName+" could not be instantiated: "+x, 235 x); 236 } 237 } // lookUpFactoryClass(String,String,String):Class 238 239 /** 240 * Finds the name of the required implementation class in the specified 241 * order. The specified order is the following: 242 * <ol> 243 * <li>query the system property using <code>System.getProperty</code> 244 * <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file 245 * <li>read <code>META-INF/services/<i>factoryId</i></code> file 246 * <li>use fallback classname 247 * </ol> 248 * 249 * @return name of class that provides factory service, never null 250 * 251 * @param factoryId Name of the factory to find, same as 252 * a property name 253 * @param propertiesFilename The filename in the $java.home/lib directory 254 * of the properties file. If none specified, 255 * ${java.home}/lib/xalan.properties will be used. 256 * @param fallbackClassName Implementation class name, if nothing else 257 * is found. Use null to mean no fallback. 258 * 259 * @exception ObjectFactory.ConfigurationError 260 */ 261 static String lookUpFactoryClassName(String factoryId, 262 String propertiesFilename, 263 String fallbackClassName) 264 { 265 // Use the system property first 266 try { 267 String systemProp = SecuritySupport.getSystemProperty(factoryId); 268 if (systemProp != null) { 269 if (DEBUG) debugPrintln("found system property, value=" + systemProp); 270 return systemProp; 271 } 272 } catch (SecurityException se) { 273 // Ignore and continue w/ next location 274 } 275 276 // Try to read from propertiesFilename, or 277 // $java.home/lib/xalan.properties 278 String factoryClassName = null; 279 // no properties file name specified; use 280 // $JAVA_HOME/lib/xalan.properties: 281 if (propertiesFilename == null) { 282 File propertiesFile = null; 283 boolean propertiesFileExists = false; 284 try { 285 String javah = SecuritySupport.getSystemProperty("java.home"); 286 propertiesFilename = javah + File.separator + 287 "lib" + File.separator + DEFAULT_PROPERTIES_FILENAME; 288 propertiesFile = new File(propertiesFilename); 289 propertiesFileExists = SecuritySupport.getFileExists(propertiesFile); 290 } catch (SecurityException e) { 291 // try again... 292 fLastModified = -1; 293 fXalanProperties = null; 294 } 295 296 synchronized (ObjectFactory.class) { 297 boolean loadProperties = false; 298 FileInputStream fis = null; 299 try { 300 // file existed last time 301 if(fLastModified >= 0) { 302 if(propertiesFileExists && 303 (fLastModified < (fLastModified = SecuritySupport.getLastModified(propertiesFile)))) { 304 loadProperties = true; 305 } else { 306 // file has stopped existing... 307 if(!propertiesFileExists) { 308 fLastModified = -1; 309 fXalanProperties = null; 310 } // else, file wasn't modified! 311 } 312 } else { 313 // file has started to exist: 314 if(propertiesFileExists) { 315 loadProperties = true; 316 fLastModified = SecuritySupport.getLastModified(propertiesFile); 317 } // else, nothing's changed 318 } 319 if(loadProperties) { 320 // must never have attempted to read xalan.properties 321 // before (or it's outdeated) 322 fXalanProperties = new Properties(); 323 fis = SecuritySupport.getFileInputStream(propertiesFile); 324 fXalanProperties.load(fis); 325 } 326 } catch (Exception x) { 327 fXalanProperties = null; 328 fLastModified = -1; 329 // assert(x instanceof FileNotFoundException 330 // || x instanceof SecurityException) 331 // In both cases, ignore and continue w/ next location 332 } 333 finally { 334 // try to close the input stream if one was opened. 335 if (fis != null) { 336 try { 337 fis.close(); 338 } 339 // Ignore the exception. 340 catch (IOException exc) {} 341 } 342 } 343 } 344 if(fXalanProperties != null) { 345 factoryClassName = fXalanProperties.getProperty(factoryId); 346 } 347 } else { 348 FileInputStream fis = null; 349 try { 350 fis = SecuritySupport.getFileInputStream(new File(propertiesFilename)); 351 Properties props = new Properties(); 352 props.load(fis); 353 factoryClassName = props.getProperty(factoryId); 354 } catch (Exception x) { 355 // assert(x instanceof FileNotFoundException 356 // || x instanceof SecurityException) 357 // In both cases, ignore and continue w/ next location 358 } 359 finally { 360 // try to close the input stream if one was opened. 361 if (fis != null) { 362 try { 363 fis.close(); 364 } 365 // Ignore the exception. 366 catch (IOException exc) {} 367 } 368 } 369 } 370 if (factoryClassName != null) { 371 if (DEBUG) debugPrintln("found in " + propertiesFilename + ", value=" 372 + factoryClassName); 373 return factoryClassName; 374 } 375 376 // Try Jar Service Provider Mechanism 377 return findJarServiceProviderName(factoryId); 378 } // lookUpFactoryClass(String,String):String 379 380 // 381 // Private static methods 382 // 383 384 /** Prints a message to standard error if debugging is enabled. */ 385 private static void debugPrintln(String msg) { 386 if (DEBUG) { 387 System.err.println("JAXP: " + msg); 388 } 389 } // debugPrintln(String) 390 391 /** 392 * Figure out which ClassLoader to use. For JDK 1.2 and later use 393 * the context ClassLoader. 394 */ 395 public static ClassLoader findClassLoader() 396 throws ConfigurationError 397 { 398 if (System.getSecurityManager()!=null) { 399 //this will ensure bootclassloader is used 400 return null; 401 } 402 403 // Figure out which ClassLoader to use for loading the provider 404 // class. If there is a Context ClassLoader then use it. 405 ClassLoader context = SecuritySupport.getContextClassLoader(); 406 ClassLoader system = SecuritySupport.getSystemClassLoader(); 407 408 ClassLoader chain = system; 409 while (true) { 410 if (context == chain) { 411 // Assert: we are on JDK 1.1 or we have no Context ClassLoader 412 // or any Context ClassLoader in chain of system classloader 413 // (including extension ClassLoader) so extend to widest 414 // ClassLoader (always look in system ClassLoader if Xalan 415 // is in boot/extension/system classpath and in current 416 // ClassLoader otherwise); normal classloaders delegate 435 // boot/extension/system ClassLoaders 436 return current; 437 } 438 439 if (chain == null) { 440 // boot ClassLoader reached 441 break; 442 } 443 444 // Check for any extension ClassLoaders in chain up to 445 // boot ClassLoader 446 chain = SecuritySupport.getParentClassLoader(chain); 447 } 448 449 // Assert: Context ClassLoader not in chain of 450 // boot/extension/system ClassLoaders 451 return context; 452 } // findClassLoader():ClassLoader 453 454 /** 455 * Create an instance of a class using the same classloader for the ObjectFactory by default 456 * or bootclassloader when Security Manager is in place 457 */ 458 public static Object newInstance(String className, boolean doFallback) 459 throws ConfigurationError 460 { 461 if (System.getSecurityManager()!=null) { 462 return newInstance(className, null, doFallback); 463 } else { 464 return newInstance(className, 465 findClassLoader (), doFallback); 466 } 467 } 468 469 /** 470 * Create an instance of a class using the specified ClassLoader 471 */ 472 static Object newInstance(String className, ClassLoader cl, 473 boolean doFallback) 474 throws ConfigurationError 475 { 476 // assert(className != null); 477 try{ 478 Class providerClass = findProviderClass(className, cl, doFallback); 479 Object instance = providerClass.newInstance(); 480 if (DEBUG) debugPrintln("created new instance of " + providerClass + 481 " using ClassLoader: " + cl); 482 return instance; 483 } catch (ClassNotFoundException x) { 484 throw new ConfigurationError( 485 "Provider " + className + " not found", x); 486 } catch (Exception x) { 487 throw new ConfigurationError( 488 "Provider " + className + " could not be instantiated: " + x, 489 x); 490 } 491 } 492 493 /** 494 * Find a Class using the same classloader for the ObjectFactory by default 495 * or bootclassloader when Security Manager is in place 496 */ 497 public static Class findProviderClass(String className, boolean doFallback) 498 throws ClassNotFoundException, ConfigurationError 499 { 500 if (System.getSecurityManager()!=null) { 501 return Class.forName(className); 502 } else { 503 return findProviderClass (className, 504 findClassLoader (), doFallback); 505 } 506 } 507 508 /** 509 * Find a Class using the specified ClassLoader 510 */ 511 static Class findProviderClass(String className, ClassLoader cl, 512 boolean doFallback) 513 throws ClassNotFoundException, ConfigurationError 514 { 515 //throw security exception if the calling thread is not allowed to access the 516 //class. Restrict the access to the package classes as specified in java.security policy. 517 SecurityManager security = System.getSecurityManager(); 518 try{ 519 if (security != null){ 520 if (className.startsWith(XALAN_INTERNAL) || 521 className.startsWith(XERCES_INTERNAL)) { 522 cl = null; 523 } else { 524 final int lastDot = className.lastIndexOf("."); 525 String packageName = className; 526 if (lastDot != -1) packageName = className.substring(0, lastDot); 527 security.checkPackageAccess(packageName); 528 } 529 } 530 }catch(SecurityException e){ 531 throw e; 532 } 533 534 Class providerClass; 535 if (cl == null) { 536 // XXX Use the bootstrap ClassLoader. There is no way to 537 // load a class using the bootstrap ClassLoader that works 538 // in both JDK 1.1 and Java 2. However, this should still 539 // work b/c the following should be true: 540 // 541 // (cl == null) iff current ClassLoader == null 542 // 543 // Thus Class.forName(String) will use the current 544 // ClassLoader which will be the bootstrap ClassLoader. 545 providerClass = Class.forName(className); 546 } else { 547 try { 548 providerClass = cl.loadClass(className); 549 } catch (ClassNotFoundException x) { 550 if (doFallback) { 551 // Fall back to current classloader 552 ClassLoader current = ObjectFactory.class.getClassLoader(); 553 if (current == null) { 554 providerClass = Class.forName(className); 555 } else if (cl != current) { 556 cl = current; 557 providerClass = cl.loadClass(className); 558 } else { 559 throw x; 560 } 561 } else { 562 throw x; 563 } 564 } 565 } 566 567 return providerClass; 568 } 569 570 /** 571 * Find the name of service provider using Jar Service Provider Mechanism 572 * 573 * @return instance of provider class if found or null 574 */ 575 private static String findJarServiceProviderName(String factoryId) 576 { 577 String serviceId = SERVICES_PATH + factoryId; 578 InputStream is = null; 579 580 // First try the Context ClassLoader 581 ClassLoader cl = findClassLoader(); 582 583 is = SecuritySupport.getResourceAsStream(cl, serviceId); 584 585 // If no provider found then try the current ClassLoader 586 if (is == null) { 587 ClassLoader current = ObjectFactory.class.getClassLoader(); 588 if (cl != current) { 589 cl = current; 590 is = SecuritySupport.getResourceAsStream(cl, serviceId); 591 } 592 } 593 594 if (is == null) { 595 // No provider found 596 return null; 597 } 598 599 if (DEBUG) debugPrintln("found jar resource=" + serviceId + 600 " using ClassLoader: " + cl); 601 602 // Read the service provider name in UTF-8 as specified in 603 // the jar spec. Unfortunately this fails in Microsoft 604 // VJ++, which does not implement the UTF-8 605 // encoding. Theoretically, we should simply let it fail in 606 // that case, since the JVM is obviously broken if it 607 // doesn't support such a basic standard. But since there 608 // are still some users attempting to use VJ++ for 609 // development, we have dropped in a fallback which makes a 610 // second attempt using the platform's default encoding. In 611 // VJ++ this is apparently ASCII, which is a subset of 612 // UTF-8... and since the strings we'll be reading here are 613 // also primarily limited to the 7-bit ASCII range (at 614 // least, in English versions), this should work well 615 // enough to keep us on the air until we're ready to 616 // officially decommit from VJ++. [Edited comment from 617 // jkesselm] 618 BufferedReader rd; 619 try { 620 rd = new BufferedReader(new InputStreamReader(is, "UTF-8")); 621 } catch (java.io.UnsupportedEncodingException e) { 622 rd = new BufferedReader(new InputStreamReader(is)); 623 } 624 625 String factoryClassName = null; 626 try { 627 // XXX Does not handle all possible input as specified by the 628 // Jar Service Provider specification 629 factoryClassName = rd.readLine(); 630 } catch (IOException x) { 631 // No provider found 632 return null; 633 } 634 finally { 635 try { 636 // try to close the reader. 637 rd.close(); 638 } 639 // Ignore the exception. 640 catch (IOException exc) {} 641 } 642 643 if (factoryClassName != null && 644 ! "".equals(factoryClassName)) { 645 if (DEBUG) debugPrintln("found in resource, value=" 646 + factoryClassName); 647 648 // Note: here we do not want to fall back to the current 649 // ClassLoader because we want to avoid the case where the 650 // resource file was found using one ClassLoader and the 651 // provider class was instantiated using a different one. 652 return factoryClassName; 653 } 654 655 // No provider found 656 return null; 657 } 658 659 } // class ObjectFactory | 6 * Copyright 2001-2004 The Apache Software Foundation. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 /* 21 * $Id: ObjectFactory.java,v 1.2.4.1 2005/09/15 02:39:54 jeffsuttor Exp $ 22 */ 23 24 package com.sun.org.apache.xalan.internal.utils; 25 26 /** 27 * This class is duplicated for each JAXP subpackage so keep it in sync. 28 * It is package private and therefore is not exposed as part of the JAXP 29 * API. 30 * <p> 31 * This class was moved from the <code>javax.xml.parsers.ObjectFactory</code> 32 * class and modified to be used as a general utility for creating objects 33 * dynamically. 34 * 35 * @version $Id: ObjectFactory.java,v 1.11 2010-11-01 04:34:25 joehw Exp $ 36 */ 37 public class ObjectFactory { 38 39 // 40 // Constants 41 // 42 private static final String XALAN_INTERNAL = "com.sun.org.apache.xalan.internal"; 43 private static final String XERCES_INTERNAL = "com.sun.org.apache.xerces.internal"; 44 45 /** Set to true for debugging */ 46 private static final boolean DEBUG = false; 47 48 49 /** Prints a message to standard error if debugging is enabled. */ 50 private static void debugPrintln(String msg) { 51 if (DEBUG) { 52 System.err.println("JAXP: " + msg); 53 } 54 } // debugPrintln(String) 55 56 /** 57 * Figure out which ClassLoader to use. For JDK 1.2 and later use 58 * the context ClassLoader. 59 */ 60 public static ClassLoader findClassLoader() 61 { 62 if (System.getSecurityManager()!=null) { 63 //this will ensure bootclassloader is used 64 return null; 65 } 66 67 // Figure out which ClassLoader to use for loading the provider 68 // class. If there is a Context ClassLoader then use it. 69 ClassLoader context = SecuritySupport.getContextClassLoader(); 70 ClassLoader system = SecuritySupport.getSystemClassLoader(); 71 72 ClassLoader chain = system; 73 while (true) { 74 if (context == chain) { 75 // Assert: we are on JDK 1.1 or we have no Context ClassLoader 76 // or any Context ClassLoader in chain of system classloader 77 // (including extension ClassLoader) so extend to widest 78 // ClassLoader (always look in system ClassLoader if Xalan 79 // is in boot/extension/system classpath and in current 80 // ClassLoader otherwise); normal classloaders delegate 99 // boot/extension/system ClassLoaders 100 return current; 101 } 102 103 if (chain == null) { 104 // boot ClassLoader reached 105 break; 106 } 107 108 // Check for any extension ClassLoaders in chain up to 109 // boot ClassLoader 110 chain = SecuritySupport.getParentClassLoader(chain); 111 } 112 113 // Assert: Context ClassLoader not in chain of 114 // boot/extension/system ClassLoaders 115 return context; 116 } // findClassLoader():ClassLoader 117 118 /** 119 * Create an instance of a class using the same class loader for the ObjectFactory by default 120 * or boot class loader when Security Manager is in place 121 */ 122 public static Object newInstance(String className, boolean doFallback) 123 throws ConfigurationError 124 { 125 if (System.getSecurityManager()!=null) { 126 return newInstance(className, null, doFallback); 127 } else { 128 return newInstance(className, 129 findClassLoader (), doFallback); 130 } 131 } 132 133 /** 134 * Create an instance of a class using the specified ClassLoader 135 */ 136 static Object newInstance(String className, ClassLoader cl, 137 boolean doFallback) 138 throws ConfigurationError 139 { 140 // assert(className != null); 141 try{ 142 Class providerClass = findProviderClass(className, cl, doFallback); 143 Object instance = providerClass.newInstance(); 144 if (DEBUG) debugPrintln("created new instance of " + providerClass + 145 " using ClassLoader: " + cl); 146 return instance; 147 } catch (ClassNotFoundException x) { 148 throw new ConfigurationError( 149 "Provider " + className + " not found", x); 150 } catch (Exception x) { 151 throw new ConfigurationError( 152 "Provider " + className + " could not be instantiated: " + x, 153 x); 154 } 155 } 156 157 /** 158 * Find a Class using the same class loader for the ObjectFactory by default 159 * or boot class loader when Security Manager is in place 160 */ 161 public static Class<?> findProviderClass(String className, boolean doFallback) 162 throws ClassNotFoundException, ConfigurationError 163 { 164 if (System.getSecurityManager()!=null) { 165 return Class.forName(className); 166 } else { 167 return findProviderClass (className, 168 findClassLoader (), doFallback); 169 } 170 } 171 172 /** 173 * Find a Class using the specified ClassLoader 174 */ 175 private static Class<?> findProviderClass(String className, ClassLoader cl, 176 boolean doFallback) 177 throws ClassNotFoundException, ConfigurationError 178 { 179 //throw security exception if the calling thread is not allowed to access the 180 //class. Restrict the access to the package classes as specified in java.security policy. 181 SecurityManager security = System.getSecurityManager(); 182 try{ 183 if (security != null){ 184 if (className.startsWith(XALAN_INTERNAL) || 185 className.startsWith(XERCES_INTERNAL)) { 186 cl = null; 187 } else { 188 final int lastDot = className.lastIndexOf("."); 189 String packageName = className; 190 if (lastDot != -1) packageName = className.substring(0, lastDot); 191 security.checkPackageAccess(packageName); 192 } 193 } 194 }catch(SecurityException e){ 195 throw e; 196 } 197 198 Class<?> providerClass; 199 if (cl == null) { 200 // XXX Use the bootstrap ClassLoader. There is no way to 201 // load a class using the bootstrap ClassLoader that works 202 // in both JDK 1.1 and Java 2. However, this should still 203 // work b/c the following should be true: 204 // 205 // (cl == null) iff current ClassLoader == null 206 // 207 // Thus Class.forName(String) will use the current 208 // ClassLoader which will be the bootstrap ClassLoader. 209 providerClass = Class.forName(className); 210 } else { 211 try { 212 providerClass = cl.loadClass(className); 213 } catch (ClassNotFoundException x) { 214 if (doFallback) { 215 // Fall back to current classloader 216 ClassLoader current = ObjectFactory.class.getClassLoader(); 217 if (current == null) { 218 providerClass = Class.forName(className); 219 } else if (cl != current) { 220 cl = current; 221 providerClass = cl.loadClass(className); 222 } else { 223 throw x; 224 } 225 } else { 226 throw x; 227 } 228 } 229 } 230 231 return providerClass; 232 } 233 234 } // class ObjectFactory |