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
7 * "License"); you may not use this file except in compliance
8 * with the License. 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,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.openjpa.kernel;
20
21 import java.lang.reflect.InvocationTargetException;
22 import java.lang.reflect.Method;
23 import java.security.AccessController;
24
25 import org.apache.openjpa.conf.BrokerFactoryValue;
26 import org.apache.openjpa.lib.conf.ConfigurationProvider;
27 import org.apache.openjpa.lib.conf.MapConfigurationProvider;
28 import org.apache.openjpa.lib.conf.ProductDerivations;
29 import org.apache.openjpa.lib.util.J2DoPrivHelper;
30 import org.apache.openjpa.lib.util.Localizer;
31 import org.apache.openjpa.util.InternalException;
32 import org.apache.openjpa.util.OpenJPAException;
33 import org.apache.openjpa.util.UserException;
34
35 /**
36 * Helper methods for acquiring {@link BrokerFactory} objects
37 *
38 * @since 0.4.0.0
39 */
40 public class Bootstrap {
41
42 private static final Class[] FACTORY_ARGS =
43 new Class[]{ ConfigurationProvider.class };
44
45 private static Localizer s_loc = Localizer.forPackage(Bootstrap.class);
46
47 /**
48 * Return a new factory for the default configuration.
49 */
50 public static BrokerFactory newBrokerFactory() {
51 return Bootstrap.newBrokerFactory(null, null);
52 }
53
54 /**
55 * Return a new factory for the given configuration. The classloader
56 * will be used to load the factory class. If no classloader is given,
57 * the thread's context classloader is used.
58 */
59 public static BrokerFactory newBrokerFactory(ConfigurationProvider conf,
60 ClassLoader loader) {
61 try {
62 return invokeFactory(conf, loader, "newInstance");
63 } catch (InvocationTargetException ite) {
64 Throwable cause = ite.getTargetException();
65 if (cause instanceof OpenJPAException)
66 throw (OpenJPAException) cause;
67 throw new InternalException(s_loc.get("new-brokerfactory-excep",
68 getFactoryClassName(conf, loader)), cause);
69 } catch (Exception e) {
70 throw new UserException(s_loc.get("bad-new-brokerfactory",
71 getFactoryClassName(conf, loader)), e).setFatal(true);
72 }
73 }
74
75 /**
76 * Return a pooled factory for the default configuration.
77 */
78 public static BrokerFactory getBrokerFactory() {
79 return Bootstrap.getBrokerFactory(null, null);
80 }
81
82 /**
83 * Return a pooled factory for the given configuration. The classloader
84 * will be used to load the factory class. If no classloader is given,
85 * the thread's context classloader is used.
86 */
87 public static BrokerFactory getBrokerFactory(ConfigurationProvider conf,
88 ClassLoader loader) {
89 try {
90 return invokeFactory(conf, loader, "getInstance");
91 } catch (InvocationTargetException ite) {
92 Throwable cause = ite.getTargetException();
93 if (cause instanceof OpenJPAException)
94 throw (OpenJPAException) cause;
95 throw new InternalException(s_loc.get("brokerfactory-excep",
96 getFactoryClassName(conf, loader)), cause);
97 } catch (Exception e) {
98 throw new UserException(s_loc.get("bad-brokerfactory",
99 getFactoryClassName(conf, loader)), e).setFatal(true);
100 }
101 }
102
103 private static BrokerFactory invokeFactory(ConfigurationProvider conf,
104 ClassLoader loader, String methodName)
105 throws InvocationTargetException, NoSuchMethodException,
106 IllegalAccessException {
107 if (conf == null)
108 conf = new MapConfigurationProvider();
109 ProductDerivations.beforeConfigurationConstruct(conf);
110
111 Class cls = getFactoryClass(conf, loader);
112 Method meth;
113 try {
114 meth = cls.getMethod(methodName, FACTORY_ARGS);
115 } catch (NoSuchMethodException nsme) {
116 // handle cases where there is a mismatch between loaders by falling
117 // back to the configuration's class loader for broker resolution
118 cls = getFactoryClass(conf,
119 (ClassLoader) AccessController.doPrivileged(
120 J2DoPrivHelper.getClassLoaderAction(conf.getClass())));
121 meth = cls.getMethod(methodName, FACTORY_ARGS);
122 }
123
124 return (BrokerFactory) meth.invoke(null, new Object[]{ conf });
125 }
126
127 private static String getFactoryClassName(ConfigurationProvider conf,
128 ClassLoader loader) {
129 try {
130 return getFactoryClass(conf, loader).getName();
131 } catch (Exception e) {
132 return "<" + e.toString() + ">";
133 }
134 }
135
136 /**
137 * Instantiate the factory class designated in properties.
138 */
139 private static Class getFactoryClass(ConfigurationProvider conf,
140 ClassLoader loader) {
141 if (loader == null)
142 loader = (ClassLoader) AccessController.doPrivileged(
143 J2DoPrivHelper.getContextClassLoaderAction());
144
145 Object cls = BrokerFactoryValue.get(conf);
146 if (cls instanceof Class)
147 return (Class) cls;
148
149 BrokerFactoryValue value = new BrokerFactoryValue();
150 value.setString((String) cls);
151 String clsName = value.getClassName();
152 if (clsName == null)
153 throw new UserException(s_loc.get("no-brokerfactory",
154 conf.getProperties())).setFatal(true);
155
156 try {
157 return Class.forName(clsName, true, loader);
158 } catch (Exception e) {
159 throw new UserException(s_loc.get("bad-brokerfactory-class",
160 clsName), e).setFatal(true);
161 }
162 }
163 }