View Javadoc

1   /*
2    * $Id: SimpleCallableJavaComponent.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.component;
12  
13  import org.mule.DefaultMuleEventContext;
14  import org.mule.VoidResult;
15  import org.mule.api.DefaultMuleException;
16  import org.mule.api.MuleEvent;
17  import org.mule.api.MuleException;
18  import org.mule.api.MuleMessage;
19  import org.mule.api.MuleRuntimeException;
20  import org.mule.api.component.JavaComponent;
21  import org.mule.api.component.LifecycleAdapter;
22  import org.mule.api.lifecycle.Callable;
23  import org.mule.api.lifecycle.Disposable;
24  import org.mule.api.lifecycle.Startable;
25  import org.mule.api.lifecycle.Stoppable;
26  import org.mule.api.model.ModelException;
27  import org.mule.api.object.ObjectFactory;
28  import org.mule.config.i18n.CoreMessages;
29  import org.mule.object.SingletonObjectFactory;
30  import org.mule.transformer.TransformerTemplate;
31  
32  import edu.emory.mathcs.backport.java.util.Collections;
33  
34  /**
35   * Simple {@link JavaComponent} implementation to be used when
36   * {@link LifecycleAdapter} is not required because i) the object instance implements
37   * {@link Callable} and so entry-point resolution is required and ii) nested-routers
38   * are not used.<br/> An {@link ObjectFactory} can be set but must return object
39   * instances that implement {@link Callable}. If one of the constructors that takes
40   * just a Class or the instance itself is used then the
41   * {@link SingletonObjectFactory} is used by default. <br/> This implementation
42   * replaces and improves on <code>OptimizedComponent</code>/<code>OptimizedMuleProxy</code>
43   */
44  public class SimpleCallableJavaComponent extends AbstractJavaComponent
45  {
46  
47      private boolean started = false;
48  
49      public SimpleCallableJavaComponent()
50      {
51          // for spring
52      }
53  
54      /**
55       * Create an SimpleCallableJavaComponent instance using an object instance that
56       * implements {@link Callable}
57       * 
58       * @param callable
59       */
60      public SimpleCallableJavaComponent(Callable callable)
61      {
62          objectFactory = new SingletonObjectFactory(callable);
63      }
64  
65      /**
66       * Create an SimpleCallableJavaComponent instance using an object class. This
67       * class should implement {@link Callable}.
68       * 
69       * @param callable
70       * @throws DefaultMuleException if the Class specified does not implement
71       *             {@link Callable}
72       */
73      public SimpleCallableJavaComponent(Class callable) throws DefaultMuleException
74      {
75          if (!(Callable.class.isAssignableFrom(callable)))
76          {
77              throw new DefaultMuleException(CoreMessages.objectNotOfCorrectType(callable, Callable.class));
78          }
79          objectFactory = new SingletonObjectFactory(callable);
80      }
81  
82      public SimpleCallableJavaComponent(ObjectFactory objectFactory) throws DefaultMuleException
83      {
84          if (!(Callable.class.isAssignableFrom(objectFactory.getObjectClass())))
85          {
86              throw new DefaultMuleException(CoreMessages.objectNotOfCorrectType(objectFactory.getObjectClass(),
87                  Callable.class));
88          }
89          this.objectFactory = objectFactory;
90      }
91  
92      protected void doStart() throws MuleException
93      {
94          super.doStart();
95          if (Startable.class.isAssignableFrom(objectFactory.getObjectClass()))
96          {
97              try
98              {
99                  ((Startable) objectFactory.getInstance()).start();
100             }
101             catch (Exception e)
102             {
103                 throw new ModelException(CoreMessages.failedToStart("Service '" + service.getName() + "'"), e);
104             }
105         }
106     }
107 
108     protected void doStop() throws MuleException
109     {
110         super.doStop();
111         if (started && Stoppable.class.isAssignableFrom(objectFactory.getObjectClass()))
112         {
113             try
114             {
115                 ((Stoppable) objectFactory.getInstance()).stop();
116             }
117             catch (Exception e)
118             {
119                 throw new ModelException(CoreMessages.failedToStop("Service '" + service.getName() + "'"), e);
120             }
121         }
122     }
123 
124     protected void doDispose()
125     {
126         super.doDispose();
127         if (Disposable.class.isAssignableFrom(objectFactory.getObjectClass()))
128         {
129             try
130             {
131                 ((Disposable) objectFactory.getInstance()).dispose();
132             }
133             catch (Exception e)
134             {
135                 logger.error("Unable to dispose component instance", e);
136             }
137         }
138     }
139 
140     public Class getObjectType()
141     {
142         if (objectFactory != null)
143         {
144             return objectFactory.getObjectClass();
145         }
146         else
147         {
148             return Callable.class;
149         }
150     }
151 
152     protected LifecycleAdapter borrowComponentLifecycleAdaptor() throws Exception
153     {
154         // no-op
155         return null;
156     }
157 
158     protected void returnComponentLifecycleAdaptor(LifecycleAdapter lifecycleAdapter)
159     {
160         // no-op
161     }
162 
163     protected MuleMessage invokeComponentInstance(MuleEvent event) throws Exception
164     {
165         Object result = ((Callable) objectFactory.getInstance()).onCall(new DefaultMuleEventContext(event));
166         if (result instanceof VoidResult)
167         {
168             // This will rewire the current message
169             event.transformMessage();
170             return event.getMessage();
171         }
172         else if (result != null)
173         {
174             if (result instanceof MuleMessage)
175             {
176                 return (MuleMessage) result;
177             }
178             else
179             {
180                 event.getMessage().applyTransformers(
181                     Collections.singletonList(new TransformerTemplate(new TransformerTemplate.OverwitePayloadCallback(
182                         result))));
183                 return event.getMessage();
184             }
185         }
186         else
187         {
188             return null;
189         }
190     }
191 
192     // @Override
193     public void setObjectFactory(ObjectFactory objectFactory)
194     {
195         if (!(Callable.class.isAssignableFrom(objectFactory.getObjectClass())))
196         {
197             throw new MuleRuntimeException(CoreMessages.objectNotOfCorrectType(objectFactory.getObjectClass(),
198                 Callable.class));
199         }
200         super.setObjectFactory(objectFactory);
201     }
202 }