View Javadoc

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