View Javadoc

1   /*
2    * $Id: MuleResourceAdapter.java 22399 2011-07-13 07:06:27Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.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.DefaultMuleContext;
14  import org.mule.MessageExchangePattern;
15  import org.mule.api.MuleContext;
16  import org.mule.api.MuleException;
17  import org.mule.api.config.ConfigurationBuilder;
18  import org.mule.api.context.MuleContextBuilder;
19  import org.mule.api.endpoint.EndpointBuilder;
20  import org.mule.api.endpoint.InboundEndpoint;
21  import org.mule.api.model.Model;
22  import org.mule.api.service.Service;
23  import org.mule.api.source.CompositeMessageSource;
24  import org.mule.config.DefaultMuleConfiguration;
25  import org.mule.config.builders.DeployableMuleXmlContextListener;
26  import org.mule.config.spring.SpringXmlConfigurationBuilder;
27  import org.mule.context.DefaultMuleContextBuilder;
28  import org.mule.context.DefaultMuleContextFactory;
29  import org.mule.endpoint.EndpointURIEndpointBuilder;
30  import org.mule.endpoint.URIBuilder;
31  import org.mule.util.ClassUtils;
32  
33  import java.io.IOException;
34  import java.io.ObjectInputStream;
35  import java.io.Serializable;
36  import java.util.HashMap;
37  import java.util.Map;
38  
39  import javax.resource.NotSupportedException;
40  import javax.resource.ResourceException;
41  import javax.resource.spi.ActivationSpec;
42  import javax.resource.spi.BootstrapContext;
43  import javax.resource.spi.ResourceAdapter;
44  import javax.resource.spi.ResourceAdapterInternalException;
45  import javax.resource.spi.endpoint.MessageEndpointFactory;
46  import javax.transaction.xa.XAResource;
47  
48  import org.apache.commons.logging.Log;
49  import org.apache.commons.logging.LogFactory;
50  
51  /**
52   * <code>MuleResourceAdapter</code> TODO
53   */
54  public class MuleResourceAdapter implements ResourceAdapter, Serializable
55  {
56      /**
57       * Serial version
58       */
59      private static final long serialVersionUID = 5727648958127416509L;
60  
61      /**
62       * logger used by this class
63       */
64      protected transient Log logger = LogFactory.getLog(this.getClass());
65  
66      protected transient MuleContext muleContext;
67  
68      protected transient BootstrapContext bootstrapContext;
69      protected final Map<MuleEndpointKey, Service> endpoints = new HashMap<MuleEndpointKey, Service>();
70      protected String defaultJcaModelName;
71  
72      private String configurationBuilder = SpringXmlConfigurationBuilder.class.getName();
73      private String configurations;
74      private String username;
75      private String password;
76  
77      private DefaultMuleConfiguration muleConfiguration = new DefaultMuleConfiguration();
78  
79      private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException
80      {
81          ois.defaultReadObject();
82          this.logger = LogFactory.getLog(this.getClass());
83      }
84  
85      /**
86       * @see javax.resource.spi.ResourceAdapter#start(javax.resource.spi.BootstrapContext)
87       */
88      @Override
89      public void start(BootstrapContext bootstrapContext) throws ResourceAdapterInternalException
90      {
91          this.bootstrapContext = bootstrapContext;
92  
93          if (configurations != null)
94          {
95              ConfigurationBuilder configBuilder = null;
96              try
97              {
98                  configBuilder = (ConfigurationBuilder) ClassUtils.instanciateClass(configurationBuilder,
99                      configurations);
100             }
101             catch (Exception e)
102             {
103                 throw new ResourceAdapterInternalException(
104                     "Failed to instanciate configurationBuilder class: " + configurationBuilder, e);
105             }
106 
107             try
108             {
109                 logger.info("Initializing Mule...");
110 
111                 MuleContextBuilder contextBuilder = new DefaultMuleContextBuilder();
112                 muleConfiguration.setSystemModelType(JcaModel.JCA_MODEL_TYPE);
113                 contextBuilder.setMuleConfiguration(muleConfiguration);
114                 muleContext = new DefaultMuleContextFactory().createMuleContext(configBuilder, contextBuilder);
115 
116                 // Make single shared application server instance of mule context
117                 // available to DeployableMuleXmlContextListener to support hot
118                 // deployment of Mule configurations in web applications.
119                 DeployableMuleXmlContextListener.setMuleContext(muleContext);
120             }
121             catch (MuleException e)
122             {
123                 logger.error(e);
124                 throw new ResourceAdapterInternalException(
125                     "Failed to load configurations: " + configurations, e);
126             }
127             try
128             {
129                 logger.info("Starting Mule...");
130                 muleContext.start();
131             }
132             catch (MuleException e)
133             {
134                 logger.error(e);
135                 throw new ResourceAdapterInternalException("Failed to start management context", e);
136             }
137         }
138     }
139 
140     /**
141      * @see javax.resource.spi.ResourceAdapter#stop()
142      */
143     @Override
144     public void stop()
145     {
146         logger.info("Stopping Mule...");
147         muleContext.dispose();
148         muleContext = null;
149         bootstrapContext = null;
150     }
151 
152     /**
153      * @return the bootstrap context for this adapter
154      */
155     public BootstrapContext getBootstrapContext()
156     {
157         return bootstrapContext;
158     }
159 
160     /**
161      * @see javax.resource.spi.ResourceAdapter#endpointActivation(javax.resource.spi.endpoint.MessageEndpointFactory,
162      *      javax.resource.spi.ActivationSpec)
163      */
164     @Override
165     public void endpointActivation(MessageEndpointFactory endpointFactory, ActivationSpec activationSpec)
166         throws ResourceException
167     {
168         if (activationSpec.getResourceAdapter() != this)
169         {
170             throw new ResourceException("ActivationSpec not initialized with this ResourceAdapter instance");
171         }
172 
173         if (activationSpec.getClass().equals(MuleActivationSpec.class))
174         {
175             MuleActivationSpec muleActivationSpec = (MuleActivationSpec) activationSpec;
176             try
177             {
178                 // Resolve modelName
179                 String modelName = resolveModelName(muleActivationSpec);
180 
181                 // Lookup/create JCA Model
182                 JcaModel model = getJcaModel(modelName);
183 
184                 // Create Endpoint
185                 InboundEndpoint endpoint = createMessageInflowEndpoint(muleActivationSpec);
186 
187                 // Create Service
188                 Service service = createJcaService(endpointFactory, model, endpoint);
189 
190                 // Keep reference to JcaService descriptor for endpointDeactivation
191                 MuleEndpointKey key = new MuleEndpointKey(endpointFactory, muleActivationSpec);
192                 endpoints.put(key, service);
193             }
194             catch (Exception e)
195             {
196                 logger.error(e.getMessage(), e);
197             }
198         }
199         else
200         {
201             throw new NotSupportedException("That type of ActicationSpec not supported: "
202                                             + activationSpec.getClass());
203         }
204 
205     }
206 
207     /**
208      * @see javax.resource.spi.ResourceAdapter#endpointDeactivation(javax.resource.spi.endpoint.MessageEndpointFactory,
209      *      javax.resource.spi.ActivationSpec)
210      */
211     @Override
212     public void endpointDeactivation(MessageEndpointFactory endpointFactory, ActivationSpec activationSpec)
213     {
214         if (activationSpec.getClass().equals(MuleActivationSpec.class))
215         {
216             MuleActivationSpec muleActivationSpec = (MuleActivationSpec) activationSpec;
217             MuleEndpointKey key = new MuleEndpointKey(endpointFactory, (MuleActivationSpec) activationSpec);
218             Service service = endpoints.remove(key);
219             if (service == null)
220             {
221                 logger.warn("No endpoint was registered with key: " + key);
222                 return;
223             }
224 
225             // Resolve modelName
226             String modelName = null;
227             try
228             {
229                 modelName = resolveModelName(muleActivationSpec);
230             }
231             catch (ResourceException e)
232             {
233                 logger.error(e.getMessage(), e);
234             }
235 
236             try
237             {
238                 muleContext.getRegistry().unregisterService(service.getName());
239             }
240             catch (MuleException e)
241             {
242                 logger.error(e.getMessage(), e);
243             }
244         }
245     }
246 
247     protected String resolveModelName(MuleActivationSpec activationSpec) throws ResourceException
248     {
249         // JCA specification mentions activationSpec properties inheriting
250         // resourceAdaptor properties, but this doesn't seem to work, at
251         // least with JBOSS, so do it manually.
252         String modelName = activationSpec.getModelName();
253         if (modelName == null)
254         {
255             modelName = defaultJcaModelName;
256         }
257         if (modelName == null)
258         {
259             throw new ResourceException(
260                 "The 'modelName' property has not been configured for either the MuleResourceAdaptor or MuleActicationSpec.");
261         }
262         return modelName;
263     }
264 
265     protected JcaModel getJcaModel(String modelName) throws MuleException, ResourceException
266     {
267         Model model = muleContext.getRegistry().lookupModel(modelName);
268         if (model != null)
269         {
270             if (model instanceof JcaModel)
271             {
272                 return (JcaModel) model;
273             }
274             else
275             {
276                 throw new ResourceException("Model:-" + modelName + "  is not compatible with JCA type");
277             }
278         }
279         else
280         {
281             JcaModel jcaModel = new JcaModel();
282             jcaModel.setName(modelName);
283             muleContext.getRegistry().registerModel(jcaModel);
284             return jcaModel;
285         }
286     }
287 
288     protected Service createJcaService(MessageEndpointFactory endpointFactory,
289                                        JcaModel model,
290                                        InboundEndpoint endpoint) throws MuleException
291     {
292         String name = "JcaService#" + endpointFactory.hashCode();
293         Service service = new JcaService(muleContext);
294         service.setName(name);
295         ((CompositeMessageSource) service.getMessageSource()).addSource(endpoint);
296 
297         // Set endpointFactory rather than endpoint here, so we can obtain a
298         // new endpoint instance from factory for each incoming message in
299         // JcaComponet as reccomended by JCA specification
300         service.setComponent(new JcaComponent(endpointFactory, model.getEntryPointResolverSet(), service,
301             new DelegateWorkManager(bootstrapContext.getWorkManager())));
302         service.setModel(model);
303         muleContext.getRegistry().registerService(service);
304         return service;
305     }
306 
307     protected InboundEndpoint createMessageInflowEndpoint(MuleActivationSpec muleActivationSpec)
308         throws MuleException
309     {
310         EndpointBuilder endpointBuilder = new EndpointURIEndpointBuilder(new URIBuilder(
311             muleActivationSpec.getEndpoint(), muleContext));
312 
313         endpointBuilder.setExchangePattern(MessageExchangePattern.ONE_WAY);
314 
315         return muleContext.getEndpointFactory().getInboundEndpoint(endpointBuilder);
316     }
317 
318     /**
319      * We only connect to one resource manager per ResourceAdapter instance, so any
320      * ActivationSpec will return the same XAResource.
321      *
322      * @see javax.resource.spi.ResourceAdapter#getXAResources(javax.resource.spi.ActivationSpec[])
323      */
324     @Override
325     public XAResource[] getXAResources(ActivationSpec[] activationSpecs) throws ResourceException
326     {
327         return new XAResource[]{};
328     }
329 
330     /**
331      * @param password
332      */
333     public void setPassword(String password)
334     {
335         this.password = password;
336     }
337 
338     /**
339      * @param configurations
340      */
341     public void setConfigurations(String configurations)
342     {
343         this.configurations = configurations;
344     }
345 
346     /**
347      * @param userid
348      */
349     public void setUserName(String userid)
350     {
351         this.username = userid;
352     }
353 
354     public void setConfigurationBuilder(String configbuilder)
355     {
356         this.configurationBuilder = configbuilder;
357     }
358 
359     public void setModelName(String modelName)
360     {
361         this.defaultJcaModelName = modelName;
362     }
363 
364     public void setAutoWrapMessageAwareTransform(Boolean autoWrapMessageAwareTransform)
365     {
366         if (autoWrapMessageAwareTransform != null)
367         {
368             muleConfiguration.setAutoWrapMessageAwareTransform(autoWrapMessageAwareTransform);
369         }
370     }
371 
372     public void setCacheMessageAsBytes(Boolean cacheMessageAsBytes)
373     {
374         if (cacheMessageAsBytes != null)
375         {
376             muleConfiguration.setCacheMessageAsBytes(cacheMessageAsBytes);
377         }
378     }
379 
380     public void setCacheMessageOriginalPayload(Boolean cacheMessageOriginalPayload)
381     {
382         if (cacheMessageOriginalPayload != null)
383         {
384             muleConfiguration.setCacheMessageOriginalPayload(cacheMessageOriginalPayload);
385         }
386     }
387 
388     public void setClusterId(String clusterId)
389     {
390         ((DefaultMuleContext) muleContext).setClusterId(clusterId);
391     }
392 
393     public void setDefaultEncoding(String encoding)
394     {
395         muleConfiguration.setDefaultEncoding(encoding);
396     }
397 
398     public void setDefaultQueueTimeout(Integer defaultQueueTimeout)
399     {
400         if (defaultQueueTimeout != null)
401         {
402             muleConfiguration.setDefaultQueueTimeout(defaultQueueTimeout);
403         }
404     }
405 
406     public void setDefaultResponseTimeout(Integer responseTimeout)
407     {
408         if (responseTimeout != null)
409         {
410             muleConfiguration.setDefaultResponseTimeout(responseTimeout);
411         }
412     }
413 
414     public void setDefaultSynchronousEndpoints(Boolean synchronous)
415     {
416         if (synchronous != null)
417         {
418             muleConfiguration.setDefaultSynchronousEndpoints(synchronous);
419         }
420     }
421 
422     public void setDefaultTransactionTimeout(Integer defaultTransactionTimeout)
423     {
424         if (defaultTransactionTimeout != null)
425         {
426             muleConfiguration.setDefaultTransactionTimeout(defaultTransactionTimeout);
427         }
428     }
429 
430     public void setDomainId(String domainId)
431     {
432         muleConfiguration.setDomainId(domainId);
433     }
434 
435     public void setServerId(String serverId)
436     {
437         muleConfiguration.setId(serverId);
438     }
439 
440     public void setShutdownTimeout(Integer shutdownTimeout)
441     {
442         if (shutdownTimeout != null)
443         {
444             muleConfiguration.setShutdownTimeout(shutdownTimeout);
445         }
446     }
447 
448     public void setWorkingDirectory(String workingDirectory)
449     {
450         muleConfiguration.setWorkingDirectory(workingDirectory);
451     }
452 
453     // Although get methods for config properties aren't really required we need to
454     // include them otherwise Geronimo does not consider them valid properties
455 
456     public String getConfigurationBuilder()
457     {
458         return configurationBuilder;
459     }
460 
461     public String getConfigurations()
462     {
463         return configurations;
464     }
465 
466     public String getUserName()
467     {
468         return username;
469     }
470 
471     public String getPassword()
472     {
473         return password;
474     }
475 
476     public String getModelName()
477     {
478         return defaultJcaModelName;
479     }
480 
481     public String getClusterId()
482     {
483         return muleContext.getClusterId();
484     }
485 
486     public String getDefaultEncoding()
487     {
488         return muleConfiguration.getDefaultEncoding();
489     }
490 
491     public int getDefaultQueueTimeout()
492     {
493         return muleConfiguration.getDefaultQueueTimeout();
494     }
495 
496     public int getDefaultResponseTimeout()
497     {
498         return muleConfiguration.getDefaultResponseTimeout();
499     }
500 
501     public int getDefaultTransactionTimeout()
502     {
503         return muleConfiguration.getDefaultTransactionTimeout();
504     }
505 
506     public String getDomainId()
507     {
508         return muleConfiguration.getDomainId();
509     }
510 
511     public String getId()
512     {
513         return muleConfiguration.getId();
514     }
515 
516     public String getMuleHomeDirectory()
517     {
518         return muleConfiguration.getMuleHomeDirectory();
519     }
520 
521     public int getShutdownTimeout()
522     {
523         return muleConfiguration.getShutdownTimeout();
524     }
525 
526     public String getSystemModelType()
527     {
528         return muleConfiguration.getSystemModelType();
529     }
530 
531     public String getSystemName()
532     {
533         return muleConfiguration.getSystemName();
534     }
535 
536     public String getWorkingDirectory()
537     {
538         return muleConfiguration.getWorkingDirectory();
539     }
540 
541     public boolean isAutoWrapMessageAwareTransform()
542     {
543         return muleConfiguration.isAutoWrapMessageAwareTransform();
544     }
545 
546     public boolean isCacheMessageAsBytes()
547     {
548         return muleConfiguration.isCacheMessageAsBytes();
549     }
550 
551     public boolean isCacheMessageOriginalPayload()
552     {
553         return muleConfiguration.isCacheMessageOriginalPayload();
554     }
555 
556     public boolean isClientMode()
557     {
558         return muleConfiguration.isClientMode();
559     }
560 
561     public boolean isEnableStreaming()
562     {
563         return muleConfiguration.isEnableStreaming();
564     }
565 
566     @Override
567     public int hashCode()
568     {
569         final int prime = 31;
570         int result = 1;
571         result = prime * result + ((configurationBuilder == null) ? 0 : configurationBuilder.hashCode());
572         result = prime * result + ((configurations == null) ? 0 : configurations.hashCode());
573         result = prime * result + ((defaultJcaModelName == null) ? 0 : defaultJcaModelName.hashCode());
574         result = prime * result + ((endpoints == null) ? 0 : endpoints.hashCode());
575         result = prime * result + ((muleConfiguration == null) ? 0 : muleConfiguration.hashCode());
576         result = prime * result + ((password == null) ? 0 : password.hashCode());
577         result = prime * result + ((username == null) ? 0 : username.hashCode());
578         return result;
579     }
580 
581     @Override
582     public boolean equals(Object obj)
583     {
584         if (this == obj) return true;
585         if (obj == null) return false;
586         if (getClass() != obj.getClass()) return false;
587         MuleResourceAdapter other = (MuleResourceAdapter) obj;
588         if (configurationBuilder == null)
589         {
590             if (other.configurationBuilder != null) return false;
591         }
592         else if (!configurationBuilder.equals(other.configurationBuilder)) return false;
593         if (configurations == null)
594         {
595             if (other.configurations != null) return false;
596         }
597         else if (!configurations.equals(other.configurations)) return false;
598         if (defaultJcaModelName == null)
599         {
600             if (other.defaultJcaModelName != null) return false;
601         }
602         else if (!defaultJcaModelName.equals(other.defaultJcaModelName)) return false;
603         if (endpoints == null)
604         {
605             if (other.endpoints != null) return false;
606         }
607         else if (!endpoints.equals(other.endpoints)) return false;
608         if (muleConfiguration == null)
609         {
610             if (other.muleConfiguration != null) return false;
611         }
612         else if (!muleConfiguration.equals(other.muleConfiguration)) return false;
613         if (password == null)
614         {
615             if (other.password != null) return false;
616         }
617         else if (!password.equals(other.password)) return false;
618         if (username == null)
619         {
620             if (other.username != null) return false;
621         }
622         else if (!username.equals(other.username)) return false;
623         return true;
624     }
625 
626 }