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