1 /**
2 *
3 * Copyright 2003-2005 The Apache Software Foundation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.geronimo.connector.outbound;
19
20 import java.lang.reflect.Constructor;
21 import java.util.HashMap;
22 import java.util.Map;
23 import java.util.LinkedHashSet;
24
25 import javax.management.ObjectName;
26 import javax.resource.ResourceException;
27 import javax.resource.spi.ManagedConnectionFactory;
28 import javax.resource.spi.ResourceAdapterAssociation;
29 import javax.transaction.SystemException;
30
31 import net.sf.cglib.proxy.Callback;
32 import net.sf.cglib.proxy.Enhancer;
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.apache.geronimo.connector.ConnectorMethodInterceptor;
36 import org.apache.geronimo.connector.ResourceAdapterWrapper;
37 import org.apache.geronimo.gbean.DynamicGBean;
38 import org.apache.geronimo.gbean.DynamicGBeanDelegate;
39 import org.apache.geronimo.gbean.GBeanLifecycle;
40 import org.apache.geronimo.gbean.AbstractName;
41 import org.apache.geronimo.kernel.Kernel;
42 import org.apache.geronimo.management.geronimo.JCAManagedConnectionFactory;
43 import org.apache.geronimo.transaction.manager.NamedXAResource;
44 import org.apache.geronimo.transaction.manager.ResourceManager;
45
46 /**
47 * @version $Rev: 421362 $ $Date: 2006-07-12 11:35:32 -0700 (Wed, 12 Jul 2006) $
48 */
49 public class ManagedConnectionFactoryWrapper implements GBeanLifecycle, DynamicGBean, ResourceManager, JCAManagedConnectionFactory, ConnectionFactorySource {
50
51 private static final Log log = LogFactory.getLog(ManagedConnectionFactoryWrapper.class);
52
53 private final String managedConnectionFactoryClass;
54 private final String connectionFactoryInterface;
55 private final String[] implementedInterfaces;
56 private final String connectionFactoryImplClass;
57 private final String connectionInterface;
58 private final String connectionImplClass;
59
60 private final Class[] allImplementedInterfaces;
61
62 private final ResourceAdapterWrapper resourceAdapterWrapper;
63 private final ConnectionManagerContainer connectionManagerContainer;
64
65 private ManagedConnectionFactory managedConnectionFactory;
66
67 private Object connectionFactory;
68
69 private DynamicGBeanDelegate delegate;
70
71
72 private boolean registered = false;
73 private Object proxy;
74 private ConnectorMethodInterceptor interceptor;
75 private final Kernel kernel;
76 private final AbstractName abstractName;
77 private final String objectName;
78 private final boolean isProxyable;
79 private final ClassLoader classLoader;
80
81
82 public ManagedConnectionFactoryWrapper() {
83 managedConnectionFactoryClass = null;
84 connectionFactoryInterface = null;
85 implementedInterfaces = null;
86 connectionFactoryImplClass = null;
87 connectionInterface = null;
88 connectionImplClass = null;
89 kernel = null;
90 abstractName = null;
91 objectName = null;
92 allImplementedInterfaces = null;
93 isProxyable = false;
94 classLoader = null;
95 resourceAdapterWrapper = null;
96 connectionManagerContainer = null;
97 }
98
99 public ManagedConnectionFactoryWrapper(String managedConnectionFactoryClass,
100 String connectionFactoryInterface,
101 String[] implementedInterfaces,
102 String connectionFactoryImplClass,
103 String connectionInterface,
104 String connectionImplClass,
105 ResourceAdapterWrapper resourceAdapterWrapper,
106 ConnectionManagerContainer connectionManagerContainer,
107 Kernel kernel,
108 AbstractName abstractName,
109 String objectName,
110 ClassLoader cl) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
111 this.managedConnectionFactoryClass = managedConnectionFactoryClass;
112 this.connectionFactoryInterface = connectionFactoryInterface;
113 this.implementedInterfaces = implementedInterfaces;
114 this.connectionFactoryImplClass = connectionFactoryImplClass;
115 this.connectionInterface = connectionInterface;
116 this.connectionImplClass = connectionImplClass;
117
118 LinkedHashSet allInterfaceSet = new LinkedHashSet();
119 allInterfaceSet.add(cl.loadClass(connectionFactoryInterface));
120 for (int i = 0; i < implementedInterfaces.length; i++) {
121 allInterfaceSet.add(cl.loadClass(implementedInterfaces[i]));
122 }
123 allImplementedInterfaces = (Class[])allInterfaceSet.toArray(new Class[allInterfaceSet.size()]);
124
125 boolean mightBeProxyable = true;
126 for (int i = 0; i < allImplementedInterfaces.length; i++) {
127 Class implementedInterface = allImplementedInterfaces[i];
128 if (!implementedInterface.isInterface()) {
129 mightBeProxyable = false;
130 break;
131 }
132 }
133 isProxyable = mightBeProxyable;
134
135 this.resourceAdapterWrapper = resourceAdapterWrapper;
136 this.connectionManagerContainer = connectionManagerContainer;
137
138
139 classLoader = cl;
140 Class clazz = cl.loadClass(managedConnectionFactoryClass);
141 managedConnectionFactory = (ManagedConnectionFactory) clazz.newInstance();
142 delegate = new DynamicGBeanDelegate();
143 delegate.addAll(managedConnectionFactory);
144 this.kernel = kernel;
145 this.abstractName = abstractName;
146 this.objectName = objectName;
147 }
148
149 public String getManagedConnectionFactoryClass() {
150 return managedConnectionFactoryClass;
151 }
152
153 public String getConnectionFactoryInterface() {
154 return connectionFactoryInterface;
155 }
156
157 public String[] getImplementedInterfaces() {
158 return implementedInterfaces;
159 }
160
161 public String getConnectionFactoryImplClass() {
162 return connectionFactoryImplClass;
163 }
164
165 public String getConnectionInterface() {
166 return connectionInterface;
167 }
168
169 public String getConnectionImplClass() {
170 return connectionImplClass;
171 }
172
173 public ResourceAdapterWrapper getResourceAdapterWrapper() {
174 return resourceAdapterWrapper;
175 }
176
177 public ConnectionManagerContainer getConnectionManagerFactory() {
178 return connectionManagerContainer;
179 }
180
181 public Object getConnectionManager() {
182 return connectionManagerContainer.getConnectionManager();
183 }
184
185 public void doStart() throws Exception {
186
187 if (!registered && (managedConnectionFactory instanceof ResourceAdapterAssociation)) {
188 if (resourceAdapterWrapper == null) {
189 throw new IllegalStateException("Managed connection factory expects to be registered with a ResourceAdapter, but there is no ResourceAdapter");
190 }
191 resourceAdapterWrapper.registerResourceAdapterAssociation((ResourceAdapterAssociation) managedConnectionFactory);
192 registered = true;
193 log.debug("Registered managedConnectionFactory with ResourceAdapter " + resourceAdapterWrapper.toString());
194 }
195
196
197 connectionFactory = connectionManagerContainer.createConnectionFactory(managedConnectionFactory);
198
199
200 if (isProxyable) {
201 Enhancer enhancer = new Enhancer();
202 enhancer.setInterfaces(allImplementedInterfaces);
203 enhancer.setCallbackType(net.sf.cglib.proxy.MethodInterceptor.class);
204 enhancer.setUseFactory(false);
205 interceptor = new ConnectorMethodInterceptor(kernel.getKernelName(), abstractName);
206 enhancer.setCallbacks(new Callback[]{interceptor});
207 proxy = enhancer.create(new Class[0], new Object[0]);
208 } else {
209 proxy = connectionFactory;
210 }
211
212
213 if (interceptor != null) {
214 interceptor.setInternalProxy(connectionFactory);
215 }
216 }
217
218 public void doStop() {
219 if (interceptor != null) {
220 interceptor.setInternalProxy(null);
221 }
222 connectionFactory = null;
223 }
224
225 public void doFail() {
226 doStop();
227 }
228
229
230 public Object getAttribute(String name) throws Exception {
231 Thread thread = Thread.currentThread();
232 ClassLoader oldTCL = thread.getContextClassLoader();
233 thread.setContextClassLoader(classLoader);
234 try {
235 return delegate.getAttribute(name);
236 } finally {
237 thread.setContextClassLoader(oldTCL);
238 }
239 }
240
241 public void setAttribute(String name, Object value) throws Exception {
242 Thread thread = Thread.currentThread();
243 ClassLoader oldTCL = thread.getContextClassLoader();
244 thread.setContextClassLoader(classLoader);
245 try {
246 delegate.setAttribute(name, value);
247 } finally {
248 thread.setContextClassLoader(oldTCL);
249 }
250 }
251
252 public Object invoke(String name, Object[] arguments, String[] types) throws Exception {
253
254 return null;
255 }
256
257 public Object getConnectionFactory() {
258 return $getResource();
259 }
260
261 public Object $getResource() {
262 return proxy;
263 }
264
265 public Object $getConnectionFactory() {
266 return connectionFactory;
267 }
268
269 public ManagedConnectionFactory $getManagedConnectionFactory() {
270 return managedConnectionFactory;
271 }
272
273 /**
274 * Gets the config properties in the form of a map where the key is the
275 * property name and the value is property type (as a String not a Class).
276 */
277 public Map getConfigProperties() {
278 String[] props = delegate.getProperties();
279 Map map = new HashMap();
280 for (int i = 0; i < props.length; i++) {
281 String prop = props[i];
282 if(prop.equals("logWriter")) {
283 continue;
284 }
285 map.put(prop, delegate.getPropertyType(prop));
286 }
287 return map;
288 }
289
290 public void setConfigProperty(String property, Object value) throws Exception {
291 Class cls = delegate.getPropertyType(property);
292 if(value != null && value instanceof String && !cls.getName().equals("java.lang.String")) {
293 if(cls.isPrimitive()) {
294 if(cls.equals(int.class)) {
295 cls = Integer.class;
296 } else if(cls.equals(boolean.class)) {
297 cls = Boolean.class;
298 } else if(cls.equals(float.class)) {
299 cls = Float.class;
300 } else if(cls.equals(double.class)) {
301 cls = Double.class;
302 } else if(cls.equals(long.class)) {
303 cls = Long.class;
304 } else if(cls.equals(short.class)) {
305 cls = Short.class;
306 } else if(cls.equals(byte.class)) {
307 cls = Byte.class;
308 } else if(cls.equals(char.class)) {
309 cls = Character.class;
310 }
311 }
312 Constructor con = cls.getConstructor(new Class[]{String.class});
313 value = con.newInstance(new Object[]{value});
314 }
315 kernel.setAttribute(abstractName, property, value);
316 }
317
318 public Object getConfigProperty(String property) throws Exception {
319 return delegate.getAttribute(property);
320 }
321
322
323 public NamedXAResource getRecoveryXAResources() throws SystemException {
324 try {
325 return connectionManagerContainer.getRecoveryXAResource(managedConnectionFactory);
326 } catch (ResourceException e) {
327 throw (SystemException) new SystemException("Could not obtain recovery XAResource for managedConnectionFactory " + objectName).initCause(e);
328 }
329 }
330
331 public void returnResource(NamedXAResource xaResource) {
332 ((ConnectionManagerContainer.ReturnableXAResource) xaResource).returnConnection();
333 }
334
335 public String getObjectName() {
336 return objectName;
337 }
338
339 public boolean isStateManageable() {
340 return false;
341 }
342
343 public boolean isStatisticsProvider() {
344 return false;
345 }
346
347 public boolean isEventProvider() {
348 return false;
349 }
350 }