View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.deploy;
20  
21  import java.util.ArrayList;
22  import java.util.HashMap;
23  import java.util.HashSet;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Set;
27  
28  import org.eclipse.jetty.deploy.graph.Graph;
29  import org.eclipse.jetty.deploy.graph.Node;
30  import org.eclipse.jetty.util.log.Log;
31  import org.eclipse.jetty.util.log.Logger;
32  
33  /**
34   * The lifecycle of an App in the {@link DeploymentManager}.
35   * <p>
36   * Setups a the default {@link Graph}, and manages the bindings to the life cycle via the {@link AppLifeCycle.Binding}
37   * annotation.
38   * <p>
39   * <img alt="app lifecycle graph" src="doc-files/AppLifeCycle.png">
40   */
41  public class AppLifeCycle extends Graph
42  {
43      private static final Logger LOG = Log.getLogger(AppLifeCycle.class);
44  
45      private static final String ALL_NODES = "*";
46  
47      public static interface Binding
48      {
49          /**
50           * Get a list of targets that this implementation should bind to.
51           * 
52           * @return the array of String node names to bind to. (use <code>"*"</code> to bind to all known node names)
53           */
54          String[] getBindingTargets();
55  
56          /**
57           * Event called to process a {@link AppLifeCycle} binding.
58           * 
59           * @param node
60           *            the node being processed
61           * @param app
62           *            the app being processed
63           * @throws Exception
64           *             if any problem severe enough to halt the AppLifeCycle processing
65           */
66          void processBinding(Node node, App app) throws Exception;
67      }
68  
69      // Well known existing lifecycle Nodes
70      public static final String UNDEPLOYED = "undeployed";
71      public static final String DEPLOYING = "deploying";
72      public static final String DEPLOYED = "deployed";
73      public static final String STARTING = "starting";
74      public static final String STARTED = "started";
75      public static final String STOPPING = "stopping";
76      public static final String UNDEPLOYING = "undeploying";
77      
78      
79      private Map<String, List<Binding>> lifecyclebindings = new HashMap<String, List<Binding>>();
80  
81      public AppLifeCycle()
82      {
83          // Define Default Graph
84  
85          // undeployed -> deployed
86          addEdge(UNDEPLOYED,DEPLOYING);
87          addEdge(DEPLOYING,DEPLOYED);
88  
89          // deployed -> started
90          addEdge(DEPLOYED,STARTING);
91          addEdge(STARTING,STARTED);
92  
93          // started -> deployed
94          addEdge(STARTED,STOPPING);
95          addEdge(STOPPING,DEPLOYED);
96  
97          // deployed -> undeployed
98          addEdge(DEPLOYED,UNDEPLOYING);
99          addEdge(UNDEPLOYING,UNDEPLOYED);
100     }
101 
102     public void addBinding(AppLifeCycle.Binding binding)
103     {
104         for (String nodeName : binding.getBindingTargets())
105         {
106             List<Binding> bindings = lifecyclebindings.get(nodeName);
107             if (bindings == null)
108             {
109                 bindings = new ArrayList<Binding>();
110             }
111             bindings.add(binding);
112 
113             lifecyclebindings.put(nodeName,bindings);
114         }
115     }
116     
117     public void removeBinding(AppLifeCycle.Binding binding)
118     {
119         for (String nodeName : binding.getBindingTargets())
120         {
121             List<Binding> bindings = lifecyclebindings.get(nodeName);
122             if (bindings != null)
123                 bindings.remove(binding);
124         }
125     }
126 
127     /**
128      * Get all {@link Node} bound objects.
129      * 
130      * @return Set of Object(s) for all lifecycle bindings. never null.
131      */
132     public Set<AppLifeCycle.Binding> getBindings()
133     {
134         Set<Binding> boundset = new HashSet<Binding>();
135 
136         for (List<Binding> bindings : lifecyclebindings.values())
137         {
138             boundset.addAll(bindings);
139         }
140 
141         return boundset;
142     }
143 
144     /**
145      * Get all objects bound to a specific {@link Node}
146      * 
147      * @param node the deployment graph node 
148      * @return Set of Object(s) for specific lifecycle bindings. never null.
149      */
150     public Set<AppLifeCycle.Binding> getBindings(Node node)
151     {
152         return getBindings(node.getName());
153     }
154 
155     /**
156      * Get all objects bound to a specific {@link Node}
157      * 
158      * @param nodeName the node name 
159      * @return Set of Object(s) for specific lifecycle bindings. never null.
160      */
161     public Set<AppLifeCycle.Binding> getBindings(String nodeName)
162     {
163         Set<Binding> boundset = new HashSet<Binding>();
164 
165         // Specific node binding
166         List<Binding> bindings = lifecyclebindings.get(nodeName);
167         if (bindings != null)
168         {
169             boundset.addAll(bindings);
170         }
171 
172         // Special 'all nodes' binding
173         bindings = lifecyclebindings.get(ALL_NODES);
174         if (bindings != null)
175         {
176             boundset.addAll(bindings);
177         }
178 
179         return boundset;
180     }
181 
182     public void runBindings(Node node, App app, DeploymentManager deploymentManager) throws Throwable
183     {
184         for (Binding binding : getBindings(node))
185         {
186             if (LOG.isDebugEnabled())
187                 LOG.debug("Calling " + binding.getClass().getName()+" for "+app);
188             binding.processBinding(node,app);
189         }
190     }
191 }