View Javadoc

1   /*
2    * $Id: AbstractJavaComponent.java 20486 2010-12-07 11:12:25Z dirk.olmes $
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.api.MuleEvent;
14  import org.mule.api.MuleException;
15  import org.mule.api.component.InterfaceBinding;
16  import org.mule.api.component.JavaComponent;
17  import org.mule.api.component.LifecycleAdapter;
18  import org.mule.api.component.LifecycleAdapterFactory;
19  import org.mule.api.construct.FlowConstruct;
20  import org.mule.api.construct.FlowConstructAware;
21  import org.mule.api.lifecycle.InitialisationException;
22  import org.mule.api.model.EntryPointResolver;
23  import org.mule.api.model.EntryPointResolverSet;
24  import org.mule.api.object.ObjectFactory;
25  import org.mule.api.service.Service;
26  import org.mule.config.i18n.CoreMessages;
27  import org.mule.model.resolvers.DefaultEntryPointResolverSet;
28  import org.mule.model.resolvers.LegacyEntryPointResolverSet;
29  
30  import java.util.ArrayList;
31  import java.util.Collection;
32  import java.util.List;
33  
34  /**
35   * Abstract implementation of JavaComponent adds JavaComponent specific's:
36   * {@link EntryPointResolverSet}, {@link org.mule.api.routing.BindingCollection} and
37   * {@link ObjectFactory}. Provides default implementations of doOnCall and doOnEvent
38   * and defines abstract template methods provided for obtaining and returning the
39   * component object instance.
40   */
41  public abstract class AbstractJavaComponent extends AbstractComponent implements JavaComponent
42  {
43      protected EntryPointResolverSet entryPointResolverSet;
44  
45      protected List<InterfaceBinding> bindings = new ArrayList<InterfaceBinding>();
46  
47      protected ObjectFactory objectFactory;
48  
49      protected LifecycleAdapterFactory lifecycleAdapterFactory;
50  
51      /**
52       * For Spring only
53       */
54      public AbstractJavaComponent()
55      {
56          super();
57      }
58  
59      public AbstractJavaComponent(ObjectFactory objectFactory)
60      {
61          this(objectFactory, null, null);
62      }
63  
64      public AbstractJavaComponent(ObjectFactory objectFactory,
65                                   EntryPointResolverSet entryPointResolverSet,
66                                   List<InterfaceBinding> bindings)
67      {
68          super();
69          this.objectFactory = objectFactory;
70          this.entryPointResolverSet = entryPointResolverSet;
71          if (bindings != null)
72          {
73              this.bindings = bindings;
74          }
75      }
76  
77      @Override
78      protected Object doInvoke(MuleEvent event) throws Exception
79      {
80          return invokeComponentInstance(event);
81      }
82  
83      protected Object invokeComponentInstance(MuleEvent event) throws Exception
84      {
85          LifecycleAdapter componentLifecycleAdapter = null;
86          try
87          {
88              componentLifecycleAdapter = borrowComponentLifecycleAdaptor();
89              return componentLifecycleAdapter.invoke(event);
90          }
91          finally
92          {
93              if (componentLifecycleAdapter != null)
94              {
95                  returnComponentLifecycleAdaptor(componentLifecycleAdapter);
96              }
97          }
98      }
99  
100     public Class<?> getObjectType()
101     {
102         return objectFactory.getObjectClass();
103     }
104 
105     /**
106      * Creates and initialises a new LifecycleAdaptor instance wrapped the component
107      * object instance obtained from the configured object factory.
108      * 
109      * @throws MuleException
110      * @throws Exception
111      */
112     protected LifecycleAdapter createLifecycleAdaptor() throws Exception
113     {
114         //Todo this could be moved to the LCAFactory potentially
115         Object object = objectFactory.getInstance(muleContext);
116 
117         LifecycleAdapter lifecycleAdapter;
118         if (lifecycleAdapterFactory != null)
119         {
120             // Custom lifecycleAdapterFactory set on component
121             lifecycleAdapter = 
122                 lifecycleAdapterFactory.create(object, this, flowConstruct, entryPointResolverSet, muleContext);
123         }
124         else if (objectFactory.isExternallyManagedLifecycle())
125         {
126             // If no lifecycleAdapterFactory is configured explicitly and object factory returns 
127             // externally managed instance then use NullLifecycleAdapter so that lifecycle 
128             // is not propagated
129             lifecycleAdapter = 
130                 new NullLifecycleAdapter(object, this, flowConstruct, entryPointResolverSet, muleContext);
131         }
132         else if (flowConstruct instanceof Service)
133         {
134             // Inherit lifecycleAdapterFactory from model
135             lifecycleAdapter = ((Service) flowConstruct).getModel().getLifecycleAdapterFactory().create(
136                 object, this, flowConstruct, entryPointResolverSet, muleContext);
137         }
138         else
139         {
140             lifecycleAdapter = new DefaultComponentLifecycleAdapterFactory().create(object, this,
141                 flowConstruct, entryPointResolverSet, muleContext);
142         }
143         lifecycleAdapter.initialise();
144         return lifecycleAdapter;
145     }
146 
147     protected abstract LifecycleAdapter borrowComponentLifecycleAdaptor() throws Exception;
148 
149     protected abstract void returnComponentLifecycleAdaptor(LifecycleAdapter lifecycleAdapter) throws Exception;
150 
151     @Override
152     protected void doInitialise() throws InitialisationException
153     {
154         if (objectFactory == null)
155         {
156             throw new InitialisationException(CoreMessages.objectIsNull("object factory"), this);
157         }
158         objectFactory.initialise();
159     }
160 
161     @Override
162     protected void doStart() throws MuleException
163     {
164         // We need to resolve entry point resolvers here rather than in initialise()
165         // because when configuring with spring, although the service has been
166         // injected and is available the injected service construction has not been
167         // completed and model is still in null.
168         if (entryPointResolverSet == null)
169         {
170             if (flowConstruct instanceof Service)
171             {
172                 entryPointResolverSet = ((Service) flowConstruct).getModel().getEntryPointResolverSet();
173             }
174             else
175             {
176                 entryPointResolverSet = new LegacyEntryPointResolverSet();
177             }
178         }
179     }
180 
181     @Override
182     protected void doDispose()
183     {
184         if (objectFactory!=null)
185         {
186             objectFactory.dispose();
187         }
188     }
189 
190     public EntryPointResolverSet getEntryPointResolverSet()
191     {
192         return entryPointResolverSet;
193     }
194 
195     public List<InterfaceBinding> getInterfaceBindings()
196     {
197         return bindings;
198     }
199 
200     public void setEntryPointResolverSet(EntryPointResolverSet entryPointResolverSet)
201     {
202         this.entryPointResolverSet = entryPointResolverSet;
203     }
204 
205     public void setInterfaceBindings(List<InterfaceBinding> bindings)
206     {
207         this.bindings = bindings;
208     }
209 
210     /**
211      * Allow for incremental addition of resolvers by for example the spring-config
212      * module
213      * 
214      * @param entryPointResolvers Resolvers to add
215      */
216     public void setEntryPointResolvers(Collection<EntryPointResolver> entryPointResolvers)
217     {
218         if (null == entryPointResolverSet)
219         {
220             entryPointResolverSet = new DefaultEntryPointResolverSet();
221         }
222         
223         for (EntryPointResolver resolver : entryPointResolvers)
224         {
225             entryPointResolverSet.addEntryPointResolver(resolver);
226         }
227     }
228 
229     public ObjectFactory getObjectFactory()
230     {
231         return objectFactory;
232     }
233 
234     public void setObjectFactory(ObjectFactory objectFactory)
235     {
236         this.objectFactory = objectFactory;
237         injectService();
238     }
239 
240     public LifecycleAdapterFactory getLifecycleAdapterFactory()
241     {
242         return lifecycleAdapterFactory;
243     }
244 
245     public void setLifecycleAdapterFactory(LifecycleAdapterFactory lifecycleAdapterFactory)
246     {
247         this.lifecycleAdapterFactory = lifecycleAdapterFactory;
248     }
249 
250     @Override
251     public void setFlowConstruct(FlowConstruct flowConstruct)
252     {
253         super.setFlowConstruct(flowConstruct);
254         injectService();
255     }
256 
257     protected void injectService()
258     {
259         if (objectFactory != null && objectFactory instanceof FlowConstructAware && flowConstruct != null)
260         {
261             // The registry cannot inject the Service for this object since there is
262             // no way to tie the two together, so
263             // we set the service on the object factory, that way the factory is
264             // responsible for injecting all properties
265             // on the result object
266             ((FlowConstructAware) objectFactory).setFlowConstruct(flowConstruct);
267         }
268     }
269 }