View Javadoc

1   /*
2    * $Id: AbstractObjectFactory.java 19853 2010-10-06 18:59:32Z dfeist $
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.object;
12  
13  import org.mule.api.MuleContext;
14  import org.mule.api.construct.FlowConstruct;
15  import org.mule.api.construct.FlowConstructAware;
16  import org.mule.api.lifecycle.InitialisationCallback;
17  import org.mule.api.lifecycle.InitialisationException;
18  import org.mule.api.object.ObjectFactory;
19  import org.mule.api.service.Service;
20  import org.mule.api.service.ServiceAware;
21  import org.mule.config.i18n.MessageFactory;
22  import org.mule.util.BeanUtils;
23  import org.mule.util.ClassUtils;
24  
25  import java.util.ArrayList;
26  import java.util.List;
27  import java.util.Map;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  
32  /**
33   * Creates object instances based on the class and sets any properties.  This factory is also responsible for applying
34   * any object processors on the object before the lifecycle callbacks are called.
35   */
36  public abstract class AbstractObjectFactory implements ObjectFactory, FlowConstructAware
37  {
38      public static final String ATTRIBUTE_OBJECT_CLASS_NAME = "objectClassName";
39      public static final String ATTRIBUTE_OBJECT_CLASS = "objectClass";
40  
41      protected String objectClassName;
42      protected Class<?> objectClass = null;
43      protected Map properties = null;
44      protected List<InitialisationCallback> initialisationCallbacks = new ArrayList<InitialisationCallback>();
45      protected FlowConstruct flowConstruct;
46      protected boolean disposed = false;
47  
48      protected transient Log logger = LogFactory.getLog(getClass());
49  
50      /** For Spring only */
51      public AbstractObjectFactory()
52      {
53          // nop
54      }
55  
56      public AbstractObjectFactory(String objectClassName)
57      {
58          this(objectClassName, null);
59      }
60  
61      public AbstractObjectFactory(String objectClassName, Map properties)
62      {
63          super();
64          this.objectClassName = objectClassName;
65          this.properties = properties;
66          setupObjectClassFromObjectClassName();
67      }
68  
69      public AbstractObjectFactory(Class<?> objectClass)
70      {
71          this(objectClass, null);
72      }
73  
74      public AbstractObjectFactory(Class<?> objectClass, Map properties)
75      {
76          super();
77          this.objectClassName = objectClass.getName();
78          this.objectClass = objectClass;
79          this.properties = properties;
80      }
81  
82      protected Class<?> setupObjectClassFromObjectClassName()
83      {
84          try
85          {
86              Class<?> klass = ClassUtils.getClass(objectClassName);
87              objectClass = klass;
88              return klass;
89          }
90          catch (ClassNotFoundException e)
91          {
92              throw new IllegalArgumentException(e);
93          }
94      }
95  
96      public void setFlowConstruct(FlowConstruct flowConstruct)
97      {
98          this.flowConstruct = flowConstruct;
99      }
100 
101     public void initialise() throws InitialisationException
102     {
103         if ((objectClassName == null) || (objectClass == null))
104         {
105             throw new InitialisationException(
106                 MessageFactory.createStaticMessage("Object factory has not been initialized."), this);
107         }
108         disposed=false;
109     }
110     
111     public void dispose()
112     {
113         disposed=true;
114         //Don't reset the component config state i.e. objectClass since service objects can be recycled
115     }
116 
117     /**
118      * Creates an initialized object instance based on the class and sets any properties.
119      * This method handles all injection of properties for the resulting object
120      * @param muleContext the current {@link org.mule.api.MuleContext} instance. This can be used for performing registry lookups
121      * applying processors to newly created objects or even firing custom notifications
122      * @throws Exception Can throw any type of exception while creating a new object
123      */
124     public Object getInstance(MuleContext muleContext) throws Exception
125     {
126         if (objectClass == null || disposed)
127         {
128             throw new InitialisationException(
129                 MessageFactory.createStaticMessage("Object factory has not been initialized."), this);
130         }
131         
132         Class<?> klass = objectClass;
133         if (klass == null)
134         {
135             klass = setupObjectClassFromObjectClassName();
136         }
137 
138         Object object = ClassUtils.instanciateClass(klass);
139 
140         if (properties != null)
141         {
142             BeanUtils.populateWithoutFail(object, properties, true);
143         }
144 
145         if(object instanceof FlowConstructAware)
146         {
147             ((FlowConstructAware)object).setFlowConstruct(flowConstruct);
148         }
149         
150         if(object instanceof ServiceAware && flowConstruct instanceof Service)
151         {
152             ((ServiceAware)object).setService((Service) flowConstruct);
153         }
154 
155         if(isAutoWireObject())
156         {
157             muleContext.getRegistry().applyProcessors(object);
158         }
159         fireInitialisationCallbacks(object);
160         
161         return object;
162     }
163 
164     protected void fireInitialisationCallbacks(Object component) throws InitialisationException
165     {
166         for (InitialisationCallback callback : initialisationCallbacks)
167         {
168             callback.initialise(component);
169         }
170     }
171 
172     public Class<?> getObjectClass()
173     {
174         if (objectClass != null)
175         {
176             Class<?> klass = objectClass;
177             if (klass == null)
178             {
179                 klass = setupObjectClassFromObjectClassName();
180             }
181             return klass;
182         }
183 
184         // objectClass may be null if this factory was not yet initialized or was disposed
185         return null;
186     }
187 
188     public void setObjectClass(Class<?> objectClass)
189     {
190         this.objectClass = objectClass;
191         this.objectClassName = objectClass.getName();
192     }
193 
194     protected String getObjectClassName()
195     {
196         return objectClassName;
197     }
198 
199     public void setObjectClassName(String objectClassName)
200     {
201         this.objectClassName = objectClassName;
202         setupObjectClassFromObjectClassName();
203     }
204 
205     protected Map getProperties()
206     {
207         return properties;
208     }
209 
210     public void setProperties(Map properties)
211     {
212         this.properties = properties;
213     }
214     
215     public void addObjectInitialisationCallback(InitialisationCallback callback)
216     {
217         initialisationCallbacks.add(callback);
218     }
219     
220     public boolean isSingleton()
221     {
222         return false;
223     }
224 
225     public boolean isExternallyManagedLifecycle()
226     {
227         return false;
228     }
229 
230     public boolean isAutoWireObject()
231     {
232         return true;
233     }
234 }