View Javadoc

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