src/javax/xml/validation/SchemaFactoryFinder.java

Print this page




   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.BufferedReader;
  29 import java.io.File;
  30 import java.io.IOException;
  31 import java.io.InputStream;
  32 import java.io.InputStreamReader;
  33 import java.lang.reflect.Method;
  34 import java.lang.reflect.InvocationTargetException;
  35 import java.net.URL;
  36 import java.util.ArrayList;
  37 import java.util.Enumeration;
  38 import java.util.Iterator;
  39 import java.util.NoSuchElementException;
  40 import java.util.Properties;


  41 
  42 /**
  43  * Implementation of {@link SchemaFactory#newInstance(String)}.
  44  *
  45  * @author <a href="Kohsuke.Kawaguchi@Sun.com">Kohsuke Kawaguchi</a>
  46  * @version $Revision: 1.8 $, $Date: 2010-11-01 04:36:13 $
  47  * @since 1.5
  48  */
  49 class SchemaFactoryFinder  {
  50 
  51     /** debug support code. */
  52     private static boolean debug = false;
  53     /**
  54      *<p> Take care of restrictions imposed by java security model </p>
  55      */
  56     private static SecuritySupport ss = new SecuritySupport();
  57     /**
  58      * <p>Cache properties for performance.</p>
  59      */
  60         private static Properties cacheProps = new Properties();
  61 
  62         /**
  63          * <p>First time requires initialization overhead.</p>
  64          */
  65         private static volatile boolean firstTime = true;
  66 
  67     static {
  68         // Use try/catch block to support applets
  69         try {
  70             debug = ss.getSystemProperty("jaxp.debug") != null;
  71         } catch (Exception _) {
  72             debug = false;
  73         }
  74     }
  75 
  76     /**
  77      * <p>Conditional debug printing.</p>
  78      *
  79      * @param msg to print
  80      */
  81     private static void debugPrintln(String msg) {


  97      *      to be used to load resource, {@link SchemaFactory}, and
  98      *      {@link SchemaFactoryLoader} implementations during
  99      *      the resolution process.
 100      *      If this parameter is null, the default system class loader
 101      *      will be used.
 102      */
 103     public SchemaFactoryFinder(ClassLoader loader) {
 104         this.classLoader = loader;
 105         if( debug ) {
 106             debugDisplayClassLoader();
 107         }
 108     }
 109 
 110     private void debugDisplayClassLoader() {
 111         try {
 112             if( classLoader == ss.getContextClassLoader() ) {
 113                 debugPrintln("using thread context class loader ("+classLoader+") for search");
 114                 return;
 115             }
 116         } catch( Throwable _ ) {
 117             ; // getContextClassLoader() undefined in JDK1.1
 118         }
 119 
 120         if( classLoader==ClassLoader.getSystemClassLoader() ) {
 121             debugPrintln("using system class loader ("+classLoader+") for search");
 122             return;
 123         }
 124 
 125         debugPrintln("using class loader ("+classLoader+") for search");
 126     }
 127 
 128     /**
 129      * <p>Creates a new {@link SchemaFactory} object for the specified
 130      * schema language.</p>
 131      *
 132      * @param schemaLanguage
 133      *      See {@link SchemaFactory Schema Language} table in <code>SchemaFactory</code>
 134      *      for the list of available schema languages.
 135      *
 136      * @return <code>null</code> if the callee fails to create one.
 137      *
 138      * @throws NullPointerException
 139      *      If the <code>schemaLanguage</code> parameter is null.


 140      */
 141     public SchemaFactory newFactory(String schemaLanguage) {
 142         if(schemaLanguage==null)        throw new NullPointerException();


 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;


 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         "lib" + File.separator + "jaxp.properties";
 184 
 185         String factoryClassName = null ;
 186 
 187         // try to read from $java.home/lib/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             factoryClassName = cacheProps.getProperty(propertyName);
 202             debugPrintln("found " + factoryClassName + " in $java.home/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         /**
 217         // try to read from $java.home/lib/jaxp.properties
 218         try {
 219             String javah = ss.getSystemProperty( "java.home" );
 220             String configFile = javah + File.separator +
 221             "lib" + File.separator + "jaxp.properties";
 222             File f = new File( configFile );
 223             if( ss.doesFileExist(f)) {
 224                 sf = loadFromProperty(
 225                         propertyName,f.getAbsolutePath(), new FileInputStream(f));
 226                 if(sf!=null)    return sf;
 227             } else {
 228                 debugPrintln("Tried to read "+ f.getAbsolutePath()+", but it doesn't exist.");
 229             }
 230         } catch(Throwable e) {
 231             if( debug ) {
 232                 debugPrintln("failed to read $java.home/lib/jaxp.properties");
 233                 e.printStackTrace();
 234             }
 235         }
 236          */
 237 
 238         // try META-INF/services files
 239         Iterator sitr = createServiceFileIterator();
 240         while(sitr.hasNext()) {
 241             URL resource = (URL)sitr.next();
 242             debugPrintln("looking into " + resource);
 243             try {
 244                 sf = loadFromService(schemaLanguage,resource.toExternalForm(),
 245                                                 ss.getURLInputStream(resource));
 246                 if(sf!=null)    return sf;
 247             } catch(IOException e) {
 248                 if( debug ) {
 249                     debugPrintln("failed to read "+resource);
 250                     e.printStackTrace();
 251                 }
 252             }
 253         }
 254 
 255         // platform default
 256         if(schemaLanguage.equals("http://www.w3.org/2001/XMLSchema")) {
 257             debugPrintln("attempting to use the platform default XML Schema validator");
 258             return createInstance("com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory", true);
 259         }
 260 
 261         debugPrintln("all things were tried, but none was found. bailing out.");
 262         return null;
 263     }
 264 
 265     /** <p>Create class using appropriate ClassLoader.</p>
 266      *
 267      * @param className Name of class to create.
 268      * @return Created class or <code>null</code>.
 269      */
 270     private Class createClass(String className) {
 271             Class clazz;
 272 
 273             // use approprite ClassLoader
 274             try {
 275                     if (classLoader != null) {
 276                             clazz = classLoader.loadClass(className);
 277                     } else {
 278                             clazz = Class.forName(className);
 279                     }
 280             } catch (Throwable t) {
 281                 if(debug)   t.printStackTrace();


 282                     return null;
 283             }
 284 
 285             return clazz;
 286     }
 287 
 288     /**
 289      * <p>Creates an instance of the specified and returns it.</p>
 290      *
 291      * @param className
 292      *      fully qualified class name to be instanciated.
 293      *
 294      * @return null
 295      *      if it fails. Error messages will be printed by this method.
 296      */
 297     SchemaFactory createInstance( String className ) {
 298         return createInstance( className, false );
 299     }
 300 
 301     SchemaFactory createInstance( String className, boolean useServicesMechanism ) {
 302         SchemaFactory schemaFactory = null;
 303 
 304         debugPrintln("createInstance(" + className + ")");
 305 
 306         // get Class from className
 307         Class clazz = createClass(className);
 308         if (clazz == null) {
 309                 debugPrintln("failed to getClass(" + className + ")");
 310                 return null;
 311         }
 312         debugPrintln("loaded " + className + " from " + which(clazz));
 313 
 314         // instantiate Class as a SchemaFactory
 315         try {




 316             if (!useServicesMechanism) {
 317                 schemaFactory = (SchemaFactory) newInstanceNoServiceLoader(clazz);
 318             }
 319                 if (schemaFactory == null) {
 320                     schemaFactory = (SchemaFactory) clazz.newInstance();
 321                 }
 322         } catch (ClassCastException classCastException) {
 323                 debugPrintln("could not instantiate " + clazz.getName());
 324                 if (debug) {
 325                         classCastException.printStackTrace();
 326                 }
 327                 return null;
 328         } catch (IllegalAccessException illegalAccessException) {
 329                 debugPrintln("could not instantiate " + clazz.getName());
 330                 if (debug) {
 331                         illegalAccessException.printStackTrace();
 332                 }
 333                 return null;
 334         } catch (InstantiationException instantiationException) {
 335                 debugPrintln("could not instantiate " + clazz.getName());
 336                 if (debug) {
 337                         instantiationException.printStackTrace();
 338                 }
 339                 return null;
 340         }
 341 
 342         return schemaFactory;
 343     }

 344     /**
 345      * Try to construct using newTransformerFactoryNoServiceLoader
 346      *   method if available.
 347      */
 348     private static Object newInstanceNoServiceLoader(
 349          Class<?> providerClass
 350     ) {
 351         // Retain maximum compatibility if no security manager.
 352         if (System.getSecurityManager() == null) {
 353             return null;
 354         }
 355         try {
 356             Method creationMethod =
 357                 providerClass.getDeclaredMethod(
 358                     "newXMLSchemaFactoryNoServiceLoader"
 359                 );
 360                 return creationMethod.invoke(null, (Object[])null);
 361             } catch (NoSuchMethodException exc) {
 362                 return null;
 363             } catch (Exception exc) {
 364                 return null;
 365         }
 366     }
 367 
 368     /** Iterator that lazily computes one value and returns it. */
 369     private static abstract class SingleIterator implements Iterator {
 370         private boolean seen = false;
 371 
 372         public final void remove() { throw new UnsupportedOperationException(); }
 373         public final boolean hasNext() { return !seen; }
 374         public final Object next() {
 375             if(seen)    throw new NoSuchElementException();
 376             seen = true;
 377             return value();
 378         }
 379 
 380         protected abstract Object value();
 381     }
 382 
 383     /**
 384      * Looks up a value in a property file
 385      * while producing all sorts of debug messages.
 386      *
 387      * @return null
 388      *      if there was an error.
 389      */
 390     private SchemaFactory loadFromProperty( String keyName, String resourceName, InputStream in )
 391         throws IOException {
 392         debugPrintln("Reading "+resourceName );
 393 
 394         Properties props=new Properties();
 395         props.load(in);
 396         in.close();
 397         String factoryClassName = props.getProperty(keyName);
 398         if(factoryClassName != null){
 399             debugPrintln("found "+keyName+" = " + factoryClassName);
 400             return createInstance(factoryClassName);
 401         } else {
 402             debugPrintln(keyName+" is not in the property file");
 403             return null;
 404         }
 405     }
 406 
 407     /**
 408      * <p>Look up a value in a property file.</p>
 409      *
 410      * <p>Set <code>debug</code> to <code>true</code> to trace property evaluation.</p>
 411      *
 412      * @param schemaLanguage Schema Language to support.
 413      * @param inputName Name of <code>InputStream</code>.
 414      * @param in <code>InputStream</code> of properties.
 415      *
 416      * @return <code>SchemaFactory</code> as determined by <code>keyName</code> value or <code>null</code> if there was an error.
 417      *
 418      * @throws IOException If IO error reading from <code>in</code>.
 419      */
 420     private SchemaFactory loadFromService(
 421             String schemaLanguage,
 422             String inputName,
 423             InputStream in)
 424             throws IOException {
 425 
 426             SchemaFactory schemaFactory = null;
 427             final Class[] stringClassArray = {"".getClass()};
 428             final Object[] schemaLanguageObjectArray = {schemaLanguage};
 429             final String isSchemaLanguageSupportedMethod = "isSchemaLanguageSupported";
 430 
 431             debugPrintln("Reading " + inputName);
 432 
 433             // read from InputStream until a match is found
 434             BufferedReader configFile = new BufferedReader(new InputStreamReader(in));
 435             String line = null;
 436             while ((line = configFile.readLine()) != null) {
 437                     // '#' is comment char
 438                     int comment = line.indexOf("#");
 439                     switch (comment) {
 440                             case -1: break; // no comment
 441                             case 0: line = ""; break; // entire line is a comment
 442                             default: line = line.substring(0, comment); break; // trim comment
 443                     }
 444 
 445                     // trim whitespace
 446                     line = line.trim();
 447 
 448                     // any content left on line?
 449                     if (line.length() == 0) {
 450                             continue;
 451                     }
 452 
 453                     // line content is now the name of the class
 454                     Class clazz = createClass(line);
 455                     if (clazz == null) {
 456                             continue;
 457                     }
 458 
 459                     // create an instance of the Class
 460                     try {
 461                             schemaFactory = (SchemaFactory) clazz.newInstance();
 462                     } catch (ClassCastException classCastExcpetion) {
 463                             schemaFactory = null;
 464                             continue;
 465                     } catch (InstantiationException instantiationException) {
 466                             schemaFactory = null;
 467                             continue;
 468                     } catch (IllegalAccessException illegalAccessException) {
 469                             schemaFactory = null;
 470                             continue;
 471                     }
 472 
 473                     // does this Class support desired Schema?
 474                     try {
 475                             Method isSchemaLanguageSupported = clazz.getMethod(isSchemaLanguageSupportedMethod, stringClassArray);
 476                             Boolean supported = (Boolean) isSchemaLanguageSupported.invoke(schemaFactory, schemaLanguageObjectArray);
 477                             if (supported.booleanValue()) {
 478                                     break;
 479                             }
 480                     } catch (NoSuchMethodException noSuchMethodException) {
 481 
 482                     } catch (IllegalAccessException illegalAccessException) {
 483 
 484                     } catch (InvocationTargetException invocationTargetException) {
 485 







 486                     }
 487                     schemaFactory = null;
 488             }
 489 
 490             // clean up
 491             configFile.close();
 492 
 493             // return new instance of SchemaFactory or null
 494             return schemaFactory;
 495     }
 496 
 497     /**
 498      * Returns an {@link Iterator} that enumerates all
 499      * the META-INF/services files that we care.





 500      */
 501     private Iterator createServiceFileIterator() {
 502         if (classLoader == null) {
 503             return new SingleIterator() {
 504                 protected Object value() {
 505                     ClassLoader classLoader = SchemaFactoryFinder.class.getClassLoader();
 506                     //return (ClassLoader.getSystemResource( SERVICE_ID ));
 507                     return ss.getResourceAsURL(classLoader, SERVICE_ID);
 508                 }
 509             };
 510         } else {
 511             try {
 512                 //final Enumeration e = classLoader.getResources(SERVICE_ID);
 513                 final Enumeration e = ss.getResources(classLoader, SERVICE_ID);
 514                 if(!e.hasMoreElements()) {
 515                     debugPrintln("no "+SERVICE_ID+" file was found");
 516                 }
 517 
 518                 // wrap it into an Iterator.
 519                 return new Iterator() {
 520                     public void remove() {
 521                         throw new UnsupportedOperationException();
 522                     }
 523 
 524                     public boolean hasNext() {
 525                         return e.hasMoreElements();
 526                     }
 527 
 528                     public Object next() {
 529                         return e.nextElement();
 530                     }
 531                 };
 532             } catch (IOException e) {
 533                 debugPrintln("failed to enumerate resources "+SERVICE_ID);
 534                 if(debug)   e.printStackTrace();
 535                 return new ArrayList().iterator();  // empty iterator
 536             }
 537         }
 538     }
 539 
 540     private static final Class SERVICE_CLASS = SchemaFactory.class;
 541     private static final String SERVICE_ID = "META-INF/services/" + SERVICE_CLASS.getName();
 542 

 543 
 544 
 545     private static String which( Class clazz ) {
 546         return which( clazz.getName(), clazz.getClassLoader() );
 547     }
 548 
 549     /**
 550      * <p>Search the specified classloader for the given classname.</p>
 551      *
 552      * @param classname the fully qualified name of the class to search for
 553      * @param loader the classloader to search
 554      *
 555      * @return the source location of the resource, or null if it wasn't found
 556      */
 557     private static String which(String classname, ClassLoader loader) {
 558 
 559         String classnameAsResource = classname.replace('.', '/') + ".class";
 560 
 561         if( loader==null )  loader = ClassLoader.getSystemClassLoader();
 562 
 563         //URL it = loader.getResource(classnameAsResource);
 564         URL it = ss.getResourceAsURL(loader, classnameAsResource);
 565         if (it != null) {


   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.net.URL;
  32 import java.security.AccessControlContext;
  33 import java.security.AccessController;
  34 import java.security.PrivilegedAction;

  35 import java.util.Properties;
  36 import java.util.ServiceConfigurationError;
  37 import java.util.ServiceLoader;
  38 
  39 /**
  40  * Implementation of {@link SchemaFactory#newInstance(String)}.
  41  *
  42  * @author <a href="Kohsuke.Kawaguchi@Sun.com">Kohsuke Kawaguchi</a>
  43  * @version $Revision: 1.8 $, $Date: 2010-11-01 04:36:13 $
  44  * @since 1.5
  45  */
  46 class SchemaFactoryFinder  {
  47 
  48     /** debug support code. */
  49     private static boolean debug = false;
  50     /**
  51      *<p> Take care of restrictions imposed by java security model </p>
  52      */
  53     private static final SecuritySupport ss = new SecuritySupport();
  54     /**
  55      * <p>Cache properties for performance.</p>
  56      */
  57     private static final Properties cacheProps = new Properties();

  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 _) {
  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) {


  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 _ ) {
 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;


 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         "lib" + File.separator + "jaxp.properties";
 184 
 185         String factoryClassName;
 186 
 187         // try to read from $java.home/lib/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             factoryClassName = cacheProps.getProperty(propertyName);
 202             debugPrintln("found " + factoryClassName + " in $java.home/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         assert factoryImpl == null || factoryImpl.isSchemaLanguageSupported(schemaLanguage);
 219         if (factoryImpl != null) {
 220             return factoryImpl;
































 221         }
 222 
 223         // platform default
 224         if(schemaLanguage.equals("http://www.w3.org/2001/XMLSchema")) {
 225             debugPrintln("attempting to use the platform default XML Schema validator");
 226             return createInstance("com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory", true);
 227         }
 228 
 229         debugPrintln("all things were tried, but none was found. bailing out.");
 230         return null;
 231     }
 232 
 233     /** <p>Create class using appropriate ClassLoader.</p>
 234      *
 235      * @param className Name of class to create.
 236      * @return Created class or <code>null</code>.
 237      */
 238     private Class<?> createClass(String className) {
 239         Class<?> clazz;
 240 
 241         // use approprite ClassLoader
 242         try {
 243             if (classLoader != null) {
 244                 clazz = Class.forName(className, false, classLoader);
 245             } else {
 246                 clazz = Class.forName(className);
 247             }
 248         } catch (Throwable t) {
 249             if (debug) {
 250                 t.printStackTrace();
 251             }
 252             return null;
 253         }
 254 
 255         return clazz;
 256     }
 257 
 258     /**
 259      * <p>Creates an instance of the specified and returns it.</p>
 260      *
 261      * @param className
 262      *      fully qualified class name to be instantiated.
 263      *
 264      * @return null
 265      *      if it fails. Error messages will be printed by this method.
 266      */
 267     SchemaFactory createInstance( String className ) {
 268         return createInstance( className, false );
 269     }
 270 
 271     SchemaFactory createInstance( String className, boolean useServicesMechanism ) {
 272         SchemaFactory schemaFactory = null;
 273 
 274         debugPrintln("createInstance(" + className + ")");
 275 
 276         // get Class from className
 277         Class<?> clazz = createClass(className);
 278         if (clazz == null) {
 279                 debugPrintln("failed to getClass(" + className + ")");
 280                 return null;
 281         }
 282         debugPrintln("loaded " + className + " from " + which(clazz));
 283 
 284         // instantiate Class as a SchemaFactory
 285         try {
 286                 if (!SchemaFactory.class.isAssignableFrom(clazz)) {
 287                     throw new ClassCastException(clazz.getName()
 288                                 + " cannot be cast to " + SchemaFactory.class);
 289                 }
 290                 if (!useServicesMechanism) {
 291                     schemaFactory = newInstanceNoServiceLoader(clazz);
 292                 }
 293                 if (schemaFactory == null) {
 294                     schemaFactory = (SchemaFactory) clazz.newInstance();
 295                 }
 296         } catch (ClassCastException classCastException) {
 297                 debugPrintln("could not instantiate " + clazz.getName());
 298                 if (debug) {
 299                         classCastException.printStackTrace();
 300                 }
 301                 return null;
 302         } catch (IllegalAccessException illegalAccessException) {
 303                 debugPrintln("could not instantiate " + clazz.getName());
 304                 if (debug) {
 305                         illegalAccessException.printStackTrace();
 306                 }
 307                 return null;
 308         } catch (InstantiationException instantiationException) {
 309                 debugPrintln("could not instantiate " + clazz.getName());
 310                 if (debug) {
 311                         instantiationException.printStackTrace();
 312                 }
 313                 return null;
 314         }
 315 
 316         return schemaFactory;
 317     }
 318 
 319     /**
 320      * Try to construct using newXMLSchemaFactoryNoServiceLoader
 321      *   method if available.
 322      */
 323     private static SchemaFactory newInstanceNoServiceLoader(
 324          Class<?> providerClass
 325     ) {
 326         // Retain maximum compatibility if no security manager.
 327         if (System.getSecurityManager() == null) {
 328             return null;
 329         }
 330         try {
 331             final Method creationMethod =
 332                 providerClass.getDeclaredMethod(
 333                     "newXMLSchemaFactoryNoServiceLoader"
 334                 );
 335             final int modifiers = creationMethod.getModifiers();





















 336 
 337             // Do not call the method if it's not public static.
 338             if (!Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers)) {


















 339                 return null;
 340             }

 341             
 342             // Only calls "newXMLSchemaFactoryNoServiceLoader" if it's
 343             // declared to return an instance of SchemaFactory.
 344             final Class<?> returnType = creationMethod.getReturnType();
 345             if (SERVICE_CLASS.isAssignableFrom(returnType)) {
 346                 return SERVICE_CLASS.cast(creationMethod.invoke(null, (Object[])null));
 347             } else {
 348                 // Should not happen since
 349                 // XMLSchemaFactory.newXMLSchemaFactoryNoServiceLoader is
 350                 // declared to return XMLSchemaFactory.
 351                 throw new ClassCastException(returnType
 352                             + " cannot be cast to " + SERVICE_CLASS);







































 353             }
 354         } catch(ClassCastException e) {
 355             throw new SchemaFactoryConfigurationError(e.getMessage(), e);
 356         } catch (NoSuchMethodException exc) {
 357             return null;
 358         } catch (Exception exc) {
 359             return null;







 360         }







 361     }





 362 
 363     // Call isSchemaLanguageSupported with initial context.
 364     private boolean isSchemaLanguageSupportedBy(final SchemaFactory factory,
 365             final String schemaLanguage,
 366             AccessControlContext acc) {
 367         return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
 368             public Boolean run() {
 369                 return factory.isSchemaLanguageSupported(schemaLanguage);
 370             }
 371         }, acc);







 372     }
 373 
 374     /**
 375      * Finds a service provider subclass of SchemaFactory that supports the
 376      * given schema language using the ServiceLoader.
 377      *
 378      * @param schemaLanguage The schema language for which we seek a factory.
 379      * @return A SchemaFactory supporting the specified schema language, or null
 380      *         if none is found.
 381      * @throws SchemaFactoryConfigurationError if a configuration error is found.
 382      */
 383     private SchemaFactory findServiceProvider(final String schemaLanguage) {
 384         assert schemaLanguage != null;
 385         // store current context. 
 386         final AccessControlContext acc = AccessController.getContext();






 387         try {
 388             return AccessController.doPrivileged(new PrivilegedAction<SchemaFactory>() {
 389                 public SchemaFactory run() {
 390                     final ServiceLoader<SchemaFactory> loader =
 391                             ServiceLoader.load(SERVICE_CLASS);
 392                     for (SchemaFactory factory : loader) {
 393                         // restore initial context to call 
 394                         // factory.isSchemaLanguageSupported
 395                         if (isSchemaLanguageSupportedBy(factory, schemaLanguage, acc)) {
 396                             return factory;

 397                         }



 398                     }
 399                     return null; // no factory found.


 400                 }
 401             });
 402         } catch (ServiceConfigurationError error) {
 403             throw new SchemaFactoryConfigurationError(
 404                     "Provider for " + SERVICE_CLASS + " cannot be created", error);

 405         }
 406     }




 407 
 408     private static final Class<SchemaFactory> SERVICE_CLASS = SchemaFactory.class;
 409 
 410 
 411     private static String which( Class<?> clazz ) {
 412         return which( clazz.getName(), clazz.getClassLoader() );
 413     }
 414 
 415     /**
 416      * <p>Search the specified classloader for the given classname.</p>
 417      *
 418      * @param classname the fully qualified name of the class to search for
 419      * @param loader the classloader to search
 420      *
 421      * @return the source location of the resource, or null if it wasn't found
 422      */
 423     private static String which(String classname, ClassLoader loader) {
 424 
 425         String classnameAsResource = classname.replace('.', '/') + ".class";
 426 
 427         if( loader==null )  loader = ClassLoader.getSystemClassLoader();
 428 
 429         //URL it = loader.getResource(classnameAsResource);
 430         URL it = ss.getResourceAsURL(loader, classnameAsResource);
 431         if (it != null) {