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 468637 2006-10-28 06:51:02Z minchau $
20 */
21
22package org.apache.xalan.extensions;
23
24/**
25 * This class is duplicated for each JAXP subpackage so keep it in sync.
26 * It is package private and therefore is not exposed as part of the JAXP
27 * API.
28 * <p>
29 * This code is designed to implement the JAXP 1.1 spec pluggability
30 * feature and is designed to run on JDK version 1.1 and
31 * later, and to compile on JDK 1.2 and onward.
32 * The code also runs both as part of an unbundled jar file and
33 * when bundled as part of the JDK.
34 * <p>
35 * This class was moved from the <code>javax.xml.parsers.ObjectFactory</code>
36 * class and modified to be used as a general utility for creating objects
37 * dynamically.
38 *
39 * @version $Id: ObjectFactory.java 468637 2006-10-28 06:51:02Z minchau $
40 */
41class ObjectFactory {
42
43    /**
44     * Figure out which ClassLoader to use.  For JDK 1.2 and later use
45     * the context ClassLoader.
46     */
47    static ClassLoader findClassLoader()
48        throws ConfigurationError
49    {
50        // BEGIN android-changed
51        //     the context class loader is always sufficient
52        return Thread.currentThread().getContextClassLoader();
53        // END android-changed
54    } // findClassLoader():ClassLoader
55
56    /**
57     * Find a Class using the specified ClassLoader
58     */
59    static Class findProviderClass(String className, ClassLoader cl,
60                                           boolean doFallback)
61        throws ClassNotFoundException, ConfigurationError
62    {
63        //throw security exception if the calling thread is not allowed to access the
64        //class. Restrict the access to the package classes as specified in java.security policy.
65        SecurityManager security = System.getSecurityManager();
66        try{
67                if (security != null){
68                    final int lastDot = className.lastIndexOf(".");
69                    String packageName = className;
70                    if (lastDot != -1) packageName = className.substring(0, lastDot);
71                    security.checkPackageAccess(packageName);
72                 }
73        }catch(SecurityException e){
74            throw e;
75        }
76
77        Class providerClass;
78        if (cl == null) {
79            // XXX Use the bootstrap ClassLoader.  There is no way to
80            // load a class using the bootstrap ClassLoader that works
81            // in both JDK 1.1 and Java 2.  However, this should still
82            // work b/c the following should be true:
83            //
84            // (cl == null) iff current ClassLoader == null
85            //
86            // Thus Class.forName(String) will use the current
87            // ClassLoader which will be the bootstrap ClassLoader.
88            providerClass = Class.forName(className);
89        } else {
90            try {
91                providerClass = cl.loadClass(className);
92            } catch (ClassNotFoundException x) {
93                if (doFallback) {
94                    // Fall back to current classloader
95                    ClassLoader current = ObjectFactory.class.getClassLoader();
96                    if (current == null) {
97                        providerClass = Class.forName(className);
98                    } else if (cl != current) {
99                        cl = current;
100                        providerClass = cl.loadClass(className);
101                    } else {
102                        throw x;
103                    }
104                } else {
105                    throw x;
106                }
107            }
108        }
109
110        return providerClass;
111    }
112
113    //
114    // Classes
115    //
116
117    /**
118     * A configuration error.
119     */
120    static class ConfigurationError
121        extends Error {
122                static final long serialVersionUID = 8564305128443551853L;
123        //
124        // Data
125        //
126
127        /** Exception. */
128        private Exception exception;
129
130        //
131        // Constructors
132        //
133
134        /**
135         * Construct a new instance with the specified detail string and
136         * exception.
137         */
138        ConfigurationError(String msg, Exception x) {
139            super(msg);
140            this.exception = x;
141        } // <init>(String,Exception)
142
143        //
144        // Public methods
145        //
146
147        /** Returns the exception associated to this error. */
148        Exception getException() {
149            return exception;
150        } // getException():Exception
151
152    } // class ConfigurationError
153
154} // class ObjectFactory
155