1.1 --- a/src/share/jaxws_classes/javax/xml/soap/FactoryFinder.java Thu Apr 04 19:05:24 2013 -0700 1.2 +++ b/src/share/jaxws_classes/javax/xml/soap/FactoryFinder.java Tue Apr 09 14:51:13 2013 +0100 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -39,16 +39,12 @@ 1.11 * or could not be instantiated 1.12 */ 1.13 private static Object newInstance(String className, 1.14 - ClassLoader classLoader) 1.15 + ClassLoader classLoader, 1.16 + String defaultFactoryClass) 1.17 throws SOAPException 1.18 { 1.19 try { 1.20 - Class spiClass; 1.21 - if (classLoader == null) { 1.22 - spiClass = Class.forName(className); 1.23 - } else { 1.24 - spiClass = classLoader.loadClass(className); 1.25 - } 1.26 + Class spiClass = safeLoadClass(className, classLoader, defaultFactoryClass); 1.27 return spiClass.newInstance(); 1.28 } catch (ClassNotFoundException x) { 1.29 throw new SOAPException( 1.30 @@ -73,68 +69,10 @@ 1.31 * a system property 1.32 * @exception SOAPException if there is a SOAP error 1.33 */ 1.34 - static Object find(String factId) 1.35 + static Object find(String factoryId) 1.36 throws SOAPException 1.37 { 1.38 - final ClassLoader classLoader; 1.39 - final String factoryId = factId; 1.40 - try { 1.41 - classLoader = Thread.currentThread().getContextClassLoader(); 1.42 - } catch (Exception x) { 1.43 - throw new SOAPException(x.toString(), x); 1.44 - } 1.45 - 1.46 - // Use the system property first 1.47 - try { 1.48 - String systemProp = 1.49 - System.getProperty( factoryId ); 1.50 - if( systemProp!=null) { 1.51 - return newInstance(systemProp, classLoader); 1.52 - } 1.53 - } catch (SecurityException se) { 1.54 - } 1.55 - 1.56 - // try to read from $java.home/lib/jaxm.properties 1.57 - try { 1.58 - String javah=System.getProperty( "java.home" ); 1.59 - String configFile = javah + File.separator + 1.60 - "lib" + File.separator + "jaxm.properties"; 1.61 - final File f=new File( configFile ); 1.62 - if( f.exists()) { 1.63 - Properties props=new Properties(); 1.64 - props.load( new FileInputStream(f)); 1.65 - String factoryClassName = props.getProperty(factoryId); 1.66 - return newInstance(factoryClassName, classLoader); 1.67 - } 1.68 - } catch(Exception ex ) { 1.69 - } 1.70 - 1.71 - String serviceId = "META-INF/services/" + factoryId; 1.72 - // try to find services in CLASSPATH 1.73 - try { 1.74 - InputStream is=null; 1.75 - if (classLoader == null) { 1.76 - is=ClassLoader.getSystemResourceAsStream(serviceId); 1.77 - } else { 1.78 - is=classLoader.getResourceAsStream(serviceId); 1.79 - } 1.80 - 1.81 - if( is!=null ) { 1.82 - BufferedReader rd = 1.83 - new BufferedReader(new InputStreamReader(is, "UTF-8")); 1.84 - 1.85 - String factoryClassName = rd.readLine(); 1.86 - rd.close(); 1.87 - 1.88 - if (factoryClassName != null && 1.89 - ! "".equals(factoryClassName)) { 1.90 - return newInstance(factoryClassName, classLoader); 1.91 - } 1.92 - } 1.93 - } catch( Exception ex ) { 1.94 - } 1.95 - 1.96 - return null; 1.97 + return find(factoryId, null, false); 1.98 } 1.99 1.100 /** 1.101 @@ -160,11 +98,35 @@ 1.102 static Object find(String factoryId, String fallbackClassName) 1.103 throws SOAPException 1.104 { 1.105 + return find(factoryId, fallbackClassName, true); 1.106 + } 1.107 1.108 - Object obj = find(factoryId); 1.109 - if (obj != null) 1.110 - return obj; 1.111 - 1.112 + /** 1.113 + * Finds the implementation <code>Class</code> object for the given 1.114 + * factory name, or if that fails, finds the <code>Class</code> object 1.115 + * for the given default class name, but only if <code>tryFallback</code> 1.116 + * is <code>true</code>. The arguments supplied must be used in order 1.117 + * If using the first argument is successful, the second one will not 1.118 + * be used. Note the default class name may be needed even if fallback 1.119 + * is not to be attempted, so certain error condiitons can be handled. 1.120 + * <P> 1.121 + * This method is package private so that this code can be shared. 1.122 + * 1.123 + * @return the <code>Class</code> object of the specified message factory; 1.124 + * may not be <code>null</code> 1.125 + * 1.126 + * @param factoryId the name of the factory to find, which is 1.127 + * a system property 1.128 + * @param defaultClassName the implementation class name, which is 1.129 + * to be used only if nothing else 1.130 + * is found; <code>null</code> to indicate 1.131 + * that there is no default class name 1.132 + * @param tryFallback whether to try the default class as a 1.133 + * fallback 1.134 + * @exception SOAPException if there is a SOAP error 1.135 + */ 1.136 + static Object find(String factoryId, String defaultClassName, 1.137 + boolean tryFallback) throws SOAPException { 1.138 ClassLoader classLoader; 1.139 try { 1.140 classLoader = Thread.currentThread().getContextClassLoader(); 1.141 @@ -172,11 +134,99 @@ 1.142 throw new SOAPException(x.toString(), x); 1.143 } 1.144 1.145 - if (fallbackClassName == null) { 1.146 + // Use the system property first 1.147 + try { 1.148 + String systemProp = 1.149 + System.getProperty( factoryId ); 1.150 + if( systemProp!=null) { 1.151 + return newInstance(systemProp, classLoader, defaultClassName); 1.152 + } 1.153 + } catch (SecurityException se) { 1.154 + } 1.155 + 1.156 + // try to read from $java.home/lib/jaxm.properties 1.157 + try { 1.158 + String javah=System.getProperty( "java.home" ); 1.159 + String configFile = javah + File.separator + 1.160 + "lib" + File.separator + "jaxm.properties"; 1.161 + File f=new File( configFile ); 1.162 + if( f.exists()) { 1.163 + Properties props=new Properties(); 1.164 + props.load( new FileInputStream(f)); 1.165 + String factoryClassName = props.getProperty(factoryId); 1.166 + return newInstance(factoryClassName, classLoader, defaultClassName); 1.167 + } 1.168 + } catch(Exception ex ) { 1.169 + } 1.170 + 1.171 + String serviceId = "META-INF/services/" + factoryId; 1.172 + // try to find services in CLASSPATH 1.173 + try { 1.174 + InputStream is=null; 1.175 + if (classLoader == null) { 1.176 + is=ClassLoader.getSystemResourceAsStream(serviceId); 1.177 + } else { 1.178 + is=classLoader.getResourceAsStream(serviceId); 1.179 + } 1.180 + 1.181 + if( is!=null ) { 1.182 + BufferedReader rd = 1.183 + new BufferedReader(new InputStreamReader(is, "UTF-8")); 1.184 + 1.185 + String factoryClassName = rd.readLine(); 1.186 + rd.close(); 1.187 + 1.188 + if (factoryClassName != null && 1.189 + ! "".equals(factoryClassName)) { 1.190 + return newInstance(factoryClassName, classLoader, defaultClassName); 1.191 + } 1.192 + } 1.193 + } catch( Exception ex ) { 1.194 + } 1.195 + 1.196 + // If not found and fallback should not be tried, return a null result. 1.197 + if (!tryFallback) 1.198 + return null; 1.199 + 1.200 + // We didn't find the class through the usual means so try the default 1.201 + // (built in) factory if specified. 1.202 + if (defaultClassName == null) { 1.203 throw new SOAPException( 1.204 "Provider for " + factoryId + " cannot be found", null); 1.205 } 1.206 + return newInstance(defaultClassName, classLoader, defaultClassName); 1.207 + } 1.208 1.209 - return newInstance(fallbackClassName, classLoader); 1.210 + /** 1.211 + * Loads the class, provided that the calling thread has an access to the 1.212 + * class being loaded. If this is the specified default factory class and it 1.213 + * is restricted by package.access we get a SecurityException and can do a 1.214 + * Class.forName() on it so it will be loaded by the bootstrap class loader. 1.215 + */ 1.216 + private static Class safeLoadClass(String className, 1.217 + ClassLoader classLoader, String defaultFactoryClass) 1.218 + throws ClassNotFoundException { 1.219 + try { 1.220 + // make sure that the current thread has an access to the package of the given name. 1.221 + SecurityManager s = System.getSecurityManager(); 1.222 + if (s != null) { 1.223 + int i = className.lastIndexOf('.'); 1.224 + if (i != -1) { 1.225 + s.checkPackageAccess(className.substring(0, i)); 1.226 + } 1.227 + } 1.228 + 1.229 + if (classLoader == null) 1.230 + return Class.forName(className); 1.231 + else 1.232 + return classLoader.loadClass(className); 1.233 + } catch (SecurityException se) { 1.234 + // The FactoryFinder is in the bootstrap class loader, so 1.235 + // the following should work, but we only attempt it 1.236 + // if it the the default class. 1.237 + if (className.equals(defaultFactoryClass)) 1.238 + return Class.forName(className); 1.239 + throw se; 1.240 + } 1.241 } 1.242 }