View Javadoc

1   /*
2    * $Id: DefaultLifecyclePhase.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.lifecycle.phases;
12  
13  import java.lang.reflect.Method;
14  import java.util.ArrayList;
15  import java.util.Collection;
16  import java.util.HashSet;
17  import java.util.LinkedHashSet;
18  import java.util.List;
19  import java.util.Set;
20  
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  import org.mule.api.MuleContext;
24  import org.mule.api.context.MuleContextAware;
25  import org.mule.api.lifecycle.LifecycleException;
26  import org.mule.api.lifecycle.LifecyclePhase;
27  import org.mule.api.lifecycle.LifecycleStateEnabled;
28  import org.mule.config.ExceptionHelper;
29  import org.mule.config.i18n.CoreMessages;
30  import org.mule.lifecycle.LifecycleObject;
31  
32  /**
33   * Represents a configurable lifecycle phase. This is a default implementation of a
34   * 'generic phase' in that is can be configured to represnt any phase. Instances of
35   * this phase can then be registered with a
36   * {@link org.mule.api.lifecycle.LifecycleManager} and by used to enforce a lifecycle
37   * phase on an object. Usually, Lifecycle phases have a fixed configuration in which
38   * case a specialisation of this class should be created that initialises its
39   * configuration internally.
40   * <p>
41   * Note that this class and {@link org.mule.api.lifecycle.LifecycleTransitionResult}
42   * both make assumptions about the interfaces used - the return values and
43   * exceptions. These are, currently, that the return value is either void or
44   * {@link org.mule.api.lifecycle.LifecycleTransitionResult} and either 0 or 1
45   * exceptions can be thrown which are either {@link InstantiationException} or
46   * {@link org.mule.api.lifecycle.LifecycleException}.
47   * 
48   * @see org.mule.api.lifecycle.LifecyclePhase
49   */
50  public class DefaultLifecyclePhase implements LifecyclePhase, MuleContextAware
51  {
52      protected transient final Log logger = LogFactory.getLog(DefaultLifecyclePhase.class);
53      private Class<?> lifecycleClass;
54      private final Method lifecycleMethod;
55      private Set<LifecycleObject> orderedLifecycleObjects = new LinkedHashSet<LifecycleObject>(6);
56      private Class<?>[] ignorredObjectTypes;
57      private final String name;
58      private final String oppositeLifecyclePhase;
59      private Set<String> supportedPhases;
60      private MuleContext muleContext;
61  
62      public DefaultLifecyclePhase(String name, Class<?> lifecycleClass, String oppositeLifecyclePhase)
63      {
64          this.name = name;
65          this.lifecycleClass = lifecycleClass;
66          // DefaultLifecyclePhase interface only has one method
67          lifecycleMethod = lifecycleClass.getMethods()[0];
68          this.oppositeLifecyclePhase = oppositeLifecyclePhase;
69      }
70  
71      public void setMuleContext(MuleContext context)
72      {
73          this.muleContext = context;
74      }
75  
76      /**
77       * Subclasses can override this method to order <code>objects</code> before the
78       * lifecycle method is applied to them. This method does not apply any special
79       * ordering to <code>objects</code>.
80       * 
81       * @param objects
82       * @param lo
83       * @return List with ordered objects
84       */
85      protected List sortLifecycleInstances(Collection objects, LifecycleObject lo)
86      {
87          return new ArrayList(objects);
88      }
89  
90      public void addOrderedLifecycleObject(LifecycleObject lco)
91      {
92          orderedLifecycleObjects.add(lco);
93      }
94  
95      public void removeOrderedLifecycleObject(LifecycleObject lco)
96      {
97          orderedLifecycleObjects.remove(lco);
98      }
99  
100     protected boolean ignoreType(Class<?> type)
101     {
102         if (ignorredObjectTypes == null)
103         {
104             return false;
105         }
106         else
107         {
108             for (int i = 0; i < ignorredObjectTypes.length; i++)
109             {
110                 Class<?> ignorredObjectType = ignorredObjectTypes[i];
111                 if (ignorredObjectType.isAssignableFrom(type))
112                 {
113                     return true;
114                 }
115             }
116         }
117         return false;
118     }
119 
120     public Set<LifecycleObject> getOrderedLifecycleObjects()
121     {
122         return orderedLifecycleObjects;
123     }
124 
125     public void setOrderedLifecycleObjects(Set<LifecycleObject> orderedLifecycleObjects)
126     {
127         this.orderedLifecycleObjects = orderedLifecycleObjects;
128     }
129 
130     public Class<?>[] getIgnoredObjectTypes()
131     {
132         return ignorredObjectTypes;
133     }
134 
135     public void setIgnoredObjectTypes(Class<?>[] ignorredObjectTypes)
136     {
137         this.ignorredObjectTypes = ignorredObjectTypes;
138     }
139 
140     public Class<?> getLifecycleClass()
141     {
142         return lifecycleClass;
143     }
144 
145     public void setLifecycleClass(Class<?> lifecycleClass)
146     {
147         this.lifecycleClass = lifecycleClass;
148     }
149 
150     public String getName()
151     {
152         return name;
153     }
154 
155     public Set<String> getSupportedPhases()
156     {
157         return supportedPhases;
158     }
159 
160     public void setSupportedPhases(Set<String> supportedPhases)
161     {
162         this.supportedPhases = supportedPhases;
163     }
164 
165     public void registerSupportedPhase(String phase)
166     {
167         if (supportedPhases == null)
168         {
169             supportedPhases = new HashSet<String>();
170         }
171         supportedPhases.add(phase);
172     }
173 
174     public boolean isPhaseSupported(String phase)
175     {
176         if (getSupportedPhases() == null)
177         {
178             return false;
179         }
180         else
181         {
182             if (getSupportedPhases().contains(ALL_PHASES))
183             {
184                 return true;
185             }
186             else
187             {
188                 return getSupportedPhases().contains(phase);
189             }
190         }
191     }
192 
193     public void applyLifecycle(Object o) throws LifecycleException
194     {
195         if (o == null)
196         {
197             return;
198         }
199         if (ignoreType(o.getClass()))
200         {
201             return;
202         }
203         if (!getLifecycleClass().isAssignableFrom(o.getClass()))
204         {
205             return;
206         }
207         if (o instanceof LifecycleStateEnabled)
208         {
209             // If an object has its own lifecycle manager "LifecycleStateEnabled" it
210             // is possible that
211             // its state can be controlled outside the registry i.e. via JMX, double
212             // check here that we are
213             // not calling the same lifecycle twice
214             if (((LifecycleStateEnabled) o).getLifecycleState().isPhaseComplete(this.getName()))
215             {
216                 return;
217             }
218             else if (!((LifecycleStateEnabled) o).getLifecycleState().isValidTransition(this.getName()))
219             {
220                 return;
221             }
222         }
223         try
224         {
225             lifecycleMethod.invoke(o);
226         }
227         catch (final Exception e)
228         {
229             Throwable t = ExceptionHelper.unwrap(e);
230 
231             if (t instanceof LifecycleException)
232             {
233                 throw (LifecycleException) t;
234             }
235 
236             throw new LifecycleException(CoreMessages.failedToInvokeLifecycle(lifecycleMethod.getName(), o),
237                 t, this);
238         }
239     }
240 
241     public String getOppositeLifecyclePhase()
242     {
243         return oppositeLifecyclePhase;
244     }
245 }