| // ======================================================================== |
| // Copyright (c) Webtide LLC |
| // ------------------------------------------------------------------------ |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // and Apache License v2.0 which accompanies this distribution. |
| // |
| // The Eclipse Public License is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // The Apache License v2.0 is available at |
| // http://www.apache.org/licenses/LICENSE-2.0.txt |
| // |
| // You may elect to redistribute this code under either of these licenses. |
| // ======================================================================== |
| package org.eclipse.jetty.deploy; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.jetty.deploy.graph.Graph; |
| import org.eclipse.jetty.deploy.graph.Node; |
| import org.eclipse.jetty.util.log.Log; |
| |
| /** |
| * The lifecycle of an App in the {@link DeploymentManager}. |
| * |
| * Setups a the default {@link Graph}, and manages the bindings to the life cycle via the {@link DeployLifeCycleBinding} |
| * annotation. |
| * <p> |
| * <img src="doc-files/AppLifeCycle.png"> |
| */ |
| public class AppLifeCycle extends Graph |
| { |
| public static interface Binding |
| { |
| /** |
| * Get a list of targets that this implementation should bind to. |
| * |
| * @return the array of String node names to bind to. (use <code>"*"</code> to bind to all known node names) |
| */ |
| String[] getBindingTargets(); |
| |
| /** |
| * Event called to process a {@link AppLifeCycle} binding. |
| * |
| * @param node |
| * the node being processed |
| * @param app |
| * the app being processed |
| * @param deploymentManager |
| * the {@link DeploymentManager} tracking the {@link AppLifeCycle} and {@link App} |
| * @throws Exception |
| * if any problem severe enough to halt the AppLifeCycle processing |
| */ |
| void processBinding(Node node, App app, DeploymentManager deploymentManager) throws Exception; |
| } |
| |
| // Private string constants defined to avoid typos on repeatedly used strings |
| private static final String NODE_UNDEPLOYED = "undeployed"; |
| private static final String NODE_PRE_DEPLOYING = "pre-deploying"; |
| private static final String NODE_DEPLOYING = "deploying"; |
| private static final String NODE_DEPLOYED = "deployed"; |
| private static final String NODE_PRE_STARTING = "pre-starting"; |
| private static final String NODE_STARTING = "starting"; |
| private static final String NODE_STARTED = "started"; |
| private static final String NODE_PRE_STOPPING = "pre-stopping"; |
| private static final String NODE_STOPPING = "stopping"; |
| private static final String NODE_PRE_UNDEPLOYING = "pre-undeploying"; |
| private static final String NODE_UNDEPLOYING = "undeploying"; |
| private Map<Node, List<Binding>> lifecyclebindings = new HashMap<Node, List<Binding>>(); |
| |
| public AppLifeCycle() |
| { |
| // Define Default Graph |
| |
| // undeployed -> deployed |
| addEdge(NODE_UNDEPLOYED,NODE_PRE_DEPLOYING); |
| addEdge(NODE_PRE_DEPLOYING,NODE_DEPLOYING); |
| addEdge(NODE_DEPLOYING,NODE_DEPLOYED); |
| |
| // deployed -> started |
| addEdge(NODE_DEPLOYED,NODE_PRE_STARTING); |
| addEdge(NODE_PRE_STARTING,NODE_STARTING); |
| addEdge(NODE_STARTING,NODE_STARTED); |
| |
| // started -> deployed |
| addEdge(NODE_STARTED,NODE_PRE_STOPPING); |
| addEdge(NODE_PRE_STOPPING,NODE_STOPPING); |
| addEdge(NODE_STOPPING,NODE_DEPLOYED); |
| |
| // deployed -> undeployed |
| addEdge(NODE_DEPLOYED,NODE_PRE_UNDEPLOYING); |
| addEdge(NODE_PRE_UNDEPLOYING,NODE_UNDEPLOYING); |
| addEdge(NODE_UNDEPLOYING,NODE_UNDEPLOYED); |
| } |
| |
| public void addBinding(AppLifeCycle.Binding binding) |
| { |
| for (String nodeName : binding.getBindingTargets()) |
| { |
| if (nodeName.equals("*")) |
| { |
| // Special Case: Bind to all Nodes |
| for (Node node : getNodes()) |
| { |
| bindToNode(node,binding); |
| } |
| } |
| else |
| { |
| // Bind to specific node |
| Node node = getNodeByName(nodeName); |
| bindToNode(node,binding); |
| } |
| } |
| } |
| |
| private void bindToNode(Node node, AppLifeCycle.Binding binding) |
| { |
| List<Binding> bindings = lifecyclebindings.get(node); |
| if (bindings == null) |
| { |
| bindings = new ArrayList<Binding>(); |
| } |
| bindings.add(binding); |
| |
| lifecyclebindings.put(node,bindings); |
| } |
| |
| /** |
| * Get all {@link Node} bound objects. |
| * |
| * @return Set of Object(s) for all lifecycle bindings. never null. |
| */ |
| public Set<AppLifeCycle.Binding> getBindings() |
| { |
| Set<Binding> boundset = new HashSet<Binding>(); |
| |
| for (List<Binding> bindings : lifecyclebindings.values()) |
| { |
| boundset.addAll(bindings); |
| } |
| |
| return boundset; |
| } |
| |
| /** |
| * Get all objects bound to a specific {@link Node} |
| * |
| * @return Set of Object(s) for specific lifecycle bindings. never null. |
| */ |
| public Set<AppLifeCycle.Binding> getBindings(Node node) |
| { |
| Set<Binding> boundset = new HashSet<Binding>(); |
| |
| List<Binding> bindings = lifecyclebindings.get(node); |
| if (bindings == null) |
| { |
| return boundset; |
| } |
| |
| boundset.addAll(bindings); |
| |
| return boundset; |
| } |
| |
| public Set<Binding> getBindings(String nodeName) |
| { |
| Node node = getNodeByName(nodeName); |
| return getBindings(node); |
| } |
| |
| public void runBindings(Node node, App app, DeploymentManager deploymentManager) throws Throwable |
| { |
| List<Binding> bindings = this.lifecyclebindings.get(node); |
| if (bindings == null) |
| { |
| return; |
| } |
| |
| for (Binding binding : bindings) |
| { |
| Log.info("Calling " + binding.getClass().getName()); |
| binding.processBinding(node,app,deploymentManager); |
| } |
| } |
| } |