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