View Javadoc

1   /*
2    * $Id: SimpleCallableJavaComponent.java 19191 2010-08-25 21:05:23Z tcarlson $
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.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.object.ObjectFactory;
27  import org.mule.api.registry.ServiceException;
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) component bindings
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      @Override
93      protected void doStart() throws MuleException
94      {
95          super.doStart();
96          if (Startable.class.isAssignableFrom(objectFactory.getObjectClass()))
97          {
98              try
99              {
100                 ((Startable) objectFactory.getInstance(muleContext)).start();
101             }
102             catch (Exception e)
103             {
104                 throw new ServiceException(CoreMessages.failedToStart("Service '" + flowConstruct.getName() + "'"), e);
105             }
106         }
107     }
108 
109     @Override
110     protected void doStop() throws MuleException
111     {
112         super.doStop();
113         if (started && Stoppable.class.isAssignableFrom(objectFactory.getObjectClass()))
114         {
115             try
116             {
117                 ((Stoppable) objectFactory.getInstance(muleContext)).stop();
118             }
119             catch (Exception e)
120             {
121                 throw new ServiceException(CoreMessages.failedToStop("Service '" + flowConstruct.getName() + "'"), e);
122             }
123         }
124     }
125 
126     @Override
127     protected void doDispose()
128     {
129         super.doDispose();
130         if (Disposable.class.isAssignableFrom(objectFactory.getObjectClass()))
131         {
132             try
133             {
134                 ((Disposable) objectFactory.getInstance(muleContext)).dispose();
135             }
136             catch (Exception e)
137             {
138                 logger.error("Unable to dispose component instance", e);
139             }
140         }
141     }
142 
143     @Override
144     public Class getObjectType()
145     {
146         if (objectFactory != null)
147         {
148             return objectFactory.getObjectClass();
149         }
150         else
151         {
152             return Callable.class;
153         }
154     }
155 
156     @Override
157     protected LifecycleAdapter borrowComponentLifecycleAdaptor() throws Exception
158     {
159         // no-op
160         return null;
161     }
162 
163     @Override
164     protected void returnComponentLifecycleAdaptor(LifecycleAdapter lifecycleAdapter)
165     {
166         // no-op
167     }
168 
169     @Override
170     protected Object invokeComponentInstance(MuleEvent event) throws Exception
171     {
172         Object result = ((Callable) objectFactory.getInstance(muleContext)).onCall(new DefaultMuleEventContext(event));
173         if (result instanceof VoidResult)
174         {
175             // This will rewire the current message
176             return event.getMessage();
177         }
178         else if (result != null)
179         {
180             if (result instanceof MuleMessage)
181             {
182                 return result;
183             }
184             else
185             {
186                 event.getMessage().applyTransformers(
187                     event, Collections.singletonList(new TransformerTemplate(new TransformerTemplate.OverwitePayloadCallback(
188                         result))));
189                 return event.getMessage();
190             }
191         }
192         else
193         {
194             return null;
195         }
196     }
197 
198     @Override
199     public void setObjectFactory(ObjectFactory objectFactory)
200     {
201         if (!(Callable.class.isAssignableFrom(objectFactory.getObjectClass())))
202         {
203             throw new MuleRuntimeException(CoreMessages.objectNotOfCorrectType(objectFactory.getObjectClass(),
204                 Callable.class));
205         }
206         super.setObjectFactory(objectFactory);
207     }
208 }