View Javadoc

1   /*
2    * $Id: AbstractJbiComponent.java 7976 2007-08-21 14:26:13Z 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.providers.jbi.components;
12  
13  import org.mule.MuleManager;
14  import org.mule.config.converters.QNameConverter;
15  import org.mule.util.concurrent.WaitableBoolean;
16  
17  import java.util.HashMap;
18  import java.util.Map;
19  
20  import javax.jbi.JBIException;
21  import javax.jbi.component.Component;
22  import javax.jbi.component.ComponentContext;
23  import javax.jbi.component.ComponentLifeCycle;
24  import javax.jbi.component.ServiceUnitManager;
25  import javax.jbi.management.DeploymentException;
26  import javax.jbi.messaging.DeliveryChannel;
27  import javax.jbi.messaging.ExchangeStatus;
28  import javax.jbi.messaging.Fault;
29  import javax.jbi.messaging.MessageExchange;
30  import javax.jbi.messaging.MessageExchangeFactory;
31  import javax.jbi.messaging.MessagingException;
32  import javax.jbi.servicedesc.ServiceEndpoint;
33  import javax.management.MBeanServer;
34  import javax.management.ObjectName;
35  import javax.resource.spi.work.Work;
36  import javax.resource.spi.work.WorkException;
37  import javax.resource.spi.work.WorkManager;
38  import javax.xml.namespace.QName;
39  
40  import org.apache.commons.logging.Log;
41  import org.apache.commons.logging.LogFactory;
42  import org.w3c.dom.Document;
43  import org.w3c.dom.DocumentFragment;
44  
45  /**
46   * A base Jbi component implementation. This is agnostic to any particular Jbi
47   * container
48   * 
49   * @author <a href="mailto:ross.mason@symphonysoft.com">Ross Mason</a>
50   * @version $Revision: 7976 $
51   */
52  public abstract class AbstractJbiComponent implements Component, Work, ComponentLifeCycle
53  {
54  
55      public static final String IN = "in";
56      public static final String OUT = "out";
57      /**
58       * logger used by this class
59       */
60      protected transient Log logger = LogFactory.getLog(getClass());
61  
62      protected ComponentContext context;
63  
64      protected Map serviceDescriptions = new HashMap();
65  
66      protected QName service;
67  
68      protected String name;
69  
70      protected WorkManager workManager;
71  
72      protected DeliveryChannel deliveryChannel;
73  
74      protected ObjectName mbeanName;
75  
76      protected ServiceUnitManager serviceUnitManager;
77  
78      protected MessageExchangeFactory exchangeFactory;
79  
80      protected WaitableBoolean started = new WaitableBoolean(false);
81  
82      public ComponentLifeCycle getLifeCycle()
83      {
84          return this;
85      }
86  
87      public ServiceUnitManager getServiceUnitManager()
88      {
89          return serviceUnitManager;
90      }
91  
92      public Document getServiceDescription(ServiceEndpoint endpoint)
93      {
94          if (logger.isDebugEnabled())
95          {
96              logger.debug("Querying service description for " + endpoint);
97          }
98          String key = getKey(endpoint);
99          Document doc = (Document)this.serviceDescriptions.get(key);
100         if (logger.isDebugEnabled())
101         {
102             if (doc != null)
103             {
104                 logger.debug("Description found");
105             }
106             else
107             {
108                 logger.debug("Description not found");
109             }
110         }
111         return doc;
112     }
113 
114     public void setServiceDescription(ServiceEndpoint endpoint, Document doc)
115     {
116         if (logger.isDebugEnabled())
117         {
118             logger.debug("Setting service description for " + endpoint);
119         }
120         String key = getKey(endpoint);
121         this.serviceDescriptions.put(key, doc);
122     }
123 
124     private String getKey(ServiceEndpoint endpoint)
125     {
126         StringBuffer sb = new StringBuffer();
127         sb.append("{");
128         sb.append(endpoint.getServiceName().getNamespaceURI());
129         sb.append("}");
130         sb.append(endpoint.getServiceName().getLocalPart());
131         sb.append(":");
132         sb.append(endpoint.getEndpointName());
133         return sb.toString();
134     }
135 
136     /*
137      * (non-Javadoc)
138      * 
139      * @see javax.jbi.component.Component#isExchangeWithConsumerOkay(javax.jbi.servicedesc.ServiceEndpoint,
140      *      javax.jbi.messaging.MessageExchange)
141      */
142     public boolean isExchangeWithConsumerOkay(ServiceEndpoint endpoint, MessageExchange exchange)
143     {
144         return true;
145     }
146 
147     /*
148      * (non-Javadoc)
149      * 
150      * @see javax.jbi.component.Component#isExchangeWithProviderOkay(javax.jbi.servicedesc.ServiceEndpoint,
151      *      javax.jbi.messaging.MessageExchange)
152      */
153     public boolean isExchangeWithProviderOkay(ServiceEndpoint endpoint, MessageExchange exchange)
154     {
155         return true;
156     }
157 
158     /*
159      * (non-Javadoc)
160      * 
161      * @see javax.jbi.component.Component#resolveEndpointReference(org.w3c.dom.DocumentFragment)
162      */
163     public ServiceEndpoint resolveEndpointReference(DocumentFragment epr)
164     {
165         return null;
166     }
167 
168     protected ObjectName createExtensionMBeanName() throws Exception
169     {
170         return this.context.getMBeanNames().createCustomComponentMBeanName("extension");
171     }
172 
173     public Object getExtensionMBean()
174     {
175         return null; // todo
176     }
177 
178     public QName getService()
179     {
180         return service;
181     }
182 
183     public void setService(QName service)
184     {
185         this.service = service;
186     }
187 
188     public String getName()
189     {
190         return name;
191     }
192 
193     public void setName(String name)
194     {
195         this.name = name;
196     }
197 
198     public WorkManager getWorkManager()
199     {
200         return workManager;
201     }
202 
203     public void setWorkManager(WorkManager workManager)
204     {
205         this.workManager = workManager;
206     }
207 
208     // ----------Component Lifecycle methods ----------------//
209 
210     /*
211      * (non-Javadoc)
212      * 
213      * @see javax.jbi.component.ComponentLifeCycle#init(javax.jbi.component.ComponentContext)
214      */
215     public synchronized final void init(ComponentContext context) throws JBIException
216     {
217         try
218         {
219             if (context.getComponentName() != null)
220             {
221                 name = context.getComponentName();
222             }
223             if (name == null)
224             {
225                 throw new IllegalArgumentException("No name has been set for this component");
226             }
227 
228             if (service == null)
229             {
230                 service = (QName)new QNameConverter().convert(QName.class, name);
231             }
232 
233             context.activateEndpoint(service, service.getLocalPart());
234 
235             if (logger.isDebugEnabled())
236             {
237                 logger.debug("Initializing component: " + name);
238             }
239             this.context = context;
240             deliveryChannel = context.getDeliveryChannel();
241             exchangeFactory = deliveryChannel.createExchangeFactory();
242             Object mbean = getExtensionMBean();
243             if (serviceUnitManager == null)
244             {
245                 serviceUnitManager = new DefaultServiceUnitManager();
246             }
247 
248             if (workManager == null)
249             {
250                 workManager = MuleManager.getInstance().getWorkManager();
251             }
252 
253             if (mbean != null)
254             {
255                 if (mbeanName == null)
256                 {
257                     this.mbeanName = createExtensionMBeanName();
258                 }
259                 MBeanServer server = AbstractJbiComponent.this.context.getMBeanServer();
260                 if (server == null)
261                 {
262                     throw new JBIException("null mBeanServer");
263                 }
264 
265                 if (server.isRegistered(this.mbeanName))
266                 {
267                     server.unregisterMBean(this.mbeanName);
268                 }
269                 server.registerMBean(mbean, this.mbeanName);
270             }
271 
272             doInit();
273             if (logger.isDebugEnabled())
274             {
275                 logger.debug("Jbi Receiver Component initialized: " + name);
276             }
277         }
278         catch (JBIException e)
279         {
280             throw e;
281         }
282         catch (Exception e)
283         {
284             throw new JBIException("Error calling init on " + name, e);
285         }
286     }
287 
288     public final void shutDown() throws JBIException
289     {
290         try
291         {
292             if (logger.isDebugEnabled())
293             {
294                 logger.debug("Shutting down component: " + getName());
295             }
296             started.set(false);
297             doShutdown();
298             if (this.mbeanName != null)
299             {
300                 MBeanServer server = context.getMBeanServer();
301                 if (server == null)
302                 {
303                     throw new JBIException("null mBeanServer");
304                 }
305                 if (server.isRegistered(this.mbeanName))
306                 {
307                     server.unregisterMBean(this.mbeanName);
308                 }
309             }
310             this.context = null;
311             if (logger.isDebugEnabled())
312             {
313                 logger.debug("Component shut down: " + getName());
314             }
315         }
316         catch (JBIException e)
317         {
318             throw e;
319         }
320         catch (Exception e)
321         {
322             throw new JBIException("Error calling shutdown on " + getName(), e);
323         }
324     }
325 
326     public final void start() throws JBIException
327     {
328         logger.debug("Starting Mule Jbi component: " + name);
329         started.set(true);
330         if (this instanceof MessageExchangeListener)
331         {
332             try
333             {
334                 logger.debug("Starting ME thread for: " + name);
335                 getWorkManager().scheduleWork(this);
336             }
337             catch (WorkException e)
338             {
339                 throw new JBIException(e);
340             }
341         }
342         doStart();
343 
344     }
345 
346     public final void stop() throws JBIException
347     {
348         started.set(false);
349         doStop();
350     }
351 
352     protected void doInit() throws JBIException
353     {
354         // template method
355     }
356 
357     protected void doStart() throws JBIException
358     {
359         // template method
360     }
361 
362     protected void doStop() throws JBIException
363     {
364         // template method
365     }
366 
367     protected void doShutdown() throws JBIException
368     {
369         // template method
370     }
371 
372     public ObjectName getExtensionMBeanName()
373     {
374         return mbeanName;
375     }
376 
377     public void setExtensionMBeanName(ObjectName mbeanName)
378     {
379         this.mbeanName = mbeanName;
380     }
381 
382     public void release()
383     {
384         // nothing to do
385     }
386 
387     // TODO This receive code should be separated out to pluggable invocation
388     // strategies
389 
390     public void run()
391     {
392         while (started.get())
393         {
394             try
395             {
396                 final MessageExchange me = deliveryChannel.accept();
397                 if (me != null)
398                 {
399                     getWorkManager().scheduleWork(
400                         new MessageExchangeWorker(me, (MessageExchangeListener)this));
401                 }
402             }
403             catch (Exception e)
404             {
405                 logger.error(e.getMessage(), e);
406             }
407         }
408     }
409 
410     protected class MessageExchangeWorker implements Work
411     {
412         private MessageExchange me;
413         private MessageExchangeListener listener;
414 
415         public MessageExchangeWorker(MessageExchange me, MessageExchangeListener listener)
416         {
417             this.me = me;
418             this.listener = listener;
419         }
420 
421         public void release()
422         {
423             // nothing to do
424         }
425 
426         public void run()
427         {
428             try
429             {
430                 try
431                 {
432                     listener.onExchange(me);
433                     done(me);
434                 }
435                 catch (MessagingException e)
436                 {
437                     error(me, e);
438                 }
439             }
440             catch (Exception e)
441             {
442                 handleException(e);
443             }
444         }
445     }
446 
447     protected void handleException(Throwable t)
448     {
449         logger.error(t.getMessage(), t);
450     }
451 
452     protected void error(MessageExchange me, Fault fault) throws MessagingException
453     {
454         me.setFault(fault);
455         me.setStatus(ExchangeStatus.ERROR);
456         context.getDeliveryChannel().send(me);
457     }
458 
459     protected void done(MessageExchange me) throws MessagingException
460     {
461         me.setStatus(ExchangeStatus.DONE);
462         context.getDeliveryChannel().send(me);
463     }
464 
465     protected void error(MessageExchange me, Exception e) throws MessagingException
466     {
467         me.setError(e);
468         me.setStatus(ExchangeStatus.ERROR);
469         context.getDeliveryChannel().send(me);
470     }
471 
472     private class DefaultServiceUnitManager implements ServiceUnitManager
473     {
474         public String deploy(String string, String string1) throws DeploymentException
475         {
476             return null;
477         }
478 
479         public void init(String string, String string1) throws DeploymentException
480         {
481             // nothing to do (yet?)
482         }
483 
484         public void start(String string) throws DeploymentException
485         {
486             // nothing to do (yet?)
487         }
488 
489         public void stop(String string) throws DeploymentException
490         {
491             // nothing to do (yet?)
492         }
493 
494         public void shutDown(String string) throws DeploymentException
495         {
496             // nothing to do (yet?)
497         }
498 
499         public String undeploy(String string, String string1) throws DeploymentException
500         {
501             return null;
502         }
503     }
504 }