View Javadoc

1   /*
2    * $Id: MuleResourceAdapter.java 10132 2007-12-26 15:05:48Z dfeist $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.ra;
12  
13  import org.mule.MuleManager;
14  import org.mule.config.ConfigurationBuilder;
15  import org.mule.config.ConfigurationException;
16  import org.mule.impl.MuleDescriptor;
17  import org.mule.impl.endpoint.MuleEndpointURI;
18  import org.mule.impl.model.ModelFactory;
19  import org.mule.providers.service.TransportFactory;
20  import org.mule.umo.UMODescriptor;
21  import org.mule.umo.UMOException;
22  import org.mule.umo.endpoint.EndpointException;
23  import org.mule.umo.endpoint.MalformedEndpointException;
24  import org.mule.umo.endpoint.UMOEndpoint;
25  import org.mule.umo.endpoint.UMOEndpointURI;
26  import org.mule.umo.manager.UMOManager;
27  import org.mule.umo.model.UMOModel;
28  import org.mule.util.ClassUtils;
29  
30  import java.io.IOException;
31  import java.io.ObjectInputStream;
32  import java.io.Serializable;
33  import java.util.HashMap;
34  import java.util.Map;
35  
36  import javax.resource.NotSupportedException;
37  import javax.resource.ResourceException;
38  import javax.resource.spi.ActivationSpec;
39  import javax.resource.spi.BootstrapContext;
40  import javax.resource.spi.ResourceAdapter;
41  import javax.resource.spi.ResourceAdapterInternalException;
42  import javax.resource.spi.endpoint.MessageEndpointFactory;
43  import javax.transaction.xa.XAResource;
44  
45  import org.apache.commons.logging.Log;
46  import org.apache.commons.logging.LogFactory;
47  
48  /**
49   * <code>MuleResourceAdapter</code> TODO
50   */
51  public class MuleResourceAdapter implements ResourceAdapter, Serializable
52  {
53      /**
54       * Serial version
55       */
56      private static final long serialVersionUID = 5727648958127416509L;
57  
58      /**
59       * logger used by this class
60       */
61      protected transient Log logger = LogFactory.getLog(this.getClass());
62  
63      protected transient UMOManager manager;
64  
65      protected transient BootstrapContext bootstrapContext;
66      protected MuleConnectionRequestInfo info = new MuleConnectionRequestInfo();
67      protected final Map endpoints = new HashMap();
68      protected String defaultJcaModelName;
69  
70      public MuleResourceAdapter()
71      {
72          MuleManager.getConfiguration().setModelType(JcaModel.JCA_MODEL_TYPE);
73      }
74  
75      private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException
76      {
77          ois.defaultReadObject();
78          this.logger = LogFactory.getLog(this.getClass());
79          this.manager = MuleManager.getInstance();
80      }
81  
82      /**
83       * @see javax.resource.spi.ResourceAdapter#start(javax.resource.spi.BootstrapContext)
84       */
85      public void start(BootstrapContext bootstrapContext) throws ResourceAdapterInternalException
86      {
87          this.bootstrapContext = bootstrapContext;
88          if (info.getConfigurations() != null)
89          {
90              if (MuleManager.isInstanciated())
91              {
92                  throw new ResourceAdapterInternalException(
93                      "A manager is already configured, cannot configure a new one using the configurations set on the Resource Adapter");
94              }
95              else
96              {
97                  ConfigurationBuilder builder = null;
98                  try
99                  {
100                     builder = (ConfigurationBuilder) ClassUtils.instanciateClass(info.getConfigurationBuilder(),
101                         ClassUtils.NO_ARGS);
102 
103                 }
104                 catch (Exception e)
105                 {
106                     throw new ResourceAdapterInternalException("Failed to instanciate configurationBuilder class: "
107                                                                + info.getConfigurationBuilder(), e);
108                 }
109 
110                 try
111                 {
112                     manager = builder.configure(info.getConfigurations(), null);
113                 }
114                 catch (ConfigurationException e)
115                 {
116                     logger.error(e);
117                     throw new ResourceAdapterInternalException("Failed to load configurations: "
118                                                                + info.getConfigurations(), e);
119                 }
120             }
121         }
122         manager = MuleManager.getInstance();
123     }
124 
125     /**
126      * @see javax.resource.spi.ResourceAdapter#stop()
127      */
128     public void stop()
129     {
130         manager.dispose();
131         manager = null;
132         bootstrapContext = null;
133     }
134 
135     /**
136      * @return the bootstrap context for this adapter
137      */
138     public BootstrapContext getBootstrapContext()
139     {
140         return bootstrapContext;
141     }
142 
143     /**
144      * @see javax.resource.spi.ResourceAdapter#endpointActivation(javax.resource.spi.endpoint.MessageEndpointFactory,
145      *      javax.resource.spi.ActivationSpec)
146      */
147     public void endpointActivation(MessageEndpointFactory endpointFactory, ActivationSpec activationSpec)
148         throws ResourceException
149     {
150         if (activationSpec.getResourceAdapter() != this)
151         {
152             throw new ResourceException("ActivationSpec not initialized with this ResourceAdapter instance");
153         }
154 
155         if (activationSpec.getClass().equals(MuleActivationSpec.class))
156         {
157             MuleActivationSpec muleActivationSpec = (MuleActivationSpec) activationSpec;
158             try
159             {
160                 // Resolve modelName
161                 String modelName = resolveModelName(muleActivationSpec);
162 
163                 // Lookup/create JCA Model
164                 JcaModel model = getJcaModel(modelName);
165 
166                 // Create Endpoint
167                 UMOEndpoint endpoint = createMessageInflowEndpoint(muleActivationSpec);
168 
169                 // Create Component
170                 MuleDescriptor descriptor = createJcaComponent(endpointFactory, model, endpoint);
171 
172                 // Keep reference to JcaComponent descriptor for endpointDeactivation
173                 MuleEndpointKey key = new MuleEndpointKey(endpointFactory, muleActivationSpec);
174                 endpoints.put(key, descriptor);
175             }
176             catch (Exception e)
177             {
178                 logger.error(e.getMessage(), e);
179             }
180         }
181         else
182         {
183             throw new NotSupportedException("That type of ActicationSpec not supported: " + activationSpec.getClass());
184         }
185 
186     }
187 
188     /**
189      * @see javax.resource.spi.ResourceAdapter#endpointDeactivation(javax.resource.spi.endpoint.MessageEndpointFactory,
190      *      javax.resource.spi.ActivationSpec)
191      */
192     public void endpointDeactivation(MessageEndpointFactory endpointFactory, ActivationSpec activationSpec)
193     {
194 
195         if (activationSpec.getClass().equals(MuleActivationSpec.class))
196         {
197             MuleActivationSpec muleActivationSpec = (MuleActivationSpec) activationSpec;
198             MuleEndpointKey key = new MuleEndpointKey(endpointFactory, (MuleActivationSpec) activationSpec);
199             UMODescriptor descriptor = (UMODescriptor) endpoints.remove(key);
200             if (descriptor == null)
201             {
202                 logger.warn("No endpoint was registered with key: " + key);
203                 return;
204             }
205 
206             // Resolve modelName
207             String modelName = null;
208             try
209             {
210                 modelName = resolveModelName(muleActivationSpec);
211             }
212             catch (ResourceException e)
213             {
214                 logger.error(e.getMessage(), e);
215             }
216 
217             try
218             {
219                 UMOModel model = MuleManager.getInstance().lookupModel(modelName);
220                 model.unregisterComponent(descriptor);
221             }
222             catch (UMOException e)
223             {
224                 logger.error(e.getMessage(), e);
225             }
226         }
227     }
228 
229     protected String resolveModelName(MuleActivationSpec activationSpec) throws ResourceException
230     {
231         // JCA specification mentions activationSpec properties inheriting
232         // resourceAdaptor properties, but this doesn't seem to work, at
233         // least with JBOSS, so do it manually.
234         String modelName = activationSpec.getModelName();
235         if (modelName == null)
236         {
237             modelName = defaultJcaModelName;
238         }
239         if (modelName == null)
240         {
241             throw new ResourceException(
242                 "The 'modelName' property has not been configured for either the MuleResourceAdaptor or MuleActicationSpec.");
243         }
244         return modelName;
245     }
246 
247     protected JcaModel getJcaModel(String modelName) throws UMOException, ResourceException
248     {
249         UMOModel model = MuleManager.getInstance().lookupModel(modelName);
250         if (model != null)
251         {
252             if (model instanceof JcaModel)
253             {
254                 ((JcaModel) model).setWorkManager(new DelegateWorkManager(bootstrapContext.getWorkManager()));
255                 return (JcaModel) model;
256             }
257             else
258             {
259                 throw new ResourceException("Model:-" + modelName + "  is not compatible with JCA type");
260             }
261         }
262         else
263         {
264             JcaModel jcaModel = (JcaModel) ModelFactory.createModel(JcaModel.JCA_MODEL_TYPE);
265             jcaModel.setName(modelName);
266             manager.registerModel(jcaModel);
267             jcaModel.setWorkManager(new DelegateWorkManager(bootstrapContext.getWorkManager()));
268             return jcaModel;
269         }
270     }
271 
272     protected MuleDescriptor createJcaComponent(MessageEndpointFactory endpointFactory,
273                                                 JcaModel model,
274                                                 UMOEndpoint endpoint) throws UMOException
275     {
276         String name = "JcaComponent#" + endpointFactory.hashCode();
277         MuleDescriptor descriptor = new MuleDescriptor(name);
278         descriptor.getInboundRouter().addEndpoint(endpoint);
279 
280         // Set endpointFactory rather than endpoint here, so we can obtain a
281         // new endpoint instance from factory for each incoming message in
282         // JcaComponet as reccomended by JCA specification
283         descriptor.setImplementation(endpointFactory);
284         descriptor.setModelName(model.getName());
285 
286         model.registerComponent(descriptor);
287         return descriptor;
288     }
289 
290     protected UMOEndpoint createMessageInflowEndpoint(MuleActivationSpec muleActivationSpec)
291         throws MalformedEndpointException, EndpointException
292     {
293         UMOEndpointURI uri = new MuleEndpointURI(muleActivationSpec.getEndpoint());
294         UMOEndpoint endpoint = TransportFactory.createEndpoint(uri, UMOEndpoint.ENDPOINT_TYPE_RECEIVER);
295 
296         // Use asynchronous endpoint as we need to dispatch to component
297         // rather than send.
298         endpoint.setSynchronous(false);
299         return endpoint;
300     }
301 
302     /**
303      * We only connect to one resource manager per ResourceAdapter instance, so any
304      * ActivationSpec will return the same XAResource.
305      * 
306      * @see javax.resource.spi.ResourceAdapter#getXAResources(javax.resource.spi.ActivationSpec[])
307      */
308     public XAResource[] getXAResources(ActivationSpec[] activationSpecs) throws ResourceException
309     {
310         return new XAResource[]{};
311     }
312 
313     /**
314      * @return
315      */
316     public String getPassword()
317     {
318         return info.getPassword();
319     }
320 
321     /**
322      * @return
323      */
324     public String getConfigurations()
325     {
326         return info.getConfigurations();
327     }
328 
329     /**
330      * @return
331      */
332     public String getUserName()
333     {
334         return info.getUserName();
335     }
336 
337     /**
338      * @param password
339      */
340     public void setPassword(String password)
341     {
342         info.setPassword(password);
343     }
344 
345     /**
346      * @param configurations
347      */
348     public void setConfigurations(String configurations)
349     {
350         info.setConfigurations(configurations);
351     }
352 
353     /**
354      * @param userid
355      */
356     public void setUserName(String userid)
357     {
358         info.setUserName(userid);
359     }
360 
361     public String getConfigurationBuilder()
362     {
363         return info.getConfigurationBuilder();
364     }
365 
366     public void setConfigurationBuilder(String configbuilder)
367     {
368         info.setConfigurationBuilder(configbuilder);
369     }
370 
371     /**
372      * @return Returns the info.
373      */
374     public MuleConnectionRequestInfo getInfo()
375     {
376         return info;
377     }
378 
379     public boolean equals(Object o)
380     {
381         if (this == o)
382         {
383             return true;
384         }
385         if (!(o instanceof MuleResourceAdapter))
386         {
387             return false;
388         }
389 
390         final MuleResourceAdapter muleResourceAdapter = (MuleResourceAdapter) o;
391 
392         if (info != null ? !info.equals(muleResourceAdapter.info) : muleResourceAdapter.info != null)
393         {
394             return false;
395         }
396 
397         return true;
398     }
399 
400     public int hashCode()
401     {
402         return (info != null ? info.hashCode() : 0);
403     }
404 
405     public String getModelName()
406     {
407         return defaultJcaModelName;
408     }
409 
410     public void setModelName(String modelName)
411     {
412         this.defaultJcaModelName = modelName;
413     }
414 
415 }