~vcs-imports/xena/trunk

« back to all changes in this revision

Viewing changes to ext/src/xalan-j_2_7_1/src/org/apache/xml/utils/ObjectFactory.java

  • Committer: matthewoliver
  • Date: 2009-12-10 03:18:07 UTC
  • Revision ID: vcs-imports@canonical.com-20091210031807-l086qguzdlljtkl9
Merged Xena Testing into Xena Stable for the Xena 5 release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Licensed to the Apache Software Foundation (ASF) under one
 
3
 * or more contributor license agreements. See the NOTICE file
 
4
 * distributed with this work for additional information
 
5
 * regarding copyright ownership. The ASF licenses this file
 
6
 * to you under the Apache License, Version 2.0 (the  "License");
 
7
 * you may not use this file except in compliance with the License.
 
8
 * You may obtain a copy of the License at
 
9
 *
 
10
 *     http://www.apache.org/licenses/LICENSE-2.0
 
11
 *
 
12
 * Unless required by applicable law or agreed to in writing, software
 
13
 * distributed under the License is distributed on an "AS IS" BASIS,
 
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
15
 * See the License for the specific language governing permissions and
 
16
 * limitations under the License.
 
17
 */
 
18
/*
 
19
 * $Id: ObjectFactory.java,v 1.2 2009/12/10 03:18:23 matthewoliver Exp $
 
20
 */
 
21
 
 
22
package org.apache.xml.utils;
 
23
 
 
24
import java.io.InputStream;
 
25
import java.io.IOException;
 
26
import java.io.File;
 
27
import java.io.FileInputStream;
 
28
 
 
29
import java.util.Properties;
 
30
import java.io.BufferedReader;
 
31
import java.io.InputStreamReader;
 
32
 
 
33
/**
 
34
 * This class is duplicated for each JAXP subpackage so keep it in sync.
 
35
 * It is package private and therefore is not exposed as part of the JAXP
 
36
 * API.
 
37
 * <p>
 
38
 * This code is designed to implement the JAXP 1.1 spec pluggability
 
39
 * feature and is designed to run on JDK version 1.1 and
 
40
 * later, and to compile on JDK 1.2 and onward.  
 
41
 * The code also runs both as part of an unbundled jar file and
 
42
 * when bundled as part of the JDK.
 
43
 * <p>
 
44
 * This class was moved from the <code>javax.xml.parsers.ObjectFactory</code>
 
45
 * class and modified to be used as a general utility for creating objects 
 
46
 * dynamically.
 
47
 *
 
48
 * @version $Id: ObjectFactory.java,v 1.2 2009/12/10 03:18:23 matthewoliver Exp $
 
49
 */
 
50
class ObjectFactory {
 
51
 
 
52
    //
 
53
    // Constants
 
54
    //
 
55
 
 
56
    // name of default properties file to look for in JDK's jre/lib directory
 
57
    private static final String DEFAULT_PROPERTIES_FILENAME =
 
58
                                                     "xalan.properties";
 
59
 
 
60
    private static final String SERVICES_PATH = "META-INF/services/";
 
61
 
 
62
    /** Set to true for debugging */
 
63
    private static final boolean DEBUG = false;
 
64
 
 
65
    /** cache the contents of the xalan.properties file.
 
66
     *  Until an attempt has been made to read this file, this will
 
67
     * be null; if the file does not exist or we encounter some other error
 
68
     * during the read, this will be empty.
 
69
     */
 
70
    private static Properties fXalanProperties = null;
 
71
 
 
72
    /***
 
73
     * Cache the time stamp of the xalan.properties file so
 
74
     * that we know if it's been modified and can invalidate
 
75
     * the cache when necessary.
 
76
     */
 
77
    private static long fLastModified = -1;
 
78
 
 
79
    //
 
80
    // Public static methods
 
81
    //
 
82
 
 
83
    /**
 
84
     * Finds the implementation Class object in the specified order.  The
 
85
     * specified order is the following:
 
86
     * <ol>
 
87
     *  <li>query the system property using <code>System.getProperty</code>
 
88
     *  <li>read <code>META-INF/services/<i>factoryId</i></code> file
 
89
     *  <li>use fallback classname
 
90
     * </ol>
 
91
     *
 
92
     * @return instance of factory, never null
 
93
     *
 
94
     * @param factoryId             Name of the factory to find, same as
 
95
     *                              a property name
 
96
     * @param fallbackClassName     Implementation class name, if nothing else
 
97
     *                              is found.  Use null to mean no fallback.
 
98
     *
 
99
     * @exception ObjectFactory.ConfigurationError
 
100
     */
 
101
    static Object createObject(String factoryId, String fallbackClassName)
 
102
        throws ConfigurationError {
 
103
        return createObject(factoryId, null, fallbackClassName);
 
104
    } // createObject(String,String):Object
 
105
 
 
106
    /**
 
107
     * Finds the implementation Class object in the specified order.  The
 
108
     * specified order is the following:
 
109
     * <ol>
 
110
     *  <li>query the system property using <code>System.getProperty</code>
 
111
     *  <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file
 
112
     *  <li>read <code>META-INF/services/<i>factoryId</i></code> file
 
113
     *  <li>use fallback classname
 
114
     * </ol>
 
115
     *
 
116
     * @return instance of factory, never null
 
117
     *
 
118
     * @param factoryId             Name of the factory to find, same as
 
119
     *                              a property name
 
120
     * @param propertiesFilename The filename in the $java.home/lib directory
 
121
     *                           of the properties file.  If none specified,
 
122
     *                           ${java.home}/lib/xalan.properties will be used.
 
123
     * @param fallbackClassName     Implementation class name, if nothing else
 
124
     *                              is found.  Use null to mean no fallback.
 
125
     *
 
126
     * @exception ObjectFactory.ConfigurationError
 
127
     */
 
128
    static Object createObject(String factoryId, 
 
129
                                      String propertiesFilename,
 
130
                                      String fallbackClassName)
 
131
        throws ConfigurationError
 
132
    {
 
133
        Class factoryClass = lookUpFactoryClass(factoryId,
 
134
                                                propertiesFilename,
 
135
                                                fallbackClassName);
 
136
 
 
137
        if (factoryClass == null) {
 
138
            throw new ConfigurationError(
 
139
                "Provider for " + factoryId + " cannot be found", null);
 
140
        }
 
141
 
 
142
        try{
 
143
            Object instance = factoryClass.newInstance();
 
144
            debugPrintln("created new instance of factory " + factoryId);
 
145
            return instance;
 
146
        } catch (Exception x) {
 
147
            throw new ConfigurationError(
 
148
                "Provider for factory " + factoryId
 
149
                    + " could not be instantiated: " + x, x);
 
150
        }
 
151
    } // createObject(String,String,String):Object
 
152
 
 
153
    /**
 
154
     * Finds the implementation Class object in the specified order.  The
 
155
     * specified order is the following:
 
156
     * <ol>
 
157
     *  <li>query the system property using <code>System.getProperty</code>
 
158
     *  <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file
 
159
     *  <li>read <code>META-INF/services/<i>factoryId</i></code> file
 
160
     *  <li>use fallback classname
 
161
     * </ol>
 
162
     *
 
163
     * @return Class object of factory, never null
 
164
     *
 
165
     * @param factoryId             Name of the factory to find, same as
 
166
     *                              a property name
 
167
     * @param propertiesFilename The filename in the $java.home/lib directory
 
168
     *                           of the properties file.  If none specified,
 
169
     *                           ${java.home}/lib/xalan.properties will be used.
 
170
     * @param fallbackClassName     Implementation class name, if nothing else
 
171
     *                              is found.  Use null to mean no fallback.
 
172
     *
 
173
     * @exception ObjectFactory.ConfigurationError
 
174
     */
 
175
    static Class lookUpFactoryClass(String factoryId) 
 
176
        throws ConfigurationError
 
177
    {
 
178
        return lookUpFactoryClass(factoryId, null, null);
 
179
    } // lookUpFactoryClass(String):Class
 
180
 
 
181
    /**
 
182
     * Finds the implementation Class object in the specified order.  The
 
183
     * specified order is the following:
 
184
     * <ol>
 
185
     *  <li>query the system property using <code>System.getProperty</code>
 
186
     *  <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file
 
187
     *  <li>read <code>META-INF/services/<i>factoryId</i></code> file
 
188
     *  <li>use fallback classname
 
189
     * </ol>
 
190
     *
 
191
     * @return Class object that provides factory service, never null
 
192
     *
 
193
     * @param factoryId             Name of the factory to find, same as
 
194
     *                              a property name
 
195
     * @param propertiesFilename The filename in the $java.home/lib directory
 
196
     *                           of the properties file.  If none specified,
 
197
     *                           ${java.home}/lib/xalan.properties will be used.
 
198
     * @param fallbackClassName     Implementation class name, if nothing else
 
199
     *                              is found.  Use null to mean no fallback.
 
200
     *
 
201
     * @exception ObjectFactory.ConfigurationError
 
202
     */
 
203
    static Class lookUpFactoryClass(String factoryId,
 
204
                                           String propertiesFilename,
 
205
                                           String fallbackClassName)
 
206
        throws ConfigurationError
 
207
    {
 
208
        String factoryClassName = lookUpFactoryClassName(factoryId,
 
209
                                                         propertiesFilename,
 
210
                                                         fallbackClassName);
 
211
        ClassLoader cl = findClassLoader();
 
212
 
 
213
        if (factoryClassName == null) {
 
214
            factoryClassName = fallbackClassName;
 
215
        }
 
216
 
 
217
        // assert(className != null);
 
218
        try{
 
219
            Class providerClass = findProviderClass(factoryClassName,
 
220
                                                    cl,
 
221
                                                    true);
 
222
            debugPrintln("created new instance of " + providerClass +
 
223
                   " using ClassLoader: " + cl);
 
224
            return providerClass;
 
225
        } catch (ClassNotFoundException x) {
 
226
            throw new ConfigurationError(
 
227
                "Provider " + factoryClassName + " not found", x);
 
228
        } catch (Exception x) {
 
229
            throw new ConfigurationError(
 
230
                "Provider "+factoryClassName+" could not be instantiated: "+x,
 
231
                x);
 
232
        }
 
233
    } // lookUpFactoryClass(String,String,String):Class
 
234
 
 
235
    /**
 
236
     * Finds the name of the required implementation class in the specified
 
237
     * order.  The specified order is the following:
 
238
     * <ol>
 
239
     *  <li>query the system property using <code>System.getProperty</code>
 
240
     *  <li>read <code>$java.home/lib/<i>propertiesFilename</i></code> file
 
241
     *  <li>read <code>META-INF/services/<i>factoryId</i></code> file
 
242
     *  <li>use fallback classname
 
243
     * </ol>
 
244
     *
 
245
     * @return name of class that provides factory service, never null
 
246
     *
 
247
     * @param factoryId             Name of the factory to find, same as
 
248
     *                              a property name
 
249
     * @param propertiesFilename The filename in the $java.home/lib directory
 
250
     *                           of the properties file.  If none specified,
 
251
     *                           ${java.home}/lib/xalan.properties will be used.
 
252
     * @param fallbackClassName     Implementation class name, if nothing else
 
253
     *                              is found.  Use null to mean no fallback.
 
254
     *
 
255
     * @exception ObjectFactory.ConfigurationError
 
256
     */
 
257
    static String lookUpFactoryClassName(String factoryId,
 
258
                                                String propertiesFilename,
 
259
                                                String fallbackClassName)
 
260
    {
 
261
        SecuritySupport ss = SecuritySupport.getInstance();
 
262
 
 
263
        // Use the system property first
 
264
        try {
 
265
            String systemProp = ss.getSystemProperty(factoryId);
 
266
            if (systemProp != null) {
 
267
                debugPrintln("found system property, value=" + systemProp);
 
268
                return systemProp;
 
269
            }
 
270
        } catch (SecurityException se) {
 
271
            // Ignore and continue w/ next location
 
272
        }
 
273
 
 
274
        // Try to read from propertiesFilename, or
 
275
        // $java.home/lib/xalan.properties
 
276
        String factoryClassName = null;
 
277
        // no properties file name specified; use
 
278
        // $JAVA_HOME/lib/xalan.properties:
 
279
        if (propertiesFilename == null) {
 
280
            File propertiesFile = null;
 
281
            boolean propertiesFileExists = false;
 
282
            try {
 
283
                String javah = ss.getSystemProperty("java.home");
 
284
                propertiesFilename = javah + File.separator +
 
285
                    "lib" + File.separator + DEFAULT_PROPERTIES_FILENAME;
 
286
                propertiesFile = new File(propertiesFilename);
 
287
                propertiesFileExists = ss.getFileExists(propertiesFile);
 
288
            } catch (SecurityException e) {
 
289
                // try again...
 
290
                fLastModified = -1;
 
291
                fXalanProperties = null;
 
292
            }
 
293
 
 
294
            synchronized (ObjectFactory.class) {
 
295
                boolean loadProperties = false;
 
296
                FileInputStream fis = null;
 
297
                try {
 
298
                    // file existed last time
 
299
                    if(fLastModified >= 0) {
 
300
                        if(propertiesFileExists &&
 
301
                                (fLastModified < (fLastModified = ss.getLastModified(propertiesFile)))) {
 
302
                            loadProperties = true;
 
303
                        } else {
 
304
                            // file has stopped existing...
 
305
                            if(!propertiesFileExists) {
 
306
                                fLastModified = -1;
 
307
                                fXalanProperties = null;
 
308
                            } // else, file wasn't modified!
 
309
                        }
 
310
                    } else {
 
311
                        // file has started to exist:
 
312
                        if(propertiesFileExists) {
 
313
                            loadProperties = true;
 
314
                            fLastModified = ss.getLastModified(propertiesFile);
 
315
                        } // else, nothing's changed
 
316
                    }
 
317
                    if(loadProperties) {
 
318
                        // must never have attempted to read xalan.properties
 
319
                        // before (or it's outdeated)
 
320
                        fXalanProperties = new Properties();
 
321
                        fis = ss.getFileInputStream(propertiesFile);
 
322
                        fXalanProperties.load(fis);
 
323
                    }
 
324
                } catch (Exception x) {
 
325
                    fXalanProperties = null;
 
326
                    fLastModified = -1;
 
327
                    // assert(x instanceof FileNotFoundException
 
328
                    //        || x instanceof SecurityException)
 
329
                    // In both cases, ignore and continue w/ next location
 
330
                }
 
331
                finally {
 
332
                    // try to close the input stream if one was opened.
 
333
                    if (fis != null) {
 
334
                        try {
 
335
                            fis.close();
 
336
                        }
 
337
                        // Ignore the exception.
 
338
                        catch (IOException exc) {}
 
339
                    }
 
340
                }                   
 
341
            }
 
342
            if(fXalanProperties != null) {
 
343
                factoryClassName = fXalanProperties.getProperty(factoryId);
 
344
            }
 
345
        } else {
 
346
            FileInputStream fis = null;
 
347
            try {
 
348
                fis = ss.getFileInputStream(new File(propertiesFilename));
 
349
                Properties props = new Properties();
 
350
                props.load(fis);
 
351
                factoryClassName = props.getProperty(factoryId);
 
352
            } catch (Exception x) {
 
353
                // assert(x instanceof FileNotFoundException
 
354
                //        || x instanceof SecurityException)
 
355
                // In both cases, ignore and continue w/ next location
 
356
            }
 
357
            finally {
 
358
                // try to close the input stream if one was opened.
 
359
                if (fis != null) {
 
360
                    try {
 
361
                        fis.close();
 
362
                    }
 
363
                    // Ignore the exception.
 
364
                    catch (IOException exc) {}
 
365
                }
 
366
            }               
 
367
        }
 
368
        if (factoryClassName != null) {
 
369
            debugPrintln("found in " + propertiesFilename + ", value="
 
370
                          + factoryClassName);
 
371
            return factoryClassName;
 
372
        }
 
373
 
 
374
        // Try Jar Service Provider Mechanism
 
375
        return findJarServiceProviderName(factoryId);
 
376
    } // lookUpFactoryClass(String,String):String
 
377
 
 
378
    //
 
379
    // Private static methods
 
380
    //
 
381
 
 
382
    /** Prints a message to standard error if debugging is enabled. */
 
383
    private static void debugPrintln(String msg) {
 
384
        if (DEBUG) {
 
385
            System.err.println("JAXP: " + msg);
 
386
        }
 
387
    } // debugPrintln(String)
 
388
 
 
389
    /**
 
390
     * Figure out which ClassLoader to use.  For JDK 1.2 and later use
 
391
     * the context ClassLoader.
 
392
     */
 
393
    static ClassLoader findClassLoader()
 
394
        throws ConfigurationError
 
395
    { 
 
396
        SecuritySupport ss = SecuritySupport.getInstance();
 
397
 
 
398
        // Figure out which ClassLoader to use for loading the provider
 
399
        // class.  If there is a Context ClassLoader then use it.
 
400
        ClassLoader context = ss.getContextClassLoader();
 
401
        ClassLoader system = ss.getSystemClassLoader();
 
402
 
 
403
        ClassLoader chain = system;
 
404
        while (true) {
 
405
            if (context == chain) {
 
406
                // Assert: we are on JDK 1.1 or we have no Context ClassLoader
 
407
                // or any Context ClassLoader in chain of system classloader
 
408
                // (including extension ClassLoader) so extend to widest
 
409
                // ClassLoader (always look in system ClassLoader if Xalan
 
410
                // is in boot/extension/system classpath and in current
 
411
                // ClassLoader otherwise); normal classloaders delegate
 
412
                // back to system ClassLoader first so this widening doesn't
 
413
                // change the fact that context ClassLoader will be consulted
 
414
                ClassLoader current = ObjectFactory.class.getClassLoader();
 
415
 
 
416
                chain = system;
 
417
                while (true) {
 
418
                    if (current == chain) {
 
419
                        // Assert: Current ClassLoader in chain of
 
420
                        // boot/extension/system ClassLoaders
 
421
                        return system;
 
422
                    }
 
423
                    if (chain == null) {
 
424
                        break;
 
425
                    }
 
426
                    chain = ss.getParentClassLoader(chain);
 
427
                }
 
428
 
 
429
                // Assert: Current ClassLoader not in chain of
 
430
                // boot/extension/system ClassLoaders
 
431
                return current;
 
432
            }
 
433
 
 
434
            if (chain == null) {
 
435
                // boot ClassLoader reached
 
436
                break;
 
437
            }
 
438
 
 
439
            // Check for any extension ClassLoaders in chain up to
 
440
            // boot ClassLoader
 
441
            chain = ss.getParentClassLoader(chain);
 
442
        };
 
443
 
 
444
        // Assert: Context ClassLoader not in chain of
 
445
        // boot/extension/system ClassLoaders
 
446
        return context;
 
447
    } // findClassLoader():ClassLoader
 
448
 
 
449
    /**
 
450
     * Create an instance of a class using the specified ClassLoader
 
451
     */ 
 
452
    static Object newInstance(String className, ClassLoader cl,
 
453
                                      boolean doFallback)
 
454
        throws ConfigurationError
 
455
    {
 
456
        // assert(className != null);
 
457
        try{
 
458
            Class providerClass = findProviderClass(className, cl, doFallback);
 
459
            Object instance = providerClass.newInstance();
 
460
            debugPrintln("created new instance of " + providerClass +
 
461
                   " using ClassLoader: " + cl);
 
462
            return instance;
 
463
        } catch (ClassNotFoundException x) {
 
464
            throw new ConfigurationError(
 
465
                "Provider " + className + " not found", x);
 
466
        } catch (Exception x) {
 
467
            throw new ConfigurationError(
 
468
                "Provider " + className + " could not be instantiated: " + x,
 
469
                x);
 
470
        }
 
471
    }
 
472
 
 
473
    /**
 
474
     * Find a Class using the specified ClassLoader
 
475
     */ 
 
476
    static Class findProviderClass(String className, ClassLoader cl,
 
477
                                           boolean doFallback)
 
478
        throws ClassNotFoundException, ConfigurationError
 
479
    {   
 
480
        //throw security exception if the calling thread is not allowed to access the
 
481
        //class. Restrict the access to the package classes as specified in java.security policy.
 
482
        SecurityManager security = System.getSecurityManager();
 
483
        try{
 
484
                if (security != null){
 
485
                    final int lastDot = className.lastIndexOf(".");
 
486
                    String packageName = className;
 
487
                    if (lastDot != -1) packageName = className.substring(0, lastDot);
 
488
                    security.checkPackageAccess(packageName);
 
489
                 }   
 
490
        }catch(SecurityException e){
 
491
            throw e;
 
492
        }
 
493
        
 
494
        Class providerClass;
 
495
        if (cl == null) {
 
496
            // XXX Use the bootstrap ClassLoader.  There is no way to
 
497
            // load a class using the bootstrap ClassLoader that works
 
498
            // in both JDK 1.1 and Java 2.  However, this should still
 
499
            // work b/c the following should be true:
 
500
            //
 
501
            // (cl == null) iff current ClassLoader == null
 
502
            //
 
503
            // Thus Class.forName(String) will use the current
 
504
            // ClassLoader which will be the bootstrap ClassLoader.
 
505
            providerClass = Class.forName(className);
 
506
        } else {
 
507
            try {
 
508
                providerClass = cl.loadClass(className);
 
509
            } catch (ClassNotFoundException x) {
 
510
                if (doFallback) {
 
511
                    // Fall back to current classloader
 
512
                    ClassLoader current = ObjectFactory.class.getClassLoader();
 
513
                    if (current == null) {
 
514
                        providerClass = Class.forName(className);
 
515
                    } else if (cl != current) {
 
516
                        cl = current;
 
517
                        providerClass = cl.loadClass(className);
 
518
                    } else {
 
519
                        throw x;
 
520
                    }
 
521
                } else {
 
522
                    throw x;
 
523
                }
 
524
            }
 
525
        }
 
526
 
 
527
        return providerClass;
 
528
    }
 
529
 
 
530
    /**
 
531
     * Find the name of service provider using Jar Service Provider Mechanism
 
532
     *
 
533
     * @return instance of provider class if found or null
 
534
     */
 
535
    private static String findJarServiceProviderName(String factoryId)
 
536
    {
 
537
        SecuritySupport ss = SecuritySupport.getInstance();
 
538
        String serviceId = SERVICES_PATH + factoryId;
 
539
        InputStream is = null;
 
540
 
 
541
        // First try the Context ClassLoader
 
542
        ClassLoader cl = findClassLoader();
 
543
 
 
544
        is = ss.getResourceAsStream(cl, serviceId);
 
545
 
 
546
        // If no provider found then try the current ClassLoader
 
547
        if (is == null) {
 
548
            ClassLoader current = ObjectFactory.class.getClassLoader();
 
549
            if (cl != current) {
 
550
                cl = current;
 
551
                is = ss.getResourceAsStream(cl, serviceId);
 
552
            }
 
553
        }
 
554
 
 
555
        if (is == null) {
 
556
            // No provider found
 
557
            return null;
 
558
        }
 
559
 
 
560
        debugPrintln("found jar resource=" + serviceId +
 
561
               " using ClassLoader: " + cl);
 
562
 
 
563
        // Read the service provider name in UTF-8 as specified in
 
564
        // the jar spec.  Unfortunately this fails in Microsoft
 
565
        // VJ++, which does not implement the UTF-8
 
566
        // encoding. Theoretically, we should simply let it fail in
 
567
        // that case, since the JVM is obviously broken if it
 
568
        // doesn't support such a basic standard.  But since there
 
569
        // are still some users attempting to use VJ++ for
 
570
        // development, we have dropped in a fallback which makes a
 
571
        // second attempt using the platform's default encoding. In
 
572
        // VJ++ this is apparently ASCII, which is a subset of
 
573
        // UTF-8... and since the strings we'll be reading here are
 
574
        // also primarily limited to the 7-bit ASCII range (at
 
575
        // least, in English versions), this should work well
 
576
        // enough to keep us on the air until we're ready to
 
577
        // officially decommit from VJ++. [Edited comment from
 
578
        // jkesselm]
 
579
        BufferedReader rd;
 
580
        try {
 
581
            rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
 
582
        } catch (java.io.UnsupportedEncodingException e) {
 
583
            rd = new BufferedReader(new InputStreamReader(is));
 
584
        }
 
585
        
 
586
        String factoryClassName = null;
 
587
        try {
 
588
            // XXX Does not handle all possible input as specified by the
 
589
            // Jar Service Provider specification
 
590
            factoryClassName = rd.readLine();
 
591
        } catch (IOException x) {
 
592
            // No provider found
 
593
            return null;
 
594
        }
 
595
        finally {
 
596
            try {
 
597
                // try to close the reader.
 
598
                rd.close();
 
599
            }
 
600
            // Ignore the exception.
 
601
            catch (IOException exc) {}
 
602
        }          
 
603
 
 
604
        if (factoryClassName != null &&
 
605
            ! "".equals(factoryClassName)) {
 
606
            debugPrintln("found in resource, value="
 
607
                   + factoryClassName);
 
608
 
 
609
            // Note: here we do not want to fall back to the current
 
610
            // ClassLoader because we want to avoid the case where the
 
611
            // resource file was found using one ClassLoader and the
 
612
            // provider class was instantiated using a different one.
 
613
            return factoryClassName;
 
614
        }
 
615
 
 
616
        // No provider found
 
617
        return null;
 
618
    }
 
619
 
 
620
    //
 
621
    // Classes
 
622
    //
 
623
 
 
624
    /**
 
625
     * A configuration error.
 
626
     */
 
627
    static class ConfigurationError 
 
628
        extends Error {
 
629
                static final long serialVersionUID = 2036619216663421552L;
 
630
        //
 
631
        // Data
 
632
        //
 
633
 
 
634
        /** Exception. */
 
635
        private Exception exception;
 
636
 
 
637
        //
 
638
        // Constructors
 
639
        //
 
640
 
 
641
        /**
 
642
         * Construct a new instance with the specified detail string and
 
643
         * exception.
 
644
         */
 
645
        ConfigurationError(String msg, Exception x) {
 
646
            super(msg);
 
647
            this.exception = x;
 
648
        } // <init>(String,Exception)
 
649
 
 
650
        //
 
651
        // Public methods
 
652
        //
 
653
 
 
654
        /** Returns the exception associated to this error. */
 
655
        Exception getException() {
 
656
            return exception;
 
657
        } // getException():Exception
 
658
 
 
659
    } // class ConfigurationError
 
660
 
 
661
} // class ObjectFactory