1 /* 2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 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.validation; 27 28 import java.io.File; 29 import java.lang.reflect.Method; 30 import java.lang.reflect.Modifier; 31 import java.security.AccessControlContext; 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 SchemaFactory#newInstance(String)}. 40 * 41 * @author <a href="Kohsuke.Kawaguchi@Sun.com">Kohsuke Kawaguchi</a> 42 * @since 1.5 43 */ 44 class SchemaFactoryFinder { 45 46 /** debug support code. */ 47 private static boolean debug = false; 48 /** 49 *<p> Take care of restrictions imposed by java security model </p> 50 */ 51 private static final SecuritySupport ss = new SecuritySupport(); 52 private static final String DEFAULT_PACKAGE = "com.sun.org.apache.xerces.internal"; 53 /** 54 * <p>Cache properties for performance.</p> 55 */ 56 private static final Properties cacheProps = new Properties(); 57 58 /** 59 * <p>First time requires initialization overhead.</p> 60 */ 61 private static volatile boolean firstTime = true; 62 63 static { 64 // Use try/catch block to support applets 65 try { 66 debug = ss.getSystemProperty("jaxp.debug") != null; 67 } catch (Exception unused) { 68 debug = false; 69 } 70 } 71 72 /** 73 * <p>Conditional debug printing.</p> 74 * 75 * @param msg to print 76 */ 77 private static void debugPrintln(String msg) { 78 if (debug) { 79 System.err.println("JAXP: " + msg); 80 } 81 } 82 83 /** 84 * <p><code>ClassLoader</code> to use to find <code>SchemaFactory</code>.</p> 85 */ 86 private final ClassLoader classLoader; 87 88 /** 89 * <p>Constructor that specifies <code>ClassLoader</code> to use 90 * to find <code>SchemaFactory</code>.</p> 91 * 92 * @param loader 93 * to be used to load resource, {@link SchemaFactory}, and 94 * {@link SchemaFactoryLoader} implementations during 95 * the resolution process. 96 * If this parameter is null, the default system class loader 97 * will be used. 98 */ 99 public SchemaFactoryFinder(ClassLoader loader) { 100 this.classLoader = loader; 101 if( debug ) { 102 debugDisplayClassLoader(); 103 } 104 } 105 106 private void debugDisplayClassLoader() { 107 try { 108 if( classLoader == ss.getContextClassLoader() ) { 109 debugPrintln("using thread context class loader ("+classLoader+") for search"); 110 return; 111 } 112 } catch( Throwable unused ) { 113 // getContextClassLoader() undefined in JDK1.1 114 } 115 116 if( classLoader==ClassLoader.getSystemClassLoader() ) { 117 debugPrintln("using system class loader ("+classLoader+") for search"); 118 return; 119 } 120 121 debugPrintln("using class loader ("+classLoader+") for search"); 122 } 123 124 /** 125 * <p>Creates a new {@link SchemaFactory} object for the specified 126 * schema language.</p> 127 * 128 * @param schemaLanguage 129 * See {@link SchemaFactory Schema Language} table in <code>SchemaFactory</code> 130 * for the list of available schema languages. 131 * 132 * @return <code>null</code> if the callee fails to create one. 133 * 134 * @throws NullPointerException 135 * If the <code>schemaLanguage</code> parameter is null. 136 * @throws SchemaFactoryConfigurationError 137 * If a configuration error is encountered. 138 */ 139 public SchemaFactory newFactory(String schemaLanguage) { 140 if(schemaLanguage==null) { 141 throw new NullPointerException(); 142 } 143 SchemaFactory f = _newFactory(schemaLanguage); 144 if (f != null) { 145 debugPrintln("factory '" + f.getClass().getName() + "' was found for " + schemaLanguage); 146 } else { 147 debugPrintln("unable to find a factory for " + schemaLanguage); 148 } 149 return f; 150 } 151 152 /** 153 * <p>Lookup a <code>SchemaFactory</code> for the given <code>schemaLanguage</code>.</p> 154 * 155 * @param schemaLanguage Schema language to lookup <code>SchemaFactory</code> for. 156 * 157 * @return <code>SchemaFactory</code> for the given <code>schemaLanguage</code>. 158 */ 159 private SchemaFactory _newFactory(String schemaLanguage) { 160 SchemaFactory sf; 161 162 String propertyName = SERVICE_CLASS.getName() + ":" + schemaLanguage; 163 164 // system property look up 165 try { 166 debugPrintln("Looking up system property '"+propertyName+"'" ); 167 String r = ss.getSystemProperty(propertyName); 168 if(r!=null) { 169 debugPrintln("The value is '"+r+"'"); 170 sf = createInstance(r, true); 171 if(sf!=null) return sf; 172 } else 173 debugPrintln("The property is undefined."); 174 } catch( Throwable t ) { 175 if( debug ) { 176 debugPrintln("failed to look up system property '"+propertyName+"'" ); 177 t.printStackTrace(); 178 } 179 } 180 181 String javah = ss.getSystemProperty( "java.home" ); 182 String configFile = javah + File.separator + 183 "conf" + File.separator + "jaxp.properties"; 184 185 186 // try to read from $java.home/conf/jaxp.properties 187 try { 188 if(firstTime){ 189 synchronized(cacheProps){ 190 if(firstTime){ 191 File f=new File( configFile ); 192 firstTime = false; 193 if(ss.doesFileExist(f)){ 194 debugPrintln("Read properties file " + f); 195 cacheProps.load(ss.getFileInputStream(f)); 196 } 197 } 198 } 199 } 200 final String factoryClassName = cacheProps.getProperty(propertyName); 201 debugPrintln("found " + factoryClassName + " in $java.home/conf/jaxp.properties"); 202 203 if (factoryClassName != null) { 204 sf = createInstance(factoryClassName, true); 205 if(sf != null){ 206 return sf; 207 } 208 } 209 } catch (Exception ex) { 210 if (debug) { 211 ex.printStackTrace(); 212 } 213 } 214 215 // Try with ServiceLoader 216 final SchemaFactory factoryImpl = findServiceProvider(schemaLanguage); 217 218 // The following assertion should always be true. 219 // Uncomment it, recompile, and run with -ea in case of doubts: 220 // assert factoryImpl == null || factoryImpl.isSchemaLanguageSupported(schemaLanguage); 221 222 if (factoryImpl != null) { 223 return factoryImpl; 224 } 225 226 // platform default 227 if(schemaLanguage.equals("http://www.w3.org/2001/XMLSchema")) { 228 debugPrintln("attempting to use the platform default XML Schema validator"); 229 return createInstance("com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory", true); 230 } 231 232 debugPrintln("all things were tried, but none was found. bailing out."); 233 return null; 234 } 235 236 /** <p>Create class using appropriate ClassLoader.</p> 237 * 238 * @param className Name of class to create. 239 * @return Created class or <code>null</code>. 240 */ 241 private Class<?> createClass(String className) { 242 Class<?> clazz; 243 // make sure we have access to restricted packages 244 boolean internal = false; 245 if (System.getSecurityManager() != null) { 246 if (className != null && className.startsWith(DEFAULT_PACKAGE)) { 247 internal = true; 248 } 249 } 250 251 try { 252 if (classLoader != null && !internal) { 263 264 return clazz; 265 } 266 267 /** 268 * <p>Creates an instance of the specified and returns it.</p> 269 * 270 * @param className 271 * fully qualified class name to be instantiated. 272 * 273 * @return null 274 * if it fails. Error messages will be printed by this method. 275 */ 276 SchemaFactory createInstance( String className ) { 277 return createInstance( className, false ); 278 } 279 280 SchemaFactory createInstance( String className, boolean useServicesMechanism ) { 281 SchemaFactory schemaFactory = null; 282 283 debugPrintln("createInstance(" + className + ")"); 284 285 // get Class from className 286 Class<?> clazz = createClass(className); 287 if (clazz == null) { 288 debugPrintln("failed to getClass(" + className + ")"); 289 return null; 290 } 291 debugPrintln("loaded " + className + " from " + which(clazz)); 292 293 // instantiate Class as a SchemaFactory 294 try { 295 if (!SchemaFactory.class.isAssignableFrom(clazz)) { 296 throw new ClassCastException(clazz.getName() 297 + " cannot be cast to " + SchemaFactory.class); 298 } 299 if (!useServicesMechanism) { 300 schemaFactory = newInstanceNoServiceLoader(clazz); 301 } 302 if (schemaFactory == null) { 303 schemaFactory = (SchemaFactory) clazz.newInstance(); 304 } 305 } catch (ClassCastException classCastException) { 306 debugPrintln("could not instantiate " + clazz.getName()); 307 if (debug) { 308 classCastException.printStackTrace(); 309 } 310 return null; 311 } catch (IllegalAccessException illegalAccessException) { 312 debugPrintln("could not instantiate " + clazz.getName()); 313 if (debug) { 314 illegalAccessException.printStackTrace(); 315 } 316 return null; 317 } catch (InstantiationException instantiationException) { 318 debugPrintln("could not instantiate " + clazz.getName()); 319 if (debug) { 320 instantiationException.printStackTrace(); 321 } 322 return null; 323 } 324 325 return schemaFactory; 326 } 327 328 /** 329 * Try to construct using newXMLSchemaFactoryNoServiceLoader 330 * method if available. 331 */ 332 private static SchemaFactory newInstanceNoServiceLoader( 333 Class<?> providerClass 334 ) { 335 // Retain maximum compatibility if no security manager. 336 if (System.getSecurityManager() == null) { 337 return null; 338 } | 1 /* 2 * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 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.validation; 27 28 import java.io.File; 29 import java.lang.reflect.Method; 30 import java.lang.reflect.Modifier; 31 import java.security.AccessControlContext; 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 import java.util.function.Supplier; 38 39 /** 40 * Implementation of {@link SchemaFactory#newInstance(String)}. 41 * 42 * @author <a href="Kohsuke.Kawaguchi@Sun.com">Kohsuke Kawaguchi</a> 43 * @since 1.5 44 */ 45 class SchemaFactoryFinder { 46 47 /** debug support code. */ 48 private static boolean debug = false; 49 /** 50 *<p> Take care of restrictions imposed by java security model </p> 51 */ 52 private static final SecuritySupport ss = new SecuritySupport(); 53 private static final String DEFAULT_PACKAGE = "com.sun.org.apache.xerces.internal"; 54 /** 55 * <p>Cache properties for performance.</p> 56 */ 57 private static final Properties cacheProps = new Properties(); 58 59 /** 60 * <p>First time requires initialization overhead.</p> 61 */ 62 private static volatile boolean firstTime = true; 63 64 static { 65 // Use try/catch block to support applets 66 try { 67 debug = ss.getSystemProperty("jaxp.debug") != null; 68 } catch (Exception unused) { 69 debug = false; 70 } 71 } 72 73 /** 74 * <p>Conditional debug printing.</p> 75 * 76 * @param msgGen Supplier function that returns debug message 77 */ 78 private static void debugPrintln(Supplier<String> msgGen) { 79 if (debug) { 80 System.err.println("JAXP: " + msgGen.get()); 81 } 82 } 83 84 /** 85 * <p><code>ClassLoader</code> to use to find <code>SchemaFactory</code>.</p> 86 */ 87 private final ClassLoader classLoader; 88 89 /** 90 * <p>Constructor that specifies <code>ClassLoader</code> to use 91 * to find <code>SchemaFactory</code>.</p> 92 * 93 * @param loader 94 * to be used to load resource, {@link SchemaFactory}, and 95 * {@link SchemaFactoryLoader} implementations during 96 * the resolution process. 97 * If this parameter is null, the default system class loader 98 * will be used. 99 */ 100 public SchemaFactoryFinder(ClassLoader loader) { 101 this.classLoader = loader; 102 if( debug ) { 103 debugDisplayClassLoader(); 104 } 105 } 106 107 private void debugDisplayClassLoader() { 108 try { 109 if( classLoader == ss.getContextClassLoader() ) { 110 debugPrintln(()->"using thread context class loader ("+classLoader+") for search"); 111 return; 112 } 113 } catch( Throwable unused ) { 114 // getContextClassLoader() undefined in JDK1.1 115 } 116 117 if( classLoader==ClassLoader.getSystemClassLoader() ) { 118 debugPrintln(()->"using system class loader ("+classLoader+") for search"); 119 return; 120 } 121 122 debugPrintln(()->"using class loader ("+classLoader+") for search"); 123 } 124 125 /** 126 * <p>Creates a new {@link SchemaFactory} object for the specified 127 * schema language.</p> 128 * 129 * @param schemaLanguage 130 * See {@link SchemaFactory Schema Language} table in <code>SchemaFactory</code> 131 * for the list of available schema languages. 132 * 133 * @return <code>null</code> if the callee fails to create one. 134 * 135 * @throws NullPointerException 136 * If the <code>schemaLanguage</code> parameter is null. 137 * @throws SchemaFactoryConfigurationError 138 * If a configuration error is encountered. 139 */ 140 public SchemaFactory newFactory(String schemaLanguage) { 141 if(schemaLanguage==null) { 142 throw new NullPointerException(); 143 } 144 SchemaFactory f = _newFactory(schemaLanguage); 145 if (f != null) { 146 debugPrintln(()->"factory '" + f.getClass().getName() + "' was found for " + schemaLanguage); 147 } else { 148 debugPrintln(()->"unable to find a factory for " + schemaLanguage); 149 } 150 return f; 151 } 152 153 /** 154 * <p>Lookup a <code>SchemaFactory</code> for the given <code>schemaLanguage</code>.</p> 155 * 156 * @param schemaLanguage Schema language to lookup <code>SchemaFactory</code> for. 157 * 158 * @return <code>SchemaFactory</code> for the given <code>schemaLanguage</code>. 159 */ 160 private SchemaFactory _newFactory(String schemaLanguage) { 161 SchemaFactory sf; 162 163 String propertyName = SERVICE_CLASS.getName() + ":" + schemaLanguage; 164 165 // system property look up 166 try { 167 debugPrintln(()->"Looking up system property '"+propertyName+"'" ); 168 String r = ss.getSystemProperty(propertyName); 169 if(r!=null) { 170 debugPrintln(()->"The value is '"+r+"'"); 171 sf = createInstance(r, true); 172 if(sf!=null) return sf; 173 } else 174 debugPrintln(()->"The property is undefined."); 175 } catch( Throwable t ) { 176 if( debug ) { 177 debugPrintln(()->"failed to look up system property '"+propertyName+"'" ); 178 t.printStackTrace(); 179 } 180 } 181 182 String javah = ss.getSystemProperty( "java.home" ); 183 String configFile = javah + File.separator + 184 "conf" + File.separator + "jaxp.properties"; 185 186 187 // try to read from $java.home/conf/jaxp.properties 188 try { 189 if(firstTime){ 190 synchronized(cacheProps){ 191 if(firstTime){ 192 File f=new File( configFile ); 193 firstTime = false; 194 if(ss.doesFileExist(f)){ 195 debugPrintln(()->"Read properties file " + f); 196 cacheProps.load(ss.getFileInputStream(f)); 197 } 198 } 199 } 200 } 201 final String factoryClassName = cacheProps.getProperty(propertyName); 202 debugPrintln(()->"found " + factoryClassName + " in $java.home/conf/jaxp.properties"); 203 204 if (factoryClassName != null) { 205 sf = createInstance(factoryClassName, true); 206 if(sf != null){ 207 return sf; 208 } 209 } 210 } catch (Exception ex) { 211 if (debug) { 212 ex.printStackTrace(); 213 } 214 } 215 216 // Try with ServiceLoader 217 final SchemaFactory factoryImpl = findServiceProvider(schemaLanguage); 218 219 // The following assertion should always be true. 220 // Uncomment it, recompile, and run with -ea in case of doubts: 221 // assert factoryImpl == null || factoryImpl.isSchemaLanguageSupported(schemaLanguage); 222 223 if (factoryImpl != null) { 224 return factoryImpl; 225 } 226 227 // platform default 228 if(schemaLanguage.equals("http://www.w3.org/2001/XMLSchema")) { 229 debugPrintln(()->"attempting to use the platform default XML Schema validator"); 230 return createInstance("com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory", true); 231 } 232 233 debugPrintln(()->"all things were tried, but none was found. bailing out."); 234 return null; 235 } 236 237 /** <p>Create class using appropriate ClassLoader.</p> 238 * 239 * @param className Name of class to create. 240 * @return Created class or <code>null</code>. 241 */ 242 private Class<?> createClass(String className) { 243 Class<?> clazz; 244 // make sure we have access to restricted packages 245 boolean internal = false; 246 if (System.getSecurityManager() != null) { 247 if (className != null && className.startsWith(DEFAULT_PACKAGE)) { 248 internal = true; 249 } 250 } 251 252 try { 253 if (classLoader != null && !internal) { 264 265 return clazz; 266 } 267 268 /** 269 * <p>Creates an instance of the specified and returns it.</p> 270 * 271 * @param className 272 * fully qualified class name to be instantiated. 273 * 274 * @return null 275 * if it fails. Error messages will be printed by this method. 276 */ 277 SchemaFactory createInstance( String className ) { 278 return createInstance( className, false ); 279 } 280 281 SchemaFactory createInstance( String className, boolean useServicesMechanism ) { 282 SchemaFactory schemaFactory = null; 283 284 debugPrintln(()->"createInstance(" + className + ")"); 285 286 // get Class from className 287 Class<?> clazz = createClass(className); 288 if (clazz == null) { 289 debugPrintln(()->"failed to getClass(" + className + ")"); 290 return null; 291 } 292 debugPrintln(()->"loaded " + className + " from " + which(clazz)); 293 294 // instantiate Class as a SchemaFactory 295 try { 296 if (!SchemaFactory.class.isAssignableFrom(clazz)) { 297 throw new ClassCastException(clazz.getName() 298 + " cannot be cast to " + SchemaFactory.class); 299 } 300 if (!useServicesMechanism) { 301 schemaFactory = newInstanceNoServiceLoader(clazz); 302 } 303 if (schemaFactory == null) { 304 schemaFactory = (SchemaFactory) clazz.newInstance(); 305 } 306 } catch (ClassCastException classCastException) { 307 debugPrintln(()->"could not instantiate " + clazz.getName()); 308 if (debug) { 309 classCastException.printStackTrace(); 310 } 311 return null; 312 } catch (IllegalAccessException illegalAccessException) { 313 debugPrintln(()->"could not instantiate " + clazz.getName()); 314 if (debug) { 315 illegalAccessException.printStackTrace(); 316 } 317 return null; 318 } catch (InstantiationException instantiationException) { 319 debugPrintln(()->"could not instantiate " + clazz.getName()); 320 if (debug) { 321 instantiationException.printStackTrace(); 322 } 323 return null; 324 } 325 326 return schemaFactory; 327 } 328 329 /** 330 * Try to construct using newXMLSchemaFactoryNoServiceLoader 331 * method if available. 332 */ 333 private static SchemaFactory newInstanceNoServiceLoader( 334 Class<?> providerClass 335 ) { 336 // Retain maximum compatibility if no security manager. 337 if (System.getSecurityManager() == null) { 338 return null; 339 } |