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) {
  82         if (debug) {
  83             System.err.println("JAXP: " + msg);
  84         }
  85     }
  86 
  87     /**
  88      * <p><code>ClassLoader</code> to use to find <code>SchemaFactory</code>.</p>

  89      */
  90     private final ClassLoader classLoader;
  91 
  92     /**
  93      * <p>Constructor that specifies <code>ClassLoader</code> to use
  94      * to find <code>SchemaFactory</code>.</p>
  95      *
  96      * @param loader
  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;
 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         "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                 }


 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, 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) {
 566             return it.toString();
 567         } else {
 568             return null;
 569         }
 570     }
 571 }


   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.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 SchemaFactory#newInstance(String)}.
  40  *
  41  * @author <a href="Kohsuke.Kawaguchi@Sun.com">Kohsuke Kawaguchi</a>
  42  * @version $Revision: 1.8 $, $Date: 2010-11-01 04:36:13 $
  43  * @since 1.5
  44  */
  45 class SchemaFactoryFinder {
  46 
  47     private static final String DEFAULT_IMPL_NAME = "com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory";
  48     /**
  49      * debug support code.
  50      */
  51     private static boolean debug = false;
  52     /**
  53      * <p> Take care of restrictions imposed by java security model </p>
  54      */
  55     private static SecuritySupport ss = new SecuritySupport();
  56     /**
  57      * <p>Cache properties for performance.</p>
  58      */
  59     private static Properties cacheProps = new Properties();

  60     /**
  61      * <p>First time requires initialization overhead.</p>
  62      */
  63     private static volatile boolean firstTime = true;
  64 
  65     static {
  66         // Use try/catch block to support applets
  67         try {
  68             debug = ss.getSystemProperty("jaxp.debug") != null;
  69         } catch (Exception _) {
  70             debug = false;
  71         }
  72     }
  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      * <p><code>ClassLoader</code> to use to find
  86      * <code>SchemaFactory</code>.</p>
  87      */
  88     private final ClassLoader classLoader;
  89 
  90     /**
  91      * <p>Constructor that specifies
  92      * <code>ClassLoader</code> to use to find
  93      * <code>SchemaFactory</code>.</p>
  94      *
  95      * @param loader to be used to load resource, {@link SchemaFactory}, and
  96      * {@link SchemaFactoryLoader} implementations during the resolution
  97      * process. If this parameter is null, the default system class loader will
  98      * 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 _) {
 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 schema
 127      * language.</p>
 128      *
 129      * @param schemaLanguage See {@link SchemaFactory Schema Language} table
 130      * in <code>SchemaFactory</code> for the list of available schema languages.

 131      *
 132      * @return <code>null</code> if the callee fails to create one.
 133      *
 134      * @throws NullPointerException If the <code>schemaLanguage</code> parameter
 135      * is null.
 136      */
 137     public SchemaFactory newFactory(String schemaLanguage)
 138             throws FactoryConfigurationError {
 139         if (schemaLanguage == null) {
 140             throw new NullPointerException();
 141         }
 142         SchemaFactory f = _newFactory(schemaLanguage);
 143         if (f != null) {
 144             debugPrintln("factory '" + f.getClass().getName() + "' was found for " + schemaLanguage);
 145         } else {
 146             debugPrintln("unable to find a factory for " + schemaLanguage);
 147         }
 148         return f;
 149     }
 150 
 151     /**
 152      * <p>Lookup a
 153      * <code>SchemaFactory</code> for the given
 154      * <code>schemaLanguage</code>.</p>
 155      *
 156      * @param schemaLanguage Schema language to
 157      * lookup <code>SchemaFactory</code> for.
 158      *
 159      * @return <code>SchemaFactory</code> for the
 160      * given <code>schemaLanguage</code>.
 161      */
 162     private SchemaFactory _newFactory(String schemaLanguage)
 163             throws FactoryConfigurationError {
 164         SchemaFactory sf;
 165 
 166         String propertyName = SERVICE_CLASS.getName() + ":" + schemaLanguage;
 167 
 168         // system property look up
 169         try {
 170             debugPrintln("Looking up system property '" + propertyName + "'");
 171             String r = ss.getSystemProperty(propertyName);
 172             if (r != null) {
 173                 debugPrintln("The value is '" + r + "'");
 174                 sf = createInstance(r, true);
 175                 if (sf != null) {
 176                     return sf;
 177                 }
 178             } else {
 179                 debugPrintln("The property is undefined.");
 180             }
 181         } catch (Throwable t) {
 182             if (debug) {
 183                 debugPrintln("failed to look up system property '" + propertyName + "'");
 184                 t.printStackTrace();
 185             }
 186         }
 187 
 188         String javah = ss.getSystemProperty("java.home");
 189         String configFile = javah + File.separator
 190                 + "lib" + File.separator + "jaxp.properties";
 191 
 192         String factoryClassName = null;
 193 
 194         // try to read from $java.home/lib/jaxp.properties
 195         try {
 196             if (firstTime) {
 197                 synchronized (cacheProps) {
 198                     if (firstTime) {
 199                         File f = new File(configFile);
 200                         firstTime = false;
 201                         if (ss.doesFileExist(f)) {
 202                             debugPrintln("Read properties file " + f);
 203                             cacheProps.load(ss.getFileInputStream(f));
 204                         }
 205                     }
 206                 }
 207             }
 208             factoryClassName = cacheProps.getProperty(propertyName);
 209             debugPrintln("found " + factoryClassName + " in $java.home/jaxp.properties");
 210 
 211             if (factoryClassName != null) {
 212                 sf = createInstance(factoryClassName, true);
 213                 if (sf != null) {
 214                     return sf;
 215                 }
 216             }
 217         } catch (Exception ex) {
 218             if (debug) {
 219                 ex.printStackTrace();
 220             }
 221         }
 222 





















 223 
 224         // try finding a service provider
 225         sf = findServiceProvider(schemaLanguage, DEFAULT_IMPL_NAME);
 226         if (sf != null) {
 227             return sf;











 228         }
 229 
 230         // platform default
 231         if (schemaLanguage.equals("http://www.w3.org/2001/XMLSchema")) {
 232             debugPrintln("attempting to use the platform default XML Schema validator");
 233             return createInstance(DEFAULT_IMPL_NAME, true);
 234         }
 235 
 236         debugPrintln("all things were tried, but none was found. bailing out.");
 237         return null;
 238     }
 239 
 240     /**
 241      * <p>Create class using appropriate ClassLoader.</p>
 242      *
 243      * @param className Name of class to create.
 244      * @return Created class or <code>null</code>.
 245      */
 246     private Class createClass(String className) {
 247         Class clazz;
 248 
 249         // use approprite ClassLoader
 250         try {
 251             if (classLoader != null) {
 252                 clazz = classLoader.loadClass(className);
 253             } else {
 254                 clazz = Class.forName(className);
 255             }
 256         } catch (Throwable t) {
 257             if (debug) {
 258                 t.printStackTrace();
 259             }
 260             return null;
 261         }
 262 
 263         return clazz;
 264     }
 265 
 266     /**
 267      * <p>Creates an instance of the specified and returns it.</p>
 268      *
 269      * @param className fully qualified class name to be instanciated.

 270      *
 271      * @return null if it fails. Error messages will be printed by this method.

 272      */
 273     SchemaFactory createInstance(String className) {
 274         return createInstance(className, false);
 275     }
 276 
 277     SchemaFactory createInstance(String className, boolean useServicesMechanism) {
 278         SchemaFactory schemaFactory = 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 SchemaFactory
 291         try {
 292             if (!useServicesMechanism) {
 293                 schemaFactory = (SchemaFactory) newInstanceNoServiceLoader(clazz);
 294             }
 295             if (schemaFactory == null) {
 296                 schemaFactory = (SchemaFactory) 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 schemaFactory;
 319     }
 320 
 321     /**
 322      * Try to construct using newTransformerFactoryNoServiceLoader method if
 323      * available.
 324      */
 325     private static Object newInstanceNoServiceLoader(
 326             Class<?> providerClass) {

 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                     "newXMLSchemaFactoryNoServiceLoader");

 335             return creationMethod.invoke(null, null);
 336         } catch (NoSuchMethodException exc) {
 337             return null;
 338         } catch (Exception exc) {
 339             return null;
 340         }
 341     }
 342 














 343 
 344     /*
 345      * Try to find a provider using Service Loader

 346      *
 347      * @return instance of provider class if found or null

 348      */
 349     private SchemaFactory findServiceProvider(final String schemaLanguage, final String fallbackClassName)
 350             throws FactoryConfigurationError {
 351         try {
 352             return (SchemaFactory) AccessController.doPrivileged(new PrivilegedAction() {
 353                 public SchemaFactory run() {
 354                     SchemaFactory defaultProvider = null;
 355                     for (SchemaFactory schemaFactory : ServiceLoader.load(SchemaFactory.class, classLoader)) {
 356                         if (schemaFactory.getClass().getName().equals(fallbackClassName)) {
 357                             defaultProvider = schemaFactory;


 358                         } else {
 359                             if (isSchemaSupported(schemaFactory, schemaLanguage)) {
 360                                 return schemaFactory;
 361                             }
 362                         }
 363                     }
 364                     if (defaultProvider != null) {
 365                         return defaultProvider;
 366                     }
 367                     return null;
 368                 }
 369             });
 370         } catch (ServiceConfigurationError e) {
 371             throw new FactoryConfigurationError(e.getMessage(), (Exception) e.getCause());
 372         }
 373     }
 374 
 375     /**
 376      * <p>Test if the specified schemas are supported by the provider.</p>


 377      *
 378      * @param schemaFactory a Schema factory provider.
 379      * @param schemaLanguage Schema Language to support.




 380      *
 381      * @return <code>true</code> if the Schema Language is supported by the
 382      * provider.
 383      */
 384     private static boolean isSchemaSupported(SchemaFactory schemaFactory, String schemaLanguage) {






 385         final Class[] stringClassArray = {"".getClass()};
 386         final Object[] schemaLanguageObjectArray = {schemaLanguage};
 387         final String isSchemaLanguageSupportedMethod = "isSchemaLanguageSupported";
 388 










































 389         // does this Class support desired Schema?
 390         try {
 391             Method isSchemaLanguageSupported = schemaFactory.getClass().getMethod(isSchemaLanguageSupportedMethod, stringClassArray);
 392             Boolean supported = (Boolean) isSchemaLanguageSupported.invoke(schemaFactory, schemaLanguageObjectArray);
 393             if (supported.booleanValue()) {
 394                 return true;
 395             }
 396         } catch (NoSuchMethodException noSuchMethodException) {

 397         } catch (IllegalAccessException illegalAccessException) {

 398         } catch (InvocationTargetException invocationTargetException) {

 399         }





 400 
 401         return false;














 402     }































 403     private static final Class SERVICE_CLASS = SchemaFactory.class;


 404 
 405     private static String which(Class clazz) {
 406         return which(clazz.getName(), clazz.getClassLoader());

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