View Javadoc

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