001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    
018    package org.apache.geronimo.connector.outbound;
019    
020    import java.lang.reflect.Constructor;
021    import java.util.HashMap;
022    import java.util.LinkedHashSet;
023    import java.util.Map;
024    
025    import javax.resource.ResourceException;
026    import javax.resource.spi.ManagedConnectionFactory;
027    import javax.resource.spi.ResourceAdapterAssociation;
028    
029    import org.apache.commons.logging.Log;
030    import org.apache.commons.logging.LogFactory;
031    import org.apache.geronimo.connector.ResourceAdapterWrapper;
032    import org.apache.geronimo.gbean.AbstractName;
033    import org.apache.geronimo.gbean.DynamicGBean;
034    import org.apache.geronimo.gbean.DynamicGBeanDelegate;
035    import org.apache.geronimo.gbean.GBeanLifecycle;
036    import org.apache.geronimo.kernel.Kernel;
037    import org.apache.geronimo.management.geronimo.JCAManagedConnectionFactory;
038    
039    /**
040     * @version $Rev: 550546 $ $Date: 2007-06-25 12:52:11 -0400 (Mon, 25 Jun 2007) $
041     */
042    public class ManagedConnectionFactoryWrapper implements GBeanLifecycle, DynamicGBean, JCAManagedConnectionFactory, ConnectionFactorySource {
043    
044        private static final Log log = LogFactory.getLog(ManagedConnectionFactoryWrapper.class);
045    
046        private final String managedConnectionFactoryClass;
047        private final String connectionFactoryInterface;
048        private final String[] implementedInterfaces;
049        private final String connectionFactoryImplClass;
050        private final String connectionInterface;
051        private final String connectionImplClass;
052    
053        private final LinkedHashSet<Class> allImplementedInterfaces = new LinkedHashSet<Class>();
054    
055        private final ResourceAdapterWrapper resourceAdapterWrapper;
056        private final ConnectionManagerContainer connectionManagerContainer;
057    
058        private ManagedConnectionFactory managedConnectionFactory;
059    
060        private DynamicGBeanDelegate delegate;
061    
062    
063        private boolean registered = false;
064        private final Kernel kernel;
065        private final AbstractName abstractName;
066        private final String objectName;
067        private final ClassLoader classLoader;
068    
069        //default constructor for enhancement proxy endpoint
070        public ManagedConnectionFactoryWrapper() {
071            managedConnectionFactoryClass = null;
072            connectionFactoryInterface = null;
073            implementedInterfaces = null;
074            connectionFactoryImplClass = null;
075            connectionInterface = null;
076            connectionImplClass = null;
077            kernel = null;
078            abstractName = null;
079            objectName = null;
080            classLoader = null;
081            resourceAdapterWrapper = null;
082            connectionManagerContainer = null;
083        }
084    
085        public ManagedConnectionFactoryWrapper(String managedConnectionFactoryClass,
086                                               String connectionFactoryInterface,
087                                               String[] implementedInterfaces,
088                                               String connectionFactoryImplClass,
089                                               String connectionInterface,
090                                               String connectionImplClass,
091                                               ResourceAdapterWrapper resourceAdapterWrapper,
092                                               ConnectionManagerContainer connectionManagerContainer,
093                                               Kernel kernel,
094                                               AbstractName abstractName,
095                                               String objectName,
096                                               ClassLoader cl) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
097            this.managedConnectionFactoryClass = managedConnectionFactoryClass;
098            this.connectionFactoryInterface = connectionFactoryInterface;
099            this.implementedInterfaces = implementedInterfaces;
100            this.connectionFactoryImplClass = connectionFactoryImplClass;
101            this.connectionInterface = connectionInterface;
102            this.connectionImplClass = connectionImplClass;
103    
104            allImplementedInterfaces.add(cl.loadClass(connectionFactoryInterface));
105            for (String interfaceName: implementedInterfaces) {
106                allImplementedInterfaces.add(cl.loadClass(interfaceName));
107            }
108    
109            this.resourceAdapterWrapper = resourceAdapterWrapper;
110            this.connectionManagerContainer = connectionManagerContainer;
111    
112            //set up that must be done before start
113            classLoader = cl;
114            Class clazz = cl.loadClass(managedConnectionFactoryClass);
115            managedConnectionFactory = (ManagedConnectionFactory) clazz.newInstance();
116            delegate = new DynamicGBeanDelegate();
117            delegate.addAll(managedConnectionFactory);
118            this.kernel = kernel;
119            this.abstractName = abstractName;
120            this.objectName = objectName;
121        }
122    
123        public String getManagedConnectionFactoryClass() {
124            return managedConnectionFactoryClass;
125        }
126    
127        public String getConnectionFactoryInterface() {
128            return connectionFactoryInterface;
129        }
130    
131        public String[] getImplementedInterfaces() {
132            return implementedInterfaces;
133        }
134    
135        public String getConnectionFactoryImplClass() {
136            return connectionFactoryImplClass;
137        }
138    
139        public String getConnectionInterface() {
140            return connectionInterface;
141        }
142    
143        public String getConnectionImplClass() {
144            return connectionImplClass;
145        }
146    
147        public ResourceAdapterWrapper getResourceAdapterWrapper() {
148            return resourceAdapterWrapper;
149        }
150    
151        public Object getConnectionManagerContainer() {
152            return connectionManagerContainer;
153        }
154    
155        public void doStart() throws Exception {
156            //register with resource adapter if not yet done
157            if (!registered && (managedConnectionFactory instanceof ResourceAdapterAssociation)) {
158                if (resourceAdapterWrapper == null) {
159                    throw new IllegalStateException("Managed connection factory expects to be registered with a ResourceAdapter, but there is no ResourceAdapter");
160                }
161                resourceAdapterWrapper.registerResourceAdapterAssociation((ResourceAdapterAssociation) managedConnectionFactory);
162                registered = true;
163                log.debug("Registered managedConnectionFactory with ResourceAdapter " + resourceAdapterWrapper.toString());
164            }
165            connectionManagerContainer.doRecovery(managedConnectionFactory);
166        }
167    
168        public void doStop() {
169        }
170    
171        public void doFail() {
172            doStop();
173        }
174    
175        //DynamicGBean implementation
176        public Object getAttribute(String name) throws Exception {
177            Thread thread = Thread.currentThread();
178            ClassLoader oldTCL = thread.getContextClassLoader();
179            thread.setContextClassLoader(classLoader);
180            try {
181                return delegate.getAttribute(name);
182            } finally {
183                thread.setContextClassLoader(oldTCL);
184            }
185        }
186    
187        public void setAttribute(String name, Object value) throws Exception {
188            Thread thread = Thread.currentThread();
189            ClassLoader oldTCL = thread.getContextClassLoader();
190            thread.setContextClassLoader(classLoader);
191            try {
192                delegate.setAttribute(name, value);
193            } finally {
194                thread.setContextClassLoader(oldTCL);
195            }
196        }
197    
198        public Object invoke(String name, Object[] arguments, String[] types) throws Exception {
199            //we have no dynamic operations.
200            return null;
201        }
202    
203        public Object getConnectionFactory() throws ResourceException {
204            return $getConnectionFactory();
205        }
206    
207        public Object $getResource() throws ResourceException {
208            return $getConnectionFactory();
209        }
210    
211        public Object $getConnectionFactory() throws ResourceException {
212            Object connectionFactory =  connectionManagerContainer.createConnectionFactory(managedConnectionFactory);
213            for (Class intf: allImplementedInterfaces) {
214                if (!intf.isAssignableFrom(connectionFactory.getClass())) {
215                    throw new ResourceException("ConnectionFactory does not implement expected interface: " + intf.getName());
216                }
217            }
218            return connectionFactory;
219        }
220    
221        public ManagedConnectionFactory $getManagedConnectionFactory() {
222            return managedConnectionFactory;
223        }
224    
225        /**
226         * Gets the config properties in the form of a map where the key is the
227         * property name and the value is property type (as a Class).
228         */
229        public Map<String, Class> getConfigProperties() {
230            String[] props = delegate.getProperties();
231            Map<String, Class> map = new HashMap<String, Class>();
232            for (String prop : props) {
233                if (prop.equals("logWriter")) {
234                    continue;
235                }
236                map.put(prop, delegate.getPropertyType(prop));
237            }
238            return map;
239        }
240    
241        public void setConfigProperty(String property, Object value) throws Exception {
242            Class cls = delegate.getPropertyType(property);
243            if(value != null && value instanceof String && !cls.getName().equals("java.lang.String")) {
244                if(cls.isPrimitive()) {
245                    if(cls.equals(int.class)) {
246                        cls = Integer.class;
247                    } else if(cls.equals(boolean.class)) {
248                        cls = Boolean.class;
249                    } else if(cls.equals(float.class)) {
250                        cls = Float.class;
251                    } else if(cls.equals(double.class)) {
252                        cls = Double.class;
253                    } else if(cls.equals(long.class)) {
254                        cls = Long.class;
255                    } else if(cls.equals(short.class)) {
256                        cls = Short.class;
257                    } else if(cls.equals(byte.class)) {
258                        cls = Byte.class;
259                    } else if(cls.equals(char.class)) {
260                        cls = Character.class;
261                    }
262                }
263                Constructor con = cls.getConstructor(new Class[]{String.class});
264                value = con.newInstance(new Object[]{value});
265            }
266            kernel.setAttribute(abstractName, property, value);
267        }
268    
269        public Object getConfigProperty(String property) throws Exception {
270            return delegate.getAttribute(property);
271        }
272    
273        public String getObjectName() {
274            return objectName;
275        }
276    
277        public boolean isStateManageable() {
278            return false;
279        }
280    
281        public boolean isStatisticsProvider() {
282            return false;
283        }
284    
285        public boolean isEventProvider() {
286            return false;
287        }
288    }