8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.xml.xpath; 27 28 import java.io.BufferedReader; 29 import java.io.File; 30 import java.io.FileInputStream; 31 import java.io.IOException; 32 import java.io.InputStream; 33 import java.io.InputStreamReader; 34 import java.lang.reflect.Method; 35 import java.lang.reflect.InvocationTargetException; 36 import java.net.URL; 37 import java.util.ArrayList; 38 import java.util.Enumeration; 39 import java.util.Iterator; 40 import java.util.NoSuchElementException; 41 import java.util.Properties; 42 43 /** 44 * Implementation of {@link XPathFactory#newInstance(String)}. 45 * 46 * @author <a href="Kohsuke.Kawaguchi@Sun.com">Kohsuke Kawaguchi</a> 47 * @version $Revision: 1.7 $, $Date: 2010-11-01 04:36:14 $ 48 * @since 1.5 49 */ 50 class XPathFactoryFinder { 51 52 private static SecuritySupport ss = new SecuritySupport() ; 53 /** debug support code. */ 54 private static boolean debug = false; 55 static { 56 // Use try/catch block to support applets 57 try { 58 debug = ss.getSystemProperty("jaxp.debug") != null; 59 } catch (Exception _) { 60 debug = false; 61 } 62 } 63 64 /** 65 * <p>Cache properties for performance.</p> 66 */ 67 private static Properties cacheProps = new Properties(); 68 69 /** 70 * <p>First time requires initialization overhead.</p> 71 */ 72 private volatile static boolean firstTime = true; 73 74 /** 75 * <p>Conditional debug printing.</p> 76 * 77 * @param msg to print 78 */ 79 private static void debugPrintln(String msg) { 80 if (debug) { 81 System.err.println("JAXP: " + msg); 82 } 83 } 84 85 /** 86 * <p><code>ClassLoader</code> to use to find <code>XPathFactory</code>.</p> 87 */ 88 private final ClassLoader classLoader; 89 90 /** 91 * <p>Constructor that specifies <code>ClassLoader</code> to use 92 * to find <code>XPathFactory</code>.</p> 93 * 94 * @param loader 95 * to be used to load resource, {@link XPathFactory}, and 96 * {@link SchemaFactoryLoader} implementations during 97 * the resolution process. 98 * If this parameter is null, the default system class loader 99 * will be used. 100 */ 101 public XPathFactoryFinder(ClassLoader loader) { 102 this.classLoader = loader; 103 if( debug ) { 104 debugDisplayClassLoader(); 105 } 106 } 107 108 private void debugDisplayClassLoader() { 109 try { 110 if( classLoader == ss.getContextClassLoader() ) { 111 debugPrintln("using thread context class loader ("+classLoader+") for search"); 112 return; 113 } 114 } catch( Throwable _ ) { 115 ; // getContextClassLoader() undefined in JDK1.1 116 } 117 118 if( classLoader==ClassLoader.getSystemClassLoader() ) { 119 debugPrintln("using system class loader ("+classLoader+") for search"); 120 return; 121 } 122 123 debugPrintln("using class loader ("+classLoader+") for search"); 124 } 125 126 /** 127 * <p>Creates a new {@link XPathFactory} object for the specified 128 * schema language.</p> 129 * 130 * @param uri 131 * Identifies the underlying object model. 132 * 133 * @return <code>null</code> if the callee fails to create one. 134 * 135 * @throws NullPointerException 136 * If the parameter is null. 137 */ 138 public XPathFactory newFactory(String uri) { 139 if(uri==null) throw new NullPointerException(); 140 XPathFactory f = _newFactory(uri); 141 if (f != null) { 142 debugPrintln("factory '" + f.getClass().getName() + "' was found for " + uri); 143 } else { 144 debugPrintln("unable to find a factory for " + uri); 145 } 146 return f; 147 } 148 149 /** 150 * <p>Lookup a {@link XPathFactory} for the given object model.</p> 151 * 152 * @param uri identifies the object model. 153 * 154 * @return {@link XPathFactory} for the given object model. 155 */ 156 private XPathFactory _newFactory(String uri) { 157 XPathFactory xpathFactory; 158 159 String propertyName = SERVICE_CLASS.getName() + ":" + uri; 160 161 // system property look up 162 try { 163 debugPrintln("Looking up system property '"+propertyName+"'" ); 164 String r = ss.getSystemProperty(propertyName); 165 if(r!=null) { 166 debugPrintln("The value is '"+r+"'"); 167 xpathFactory = createInstance(r, true); 168 if(xpathFactory != null) return xpathFactory; 169 } else 170 debugPrintln("The property is undefined."); 171 } catch( Throwable t ) { 172 if( debug ) { 173 debugPrintln("failed to look up system property '"+propertyName+"'" ); 174 t.printStackTrace(); 175 } 176 } 177 178 String javah = ss.getSystemProperty( "java.home" ); 179 String configFile = javah + File.separator + 180 "lib" + File.separator + "jaxp.properties"; 181 182 String factoryClassName = null ; 183 184 // try to read from $java.home/lib/jaxp.properties 185 try { 186 if(firstTime){ 187 synchronized(cacheProps){ 188 if(firstTime){ 189 File f=new File( configFile ); 190 firstTime = false; 191 if(ss.doesFileExist(f)){ 192 debugPrintln("Read properties file " + f); 193 cacheProps.load(ss.getFileInputStream(f)); 194 } 195 } 196 } 197 } 198 factoryClassName = cacheProps.getProperty(propertyName); 199 debugPrintln("found " + factoryClassName + " in $java.home/jaxp.properties"); 200 201 if (factoryClassName != null) { 202 xpathFactory = createInstance(factoryClassName, true); 203 if(xpathFactory != null){ 204 return xpathFactory; 205 } 206 } 207 } catch (Exception ex) { 208 if (debug) { 209 ex.printStackTrace(); 210 } 211 } 212 213 // try META-INF/services files 214 Iterator sitr = createServiceFileIterator(); 215 while(sitr.hasNext()) { 216 URL resource = (URL)sitr.next(); 217 debugPrintln("looking into " + resource); 218 try { 219 xpathFactory = loadFromService(uri, resource.toExternalForm(), 220 ss.getURLInputStream(resource)); 221 if (xpathFactory != null) { 222 return xpathFactory; 223 } 224 } catch(IOException e) { 225 if( debug ) { 226 debugPrintln("failed to read "+resource); 227 e.printStackTrace(); 228 } 229 } 230 } 231 232 // platform default 233 if(uri.equals(XPathFactory.DEFAULT_OBJECT_MODEL_URI)) { 234 debugPrintln("attempting to use the platform default W3C DOM XPath lib"); 235 return createInstance("com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl", true); 236 } 237 238 debugPrintln("all things were tried, but none was found. bailing out."); 239 return null; 240 } 241 242 /** <p>Create class using appropriate ClassLoader.</p> 243 * 244 * @param className Name of class to create. 245 * @return Created class or <code>null</code>. 246 */ 247 private Class createClass(String className) { 248 Class clazz; 249 250 // use approprite ClassLoader 251 try { 252 if (classLoader != null) { 253 clazz = classLoader.loadClass(className); 254 } else { 255 clazz = Class.forName(className); 256 } 257 } catch (Throwable t) { 258 if(debug) t.printStackTrace(); 259 return null; 260 } 261 262 return clazz; 263 } 264 265 /** 266 * <p>Creates an instance of the specified and returns it.</p> 267 * 268 * @param className 269 * fully qualified class name to be instanciated. 270 * 271 * @return null 272 * if it fails. Error messages will be printed by this method. 273 */ 274 XPathFactory createInstance( String className ) { 275 return createInstance( className, false ); 276 } 277 XPathFactory createInstance( String className, boolean useServicesMechanism ) { 278 XPathFactory xPathFactory = null; 279 280 debugPrintln("createInstance(" + className + ")"); 281 282 // get Class from className 283 Class clazz = createClass(className); 284 if (clazz == null) { 285 debugPrintln("failed to getClass(" + className + ")"); 286 return null; 287 } 288 debugPrintln("loaded " + className + " from " + which(clazz)); 289 290 // instantiate Class as a XPathFactory 291 try { 292 if (!useServicesMechanism) { 293 xPathFactory = (XPathFactory) newInstanceNoServiceLoader(clazz); 294 } 295 if (xPathFactory == null) { 296 xPathFactory = (XPathFactory) clazz.newInstance(); 297 } 300 if (debug) { 301 classCastException.printStackTrace(); 302 } 303 return null; 304 } catch (IllegalAccessException illegalAccessException) { 305 debugPrintln("could not instantiate " + clazz.getName()); 306 if (debug) { 307 illegalAccessException.printStackTrace(); 308 } 309 return null; 310 } catch (InstantiationException instantiationException) { 311 debugPrintln("could not instantiate " + clazz.getName()); 312 if (debug) { 313 instantiationException.printStackTrace(); 314 } 315 return null; 316 } 317 318 return xPathFactory; 319 } 320 /** 321 * Try to construct using newXPathFactoryNoServiceLoader 322 * method if available. 323 */ 324 private static Object newInstanceNoServiceLoader( 325 Class<?> providerClass 326 ) { 327 // Retain maximum compatibility if no security manager. 328 if (System.getSecurityManager() == null) { 329 return null; 330 } 331 try { 332 Method creationMethod = 333 providerClass.getDeclaredMethod( 334 "newXPathFactoryNoServiceLoader" 335 ); 336 return creationMethod.invoke(null, null); 337 } catch (NoSuchMethodException exc) { 338 return null; 339 } catch (Exception exc) { 340 return null; 341 } 342 } 343 344 /** 345 * <p>Look up a value in a property file.</p> 346 * 347 * <p>Set <code>debug</code> to <code>true</code> to trace property evaluation.</p> 348 * 349 * @param objectModel URI of object model to support. 350 * @param inputName Name of <code>InputStream</code>. 351 * @param in <code>InputStream</code> of properties. 352 * 353 * @return <code>XPathFactory</code> as determined by <code>keyName</code> value or <code>null</code> if there was an error. 354 * 355 * @throws IOException If IO error reading from <code>in</code>. 356 */ 357 private XPathFactory loadFromService( 358 String objectModel, 359 String inputName, 360 InputStream in) 361 throws IOException { 362 363 XPathFactory xPathFactory = null; 364 final Class[] stringClassArray = {"".getClass()}; 365 final Object[] objectModelObjectArray = {objectModel}; 366 final String isObjectModelSupportedMethod = "isObjectModelSupported"; 367 368 debugPrintln("Reading " + inputName); 369 370 // read from InputStream until a match is found 371 BufferedReader configFile = new BufferedReader(new InputStreamReader(in)); 372 String line = null; 373 while ((line = configFile.readLine()) != null) { 374 // '#' is comment char 375 int comment = line.indexOf("#"); 376 switch (comment) { 377 case -1: break; // no comment 378 case 0: line = ""; break; // entire line is a comment 379 default: line = line.substring(0, comment); break; // trim comment 380 } 381 382 // trim whitespace 383 line = line.trim(); 384 385 // any content left on line? 386 if (line.length() == 0) { 387 continue; 388 } 389 390 // line content is now the name of the class 391 Class clazz = createClass(line); 392 if (clazz == null) { 393 continue; 394 } 395 396 // create an instance of the Class 397 try { 398 xPathFactory = (XPathFactory) clazz.newInstance(); 399 } catch (ClassCastException classCastExcpetion) { 400 xPathFactory = null; 401 continue; 402 } catch (InstantiationException instantiationException) { 403 xPathFactory = null; 404 continue; 405 } catch (IllegalAccessException illegalAccessException) { 406 xPathFactory = null; 407 continue; 408 } 409 410 // does this Class support desired object model? 411 try { 412 Method isObjectModelSupported = clazz.getMethod(isObjectModelSupportedMethod, stringClassArray); 413 Boolean supported = (Boolean) isObjectModelSupported.invoke(xPathFactory, objectModelObjectArray); 414 if (supported.booleanValue()) { 415 break; 416 } 417 418 } catch (NoSuchMethodException noSuchMethodException) { 419 420 } catch (IllegalAccessException illegalAccessException) { 421 422 } catch (InvocationTargetException invocationTargetException) { 423 424 } 425 xPathFactory = null; 426 } 427 428 // clean up 429 configFile.close(); 430 431 // return new instance of XPathFactory or null 432 return xPathFactory; 433 } 434 435 /** Iterator that lazily computes one value and returns it. */ 436 private static abstract class SingleIterator implements Iterator { 437 private boolean seen = false; 438 439 public final void remove() { throw new UnsupportedOperationException(); } 440 public final boolean hasNext() { return !seen; } 441 public final Object next() { 442 if(seen) throw new NoSuchElementException(); 443 seen = true; 444 return value(); 445 } 446 447 protected abstract Object value(); 448 } 449 450 /** 451 * Looks up a value in a property file 452 * while producing all sorts of debug messages. 453 * 454 * @return null 455 * if there was an error. 456 */ 457 private XPathFactory loadFromProperty( String keyName, String resourceName, InputStream in ) 458 throws IOException { 459 debugPrintln("Reading "+resourceName ); 460 461 Properties props = new Properties(); 462 props.load(in); 463 in.close(); 464 String factoryClassName = props.getProperty(keyName); 465 if(factoryClassName != null){ 466 debugPrintln("found "+keyName+" = " + factoryClassName); 467 return createInstance(factoryClassName, true); 468 } else { 469 debugPrintln(keyName+" is not in the property file"); 470 return null; 471 } 472 } 473 474 /** 475 * Returns an {@link Iterator} that enumerates all 476 * the META-INF/services files that we care. 477 */ 478 private Iterator createServiceFileIterator() { 479 if (classLoader == null) { 480 return new SingleIterator() { 481 protected Object value() { 482 ClassLoader classLoader = XPathFactoryFinder.class.getClassLoader(); 483 return ss.getResourceAsURL(classLoader, SERVICE_ID); 484 //return (ClassLoader.getSystemResource( SERVICE_ID )); 485 } 486 }; 487 } else { 488 try { 489 //final Enumeration e = classLoader.getResources(SERVICE_ID); 490 final Enumeration e = ss.getResources(classLoader, SERVICE_ID); 491 if(!e.hasMoreElements()) { 492 debugPrintln("no "+SERVICE_ID+" file was found"); 493 } 494 495 // wrap it into an Iterator. 496 return new Iterator() { 497 public void remove() { 498 throw new UnsupportedOperationException(); 499 } 500 501 public boolean hasNext() { 502 return e.hasMoreElements(); 503 } 504 505 public Object next() { 506 return e.nextElement(); 507 } 508 }; 509 } catch (IOException e) { 510 debugPrintln("failed to enumerate resources "+SERVICE_ID); 511 if(debug) e.printStackTrace(); 512 return new ArrayList().iterator(); // empty iterator 513 } 514 } 515 } 516 517 private static final Class SERVICE_CLASS = XPathFactory.class; 518 private static final String SERVICE_ID = "META-INF/services/" + SERVICE_CLASS.getName(); 519 520 521 522 private static String which( Class clazz ) { 523 return which( clazz.getName(), clazz.getClassLoader() ); 524 } 525 526 /** 527 * <p>Search the specified classloader for the given classname.</p> 528 * 529 * @param classname the fully qualified name of the class to search for 530 * @param loader the classloader to search 531 * 532 * @return the source location of the resource, or null if it wasn't found 533 */ 534 private static String which(String classname, ClassLoader loader) { 535 536 String classnameAsResource = classname.replace('.', '/') + ".class"; 537 538 if( loader==null ) loader = ClassLoader.getSystemClassLoader(); 539 540 //URL it = loader.getResource(classnameAsResource); 541 URL it = ss.getResourceAsURL(loader, classnameAsResource); 542 if (it != null) { 543 return it.toString(); 544 } else { 545 return null; 546 } 547 } 548 } | 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.xml.xpath; 27 28 import java.io.File; 29 import java.lang.reflect.InvocationTargetException; 30 import java.lang.reflect.Method; 31 import java.net.URL; 32 import java.security.AccessController; 33 import java.security.PrivilegedAction; 34 import java.util.Properties; 35 import java.util.ServiceConfigurationError; 36 import java.util.ServiceLoader; 37 38 /** 39 * Implementation of {@link XPathFactory#newInstance(String)}. 40 * 41 * @author <a href="Kohsuke.Kawaguchi@Sun.com">Kohsuke Kawaguchi</a> 42 * @version $Revision: 1.7 $, $Date: 2010-11-01 04:36:14 $ 43 * @since 1.5 44 */ 45 class XPathFactoryFinder { 46 47 private static final String DEFAULT_IMPL_NAME = "com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl"; 48 private static SecuritySupport ss = new SecuritySupport(); 49 /** 50 * debug support code. 51 */ 52 private static boolean debug = false; 53 54 static { 55 // Use try/catch block to support applets 56 try { 57 debug = ss.getSystemProperty("jaxp.debug") != null; 58 } catch (Exception _) { 59 debug = false; 60 } 61 } 62 /** 63 * <p>Cache properties for performance.</p> 64 */ 65 private static Properties cacheProps = new Properties(); 66 /** 67 * <p>First time requires initialization overhead.</p> 68 */ 69 private volatile static boolean firstTime = true; 70 71 /** 72 * <p>Conditional debug printing.</p> 73 * 74 * @param msg to print 75 */ 76 private static void debugPrintln(String msg) { 77 if (debug) { 78 System.err.println("JAXP: " + msg); 79 } 80 } 81 /** 82 * <p><code>ClassLoader</code> to use to find 83 * <code>XPathFactory</code>.</p> 84 */ 85 private final ClassLoader classLoader; 86 87 /** 88 * <p>Constructor that specifies 89 * <code>ClassLoader</code> to use to find 90 * <code>XPathFactory</code>.</p> 91 * 92 * @param loader to be used to load resource, {@link XPathFactory}, and 93 * {@link SchemaFactoryLoader} implementations during the resolution 94 * process. If this parameter is null, the default system class loader will 95 * be used. 96 */ 97 public XPathFactoryFinder(ClassLoader loader) { 98 this.classLoader = loader; 99 if (debug) { 100 debugDisplayClassLoader(); 101 } 102 } 103 104 private void debugDisplayClassLoader() { 105 try { 106 if (classLoader == ss.getContextClassLoader()) { 107 debugPrintln("using thread context class loader (" + classLoader + ") for search"); 108 return; 109 } 110 } catch (Throwable _) { 111 ; // getContextClassLoader() undefined in JDK1.1 112 } 113 114 if (classLoader == ClassLoader.getSystemClassLoader()) { 115 debugPrintln("using system class loader (" + classLoader + ") for search"); 116 return; 117 } 118 119 debugPrintln("using class loader (" + classLoader + ") for search"); 120 } 121 122 /** 123 * <p>Creates a new {@link XPathFactory} object for the specified schema 124 * language.</p> 125 * 126 * @param uri Identifies the underlying object model. 127 * 128 * @return <code>null</code> if the callee fails to create one. 129 * 130 * @throws NullPointerException If the parameter is null. 131 */ 132 public XPathFactory newFactory(String uri) throws XPathFactoryConfigurationException { 133 if (uri == null) { 134 throw new NullPointerException(); 135 } 136 XPathFactory f = _newFactory(uri); 137 if (f != null) { 138 debugPrintln("factory '" + f.getClass().getName() + "' was found for " + uri); 139 } else { 140 debugPrintln("unable to find a factory for " + uri); 141 } 142 return f; 143 } 144 145 /** 146 * <p>Lookup a {@link XPathFactory} for the given object model.</p> 147 * 148 * @param uri identifies the object model. 149 * 150 * @return {@link XPathFactory} for the given object model. 151 */ 152 private XPathFactory _newFactory(String uri) throws XPathFactoryConfigurationException { 153 XPathFactory xpathFactory; 154 155 String propertyName = SERVICE_CLASS.getName() + ":" + uri; 156 157 // system property look up 158 try { 159 debugPrintln("Looking up system property '" + propertyName + "'"); 160 String r = ss.getSystemProperty(propertyName); 161 if (r != null) { 162 debugPrintln("The value is '" + r + "'"); 163 xpathFactory = createInstance(r, true); 164 if (xpathFactory != null) { 165 return xpathFactory; 166 } 167 } else { 168 debugPrintln("The property is undefined."); 169 } 170 } catch (Throwable t) { 171 if (debug) { 172 debugPrintln("failed to look up system property '" + propertyName + "'"); 173 t.printStackTrace(); 174 } 175 } 176 177 String javah = ss.getSystemProperty("java.home"); 178 String configFile = javah + File.separator 179 + "lib" + File.separator + "jaxp.properties"; 180 181 String factoryClassName = null; 182 183 // try to read from $java.home/lib/jaxp.properties 184 try { 185 if (firstTime) { 186 synchronized (cacheProps) { 187 if (firstTime) { 188 File f = new File(configFile); 189 firstTime = false; 190 if (ss.doesFileExist(f)) { 191 debugPrintln("Read properties file " + f); 192 cacheProps.load(ss.getFileInputStream(f)); 193 } 194 } 195 } 196 } 197 factoryClassName = cacheProps.getProperty(propertyName); 198 debugPrintln("found " + factoryClassName + " in $java.home/jaxp.properties"); 199 200 if (factoryClassName != null) { 201 xpathFactory = createInstance(factoryClassName, true); 202 if (xpathFactory != null) { 203 return xpathFactory; 204 } 205 } 206 } catch (Exception ex) { 207 if (debug) { 208 ex.printStackTrace(); 209 } 210 } 211 212 // try finding a service provider 213 xpathFactory = findServiceProvider(uri, DEFAULT_IMPL_NAME); 214 if (xpathFactory != null) { 215 return xpathFactory; 216 } 217 218 // platform default 219 if (uri.equals(XPathFactory.DEFAULT_OBJECT_MODEL_URI)) { 220 debugPrintln("attempting to use the platform default W3C DOM XPath lib"); 221 return createInstance(DEFAULT_IMPL_NAME, true); 222 } 223 224 debugPrintln("all things were tried, but none was found. bailing out."); 225 return null; 226 } 227 228 /** 229 * <p>Create class using appropriate ClassLoader.</p> 230 * 231 * @param className Name of class to create. 232 * @return Created class or <code>null</code>. 233 */ 234 private Class createClass(String className) { 235 Class clazz; 236 237 // use approprite ClassLoader 238 try { 239 if (classLoader != null) { 240 clazz = classLoader.loadClass(className); 241 } else { 242 clazz = Class.forName(className); 243 } 244 } catch (Throwable t) { 245 if (debug) { 246 t.printStackTrace(); 247 } 248 return null; 249 } 250 251 return clazz; 252 } 253 254 /** 255 * <p>Creates an instance of the specified and returns it.</p> 256 * 257 * @param className fully qualified class name to be instanciated. 258 * 259 * @return null if it fails. Error messages will be printed by this method. 260 */ 261 XPathFactory createInstance(String className) { 262 return createInstance(className, false); 263 } 264 265 XPathFactory createInstance(String className, boolean useServicesMechanism) { 266 XPathFactory xPathFactory = null; 267 268 debugPrintln("createInstance(" + className + ")"); 269 270 // get Class from className 271 Class clazz = createClass(className); 272 if (clazz == null) { 273 debugPrintln("failed to getClass(" + className + ")"); 274 return null; 275 } 276 debugPrintln("loaded " + className + " from " + which(clazz)); 277 278 // instantiate Class as a XPathFactory 279 try { 280 if (!useServicesMechanism) { 281 xPathFactory = (XPathFactory) newInstanceNoServiceLoader(clazz); 282 } 283 if (xPathFactory == null) { 284 xPathFactory = (XPathFactory) clazz.newInstance(); 285 } 288 if (debug) { 289 classCastException.printStackTrace(); 290 } 291 return null; 292 } catch (IllegalAccessException illegalAccessException) { 293 debugPrintln("could not instantiate " + clazz.getName()); 294 if (debug) { 295 illegalAccessException.printStackTrace(); 296 } 297 return null; 298 } catch (InstantiationException instantiationException) { 299 debugPrintln("could not instantiate " + clazz.getName()); 300 if (debug) { 301 instantiationException.printStackTrace(); 302 } 303 return null; 304 } 305 306 return xPathFactory; 307 } 308 309 /** 310 * Try to construct using newXPathFactoryNoServiceLoader method if 311 * available. 312 */ 313 private static Object newInstanceNoServiceLoader( 314 Class<?> providerClass) { 315 // Retain maximum compatibility if no security manager. 316 if (System.getSecurityManager() == null) { 317 return null; 318 } 319 try { 320 Method creationMethod = 321 providerClass.getDeclaredMethod( 322 "newXPathFactoryNoServiceLoader"); 323 return creationMethod.invoke(null, null); 324 } catch (NoSuchMethodException exc) { 325 return null; 326 } catch (Exception exc) { 327 return null; 328 } 329 } 330 331 /* 332 * Try to find a provider using Service Loader 333 * 334 * @return instance of provider class if found or null 335 */ 336 private XPathFactory findServiceProvider(final String objectModel, final String fallbackClassName) 337 throws XPathFactoryConfigurationException { 338 try { 339 return (XPathFactory) AccessController.doPrivileged(new PrivilegedAction() { 340 public XPathFactory run() { 341 XPathFactory defaultProvider = null; 342 for (XPathFactory factory : ServiceLoader.load(XPathFactory.class)) { 343 if (factory.getClass().getName().equals(fallbackClassName)) { 344 defaultProvider = factory; 345 } else { 346 if (isObjectModelSupported(factory, objectModel)) { 347 return factory; 348 } 349 } 350 } 351 if (defaultProvider != null) { 352 return defaultProvider; 353 } 354 return null; 355 } 356 }); 357 } catch (ServiceConfigurationError e) { 358 throw new XPathFactoryConfigurationException((Exception) e.getCause()); 359 } 360 } 361 362 /** 363 * <p>Test if the specified schemas are supported by the provider.</p> 364 * 365 * @param schemaFactory a Schema factory provider. 366 * @param schemaLanguage Schema Language to support. 367 * 368 * @return <code>true</code> if the Schema Language is supported by the 369 * provider. 370 */ 371 private static boolean isObjectModelSupported(XPathFactory xPathFactory, String objectModel) { 372 final Class[] stringClassArray = {"".getClass()}; 373 final Object[] objectModelObjectArray = {objectModel}; 374 final String isObjectModelSupportedMethod = "isObjectModelSupported"; 375 // does this Class support desired Schema? 376 try { 377 Method isObjectModelSupported = xPathFactory.getClass().getMethod(isObjectModelSupportedMethod, stringClassArray); 378 Boolean supported = (Boolean) isObjectModelSupported.invoke(xPathFactory, objectModelObjectArray); 379 if (supported.booleanValue()) { 380 return true; 381 } 382 } catch (NoSuchMethodException noSuchMethodException) { 383 } catch (IllegalAccessException illegalAccessException) { 384 } catch (InvocationTargetException invocationTargetException) { 385 } 386 387 return false; 388 } 389 private static final Class SERVICE_CLASS = XPathFactory.class; 390 391 private static String which(Class clazz) { 392 return which(clazz.getName(), clazz.getClassLoader()); 393 } 394 395 /** 396 * <p>Search the specified classloader for the given classname.</p> 397 * 398 * @param classname the fully qualified name of the class to search for 399 * @param loader the classloader to search 400 * 401 * @return the source location of the resource, or null if it wasn't found 402 */ 403 private static String which(String classname, ClassLoader loader) { 404 405 String classnameAsResource = classname.replace('.', '/') + ".class"; 406 407 if (loader == null) { 408 loader = ClassLoader.getSystemClassLoader(); 409 } 410 411 //URL it = loader.getResource(classnameAsResource); 412 URL it = ss.getResourceAsURL(loader, classnameAsResource); 413 if (it != null) { 414 return it.toString(); 415 } else { 416 return null; 417 } 418 } 419 } |