View Javadoc

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      //default constructor for enhancement proxy endpoint
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         //set up that must be done before start
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         //register with resource adapter if not yet done
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         //create a new ConnectionFactory
197         connectionFactory = connectionManagerContainer.createConnectionFactory(managedConnectionFactory);
198 
199         //build proxy
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         //connect proxy
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     //DynamicGBean implementation
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         //we have no dynamic operations.
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     //ResourceManager implementation
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 }