View Javadoc

1   /*
2    * $Id: MuleContextDisposePhase.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  package org.mule.lifecycle.phases;
11  
12  import org.mule.api.agent.Agent;
13  import org.mule.api.component.Component;
14  import org.mule.api.construct.FlowConstruct;
15  import org.mule.api.lifecycle.Disposable;
16  import org.mule.api.lifecycle.Initialisable;
17  import org.mule.api.lifecycle.LifecycleException;
18  import org.mule.api.lifecycle.LifecyclePhase;
19  import org.mule.api.lifecycle.Stoppable;
20  import org.mule.api.model.Model;
21  import org.mule.api.routing.OutboundRouter;
22  import org.mule.api.routing.OutboundRouterCollection;
23  import org.mule.api.source.MessageSource;
24  import org.mule.api.transformer.Transformer;
25  import org.mule.api.transport.Connector;
26  import org.mule.config.i18n.CoreMessages;
27  import org.mule.context.notification.MuleContextNotification;
28  import org.mule.lifecycle.LifecycleObject;
29  import org.mule.lifecycle.NotificationLifecycleObject;
30  import org.mule.util.annotation.AnnotationMetaData;
31  import org.mule.util.annotation.AnnotationUtils;
32  
33  import java.lang.reflect.Method;
34  import java.util.LinkedHashSet;
35  import java.util.List;
36  import java.util.Set;
37  
38  import javax.annotation.PreDestroy;
39  
40  /**
41   * Objects are disposed of via the Registry since the Registry manages the creation/initialisation of the objects
42   * it must also take care of disposing them. However, a user may want to initiate a dispose via the
43   * {@link org.mule.DefaultMuleContext} so the dispose Lifecycle phase for the {@link org.mule.DefaultMuleContext}
44   * needs to call dispose on the Registry.
45   *
46   * The MuleContextDisposePhase defines the lifecycle behaviour when the Mule context is disposed.  The MuleContext is associated
47   * with one or more registries that inherit the lifecycle of the MuleContext.
48   *
49   * This phase is responsible for disposing objects. Any object that implements {@link org.mule.api.lifecycle.Disposable} will
50   * have its {@link org.mule.api.lifecycle.Disposable#dispose()} method called.  Objects are initialised in the order based on type:
51   * {@link org.mule.api.service.Service}, {@link org.mule.api.model.Model}, {@link org.mule.api.agent.Agent}, {@link org.mule.api.transport.Connector}, followed
52   * by any other object that implements {@link org.mule.api.lifecycle.Disposable}.
53   *
54   * @see org.mule.api.MuleContext
55   * @see org.mule.api.lifecycle.LifecycleManager
56   * @see org.mule.api.lifecycle.Disposable
57   *
58   * @since 3.0
59   */
60  public class MuleContextDisposePhase extends DefaultLifecyclePhase
61  {
62      public MuleContextDisposePhase()
63      {
64          super(Disposable.PHASE_NAME, Disposable.class, Initialisable.PHASE_NAME);
65  
66          Set<LifecycleObject> orderedObjects = new LinkedHashSet<LifecycleObject>();
67          // Stop in the opposite order to start
68          orderedObjects.add(new NotificationLifecycleObject(FlowConstruct.class));
69          orderedObjects.add(new NotificationLifecycleObject(Model.class, MuleContextNotification.class));
70          orderedObjects.add(new NotificationLifecycleObject(Agent.class));
71          orderedObjects.add(new NotificationLifecycleObject(Connector.class));
72          orderedObjects.add(new NotificationLifecycleObject(Stoppable.class));
73          orderedObjects.add(new NotificationLifecycleObject(Object.class));
74  
75          //Can call dispose from all lifecycle Phases
76          registerSupportedPhase(LifecyclePhase.ALL_PHASES);
77          setOrderedLifecycleObjects(orderedObjects);
78          /*
79          Ignored objects -
80          -Component is ignored because the FlowConstruct will manage the components lifecycle
81          -MessageSource disposal is managed by the connector it is associated with
82          -RouterCollection is ignored because the FlowConstruct will manage the lifecycle
83          -Router is ignored since its lifecycle is managed by the associated router collection
84          -Transformer is ignored since the Dispose lifecycle is managed by the base {@link AbstractTransformer} by receiving
85          a CONTEXT_DISPOSING event and calling dispose on the transformer.  This is necessary since transformers are prototype objects
86          and not managed by DI containers such as Spring after the creation of the object
87           */
88          setIgnoredObjectTypes(new Class[]{Component.class, MessageSource.class, OutboundRouterCollection.class, OutboundRouter.class, Transformer.class});
89      }
90  
91       @Override
92      public void applyLifecycle(Object o) throws LifecycleException
93      {
94          if (o == null)
95          {
96              return;
97          }
98          if (ignoreType(o.getClass()))
99          {
100             return;
101         }
102         //retain default Lifecycle behaviour
103         super.applyLifecycle(o);
104 
105         List<AnnotationMetaData> annos = AnnotationUtils.getMethodAnnotations(o.getClass(), PreDestroy.class);
106         if (annos.size() == 0)
107         {
108             return;
109         }
110         //Note that the registry has a processor that validates that there is at most one {@link PostConstruct} annotation
111         //per object and that the method conforms to a lifecycle method
112         AnnotationMetaData anno = annos.get(0);
113         try
114         {
115             ((Method) anno.getMember()).invoke(o);
116         }
117         catch (Exception e)
118         {
119             throw new LifecycleException(CoreMessages.failedToInvokeLifecycle(
120                     (anno == null ? "null" : anno.getMember().getName()), o), e, this);
121         }
122     }
123 }