Adding jetty-deploy-manager-graph
git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/sandbox/trunk@1076 7e9141cc-0065-0410-87d8-b60c137991c4
diff --git a/jetty-deploy-manager-graph/.gitignore b/jetty-deploy-manager-graph/.gitignore
new file mode 100644
index 0000000..796b602
--- /dev/null
+++ b/jetty-deploy-manager-graph/.gitignore
@@ -0,0 +1,9 @@
+target/
+.classpath
+.project
+.settings
+*/src/main/java/META-INF/
+*.log
+*.swp
+*.diff
+*.patch
diff --git a/jetty-deploy-manager-graph/pom.xml b/jetty-deploy-manager-graph/pom.xml
new file mode 100644
index 0000000..edefa9c
--- /dev/null
+++ b/jetty-deploy-manager-graph/pom.xml
@@ -0,0 +1,85 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-project</artifactId>
+ <version>7.0.1-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jetty-deploy-manager-graph</artifactId>
+ <name>Jetty :: Deployment Manager Graph Based</name>
+ <description>Jetty Deployment Manager</description>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${felix.bundle.version}</version>
+ <extensions>true</extensions>
+ <executions>
+ <execution>
+ <goals>
+ <goal>manifest</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <!--
+ Required for OSGI
+ -->
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+ </archive>
+ </configuration>
+ </plugin>
+ <!-- always include sources since jetty-xbean makes use of them -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-webapp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-xml</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.7</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.5</version>
+ <configuration>
+ <docfilessubdirs>true</docfilessubdirs>
+ <detectLinks>true</detectLinks>
+ <detectJavaApiLink>true</detectJavaApiLink>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+</project>
diff --git a/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/App.java b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/App.java
new file mode 100644
index 0000000..924c8de
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/App.java
@@ -0,0 +1,73 @@
+// ========================================================================
+// 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.io.File;
+import org.eclipse.jetty.server.handler.ContextHandler;
+
+/**
+ * The information about an App that is managed by the {@link DeploymentManager}
+ */
+public interface App
+{
+ /**
+ * The raw id of the {@link App}
+ *
+ * @return the generated Id for the App.
+ */
+ String getId();
+
+ /**
+ * Get the internally declared name of the App.
+ *
+ * @return the internal name of the App.
+ */
+ String getName();
+
+ /**
+ * Get ContextHandler for the App.
+ *
+ * Create it if needed.
+ *
+ * @return the {@link ContextHandler} to use for the App when fully started. (Portions of which might be ignored
+ * when App is in the {@link AppState#STAGED} state}
+ * @throws Exception
+ */
+ ContextHandler getContextHandler(DeploymentManager deployMgr) throws Exception;
+
+ /**
+ * Get the work dir for this App, as managed by the {@link DeploymentManager}
+ *
+ * @return the App's work dir.
+ */
+ File getWorkDir();
+
+ /**
+ * Get the archive path to the App.
+ *
+ * Might exist as a Directory (example: an exploded webapp, or a jetty:run) or a File (example: a WAR file)
+ *
+ * @return the
+ */
+ File getDir();
+
+ /**
+ * The origin of this {@link App} as specified by the {@link AppProvider}
+ *
+ * @return String representing the origin of this app.
+ */
+ String getOrigin();
+}
diff --git a/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/AppLifecycle.java b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/AppLifecycle.java
new file mode 100644
index 0000000..bf28998
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/AppLifecycle.java
@@ -0,0 +1,269 @@
+// ========================================================================
+// 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.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+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.annotations.DeployLifecycleBinding;
+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
+{
+ private static class BoundMethod
+ {
+ Object obj;
+ @SuppressWarnings("unused")
+ Node node;
+ Method method;
+ }
+
+ // 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";
+
+ public static void main(String[] args)
+ {
+ // Dump All Paths
+ AppLifecycle lifecycle = new AppLifecycle();
+
+ Set<Node> nodes = lifecycle.getNodes();
+
+ for (Node from : nodes)
+ {
+ for (Node to : nodes)
+ {
+ System.out.println();
+ System.out.printf("Paths %s -> %s:%n",from,to);
+ List<Node> path = lifecycle.findPath(from,to);
+ if (path.isEmpty())
+ {
+ System.out.printf(" (no steps needed)%n");
+ continue;
+ }
+
+ for (Node step : path)
+ {
+ System.out.printf(" %s%n",step.getName());
+ }
+ }
+ }
+ }
+
+ private Map<Node, List<BoundMethod>> lifecyclebindings = new HashMap<Node, List<BoundMethod>>();
+
+ 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(Object obj)
+ {
+ Class<?>[] expectedParams =
+ { Node.class, App.class, DeploymentManager.class };
+
+ for (Method method : obj.getClass().getDeclaredMethods())
+ {
+ // Does it have annotation?
+ if (!method.isAnnotationPresent(DeployLifecycleBinding.class))
+ {
+ continue; // skip
+ }
+
+ // Is it public?
+ if (!Modifier.isPublic(method.getModifiers()))
+ {
+ continue; // skip
+ }
+
+ // Does it return void?
+ if (method.getReturnType() != Void.TYPE)
+ {
+ continue; // skip
+ }
+
+ // Does it have specified parameters?
+ Class<?> params[] = method.getParameterTypes();
+ if (params == null)
+ {
+ continue; // skip
+ }
+ if (params.length != expectedParams.length)
+ {
+ continue; // skip
+ }
+ for (int i = 0; i < expectedParams.length; i++)
+ {
+ if (params[i].isAssignableFrom(expectedParams[i]) == false)
+ {
+ continue; // Not a match. skip it
+ }
+ }
+
+ // Has to be a match at this point.
+ DeployLifecycleBinding bindingAnno = method.getAnnotation(DeployLifecycleBinding.class);
+
+ for (String nodeName : bindingAnno.nodes())
+ {
+ if (nodeName.equals("*"))
+ {
+ // Special Case: Bind to all Nodes
+ for (Node node : getNodes())
+ {
+ bindToNode(node,obj,method);
+ }
+ }
+ else
+ {
+ // Bind to specific node
+ Node node = getNodeByName(nodeName);
+ bindToNode(node,obj,method);
+ }
+ }
+ }
+ }
+
+ private void bindToNode(Node node, Object obj, Method method)
+ {
+ // Create Method -> Object binding reference.
+ BoundMethod bound = new BoundMethod();
+ bound.obj = obj;
+ bound.method = method;
+ bound.node = node;
+
+ // Assign to map
+ List<BoundMethod> bindings = lifecyclebindings.get(node);
+ if (bindings == null)
+ {
+ bindings = new ArrayList<BoundMethod>();
+ }
+ bindings.add(bound);
+
+ lifecyclebindings.put(node,bindings);
+ }
+
+ /**
+ * Get all {@link Node} bound objects.
+ *
+ * @return Set of Object(s) for all lifecycle bindings. never null.
+ */
+ public Set<Object> getBindings()
+ {
+ Set<Object> boundset = new HashSet<Object>();
+
+ for (List<BoundMethod> bindings : lifecyclebindings.values())
+ {
+ for (BoundMethod bound : bindings)
+ {
+ boundset.add(bound.obj);
+ }
+ }
+
+ return boundset;
+ }
+
+ /**
+ * Get all objects bound to a specific {@link Node}
+ *
+ * @return Set of Object(s) for specific lifecycle bindings. never null.
+ */
+ public Set<Object> getBindings(Node node)
+ {
+ Set<Object> boundset = new HashSet<Object>();
+
+ List<BoundMethod> bindings = lifecyclebindings.get(node);
+ if (bindings == null)
+ {
+ return boundset;
+ }
+
+ for (BoundMethod bound : bindings)
+ {
+ boundset.add(bound.obj);
+ }
+
+ return boundset;
+ }
+
+ public Set<Object> getBindings(String nodeName)
+ {
+ Node node = getNodeByName(nodeName);
+ return getBindings(node);
+ }
+
+ public void runBindings(Node node, App app, DeploymentManager deploymentManager) throws Throwable
+ {
+ List<BoundMethod> bindings = this.lifecyclebindings.get(node);
+ if (bindings == null)
+ {
+ return;
+ }
+
+ Object[] params =
+ { node, app, deploymentManager };
+
+ for (BoundMethod binding : bindings)
+ {
+ Log.debug("Calling " + binding.obj.getClass().getName() + "#" + binding.method.getName());
+ binding.method.invoke(binding.obj,params);
+ }
+ }
+}
diff --git a/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/AppProvider.java b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/AppProvider.java
new file mode 100644
index 0000000..76ca1e6
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/AppProvider.java
@@ -0,0 +1,26 @@
+// ========================================================================
+// 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;
+
+/**
+ * Object responsible for providing {@link App}s to the {@link DeploymentManager}
+ */
+public interface AppProvider
+{
+ void startProvider(DeploymentManager deploymentManager) throws Exception;
+
+ void stopProvider() throws Exception;
+}
diff --git a/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/DeploymentManager.java b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/DeploymentManager.java
new file mode 100644
index 0000000..8b6fa1a
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/DeploymentManager.java
@@ -0,0 +1,379 @@
+// ========================================================================
+// 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.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.eclipse.jetty.deploy.graph.Node;
+import org.eclipse.jetty.deploy.support.ConfigurationManager;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.ContextHandlerCollection;
+import org.eclipse.jetty.util.AttributesMap;
+import org.eclipse.jetty.util.component.AbstractLifeCycle;
+import org.eclipse.jetty.util.log.Log;
+
+/**
+ * The Deployment Manager.
+ * <p>
+ * Responsibilities:
+ * <p>
+ * <img src="doc-files/DeploymentManager_Roles.png">
+ * <ol>
+ * <li>Tracking Apps and their Lifecycle Location</li>
+ * <li>Managing AppProviders and the Apps that they provide.</li>
+ * <li>Executing AppLifecycle on App based on current and desired Lifecycle Location.</li>
+ * </ol>
+ * <p>
+ * <img src="doc-files/DeploymentManager.png">
+ */
+public class DeploymentManager extends AbstractLifeCycle
+{
+ /**
+ * Represents a single tracked app within the deployment manager.
+ */
+ public class AppEntry
+ {
+ /**
+ * Version of the app.
+ *
+ * Note: Auto-increments on each {@link DeploymentManager#addApp(App)}
+ */
+ private int version;
+
+ /**
+ * The app being tracked.
+ */
+ private App app;
+
+ /**
+ * The lifecycle node location of this App
+ */
+ private Node lifecyleNode;
+
+ /**
+ * Tracking the various AppState timestamps (in system milliseconds)
+ */
+ private Map<Node, Long> stateTimestamps = new HashMap<Node, Long>();
+
+ public App getApp()
+ {
+ return app;
+ }
+
+ public int getVersion()
+ {
+ return version;
+ }
+
+ public Node getLifecyleNode()
+ {
+ return lifecyleNode;
+ }
+
+ public Map<Node, Long> getStateTimestamps()
+ {
+ return stateTimestamps;
+ }
+
+ void setLifecycleNode(Node node)
+ {
+ this.lifecyleNode = node;
+ this.stateTimestamps.put(node,Long.valueOf(System.currentTimeMillis()));
+ }
+ }
+
+ private Map<String, AppEntry> appmap = new HashMap<String, AppEntry>();
+ private List<AppProvider> providers = new ArrayList<AppProvider>();
+ private AttributesMap contextAttributes = new AttributesMap();
+ private ConfigurationManager configurationManager;
+ private ContextHandlerCollection contexts;
+ private AppLifecycle lifecycle = new AppLifecycle();
+
+ /**
+ * Receive an app for processing.
+ *
+ * Most commonly used by the various {@link AppProvider} implementations.
+ */
+ public void addApp(App app)
+ {
+ AppEntry entry = appmap.get(app.getId());
+ if (entry == null)
+ {
+ // New Entry
+ entry = new AppEntry();
+ entry.version = 0;
+ entry.setLifecycleNode(lifecycle.getNodeByName("undeployed"));
+ }
+ else
+ {
+ // Existing Entry
+ entry.version++;
+
+ // TODO: determine state change
+ // TODO: determine redeploy need?
+ }
+
+ entry.app = app;
+ appmap.put(app.getId(),entry);
+
+ // TODO: Should immediately attempt to start?
+ // this.requestAppGoal(app.getId(),AppState.STARTED);
+ }
+
+ public void addAppProvider(AppProvider provider)
+ {
+ providers.add(provider);
+ if (isStarted() || isStarting())
+ {
+ try
+ {
+ provider.startProvider(this);
+ }
+ catch (Exception e)
+ {
+ Log.warn("Unable to start AppProvider",e);
+ }
+ }
+ }
+
+ @Override
+ protected void doStart() throws Exception
+ {
+ Log.info("Starting all Providers: " + providers.size());
+ // Start all of the AppProviders
+ for (AppProvider provider : providers)
+ {
+ try
+ {
+ provider.startProvider(this);
+ }
+ catch (Exception e)
+ {
+ Log.warn("Unable to start AppProvider",e);
+ }
+ }
+ super.doStart();
+ }
+
+ @Override
+ protected void doStop() throws Exception
+ {
+ Log.info("Stopping all Providers: " + providers.size());
+
+ // Stop all of the AppProviders
+ for (AppProvider provider : providers)
+ {
+ try
+ {
+ provider.stopProvider();
+ }
+ catch (Exception e)
+ {
+ Log.warn("Unable to start AppProvider",e);
+ }
+ }
+ super.doStop();
+ }
+
+ public App getApp(String appId)
+ {
+ AppEntry entry = appmap.get(appId);
+ if (entry == null)
+ {
+ return null;
+ }
+ return entry.app;
+ }
+
+ public Collection<AppEntry> getAppEntries()
+ {
+ return appmap.values();
+ }
+
+ public AppEntry getAppEntry(String appId)
+ {
+ return appmap.get(appId);
+ }
+
+ public Collection<AppProvider> getAppProviders()
+ {
+ return providers;
+ }
+
+ public Collection<App> getApps()
+ {
+ List<App> apps = new ArrayList<App>();
+ for (AppEntry entry : appmap.values())
+ {
+ apps.add(entry.app);
+ }
+ return apps;
+ }
+
+ /**
+ * Get Set of {@link App}s by {@link Node}
+ *
+ * @param state
+ * the state to look for.
+ * @return
+ */
+ public Collection<App> getApps(Node node)
+ {
+ List<App> apps = new ArrayList<App>();
+ for (AppEntry entry : appmap.values())
+ {
+ if (entry.lifecyleNode == node)
+ {
+ apps.add(entry.app);
+ }
+ }
+ return apps;
+ }
+
+ /**
+ * Get a contextAttribute that will be set for every Context deployed by this provider.
+ *
+ * @param name
+ * @return
+ */
+ public Object getAttribute(String name)
+ {
+ return contextAttributes.getAttribute(name);
+ }
+
+ public ConfigurationManager getConfigurationManager()
+ {
+ return configurationManager;
+ }
+
+ public AttributesMap getContextAttributes()
+ {
+ return contextAttributes;
+ }
+
+ public ContextHandlerCollection getContexts()
+ {
+ return contexts;
+ }
+
+ public Server getServer()
+ {
+ if (contexts == null)
+ {
+ return null;
+ }
+ return contexts.getServer();
+ }
+
+ public void removeAppProvider(AppProvider provider)
+ {
+ providers.remove(provider);
+ try
+ {
+ provider.stopProvider();
+ }
+ catch (Exception e)
+ {
+ Log.warn("Unable to stop Provider",e);
+ }
+ }
+
+ /**
+ * Remove a contextAttribute that will be set for every Context deployed by this provider.
+ *
+ * @param name
+ */
+ public void removeAttribute(String name)
+ {
+ contextAttributes.removeAttribute(name);
+ }
+
+ /**
+ * Move an {@link App} through the {@link AppLifecycle} to the desired {@link Node}, executing each lifecycle step
+ * in the process to reach the desired state.
+ *
+ * @param appId
+ * the id of the app to move through the process
+ * @param nodeName
+ * the name of the node to attain
+ */
+ public void requestAppGoal(String appId, String nodeName)
+ {
+ AppEntry appentry = getAppEntry(appId);
+
+ Node destinationNode = lifecycle.getNodeByName(nodeName);
+ // Compute lifecycle steps
+ List<Node> path = lifecycle.findPath(appentry.lifecyleNode,destinationNode);
+ if (path.isEmpty())
+ {
+ // nothing to do. already there.
+ return;
+ }
+
+ // Execute each Node binding. Stopping at any thrown exception.
+ try
+ {
+ for (Node node : path)
+ {
+ Log.info("Executing Node: " + node);
+ lifecycle.runBindings(node,appentry.app,this);
+ }
+ }
+ catch (Throwable t)
+ {
+ Log.warn("Unable to reach node goal: " + nodeName,t);
+ }
+ }
+
+ /**
+ * Set a contextAttribute that will be set for every Context deployed by this provider.
+ *
+ * @param name
+ * @param value
+ */
+ public void setAttribute(String name, Object value)
+ {
+ contextAttributes.setAttribute(name,value);
+ }
+
+ public void setConfigurationManager(ConfigurationManager configurationManager)
+ {
+ this.configurationManager = configurationManager;
+ }
+
+ public void setContextAttributes(AttributesMap contextAttributes)
+ {
+ this.contextAttributes = contextAttributes;
+ }
+
+ public void setContexts(ContextHandlerCollection contexts)
+ {
+ this.contexts = contexts;
+ }
+
+ public void addLifecycleBinding(Object binding)
+ {
+ lifecycle.addBinding(binding);
+ }
+
+ public AppLifecycle getLifecycle()
+ {
+ return lifecycle;
+ }
+}
diff --git a/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/annotations/DeployLifecycleBinding.java b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/annotations/DeployLifecycleBinding.java
new file mode 100644
index 0000000..5e8df39
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/annotations/DeployLifecycleBinding.java
@@ -0,0 +1,30 @@
+// ========================================================================
+// 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.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+@Documented
+public @interface DeployLifecycleBinding
+{
+ String[] nodes();
+}
diff --git a/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/bindings/DefaultDeployer.java b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/bindings/DefaultDeployer.java
new file mode 100644
index 0000000..baed599
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/bindings/DefaultDeployer.java
@@ -0,0 +1,32 @@
+// ========================================================================
+// 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.bindings;
+
+import org.eclipse.jetty.deploy.App;
+import org.eclipse.jetty.deploy.DeploymentManager;
+import org.eclipse.jetty.deploy.annotations.DeployLifecycleBinding;
+import org.eclipse.jetty.deploy.graph.Node;
+import org.eclipse.jetty.server.handler.ContextHandler;
+
+public class DefaultDeployer
+{
+ @DeployLifecycleBinding(nodes = "deploying")
+ public void handleAppDeploy(DeploymentManager deployMgr, Node lifecycleNode, App app) throws Exception
+ {
+ ContextHandler handler = app.getContextHandler(deployMgr);
+ deployMgr.getContexts().addHandler(handler);
+ }
+}
diff --git a/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/bindings/DefaultStarter.java b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/bindings/DefaultStarter.java
new file mode 100644
index 0000000..3e367cc
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/bindings/DefaultStarter.java
@@ -0,0 +1,35 @@
+// ========================================================================
+// 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.bindings;
+
+import org.eclipse.jetty.deploy.App;
+import org.eclipse.jetty.deploy.DeploymentManager;
+import org.eclipse.jetty.deploy.annotations.DeployLifecycleBinding;
+import org.eclipse.jetty.deploy.graph.Node;
+import org.eclipse.jetty.server.handler.ContextHandler;
+
+public class DefaultStarter
+{
+ @DeployLifecycleBinding(nodes = "starting")
+ public void handleAppStart(DeploymentManager deployMgr, Node lifecycleNode, App app) throws Exception
+ {
+ ContextHandler handler = app.getContextHandler(deployMgr);
+ if (!handler.isStarted())
+ {
+ handler.start();
+ }
+ }
+}
diff --git a/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/bindings/DefaultStopper.java b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/bindings/DefaultStopper.java
new file mode 100644
index 0000000..53470ba
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/bindings/DefaultStopper.java
@@ -0,0 +1,35 @@
+// ========================================================================
+// 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.bindings;
+
+import org.eclipse.jetty.deploy.App;
+import org.eclipse.jetty.deploy.DeploymentManager;
+import org.eclipse.jetty.deploy.annotations.DeployLifecycleBinding;
+import org.eclipse.jetty.deploy.graph.Node;
+import org.eclipse.jetty.server.handler.ContextHandler;
+
+public class DefaultStopper
+{
+ @DeployLifecycleBinding(nodes = "stopping")
+ public void handleAppStop(DeploymentManager deployMgr, Node lifecycleNode, App app) throws Exception
+ {
+ ContextHandler handler = app.getContextHandler(deployMgr);
+ if (!handler.isStopped())
+ {
+ handler.stop();
+ }
+ }
+}
diff --git a/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/bindings/DefaultUndeployer.java b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/bindings/DefaultUndeployer.java
new file mode 100644
index 0000000..25ab5d8
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/bindings/DefaultUndeployer.java
@@ -0,0 +1,32 @@
+// ========================================================================
+// 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.bindings;
+
+import org.eclipse.jetty.deploy.App;
+import org.eclipse.jetty.deploy.DeploymentManager;
+import org.eclipse.jetty.deploy.annotations.DeployLifecycleBinding;
+import org.eclipse.jetty.deploy.graph.Node;
+import org.eclipse.jetty.server.handler.ContextHandler;
+
+public class DefaultUndeployer
+{
+ @DeployLifecycleBinding(nodes = "undeploying")
+ public void handleAppUndeploy(DeploymentManager deployMgr, Node lifecycleNode, App app) throws Exception
+ {
+ ContextHandler handler = app.getContextHandler(deployMgr);
+ deployMgr.getContexts().removeHandler(handler);
+ }
+}
diff --git a/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/graph/Edge.java b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/graph/Edge.java
new file mode 100644
index 0000000..5e6d070
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/graph/Edge.java
@@ -0,0 +1,78 @@
+// ========================================================================
+// 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.graph;
+
+/**
+ * Basic Graph Edge
+ */
+public class Edge
+{
+ private Node from;
+ private Node to;
+
+ public Edge(Node from, Node to)
+ {
+ this.from = from;
+ this.to = to;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((from == null)?0:from.hashCode());
+ result = prime * result + ((to == null)?0:to.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Edge other = (Edge)obj;
+ if (from == null)
+ {
+ if (other.from != null)
+ return false;
+ }
+ else if (!from.equals(other.from))
+ return false;
+ if (to == null)
+ {
+ if (other.to != null)
+ return false;
+ }
+ else if (!to.equals(other.to))
+ return false;
+ return true;
+ }
+
+ public Node getFrom()
+ {
+ return from;
+ }
+
+ public Node getTo()
+ {
+ return to;
+ }
+}
\ No newline at end of file
diff --git a/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/graph/Graph.java b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/graph/Graph.java
new file mode 100644
index 0000000..1c0f644
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/graph/Graph.java
@@ -0,0 +1,385 @@
+// ========================================================================
+// 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.graph;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Set;
+import java.util.Stack;
+
+/**
+ * Basic directed graph implementation
+ */
+public class Graph
+{
+ private class EdgeSearch
+ {
+ private Set<Edge> seenEdges = new HashSet<Edge>();
+ private List<NodePath> paths = new ArrayList<NodePath>();
+
+ public EdgeSearch(Node from)
+ {
+ NodePath path = new NodePath();
+ path.add(from);
+ paths.add(path);
+ }
+
+ public void breadthFirst(Node destination)
+ {
+ // Test existing edge endpoints
+ if (hasReachedDestination(destination))
+ {
+ // Found our destination!
+
+ // Now remove the other paths that do not end at the destination
+ ListIterator<NodePath> pathiter = paths.listIterator();
+ while (pathiter.hasNext())
+ {
+ NodePath path = pathiter.next();
+ if (path.lastNode() != destination)
+ {
+ pathiter.remove();
+ }
+ }
+ return;
+ }
+
+ List<NodePath> extrapaths = null;
+
+ // Add next unseen segments to paths.
+ boolean pathsAdded = false;
+
+ for (NodePath path : paths)
+ {
+ List<Edge> next = nextUnseenEdges(path);
+ if (next.size() == 0)
+ {
+ continue; // no new edges
+ }
+
+ pathsAdded = true;
+
+ // More than 1 path out? Split it.
+ if (next.size() > 1)
+ {
+ if (extrapaths == null)
+ {
+ extrapaths = new ArrayList<NodePath>();
+ }
+
+ // Split path for other edges
+ for (int i = 1, n = next.size(); i < n; i++)
+ {
+ NodePath split = path.forkPath();
+ // Add segment to split'd path
+ split.add(next.get(i).getTo());
+
+ // Add to extra paths
+ extrapaths.add(split);
+ }
+ }
+
+ // Add edge to current path
+ Edge edge = next.get(0);
+ path.add(edge.getTo());
+
+ // Mark all edges as seen
+ for (Edge e : next)
+ {
+ seenEdges.add(e);
+ }
+ }
+
+ // Do we have any extra paths?
+ if (extrapaths != null)
+ {
+ paths.addAll(extrapaths);
+ }
+
+ if (pathsAdded)
+ {
+ // recurse
+ breadthFirst(destination);
+ }
+ }
+
+ public NodePath getShortestPath()
+ {
+ NodePath shortest = null;
+ int shortestlen = Integer.MAX_VALUE;
+
+ for (NodePath path : paths)
+ {
+ if (shortest == null)
+ {
+ shortest = path;
+ continue;
+ }
+
+ int len = path.length();
+
+ if (len < shortestlen)
+ {
+ shortest = path;
+ shortestlen = len;
+ }
+ }
+
+ return shortest;
+ }
+
+ private boolean hasReachedDestination(Node destination)
+ {
+ for (NodePath path : paths)
+ {
+ if (path.lastNode() == destination)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private List<Edge> nextUnseenEdges(NodePath path)
+ {
+ List<Edge> next = new ArrayList<Edge>();
+
+ for (Edge edge : findEdgesFrom(path.lastNode()))
+ {
+ if (seenEdges.contains(edge) == false)
+ {
+ next.add(edge);
+ }
+ }
+
+ return next;
+ }
+ }
+
+ private class NodePath implements Iterable<Node>
+ {
+ private Stack<Node> path;
+
+ public NodePath()
+ {
+ path = new Stack<Node>();
+ }
+
+ public void add(Node node)
+ {
+ path.push(node);
+ }
+
+ public NodePath forkPath()
+ {
+ NodePath ep = new NodePath();
+ for (Node node : this)
+ {
+ ep.add(node);
+ }
+ return ep;
+ }
+
+ public Collection<Node> getCollection()
+ {
+ return path;
+ }
+
+ public Iterator<Node> iterator()
+ {
+ return path.iterator();
+ }
+
+ public Node lastNode()
+ {
+ return path.peek();
+ }
+
+ public int length()
+ {
+ return path.size();
+ }
+ }
+
+ private Set<Node> nodes = new HashSet<Node>();
+ private Set<Edge> edges = new HashSet<Edge>();
+
+ public void addEdge(Edge edge)
+ {
+ this.edges.add(edge);
+ }
+
+ public void addEdge(String from, String to)
+ {
+ Node fromNode = null;
+ Node toNode = null;
+
+ try
+ {
+ fromNode = getNodeByName(from);
+ }
+ catch (NodeNotFoundException e)
+ {
+ fromNode = new Node(from);
+ addNode(fromNode);
+ }
+
+ try
+ {
+ toNode = getNodeByName(to);
+ }
+ catch (NodeNotFoundException e)
+ {
+ toNode = new Node(to);
+ addNode(toNode);
+ }
+
+ Edge edge = new Edge(fromNode,toNode);
+ addEdge(edge);
+ }
+
+ public void addNode(Node node)
+ {
+ this.nodes.add(node);
+ }
+
+ /**
+ * Find all edges that are connected to the specific node, both as an outgoing {@link Edge#getFrom()} or incoming
+ * {@link Edge#getTo()} end point.
+ *
+ * @param node
+ * the node with potential end points
+ * @return the set of edges connected to the node
+ */
+ public Set<Edge> findEdges(Node node)
+ {
+ Set<Edge> fromedges = new HashSet<Edge>();
+
+ for (Edge edge : this.edges)
+ {
+ if ((edge.getFrom() == node) || (edge.getTo() == node))
+ {
+ fromedges.add(edge);
+ }
+ }
+
+ return fromedges;
+ }
+
+ /**
+ * Find all edges that are connected {@link Edge#getFrom()} the specific node.
+ *
+ * @param node
+ * the node with potential edges from it
+ * @return the set of edges from the node
+ */
+ public Set<Edge> findEdgesFrom(Node from)
+ {
+ Set<Edge> fromedges = new HashSet<Edge>();
+
+ for (Edge edge : this.edges)
+ {
+ if (edge.getFrom() == from)
+ {
+ fromedges.add(edge);
+ }
+ }
+
+ return fromedges;
+ }
+
+ /**
+ * Using BFS (Breadth First Search) return the path from a any arbitrary node to any other.
+ *
+ * @param from
+ * the node from
+ * @param to
+ * the node to
+ * @return the path to take
+ */
+ public List<Node> findPath(Node from, Node to)
+ {
+ if (from == to)
+ {
+ return Collections.emptyList();
+ }
+
+ // Perform a Breadth First Search (BFS) of the tree.
+ EdgeSearch search = new EdgeSearch(from);
+ search.breadthFirst(to);
+
+ NodePath nodepath = search.getShortestPath();
+ List<Node> path = new ArrayList<Node>();
+ path.addAll(nodepath.getCollection());
+ return path;
+ }
+
+ public Set<Edge> getEdges()
+ {
+ return edges;
+ }
+
+ public Node getNodeByName(String name)
+ {
+ for (Node node : nodes)
+ {
+ if (node.getName().equals(name))
+ {
+ return node;
+ }
+ }
+
+ throw new NodeNotFoundException("Unable to find node: " + name);
+ }
+
+ public Set<Node> getNodes()
+ {
+ return nodes;
+ }
+
+ public void removeEdge(Edge edge)
+ {
+ this.edges.remove(edge);
+ }
+
+ public void removeEdge(String fromNodeName, String toNodeName)
+ {
+ Node fromNode = getNodeByName(fromNodeName);
+ Node toNode = getNodeByName(toNodeName);
+ Edge edge = new Edge(fromNode,toNode);
+ removeEdge(edge);
+ }
+
+ public void removeNode(Node node)
+ {
+ this.nodes.remove(node);
+ }
+
+ public void setEdges(Set<Edge> edges)
+ {
+ this.edges = edges;
+ }
+
+ public void setNodes(Set<Node> nodes)
+ {
+ this.nodes = nodes;
+ }
+}
diff --git a/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/graph/ImpossiblePathException.java b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/graph/ImpossiblePathException.java
new file mode 100644
index 0000000..7a9e871
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/graph/ImpossiblePathException.java
@@ -0,0 +1,31 @@
+// ========================================================================
+// 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.graph;
+
+public class ImpossiblePathException extends RuntimeException
+{
+ private static final long serialVersionUID = 8423437443748056467L;
+
+ public ImpossiblePathException(String message, Throwable cause)
+ {
+ super(message,cause);
+ }
+
+ public ImpossiblePathException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/graph/Node.java b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/graph/Node.java
new file mode 100644
index 0000000..ab80ea7
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/graph/Node.java
@@ -0,0 +1,69 @@
+// ========================================================================
+// 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.graph;
+
+/**
+ * Basic Graph Node
+ */
+public class Node
+{
+ private String name;
+
+ public Node(String name)
+ {
+ this.name = name;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Node[" + name + "]";
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null)?0:name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Node other = (Node)obj;
+ if (name == null)
+ {
+ if (other.name != null)
+ return false;
+ }
+ else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/graph/NodeNotFoundException.java b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/graph/NodeNotFoundException.java
new file mode 100644
index 0000000..336adf9
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/graph/NodeNotFoundException.java
@@ -0,0 +1,34 @@
+// ========================================================================
+// 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.graph;
+
+/**
+ * NodeNotFoundException for when a referenced node cannot be found.
+ */
+public class NodeNotFoundException extends RuntimeException
+{
+ private static final long serialVersionUID = -7126395440535048386L;
+
+ public NodeNotFoundException(String message, Throwable cause)
+ {
+ super(message,cause);
+ }
+
+ public NodeNotFoundException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/providers/ConfiguredContextApp.java b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/providers/ConfiguredContextApp.java
new file mode 100644
index 0000000..8ffb50d
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/providers/ConfiguredContextApp.java
@@ -0,0 +1,94 @@
+// ========================================================================
+// 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.providers;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jetty.deploy.App;
+import org.eclipse.jetty.deploy.DeploymentManager;
+import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.util.AttributesMap;
+import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.xml.XmlConfiguration;
+
+public class ConfiguredContextApp implements App
+{
+ private String filename;
+ private ContextHandler handler;
+
+ public ConfiguredContextApp(String filename)
+ {
+ this.filename = filename;
+ }
+
+ public File getDir()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public ContextHandler getContextHandler(DeploymentManager deploymgr) throws Exception
+ {
+ if (handler == null)
+ {
+ Resource resource = Resource.newResource(filename);
+ if (!resource.exists())
+ {
+ return null;
+ }
+
+ XmlConfiguration xmlc = new XmlConfiguration(resource.getURL());
+ Map props = new HashMap();
+ props.put("Server",deploymgr.getServer());
+ if (deploymgr.getConfigurationManager() != null)
+ {
+ props.putAll(deploymgr.getConfigurationManager().getProperties());
+ }
+
+ xmlc.setProperties(props);
+ this.handler = (ContextHandler)xmlc.configure();
+ this.handler.setAttributes(new AttributesMap(deploymgr.getContextAttributes()));
+ }
+ return handler;
+ }
+
+ public String getId()
+ {
+ return null;
+ }
+
+ public String getName()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String getOrigin()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public File getWorkDir()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/providers/ContextsDirAppProvider.java b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/providers/ContextsDirAppProvider.java
new file mode 100644
index 0000000..b5acb0e
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/providers/ContextsDirAppProvider.java
@@ -0,0 +1,152 @@
+// ========================================================================
+// 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.providers;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.Collections;
+import org.eclipse.jetty.deploy.App;
+import org.eclipse.jetty.deploy.AppProvider;
+import org.eclipse.jetty.deploy.DeploymentManager;
+import org.eclipse.jetty.util.Scanner;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.resource.Resource;
+
+/**
+ * Backwards Compatible AppProvider for Monitoring a Contexts directory and deploying All Contexts.
+ *
+ * Similar in scope to the original org.eclipse.jetty.deploy.ContextDeployer
+ */
+public class ContextsDirAppProvider implements AppProvider, Scanner.DiscreteListener
+{
+ private Resource contextsDir;
+ private Scanner scanner;
+ private int scanInterval = 10;
+ private boolean recursive = false;
+ private DeploymentManager deploymgr;
+
+ class XmlFilenameFilter implements FilenameFilter
+ {
+ public boolean accept(File dir, String name)
+ {
+ if (name.endsWith(".xml"))
+ {
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ public ContextsDirAppProvider()
+ {
+ scanner = new Scanner();
+ }
+
+ public void startProvider(DeploymentManager deploymentManager) throws Exception
+ {
+ Log.info(this.getClass().getSimpleName() + ".startProvider(" + deploymentManager + ")");
+ if (contextsDir == null)
+ {
+ throw new IllegalStateException("No configuration dir specified");
+ }
+
+ this.deploymgr = deploymentManager;
+
+ File scandir = contextsDir.getFile();
+ Log.info("ScanDir: " + scandir);
+ this.scanner.setScanDirs(Collections.singletonList(scandir));
+ this.scanner.setScanInterval(scanInterval);
+ this.scanner.setRecursive(recursive);
+ this.scanner.setFilenameFilter(new XmlFilenameFilter());
+ this.scanner.addListener(this);
+ this.scanner.scan();
+ this.scanner.start();
+ }
+
+ public Resource getContextsDir()
+ {
+ return contextsDir;
+ }
+
+ public void setContextsDir(Resource contextsDir)
+ {
+ this.contextsDir = contextsDir;
+ }
+
+ /**
+ * @param dir
+ * Directory to scan for context descriptors
+ */
+ public void setContextsDir(String dir)
+ {
+ try
+ {
+ contextsDir = Resource.newResource(dir);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ public int getScanInterval()
+ {
+ return scanInterval;
+ }
+
+ public void setScanInterval(int scanInterval)
+ {
+ this.scanInterval = scanInterval;
+ }
+
+ public boolean isRecursive()
+ {
+ return recursive;
+ }
+
+ public void setRecursive(boolean recursive)
+ {
+ this.recursive = recursive;
+ }
+
+ public void stopProvider()
+ {
+ this.scanner.removeListener(this);
+ this.scanner.stop();
+ }
+
+ public void fileAdded(String filename) throws Exception
+ {
+ Log.info("fileAdded(" + filename + ")");
+ App app = new ConfiguredContextApp(filename);
+ this.deploymgr.addApp(app);
+ }
+
+ public void fileChanged(String filename) throws Exception
+ {
+ Log.info("fileChanged(" + filename + ")");
+ App app = new ConfiguredContextApp(filename);
+ this.deploymgr.addApp(app);
+ }
+
+ public void fileRemoved(String filename) throws Exception
+ {
+ Log.info("fileRemoved(" + filename + ")");
+ App app = new ConfiguredContextApp(filename);
+ this.deploymgr.addApp(app);
+ }
+}
diff --git a/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/providers/WebappsDirAppProvider.java b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/providers/WebappsDirAppProvider.java
new file mode 100644
index 0000000..7e526df
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/providers/WebappsDirAppProvider.java
@@ -0,0 +1,41 @@
+// ========================================================================
+// 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.providers;
+
+import org.eclipse.jetty.deploy.AppProvider;
+import org.eclipse.jetty.deploy.DeploymentManager;
+
+/**
+ * Backwards Compatible AppProvider for Monitoring a Webapps directory and deploying All apps.
+ *
+ * Similar in scope to the original org.eclipse.jetty.deploy.WebAppDeployer
+ */
+public class WebappsDirAppProvider implements AppProvider
+{
+
+ public void startProvider(DeploymentManager deploymentManager) throws Exception
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void stopProvider()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/support/ConfigurationManager.java b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/support/ConfigurationManager.java
new file mode 100644
index 0000000..c9f7ad5
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/support/ConfigurationManager.java
@@ -0,0 +1,27 @@
+// ========================================================================
+// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// 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.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty.deploy.support;
+
+import java.util.Map;
+
+/**
+ * ConfigurationManager
+ *
+ * Type for allow injection of property values
+ * for replacement in jetty xml files during deployment.
+ */
+public interface ConfigurationManager
+{
+ public Map<?, ?> getProperties();
+}
diff --git a/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/support/FileConfigurationManager.java b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/support/FileConfigurationManager.java
new file mode 100644
index 0000000..e4dc398
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/java/org/eclipse/jetty/deploy/support/FileConfigurationManager.java
@@ -0,0 +1,66 @@
+// ========================================================================
+// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// 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.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty.deploy.support;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Map;
+import java.util.Properties;
+
+import org.eclipse.jetty.util.resource.Resource;
+
+/**
+ * FileConfigurationManager
+ *
+ * Supplies properties defined in a file.
+ */
+public class FileConfigurationManager implements ConfigurationManager
+{
+ private Resource _file;
+ private Properties _properties = new Properties();
+
+ public FileConfigurationManager()
+ {
+ }
+
+ public void setFile(String filename) throws MalformedURLException, IOException
+ {
+ _file = Resource.newResource(filename);
+ }
+
+ /**
+ * @see org.eclipse.jetty.deploy.ConfigurationManager#getProperties()
+ */
+ public Map<?, ?> getProperties()
+ {
+ try
+ {
+ loadProperties();
+ return _properties;
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void loadProperties() throws FileNotFoundException, IOException
+ {
+ if (_properties.isEmpty())
+ {
+ _properties.load(_file.getInputStream());
+ }
+ }
+}
diff --git a/jetty-deploy-manager-graph/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/AppLifecycle.png b/jetty-deploy-manager-graph/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/AppLifecycle.png
new file mode 100644
index 0000000..071c747
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/AppLifecycle.png
Binary files differ
diff --git a/jetty-deploy-manager-graph/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/AppLifecycle.svg b/jetty-deploy-manager-graph/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/AppLifecycle.svg
new file mode 100644
index 0000000..dc6974c
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/AppLifecycle.svg
@@ -0,0 +1,482 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generated by Graphviz version 2.20.2 (Mon Mar 30 10:11:53 UTC 2009)
+ For user: (joakim) Joakim Erdfelt,,, -->
+<!-- Title: G Pages: 1 -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="765"
+ height="900"
+ viewBox="0 0 327 590"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="AppLifecycle.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ version="1.0"
+ inkscape:export-filename="/home/joakim/code/webtide/jetty7-git/sandbox/jetty-deploy-manager/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/AppLifecycle.png"
+ inkscape:export-xdpi="40"
+ inkscape:export-ydpi="40">
+ <metadata
+ id="metadata184">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs182">
+ <marker
+ inkscape:stockid="Arrow2Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Lstart"
+ style="overflow:visible">
+ <path
+ id="path4328"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) translate(1,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lend"
+ style="overflow:visible">
+ <path
+ id="path3605"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="TriangleOutL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="TriangleOutL"
+ style="overflow:visible">
+ <path
+ id="path3727"
+ d="M 5.77,0 L -2.88,5 L -2.88,-5 L 5.77,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="scale(0.8,0.8)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lend"
+ style="overflow:visible">
+ <path
+ id="path3587"
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 368.75 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="408.75 : 368.75 : 1"
+ inkscape:persp3d-origin="204.375 : 245.83333 : 1"
+ id="perspective186" />
+ <title
+ id="title5">G</title>
+ <title
+ id="title10">incoming_app</title>
+ <title
+ id="title17">command_deploy</title>
+ <title
+ id="title33">state_deployed</title>
+ </defs>
+ <sodipodi:namedview
+ inkscape:window-height="1151"
+ inkscape:window-width="1920"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="1"
+ guidetolerance="10"
+ gridtolerance="10.0"
+ objecttolerance="13"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:zoom="0.92828283"
+ inkscape:cx="387.34766"
+ inkscape:cy="428.51283"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:current-layer="svg2"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:document-units="cm"
+ units="in"
+ inkscape:snap-guide="true"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="false"
+ inkscape:bbox-nodes="false"
+ inkscape:snap-intersection-line-segments="true"
+ inkscape:object-paths="true"
+ inkscape:object-nodes="true"
+ inkscape:snap-center="false">
+ <inkscape:grid
+ type="xygrid"
+ id="grid3514"
+ dotted="true"
+ visible="true"
+ enabled="true"
+ units="cm"
+ spacingx="0.25cm"
+ spacingy="0.25cm"
+ empspacing="5" />
+ </sodipodi:namedview>
+ <g
+ id="g3445"
+ transform="matrix(1.2491264,0,0,1.2491264,109.41031,84.061397)">
+ <polygon
+ style="fill:#ffa500;stroke:#ffa500;stroke-width:0.80055952"
+ points="228,-510 144,-510 144,-468 228,-468 228,-510 "
+ id="polygon3447"
+ transform="translate(4,586)" />
+ <text
+ x="190"
+ y="92.600006"
+ style="font-size:14.39999962px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ id="text3449"
+ sodipodi:linespacing="125%">
+ <tspan
+ sodipodi:role="line"
+ id="tspan3451"
+ x="190"
+ y="92.600006">Phase</tspan>
+ <tspan
+ sodipodi:role="line"
+ id="tspan3453"
+ x="190"
+ y="110.60001">DEPLOY</tspan>
+ </text>
+ </g>
+ <g
+ id="g3917">
+ <polygon
+ transform="matrix(1.6111428,0,0,1.2491264,-118.06476,648.90074)"
+ id="polygon3491"
+ points="230,-432 138,-432 138,-390 230,-390 230,-432 "
+ style="fill:#00ffff;stroke:#00ffff;stroke-width:0.70490372" />
+ <text
+ sodipodi:linespacing="125%"
+ id="text3493"
+ style="font-size:17.98741913px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ y="130.01364"
+ x="178.38551">
+ <tspan
+ sodipodi:role="line"
+ id="tspan3503"
+ x="178.38551"
+ y="130.01364">State</tspan>
+ <tspan
+ sodipodi:role="line"
+ id="tspan3505"
+ x="178.38551"
+ y="152.49792">UNAVAILABLE</tspan>
+ </text>
+ </g>
+ <g
+ id="g3549"
+ transform="matrix(1.2491264,0,0,1.2491264,-227.0731,84.061397)">
+ <polygon
+ style="fill:#ffa500;stroke:#ffa500;stroke-width:0.80055952"
+ points="228,-510 144,-510 144,-468 228,-468 228,-510 "
+ id="polygon3551"
+ transform="translate(4,586)" />
+ <text
+ x="190"
+ y="92.600006"
+ style="font-size:14.39999962px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ id="text3553"
+ sodipodi:linespacing="125%">
+ <tspan
+ sodipodi:role="line"
+ id="tspan3559"
+ x="190"
+ y="92.600006">Phase</tspan>
+ <tspan
+ sodipodi:role="line"
+ id="tspan3561"
+ x="190"
+ y="110.60001">UNDEPLOY</tspan>
+ </text>
+ </g>
+ <g
+ id="g3483"
+ transform="matrix(1.2491264,0,0,1.2491264,-102.88457,7.5836656)">
+ <ellipse
+ style="fill:#c1c1c1;fill-opacity:1;stroke:none"
+ cx="222"
+ cy="-564"
+ rx="96.784599"
+ ry="18"
+ id="ellipse3485"
+ sodipodi:cx="222"
+ sodipodi:cy="-564"
+ sodipodi:rx="96.784599"
+ sodipodi:ry="18"
+ transform="translate(4,586)" />
+ <text
+ x="226"
+ y="26.099976"
+ style="font-size:14.39999962px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ id="text3487"
+ sodipodi:linespacing="125%">Incoming WebApp</text>
+ </g>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.9988189;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
+ d="M 180.40071,57.523395 L 180.40071,108.36997"
+ id="path2594"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path3923"
+ d="M 252.49807,154.27312 L 294.28101,190.29424"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 294.28101,213.09705 L 236.46989,265.1469"
+ id="path3925"
+ sodipodi:nodetypes="cc" />
+ <g
+ id="g3469"
+ transform="matrix(1.2491264,0,0,1.2491264,-55.825685,55.721845)">
+ <polygon
+ style="fill:#00ffff;stroke:#00ffff;stroke-width:0.80055952"
+ points="230,-432 138,-432 138,-390 230,-390 230,-432 "
+ id="polygon3471"
+ transform="translate(4,586)" />
+ <text
+ x="188"
+ y="170.60001"
+ style="font-size:14.39999962px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ id="text3473"
+ sodipodi:linespacing="125%">
+ <tspan
+ sodipodi:role="line"
+ id="tspan3475"
+ x="188"
+ y="170.60001">State</tspan>
+ <tspan
+ sodipodi:role="line"
+ id="tspan3477"
+ x="188"
+ y="188.60001">DEPLOYED</tspan>
+ </text>
+ </g>
+ <g
+ id="g5403"
+ transform="matrix(1.2491264,0,0,1.2491264,-56.840602,191.55677)">
+ <polygon
+ style="fill:#00ffff;stroke:#00ffff;stroke-width:0.80055952"
+ points="230,-432 138,-432 138,-390 230,-390 230,-432 "
+ id="polygon5405"
+ transform="translate(4,586)" />
+ <text
+ x="188"
+ y="170.60001"
+ style="font-size:14.39999962px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ id="text5407"
+ sodipodi:linespacing="125%">
+ <tspan
+ sodipodi:role="line"
+ id="tspan5417"
+ x="188"
+ y="170.60001">State</tspan>
+ <tspan
+ sodipodi:role="line"
+ id="tspan5419"
+ x="188"
+ y="188.60001">STAGED</tspan>
+ </text>
+ </g>
+ <path
+ sodipodi:nodetypes="cc"
+ id="path3929"
+ d="M 120.53534,398.20562 L 62.724228,352.50272"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path3935"
+ d="M 294.28101,355.83348 L 235.45498,398.20563"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <g
+ transform="matrix(1.2491264,0,0,1.2491264,109.41031,219.89633)"
+ id="g3535">
+ <polygon
+ transform="translate(4,586)"
+ id="polygon3537"
+ points="228,-510 144,-510 144,-468 228,-468 228,-510 "
+ style="fill:#ffa500;stroke:#ffa500;stroke-width:0.80055952" />
+ <text
+ sodipodi:linespacing="125%"
+ id="text3539"
+ style="font-size:14.39999962px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ y="92.600006"
+ x="190">
+ <tspan
+ sodipodi:role="line"
+ id="tspan3545"
+ x="190"
+ y="92.600006">Phase</tspan>
+ <tspan
+ sodipodi:role="line"
+ id="tspan3547"
+ x="190"
+ y="110.60001">STAGE</tspan>
+ </text>
+ </g>
+ <path
+ sodipodi:nodetypes="cc"
+ id="path3927"
+ d="M 236.46989,284.21436 L 293.65647,330.6791"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path3941"
+ d="M 62.724228,186.76323 L 104.27295,153.52683"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path3943"
+ d="M 121.55027,263.8367 L 62.724228,212.94524"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ x="-10.835248"
+ y="23.769073"
+ style="font-size:20.46376419px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans Bold Italic"
+ id="text2456"
+ sodipodi:linespacing="100%">
+ <tspan
+ sodipodi:role="line"
+ id="tspan2460"
+ x="-10.835244"
+ y="23.769073"
+ style="font-size:20.46376419px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans Bold Italic">Deployment</tspan>
+ <tspan
+ sodipodi:role="line"
+ x="-10.835247"
+ y="44.232838"
+ id="tspan2464"
+ style="font-size:20.46376419px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans Bold Italic">Lifecycle</tspan>
+ </text>
+ <g
+ id="g2472"
+ transform="matrix(1.2491264,0,0,1.2491264,109.41031,355.73126)">
+ <polygon
+ style="fill:#ffa500;stroke:#ffa500;stroke-width:0.80055952"
+ points="228,-510 144,-510 144,-468 228,-468 228,-510 "
+ id="polygon2474"
+ transform="translate(4,586)" />
+ <text
+ x="190"
+ y="92.600006"
+ style="font-size:14.39999962px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ id="text2476"
+ sodipodi:linespacing="125%">
+ <tspan
+ y="92.600006"
+ x="190"
+ id="tspan2478"
+ sodipodi:role="line">Phase</tspan>
+ <tspan
+ y="110.60001"
+ x="190"
+ id="tspan2480"
+ sodipodi:role="line">START</tspan>
+ </text>
+ </g>
+ <g
+ id="g2482"
+ transform="matrix(1.2491264,0,0,1.2491264,-227.0731,219.89633)">
+ <polygon
+ style="fill:#ffa500;stroke:#ffa500;stroke-width:0.80055952"
+ points="228,-510 144,-510 144,-468 228,-468 228,-510 "
+ id="polygon2484"
+ transform="translate(4,586)" />
+ <text
+ x="190"
+ y="92.600006"
+ style="font-size:14.39999962px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ id="text2486"
+ sodipodi:linespacing="125%">
+ <tspan
+ y="92.600006"
+ x="190"
+ id="tspan2488"
+ sodipodi:role="line">Phase</tspan>
+ <tspan
+ y="110.60001"
+ x="190"
+ id="tspan2490"
+ sodipodi:role="line">STOP</tspan>
+ </text>
+ </g>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 236.46989,420.04929 L 293.65647,466.51403"
+ id="path2492"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 62.724228,326.37326 L 121.55027,286.42657"
+ id="path2494"
+ sodipodi:nodetypes="cc" />
+ <g
+ transform="matrix(1.2491264,0,0,1.2491264,-56.840602,327.3917)"
+ id="g2551">
+ <polygon
+ transform="translate(4,586)"
+ id="polygon2553"
+ points="230,-432 138,-432 138,-390 230,-390 230,-432 "
+ style="fill:#00ffff;stroke:#00ffff;stroke-width:0.80055952" />
+ <text
+ sodipodi:linespacing="125%"
+ id="text2555"
+ style="font-size:14.39999962px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ y="170.60001"
+ x="188">
+ <tspan
+ y="170.60001"
+ x="188"
+ id="tspan2557"
+ sodipodi:role="line">State</tspan>
+ <tspan
+ y="188.60001"
+ x="188"
+ id="tspan2559"
+ sodipodi:role="line">STARTED</tspan>
+ </text>
+ </g>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 120.53534,536.86536 L 23.883096,367.29325"
+ id="path2561"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 294.28101,491.66841 L 235.45498,545.3398"
+ id="path2563"
+ sodipodi:nodetypes="cc" />
+</svg>
diff --git a/jetty-deploy-manager-graph/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/DeploymentManager.png b/jetty-deploy-manager-graph/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/DeploymentManager.png
new file mode 100644
index 0000000..b3c0a5b
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/DeploymentManager.png
Binary files differ
diff --git a/jetty-deploy-manager-graph/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/DeploymentManager.svg b/jetty-deploy-manager-graph/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/DeploymentManager.svg
new file mode 100644
index 0000000..68a51bf
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/DeploymentManager.svg
@@ -0,0 +1,570 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generated by Graphviz version 2.20.2 (Mon Mar 30 10:11:53 UTC 2009)
+ For user: (joakim) Joakim Erdfelt,,, -->
+<!-- Title: G Pages: 1 -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="965.69556"
+ height="852.49811"
+ viewBox="0 0 327 590"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="DeploymentManager.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ version="1.0"
+ inkscape:export-filename="/home/joakim/code/webtide/jetty7-git/sandbox/jetty-deploy-manager/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/DeploymentManager.png"
+ inkscape:export-xdpi="59.964943"
+ inkscape:export-ydpi="59.964943">
+ <metadata
+ id="metadata184">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs182">
+ <marker
+ inkscape:stockid="Arrow2Lstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lstart"
+ style="overflow:visible">
+ <path
+ id="path4328"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z"
+ transform="matrix(1.1,0,0,1.1,1.1,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lend"
+ style="overflow:visible">
+ <path
+ id="path3605"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="TriangleOutL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="TriangleOutL"
+ style="overflow:visible">
+ <path
+ id="path3727"
+ d="M 5.77,0 L -2.88,5 L -2.88,-5 L 5.77,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="scale(0.8,0.8)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lend"
+ style="overflow:visible">
+ <path
+ id="path3587"
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 368.75 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="408.75 : 368.75 : 1"
+ inkscape:persp3d-origin="204.375 : 245.83333 : 1"
+ id="perspective186" />
+ <title
+ id="title5">G</title>
+ <title
+ id="title10">incoming_app</title>
+ <title
+ id="title17">command_deploy</title>
+ <title
+ id="title33">state_deployed</title>
+ </defs>
+ <sodipodi:namedview
+ inkscape:window-height="1151"
+ inkscape:window-width="1920"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="1"
+ guidetolerance="10"
+ gridtolerance="10.0"
+ objecttolerance="13"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:zoom="1"
+ inkscape:cx="474.19853"
+ inkscape:cy="442.53354"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:current-layer="svg2"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:document-units="cm"
+ units="cm"
+ inkscape:snap-guide="true"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="false"
+ inkscape:bbox-nodes="false"
+ inkscape:snap-intersection-line-segments="true"
+ inkscape:object-paths="true"
+ inkscape:object-nodes="true"
+ inkscape:snap-center="false">
+ <inkscape:grid
+ type="xygrid"
+ id="grid3514"
+ dotted="true"
+ visible="true"
+ enabled="true"
+ units="cm"
+ spacingx="0.25cm"
+ spacingy="0.25cm"
+ empspacing="5" />
+ </sodipodi:namedview>
+ <text
+ x="-78.66259"
+ y="28.720337"
+ style="font-size:20.46376419px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans Bold Italic"
+ id="text2456"
+ sodipodi:linespacing="100%">
+ <tspan
+ sodipodi:role="line"
+ id="tspan2460"
+ x="-78.662582"
+ y="28.720337"
+ style="font-size:20.46376419px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans Bold Italic">Deployment</tspan>
+ <tspan
+ sodipodi:role="line"
+ x="-78.66259"
+ y="49.184101"
+ id="tspan2464"
+ style="font-size:20.46376419px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:100%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans Bold Italic">Management</tspan>
+ </text>
+ <g
+ id="g3282"
+ transform="translate(102.27151,-84.291492)">
+ <polygon
+ style="fill:#ffad70;fill-opacity:1;stroke:none;stroke-width:0.1850972"
+ points="230,-432 138,-432 138,-390 230,-390 230,-432 "
+ id="polygon3273"
+ transform="matrix(2.3250213,0,0,1.0137256,-252.78172,805.8122)" />
+ <text
+ x="174.1483"
+ y="394.13333"
+ style="font-size:17.98741913px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ id="text3275"
+ sodipodi:linespacing="125%">
+ <tspan
+ y="394.13333"
+ x="174.1483"
+ id="tspan3277"
+ sodipodi:role="line">DeploymentManager</tspan>
+ </text>
+ </g>
+ <g
+ id="g3304"
+ transform="translate(129.1072,31.5257)">
+ <polygon
+ style="fill:#d5ff70;fill-opacity:1;stroke:none;stroke-width:0.1850972"
+ points="230,-432 138,-432 138,-390 230,-390 230,-432 "
+ id="polygon3289"
+ transform="matrix(1.5190294,0,0,1.4508985,-250.33457,723.80726)" />
+ <text
+ x="28.670605"
+ y="122.9516"
+ style="font-size:17.98741913px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ id="text3291"
+ sodipodi:linespacing="125%">
+ <tspan
+ y="122.9516"
+ x="28.670605"
+ id="tspan3293"
+ sodipodi:role="line">AppProvider</tspan>
+ <tspan
+ id="tspan3300"
+ y="145.43587"
+ x="28.670603"
+ sodipodi:role="line">Contexts Dir</tspan>
+ </text>
+ </g>
+ <g
+ id="g3310"
+ transform="translate(300.00818,31.5257)">
+ <polygon
+ transform="matrix(1.5190294,0,0,1.4508985,-250.33457,723.80726)"
+ id="polygon3312"
+ points="230,-432 138,-432 138,-390 230,-390 230,-432 "
+ style="fill:#d5ff70;fill-opacity:1;stroke:none;stroke-width:0.1850972" />
+ <text
+ sodipodi:linespacing="125%"
+ id="text3314"
+ style="font-size:17.98741913px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ y="122.9516"
+ x="28.670605">
+ <tspan
+ sodipodi:role="line"
+ id="tspan3316"
+ x="28.670605"
+ y="122.9516">AppProvider</tspan>
+ <tspan
+ sodipodi:role="line"
+ x="28.670605"
+ y="145.43587"
+ id="tspan3318">Webapps Dir</tspan>
+ </text>
+ </g>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 246.279,212.30268 L 216.9954,189.48254"
+ id="path3344"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path3879"
+ d="M 246.279,212.30268 L 281.25982,189.48254"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path3889"
+ d="M 338.25506,189.48254 L 338.25509,283.59126"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path3891"
+ d="M 177.84916,189.48255 L 177.54883,283.59124"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <g
+ id="g3916"
+ transform="translate(105.09632,-15.083658)">
+ <polygon
+ transform="matrix(1.5190294,0,0,1.0137261,-95.187633,465.47084)"
+ id="polygon3903"
+ points="230,-432 138,-432 138,-390 230,-390 230,-432 "
+ style="fill:#70d9ff;fill-opacity:1;stroke:none;stroke-width:0.1850972" />
+ <text
+ sodipodi:linespacing="125%"
+ id="text3905"
+ style="font-size:17.98741913px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ y="53.791767"
+ x="184.1996">
+ <tspan
+ id="tspan3909"
+ sodipodi:role="line"
+ x="184.1996"
+ y="53.791767">File System</tspan>
+ </text>
+ </g>
+ <path
+ sodipodi:nodetypes="cc"
+ id="path3921"
+ d="M 204.70466,128.54481 L 240.721,55.034003"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 343.12033,128.54481 L 309.92883,55.034003"
+ id="path3923"
+ sodipodi:nodetypes="cc" />
+ <polygon
+ style="fill:#ff913e;fill-opacity:1;stroke:none;stroke-width:0.1850972"
+ points="230,-432 138,-432 138,-390 230,-390 230,-432 "
+ id="polygon4134"
+ transform="matrix(0.4627878,0,0,-5.402269,346.01282,-1753.521)" />
+ <g
+ id="g3971"
+ transform="translate(328.9625,-22.190946)">
+ <polygon
+ style="fill:#ffad70;fill-opacity:1;stroke:none;stroke-width:0.1850972"
+ points="230,-432 138,-432 138,-390 230,-390 230,-432 "
+ id="polygon3958"
+ transform="matrix(1.8107217,0,0,1.0137258,-329.65122,830.47882)" />
+ <text
+ x="2.6476707"
+ y="418.79987"
+ style="font-size:17.98741913px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ id="text3960"
+ sodipodi:linespacing="125%">
+ <tspan
+ id="tspan3964"
+ y="418.79987"
+ x="2.6476688"
+ sodipodi:role="line">DefaultDeployer</tspan>
+ </text>
+ </g>
+ <g
+ id="g3976"
+ transform="translate(328.58482,33.210928)">
+ <polygon
+ style="fill:#ffad70;fill-opacity:1;stroke:none;stroke-width:0.1850972"
+ points="230,-432 138,-432 138,-390 230,-390 230,-432 "
+ id="polygon3978"
+ transform="matrix(1.8107217,0,0,1.0137258,-329.65122,830.47882)" />
+ <text
+ x="2.6476707"
+ y="418.79987"
+ style="font-size:17.98741913px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ id="text3980"
+ sodipodi:linespacing="125%">
+ <tspan
+ id="tspan3982"
+ y="418.79987"
+ x="2.6476722"
+ sodipodi:role="line">DefaultStarter</tspan>
+ </text>
+ </g>
+ <g
+ id="g3984"
+ transform="translate(329.29103,86.176108)">
+ <polygon
+ style="fill:#ffad70;fill-opacity:1;stroke:none;stroke-width:0.1850972"
+ points="230,-432 138,-432 138,-390 230,-390 230,-432 "
+ id="polygon3986"
+ transform="matrix(1.8107217,0,0,1.0137258,-329.65122,830.47882)" />
+ <text
+ x="2.6476707"
+ y="418.79987"
+ style="font-size:17.98741913px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ id="text3988"
+ sodipodi:linespacing="125%">
+ <tspan
+ id="tspan3990"
+ y="418.79987"
+ x="2.6476693"
+ sodipodi:role="line">DefaultStopper</tspan>
+ </text>
+ </g>
+ <g
+ id="g4003"
+ transform="translate(148.88088,-17.953732)">
+ <polygon
+ style="fill:#ffad70;fill-opacity:1;stroke:none;stroke-width:0.1850972"
+ points="230,-432 138,-432 138,-390 230,-390 230,-432 "
+ id="polygon3994"
+ transform="matrix(2.102414,0,0,1.0137258,-216.3303,986.86761)" />
+ <text
+ x="169.63997"
+ y="575.18866"
+ style="font-size:17.98741913px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ id="text3996"
+ sodipodi:linespacing="125%">
+ <tspan
+ id="tspan3998"
+ y="575.18866"
+ x="169.63997"
+ sodipodi:role="line">DefaultUndeployer</tspan>
+ </text>
+ </g>
+ <g
+ id="g4136"
+ transform="translate(163.00492,-10.846444)">
+ <polygon
+ transform="matrix(2.309669,0,0,3.2368503,-636.87384,1707.8548)"
+ id="polygon3927"
+ points="230,-432 138,-432 138,-390 230,-390 230,-432 "
+ style="fill:#70d9ff;fill-opacity:1;stroke:none;stroke-width:0.1850972" />
+ <text
+ sodipodi:linespacing="125%"
+ id="text3929"
+ style="font-size:17.98741913px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ y="331.32928"
+ x="-211.42046">
+ <tspan
+ id="tspan3933"
+ sodipodi:role="line"
+ x="-211.42046"
+ y="331.32928">Jetty Server</tspan>
+ </text>
+ <g
+ transform="translate(3.6339138,14.123438)"
+ id="g4042">
+ <rect
+ style="opacity:1;fill:#ffffff;fill-opacity:0.57352941;stroke:none;stroke-width:1.52362204;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect4033"
+ width="135.59087"
+ height="42.576458"
+ x="-282.93228"
+ y="367.66122"
+ ry="0" />
+ <text
+ x="-216.01076"
+ y="395.65521"
+ style="font-size:17.98741913px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ id="text4038"
+ sodipodi:linespacing="125%">
+ <tspan
+ y="395.65521"
+ x="-216.01076"
+ sodipodi:role="line"
+ id="tspan4040">Handler</tspan>
+ </text>
+ </g>
+ </g>
+ <path
+ sodipodi:nodetypes="cc"
+ id="path4027"
+ d="M 249.19086,394.86412 L 19.29742,380.32317"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 248.81318,455.59753 L 19.29742,388.44449"
+ id="path4047"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path4049"
+ d="M 249.5194,508.56271 L 19.29742,398.33131"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 236.80775,555.87827 L 19.29742,408.92435"
+ id="path4051"
+ sodipodi:nodetypes="cc" />
+ <text
+ transform="matrix(0.9979899,6.3372504e-2,-6.3372504e-2,0.9979899,0,0)"
+ id="text4053"
+ y="375.59882"
+ x="71.124741"
+ style="font-size:13.11166096px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="375.59882"
+ x="71.124741"
+ id="tspan4055"
+ sodipodi:role="line">Create/Add ContextHandler</tspan></text>
+ <text
+ transform="matrix(0.960082,0.2797186,-0.2797186,0.960082,0,0)"
+ id="text4061"
+ y="363.9259"
+ x="239.78268"
+ style="font-size:13.1116581px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="363.9259"
+ x="239.78268"
+ id="tspan4063"
+ sodipodi:role="line">Start Handler</tspan></text>
+ <text
+ transform="matrix(0.9021783,0.4313632,-0.4313632,0.9021783,0,0)"
+ id="text4065"
+ y="346.85672"
+ x="305.1987"
+ style="font-size:13.11165524px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="346.85672"
+ x="305.1987"
+ id="tspan4067"
+ sodipodi:role="line">Stop Handler</tspan></text>
+ <text
+ transform="matrix(0.8286045,0.5598344,-0.5598344,0.8286045,0,0)"
+ id="text4069"
+ y="324.38153"
+ x="358.96548"
+ style="font-size:13.1116581px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"
+ inkscape:transform-center-x="50.663071"
+ inkscape:transform-center-y="-52.951508"><tspan
+ y="324.38153"
+ x="358.96548"
+ id="tspan4071"
+ sodipodi:role="line">Remove Handler</tspan></text>
+ <path
+ sodipodi:nodetypes="cc"
+ id="path4073"
+ d="M 384.24468,305.40822 C 415.02857,303.94581 422.97175,327.74882 428.85613,353.36389"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99881887;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ transform="matrix(0.8492228,0.5280347,-0.5280347,0.8492228,0,0)"
+ id="text4075"
+ y="38.223793"
+ x="494.58685"
+ style="font-size:13.11166382px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"
+ inkscape:transform-center-x="-244.6352"
+ inkscape:transform-center-y="-504.72461"><tspan
+ y="38.223793"
+ x="494.58685"
+ sodipodi:role="line"
+ id="tspan4079">Process Phases</tspan></text>
+ <text
+ sodipodi:linespacing="125%"
+ id="text4094"
+ style="font-size:24.99049759px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ y="-423.87344"
+ x="420.23651"
+ transform="matrix(0,1,-1,0,0,0)">
+ <tspan
+ sodipodi:role="line"
+ id="tspan4096"
+ x="420.23651"
+ y="-423.87344">Lifecycle</tspan>
+ </text>
+ <text
+ transform="matrix(1,1.6038357e-4,-1.6038357e-4,1,0,0)"
+ id="text2579"
+ y="228.70334"
+ x="180.83775"
+ style="font-size:13.11166191px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"
+ inkscape:transform-center-x="-17.522216"
+ inkscape:transform-center-y="1.6854193"><tspan
+ y="228.70334"
+ x="180.83775"
+ sodipodi:role="line"
+ id="tspan3922">App</tspan></text>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.00542861;stroke-linecap:butt;stroke-linejoin:miter;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 246.54365,283.59124 L 246.279,212.30268"
+ id="path2583"
+ sodipodi:nodetypes="cc" />
+ <text
+ transform="matrix(1,1.6038357e-4,-1.6038357e-4,1,0,0)"
+ id="text3912"
+ y="228.69254"
+ x="248.14288"
+ style="font-size:13.11166191px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"
+ inkscape:transform-center-x="-17.522216"
+ inkscape:transform-center-y="1.6854193"><tspan
+ y="228.69254"
+ x="248.14288"
+ sodipodi:role="line"
+ id="tspan3916">Start</tspan><tspan
+ y="245.08211"
+ x="248.14288"
+ sodipodi:role="line"
+ id="tspan3920">Stop</tspan></text>
+ <text
+ transform="matrix(1,1.6038357e-4,-1.6038357e-4,1,0,0)"
+ id="text3926"
+ y="228.6776"
+ x="341.29437"
+ style="font-size:13.11166191px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"
+ inkscape:transform-center-x="-17.522216"
+ inkscape:transform-center-y="1.6854193"><tspan
+ y="228.6776"
+ x="341.29437"
+ sodipodi:role="line"
+ id="tspan3928">App</tspan></text>
+</svg>
diff --git a/jetty-deploy-manager-graph/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/DeploymentManager_Roles.png b/jetty-deploy-manager-graph/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/DeploymentManager_Roles.png
new file mode 100644
index 0000000..4b96a6b
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/DeploymentManager_Roles.png
Binary files differ
diff --git a/jetty-deploy-manager-graph/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/DeploymentManager_Roles.svg b/jetty-deploy-manager-graph/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/DeploymentManager_Roles.svg
new file mode 100644
index 0000000..7185759
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/DeploymentManager_Roles.svg
@@ -0,0 +1,389 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generated by Graphviz version 2.20.2 (Mon Mar 30 10:11:53 UTC 2009)
+ For user: (joakim) Joakim Erdfelt,,, -->
+<!-- Title: G Pages: 1 -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="439.37006"
+ height="729.92126"
+ viewBox="0 0 327 590"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="DeploymentManager Roles.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ version="1.0"
+ inkscape:export-filename="/home/joakim/code/webtide/jetty7-git/sandbox/jetty-deploy-manager/src/main/javadoc/org/eclipse/jetty/deploy/doc-files/DeploymentManager_Roles.png"
+ inkscape:export-xdpi="40"
+ inkscape:export-ydpi="40">
+ <metadata
+ id="metadata184">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs182">
+ <linearGradient
+ id="linearGradient3424">
+ <stop
+ style="stop-color:#ff7107;stop-opacity:1;"
+ offset="0"
+ id="stop3426" />
+ <stop
+ style="stop-color:#ffeee0;stop-opacity:1;"
+ offset="1"
+ id="stop3428" />
+ </linearGradient>
+ <marker
+ inkscape:stockid="Arrow2Lstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lstart"
+ style="overflow:visible">
+ <path
+ id="path4328"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z"
+ transform="matrix(1.1,0,0,1.1,1.1,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lend"
+ style="overflow:visible">
+ <path
+ id="path3605"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="TriangleOutL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="TriangleOutL"
+ style="overflow:visible">
+ <path
+ id="path3727"
+ d="M 5.77,0 L -2.88,5 L -2.88,-5 L 5.77,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="scale(0.8,0.8)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lend"
+ style="overflow:visible">
+ <path
+ id="path3587"
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 368.75 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="408.75 : 368.75 : 1"
+ inkscape:persp3d-origin="204.375 : 245.83333 : 1"
+ id="perspective186" />
+ <title
+ id="title5">G</title>
+ <title
+ id="title10">incoming_app</title>
+ <title
+ id="title17">command_deploy</title>
+ <title
+ id="title33">state_deployed</title>
+ </defs>
+ <sodipodi:namedview
+ inkscape:window-height="1151"
+ inkscape:window-width="1920"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="1"
+ guidetolerance="10"
+ gridtolerance="10.0"
+ objecttolerance="13"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:zoom="1"
+ inkscape:cx="261.1181"
+ inkscape:cy="392.53714"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:current-layer="svg2"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:document-units="cm"
+ units="cm"
+ inkscape:snap-guide="true"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="false"
+ inkscape:bbox-nodes="false"
+ inkscape:snap-intersection-line-segments="true"
+ inkscape:object-paths="true"
+ inkscape:object-nodes="true"
+ inkscape:snap-center="false">
+ <inkscape:grid
+ type="xygrid"
+ id="grid3514"
+ dotted="true"
+ visible="true"
+ enabled="true"
+ units="cm"
+ spacingx="0.25cm"
+ spacingy="0.25cm"
+ empspacing="5" />
+ </sodipodi:namedview>
+ <g
+ id="g4043"
+ transform="matrix(1.1578745,0,0,1.1578745,-22.605787,-30.429653)">
+ <g
+ transform="translate(6.2287521,5.1906208)"
+ id="g3432">
+ <rect
+ style="opacity:1;fill:#ff984b;fill-opacity:1;stroke:none;stroke-width:1.52362204;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2582"
+ width="271.29678"
+ height="108.65714"
+ x="18.959866"
+ y="223.19566"
+ ry="46.920952"
+ rx="50.806107" />
+ <text
+ sodipodi:linespacing="125%"
+ id="text3275"
+ style="font-size:25.83806229px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans Bold"
+ y="268.40268"
+ x="153.72513">
+ <tspan
+ sodipodi:role="line"
+ id="tspan3277"
+ x="153.72513"
+ y="268.40268">Deployment</tspan>
+ <tspan
+ sodipodi:role="line"
+ x="153.72513"
+ y="300.70026"
+ id="tspan3378">Manager</tspan>
+ </text>
+ </g>
+ <g
+ transform="translate(62.97961,2.9413488)"
+ id="g3418">
+ <rect
+ rx="20.920155"
+ ry="46.920952"
+ y="347.77072"
+ x="-37.790993"
+ height="47.75378"
+ width="119.23236"
+ id="rect3380"
+ style="opacity:1;fill:#ffd7b9;fill-opacity:1;stroke:none;stroke-width:1.52362204;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <text
+ x="21.438501"
+ y="366.92834"
+ style="font-size:17.21594238px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:110.00000238%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ id="text3382"
+ sodipodi:linespacing="110%">
+ <tspan
+ id="tspan3386"
+ y="366.92834"
+ x="21.438501"
+ sodipodi:role="line">Bind</tspan>
+ <tspan
+ y="385.86588"
+ x="21.438503"
+ sodipodi:role="line"
+ id="tspan3390">Lifecycle</tspan>
+ </text>
+ </g>
+ <g
+ transform="translate(2.1078682,5.3948095)"
+ id="g3412">
+ <rect
+ style="opacity:1;fill:#ffd7b9;fill-opacity:1;stroke:none;stroke-width:1.52362204;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3392"
+ width="119.23236"
+ height="47.75378"
+ x="175.14517"
+ y="345.31726"
+ ry="46.920952"
+ rx="20.920155" />
+ <text
+ sodipodi:linespacing="110%"
+ id="text3394"
+ style="font-size:17.21594238px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:110.00000238%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ y="364.21011"
+ x="234.37466">
+ <tspan
+ sodipodi:role="line"
+ x="234.37466"
+ y="364.21011"
+ id="tspan3396">Use</tspan>
+ <tspan
+ id="tspan3398"
+ sodipodi:role="line"
+ x="234.37466"
+ y="383.14764">Lifecycle</tspan>
+ </text>
+ </g>
+ <rect
+ style="opacity:1;fill:#ffd970;fill-opacity:1;stroke:none;stroke-width:1.52362204;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3400"
+ width="271.29678"
+ height="108.65714"
+ x="25.188618"
+ y="412.13449"
+ ry="46.920952"
+ rx="50.806107" />
+ <text
+ sodipodi:linespacing="125%"
+ id="text3402"
+ style="font-size:25.83806229px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans Bold"
+ y="458.72568"
+ x="159.2618">
+ <tspan
+ sodipodi:role="line"
+ x="159.2618"
+ y="458.72568"
+ id="tspan3406">Deployment</tspan>
+ <tspan
+ id="tspan3410"
+ sodipodi:role="line"
+ x="159.2618"
+ y="491.02325">Lifecycle</tspan>
+ </text>
+ <g
+ transform="translate(6.2287521,-178.55759)"
+ id="g3438">
+ <rect
+ rx="50.806107"
+ ry="46.920952"
+ y="223.19566"
+ x="18.959866"
+ height="108.65714"
+ width="271.29678"
+ id="rect3440"
+ style="opacity:1;fill:#d5ff70;fill-opacity:1;stroke:none;stroke-width:1.52362204;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <text
+ x="153.72513"
+ y="268.40268"
+ style="font-size:25.83806229px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans Bold"
+ id="text3442"
+ sodipodi:linespacing="125%">
+ <tspan
+ id="tspan3446"
+ y="268.40268"
+ x="153.72513"
+ sodipodi:role="line">App</tspan>
+ <tspan
+ id="tspan3450"
+ y="300.70026"
+ x="153.72513"
+ sodipodi:role="line">Provider</tspan>
+ </text>
+ </g>
+ <g
+ id="g3452"
+ transform="translate(62.97961,-180.80686)">
+ <rect
+ style="opacity:1;fill:#ffd7b9;fill-opacity:1;stroke:none;stroke-width:1.52362204;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3454"
+ width="119.23236"
+ height="47.75378"
+ x="-37.790993"
+ y="347.77072"
+ ry="46.920952"
+ rx="20.920155" />
+ <text
+ sodipodi:linespacing="110%"
+ id="text3456"
+ style="font-size:17.21594238px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:110.00000238%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ y="366.92834"
+ x="21.438501">
+ <tspan
+ id="tspan3478"
+ sodipodi:role="line"
+ x="21.438499"
+ y="366.92834">Manage</tspan>
+ <tspan
+ id="tspan3482"
+ sodipodi:role="line"
+ x="21.438501"
+ y="385.86588">Provider</tspan>
+ </text>
+ </g>
+ <g
+ transform="translate(215.04403,-180.80686)"
+ id="g3462">
+ <rect
+ rx="20.920155"
+ ry="46.920952"
+ y="347.77072"
+ x="-37.790993"
+ height="47.75378"
+ width="119.23236"
+ id="rect3464"
+ style="opacity:1;fill:#ffd7b9;fill-opacity:1;stroke:none;stroke-width:1.52362204;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <text
+ x="21.438501"
+ y="366.92834"
+ style="font-size:17.21594238px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:110.00000238%;writing-mode:lr-tb;text-anchor:middle;font-family:Sans;-inkscape-font-specification:Sans"
+ id="text3466"
+ sodipodi:linespacing="110%">
+ <tspan
+ y="366.92834"
+ x="21.438503"
+ sodipodi:role="line"
+ id="tspan3470">Process</tspan>
+ <tspan
+ id="tspan3474"
+ y="385.86588"
+ x="21.438499"
+ sodipodi:role="line">App</tspan>
+ </text>
+ </g>
+ <path
+ style="opacity:0.61261262;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.86833984;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 195.13829,151.79607 L 195.13829,229.04598"
+ id="path4023"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="opacity:0.61261262;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.86833984;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 127.84895,230.68829 L 127.84895,153.43838"
+ id="path4037"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="opacity:0.61261262;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.86833984;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 195.13829,335.87758 L 195.13829,413.12749"
+ id="path4039"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="opacity:0.61261262;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.86833984;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 127.84895,335.87758 L 127.84895,413.12749"
+ id="path4041"
+ sodipodi:nodetypes="cc" />
+ </g>
+</svg>
diff --git a/jetty-deploy-manager-graph/src/main/javadoc/overview.html b/jetty-deploy-manager-graph/src/main/javadoc/overview.html
new file mode 100644
index 0000000..689d4f4
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/javadoc/overview.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+ <HEAD>
+ <TITLE>Jetty DeploymentManager API Overview</TITLE>
+ </HEAD>
+ <BODY>
+ Short overview of the API.
+ </BODY>
+</HTML>
diff --git a/jetty-deploy-manager-graph/src/main/resources/org/eclipse/jetty/deploy/lifecycle-bindings.txt b/jetty-deploy-manager-graph/src/main/resources/org/eclipse/jetty/deploy/lifecycle-bindings.txt
new file mode 100644
index 0000000..ed00104
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/main/resources/org/eclipse/jetty/deploy/lifecycle-bindings.txt
@@ -0,0 +1 @@
+# Default Bindings
\ No newline at end of file
diff --git a/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/AppLifecycleTest.java b/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/AppLifecycleTest.java
new file mode 100644
index 0000000..7451db4
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/AppLifecycleTest.java
@@ -0,0 +1,217 @@
+// ========================================================================
+// 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.List;
+
+import org.eclipse.jetty.deploy.graph.Node;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Just an overly picky test case to validate the potential paths.
+ */
+public class AppLifecycleTest
+{
+ private void assertNoPath(String from, String to)
+ {
+ assertPath(from,to,new ArrayList<String>());
+ }
+
+ private void assertPath(AppLifecycle lifecycle, String from, String to, List<String> expected)
+ {
+ Node fromNode = lifecycle.getNodeByName(from);
+ Node toNode = lifecycle.getNodeByName(to);
+ List<Node> actual = lifecycle.findPath(fromNode,toNode);
+ String msg = "Lifecycle.path from " + from + " to " + to;
+ Assert.assertNotNull(msg + " should never be null",actual);
+
+ if (expected.size() != actual.size())
+ {
+ System.out.println();
+ System.out.printf("/* from '%s' -> '%s' */%n",from,to);
+ System.out.println("/* Expected Path */");
+ for (String path : expected)
+ {
+ System.out.println(path);
+ }
+ System.out.println("/* Actual Path */");
+ for (Node path : actual)
+ {
+ System.out.println(path.getName());
+ }
+
+ Assert.assertEquals(msg + " / count",expected.size(),actual.size());
+ }
+
+ for (int i = 0, n = expected.size(); i < n; i++)
+ {
+ Assert.assertEquals(msg + "[" + i + "]",expected.get(i),actual.get(i).getName());
+ }
+ }
+
+ private void assertPath(String from, String to, List<String> expected)
+ {
+ AppLifecycle lifecycle = new AppLifecycle();
+ assertPath(lifecycle,from,to,expected);
+ }
+
+ @Test
+ public void testFindPath_Deployed_Deployed()
+ {
+ assertNoPath("deployed","deployed");
+ }
+
+ @Test
+ public void testFindPath_Deployed_Started()
+ {
+ List<String> expected = new ArrayList<String>();
+ expected.add("deployed");
+ expected.add("pre-starting");
+ expected.add("starting");
+ expected.add("started");
+ assertPath("deployed","started",expected);
+ }
+
+ @Test
+ public void testFindPath_Deployed_Undeployed()
+ {
+ List<String> expected = new ArrayList<String>();
+ expected.add("deployed");
+ expected.add("pre-undeploying");
+ expected.add("undeploying");
+ expected.add("undeployed");
+ assertPath("deployed","undeployed",expected);
+ }
+
+ @Test
+ public void testFindPath_Started_Deployed()
+ {
+ List<String> expected = new ArrayList<String>();
+ expected.add("started");
+ expected.add("pre-stopping");
+ expected.add("stopping");
+ expected.add("deployed");
+ assertPath("started","deployed",expected);
+ }
+
+ @Test
+ public void testFindPath_Started_Started()
+ {
+ assertNoPath("started","started");
+ }
+
+ @Test
+ public void testFindPath_Started_Undeployed()
+ {
+ List<String> expected = new ArrayList<String>();
+ expected.add("started");
+ expected.add("pre-stopping");
+ expected.add("stopping");
+ expected.add("deployed");
+ expected.add("pre-undeploying");
+ expected.add("undeploying");
+ expected.add("undeployed");
+ assertPath("started","undeployed",expected);
+ }
+
+ @Test
+ public void testFindPath_Undeployed_Deployed()
+ {
+ List<String> expected = new ArrayList<String>();
+ expected.add("undeployed");
+ expected.add("pre-deploying");
+ expected.add("deploying");
+ expected.add("deployed");
+ assertPath("undeployed","deployed",expected);
+ }
+
+ @Test
+ public void testFindPath_Undeployed_Started()
+ {
+ List<String> expected = new ArrayList<String>();
+ expected.add("undeployed");
+ expected.add("pre-deploying");
+ expected.add("deploying");
+ expected.add("deployed");
+ expected.add("pre-starting");
+ expected.add("starting");
+ expected.add("started");
+ assertPath("undeployed","started",expected);
+ }
+
+ @Test
+ public void testFindPath_Undeployed_Uavailable()
+ {
+ assertNoPath("undeployed","undeployed");
+ }
+
+ /**
+ * Request multiple lifecycle paths with a single lifecycle instance. Just to ensure that there is no state
+ * maintained between {@link AppLifecycle#findPath(Node, Node)} requests.
+ */
+ @Test
+ public void testFindPathMultiple()
+ {
+ AppLifecycle lifecycle = new AppLifecycle();
+ List<String> expected = new ArrayList<String>();
+
+ lifecycle.removeEdge("deployed","pre-starting");
+ lifecycle.addEdge("deployed","staging");
+ lifecycle.addEdge("staging","staged");
+ lifecycle.addEdge("staged","pre-starting");
+
+ // Deployed -> Deployed
+ expected.clear();
+ assertPath(lifecycle,"deployed","deployed",expected);
+
+ // Deployed -> Staged
+ expected.clear();
+ expected.add("deployed");
+ expected.add("staging");
+ expected.add("staged");
+ assertPath(lifecycle,"deployed","staged",expected);
+
+ // Staged -> Undeployed
+ expected.clear();
+ expected.add("staged");
+ expected.add("pre-starting");
+ expected.add("starting");
+ expected.add("started");
+ expected.add("pre-stopping");
+ expected.add("stopping");
+ expected.add("deployed");
+ expected.add("pre-undeploying");
+ expected.add("undeploying");
+ expected.add("undeployed");
+ assertPath(lifecycle,"staged","undeployed",expected);
+
+ // Undeployed -> Started
+ expected.clear();
+ expected.add("undeployed");
+ expected.add("pre-deploying");
+ expected.add("deploying");
+ expected.add("deployed");
+ expected.add("staging");
+ expected.add("staged");
+ expected.add("pre-starting");
+ expected.add("starting");
+ expected.add("started");
+ assertPath(lifecycle,"undeployed","started",expected);
+ }
+
+}
diff --git a/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/DeploymentManagerLifecyclePathTest.java b/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/DeploymentManagerLifecyclePathTest.java
new file mode 100644
index 0000000..bebc413
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/DeploymentManagerLifecyclePathTest.java
@@ -0,0 +1,66 @@
+// ========================================================================
+// 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.List;
+import org.eclipse.jetty.deploy.graph.Node;
+import org.junit.Test;
+
+public class DeploymentManagerLifecyclePathTest
+{
+ @Test
+ public void testStateTransition_NewToDeployed()
+ {
+ LifecycleOrderTracker pathtracker = new LifecycleOrderTracker();
+ DeploymentManager depman = new DeploymentManager();
+ depman.addLifecycleBinding(pathtracker);
+ App app = new MockApp();
+
+ // Pretend to AppProvider ...
+ depman.addApp(app);
+
+ // Request Deploy of App
+ depman.requestAppGoal(app.getId(),"deployed");
+
+ // Setup Expectations.
+ List<Node> expectedOrder = new ArrayList<Node>();
+ expectedOrder.add(new Node("pre-deploying"));
+ expectedOrder.add(new Node("deploying"));
+ expectedOrder.add(new Node("deployed"));
+
+ pathtracker.assertExpected("Test StateTransition / New -> Deployed",expectedOrder);
+ }
+
+ @Test
+ public void testStateTransition_Receive()
+ {
+ LifecycleOrderTracker pathtracker = new LifecycleOrderTracker();
+ DeploymentManager depman = new DeploymentManager();
+ depman.addLifecycleBinding(pathtracker);
+ App app = new MockApp();
+
+ // Pretend to AppProvider
+ depman.addApp(app);
+
+ // Perform no goal request.
+
+ // Setup Expectations.
+ List<Node> expectedOrder = new ArrayList<Node>();
+
+ pathtracker.assertExpected("Test StateTransition / New only",expectedOrder);
+ }
+}
diff --git a/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/DeploymentManagerTest.java b/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/DeploymentManagerTest.java
new file mode 100644
index 0000000..d334fd2
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/DeploymentManagerTest.java
@@ -0,0 +1,81 @@
+package org.eclipse.jetty.deploy;
+
+import java.util.Collection;
+import java.util.Set;
+
+import org.eclipse.jetty.deploy.test.XmlConfiguredJetty;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class DeploymentManagerTest
+{
+ @Test
+ public void testReceiveApp()
+ {
+ LifecycleOrderTracker pathtracker = new LifecycleOrderTracker();
+ DeploymentManager depman = new DeploymentManager();
+ depman.addLifecycleBinding(pathtracker);
+ App app = new MockApp();
+
+ // Pretend to be AppProvider ...
+ depman.addApp(app);
+
+ // Test app tracking
+ Collection<App> apps = depman.getApps();
+ Assert.assertNotNull("Should never be null",apps);
+ Assert.assertEquals("Expected App Count",1,apps.size());
+
+ // Test app get
+ App actual = depman.getApp("mock-app");
+ Assert.assertNotNull("Should have gotten app (by id)",actual);
+ Assert.assertEquals("Should have gotten app (by id)",app.getId(),actual.getId());
+ }
+
+ @Test
+ public void testBinding()
+ {
+ LifecycleOrderTracker pathtracker = new LifecycleOrderTracker();
+ DeploymentManager depman = new DeploymentManager();
+ depman.addLifecycleBinding(pathtracker);
+
+ Set<Object> allbindings = depman.getLifecycle().getBindings();
+ Assert.assertNotNull("All Bindings should never be null",allbindings);
+ Assert.assertEquals("All Bindings.size",1,allbindings.size());
+
+ Set<Object> deploybindings = depman.getLifecycle().getBindings("deploying");
+ Assert.assertNotNull("'deploying' Bindings should not be null",deploybindings);
+ Assert.assertEquals("'deploying' Bindings.size",1,deploybindings.size());
+ }
+
+ @Test
+ public void testXmlConfigured() throws Exception
+ {
+ XmlConfiguredJetty jetty = null;
+ try
+ {
+ jetty = new XmlConfiguredJetty();
+ jetty.addConfiguration("jetty.xml");
+ jetty.addConfiguration("jetty-deploymgr-contexts.xml");
+
+ // Should not throw an Exception
+ jetty.load();
+
+ // Start it
+ jetty.start();
+ }
+ finally
+ {
+ if (jetty != null)
+ {
+ try
+ {
+ jetty.stop();
+ }
+ catch (Exception ignore)
+ {
+ // ignore
+ }
+ }
+ }
+ }
+}
diff --git a/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/LifecycleOrderTracker.java b/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/LifecycleOrderTracker.java
new file mode 100644
index 0000000..f8cbd65
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/LifecycleOrderTracker.java
@@ -0,0 +1,71 @@
+// ========================================================================
+// 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.List;
+
+import org.eclipse.jetty.deploy.annotations.DeployLifecycleBinding;
+import org.eclipse.jetty.deploy.graph.Node;
+import org.junit.Assert;
+
+/**
+ * Binds to all lifecycle nodes, and tracks the order of the lifecycle nodes for testing purposes.
+ */
+public class LifecycleOrderTracker
+{
+ List<Node> actualOrder = new ArrayList<Node>();
+
+ public void clear()
+ {
+ actualOrder.clear();
+ }
+
+ public List<Node> getCapturedPath()
+ {
+ return actualOrder;
+ }
+
+ @DeployLifecycleBinding(nodes = "*")
+ public void handleAppDeploy(Node node, App app, DeploymentManager depmgr)
+ {
+ actualOrder.add(node);
+ }
+
+ public void assertExpected(String msg, List<Node> expectedOrder)
+ {
+ if (expectedOrder.size() != actualOrder.size())
+ {
+ System.out.println("/* Expected Path */");
+ for (Node path : expectedOrder)
+ {
+ System.out.println(path);
+ }
+ System.out.println("/* Actual Path */");
+ for (Node path : actualOrder)
+ {
+ System.out.println(path);
+ }
+
+ Assert.assertEquals(msg + " / count",0,actualOrder.size());
+ }
+
+ for (int i = 0, n = expectedOrder.size(); i < n; i++)
+ {
+ Assert.assertEquals(msg + "[" + i + "]",expectedOrder.get(i),actualOrder.get(i));
+ }
+ }
+}
diff --git a/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/MockApp.java b/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/MockApp.java
new file mode 100644
index 0000000..123b66d
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/MockApp.java
@@ -0,0 +1,53 @@
+// ========================================================================
+// 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.io.File;
+
+import org.eclipse.jetty.server.handler.ContextHandler;
+
+public class MockApp implements App
+{
+ public ContextHandler getContextHandler(DeploymentManager deployMgr)
+ {
+ return null;
+ }
+
+ public File getDir()
+ {
+ return null;
+ }
+
+ public String getId()
+ {
+ return "mock-app";
+ }
+
+ public String getName()
+ {
+ return "Mock App";
+ }
+
+ public String getOrigin()
+ {
+ return "Test Cases";
+ }
+
+ public File getWorkDir()
+ {
+ return null;
+ }
+}
diff --git a/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/providers/ContextsDirAppProviderTest.java b/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/providers/ContextsDirAppProviderTest.java
new file mode 100644
index 0000000..743edb9
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/providers/ContextsDirAppProviderTest.java
@@ -0,0 +1,75 @@
+// ========================================================================
+// 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.providers;
+
+import org.eclipse.jetty.deploy.test.XmlConfiguredJetty;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.HandlerCollection;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class ContextsDirAppProviderTest
+{
+ private static XmlConfiguredJetty jetty;
+
+ @BeforeClass
+ public static void setupEnvironment() throws Exception
+ {
+ jetty = new XmlConfiguredJetty();
+ jetty.addConfiguration("jetty.xml");
+ jetty.addConfiguration("jetty-deploymgr-contexts.xml");
+
+ // Should not throw an Exception
+ jetty.load();
+
+ // Start it
+ jetty.start();
+ }
+
+ @AfterClass
+ public static void teardownEnvironment() throws Exception
+ {
+ // Stop jetty.
+ jetty.stop();
+ }
+
+ @Test
+ public void testFindContext()
+ {
+ // Check Server for Handlers
+ Server server = jetty.getServer();
+ Handler handler = server.getHandler();
+ System.out.println("handler: " + handler);
+
+ if (handler instanceof HandlerCollection)
+ {
+ System.out.printf("Handler Collection (child-handlers:%s - handlers:%d)%n",((HandlerCollection)handler).getChildHandlers().length,
+ ((HandlerCollection)handler).getHandlers().length);
+ System.out.println("is a HandlerCollection: " + ((HandlerCollection)handler).dump());
+ }
+
+ // TODO: verify that handler was created for context.
+ }
+
+ // TODO: write test that adds new app (after startup).
+
+ // TODO: write test that adds new app (after startup), then removes it from filesystem (resulting in removed from handlers).
+
+ // TODO: write test that adds new app (after startup), then updates it (redeploy).
+
+}
diff --git a/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/test/MavenTestingUtils.java b/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/test/MavenTestingUtils.java
new file mode 100644
index 0000000..b8339c7
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/test/MavenTestingUtils.java
@@ -0,0 +1,219 @@
+// ========================================================================
+// 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.test;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+import org.eclipse.jetty.util.IO;
+
+/**
+ * Common utility methods for working with JUnit tests cases in a maven friendly way.
+ */
+public class MavenTestingUtils
+{
+ private static File basedir;
+ private static File testResourcesDir;
+ private static File targetDir;
+
+ // private static Boolean surefireRunning;
+
+ public static File getBasedir()
+ {
+ if (basedir == null)
+ {
+ String cwd = System.getProperty("basedir");
+
+ if (cwd == null)
+ {
+ cwd = System.getProperty("user.dir");
+ }
+
+ basedir = new File(cwd);
+ }
+
+ return basedir;
+ }
+
+ /**
+ * Get the directory to the /target directory for this project.
+ *
+ * @return the directory path to the target directory.
+ */
+ public static File getTargetDir()
+ {
+ if (targetDir == null)
+ {
+ targetDir = new File(basedir,"target");
+ PathAssert.assertDirExists("Target Dir",targetDir);
+ }
+ return targetDir;
+ }
+
+ /**
+ * Create a {@link File} object for a path in the /target directory.
+ *
+ * @param path
+ * the path desired, no validation of existence is performed.
+ * @return the File to the path.
+ */
+ public static File getTargetFile(String path)
+ {
+ return new File(getTargetDir(),path.replace("/",File.separator));
+ }
+
+ public static File getTargetTestingDir()
+ {
+ File dir = new File(getTargetDir(),"testing");
+ if (!dir.exists())
+ {
+ dir.mkdirs();
+ }
+ return dir;
+ }
+
+ /**
+ * Get a dir in /target/ that uses the JUnit 3.x {@link TestCase#getName()} to make itself unique.
+ *
+ * @param test
+ * the junit 3.x testcase to base this new directory on.
+ * @return
+ */
+ public static File getTargetTestingDir(TestCase test)
+ {
+ return getTargetTestingDir(test.getName());
+ }
+
+ /**
+ * Get a dir in /target/ that uses the an arbitrary name.
+ *
+ * @param testname
+ * the testname to create directory against.
+ * @return
+ */
+ public static File getTargetTestingDir(String testname)
+ {
+ File dir = new File(getTargetDir(),"test-" + testname);
+ if (!dir.exists())
+ {
+ dir.mkdirs();
+ }
+ return dir;
+ }
+
+ /**
+ * Get a dir from the src/test/resource directory.
+ *
+ * @param name
+ * the name of the path to get (it must exist as a dir)
+ * @return the dir in src/test/resource
+ */
+ public static File getTestResourceDir(String name)
+ {
+ File dir = new File(getTestResourcesDir(),name);
+ PathAssert.assertDirExists("Test Resource Dir",dir);
+ return dir;
+ }
+
+ /**
+ * Get a file from the src/test/resource directory.
+ *
+ * @param name
+ * the name of the path to get (it must exist as a file)
+ * @return the file in src/test/resource
+ */
+ public static File getTestResourceFile(String name)
+ {
+ File file = new File(getTestResourcesDir(),name);
+ PathAssert.assertFileExists("Test Resource File",file);
+ return file;
+ }
+
+ /**
+ * Get a path resource (File or Dir) from the src/test/resource directory.
+ *
+ * @param name
+ * the name of the path to get (it must exist)
+ * @return the path in src/test/resource
+ */
+ public static File getTestResourcePath(String name)
+ {
+ File path = new File(getTestResourcesDir(),name);
+ PathAssert.assertExists("Test Resource Path",path);
+ return path;
+ }
+
+ /**
+ * Get the directory to the src/test/resource directory
+ *
+ * @return the directory {@link File} to the src/test/resources directory
+ */
+ public static File getTestResourcesDir()
+ {
+ if (testResourcesDir == null)
+ {
+ testResourcesDir = new File(basedir,"src/test/resources".replace("/",File.separator));
+ PathAssert.assertDirExists("Test Resources Dir",testResourcesDir);
+ }
+ return testResourcesDir;
+ }
+
+ /**
+ * Read the contents of a file into a String and return it.
+ *
+ * @param file
+ * the file to read.
+ * @return the contents of the file.
+ * @throws IOException
+ * if unable to read the file.
+ */
+ public static String readToString(File file) throws IOException
+ {
+ FileReader reader = null;
+ try
+ {
+ reader = new FileReader(file);
+ return IO.toString(reader);
+ }
+ finally
+ {
+ IO.close(reader);
+ }
+ }
+
+ /*
+ public static boolean isSurefireExecuting()
+ {
+ if (surefireRunning == null)
+ {
+ String val = System.getProperty("surefire.test.class.path");
+ if (val != null)
+ {
+ surefireRunning = Boolean.TRUE;
+ }
+ else
+ {
+ surefireRunning = Boolean.FALSE;
+ }
+ }
+
+ return surefireRunning;
+ }
+ */
+}
diff --git a/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/test/PathAssert.java b/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/test/PathAssert.java
new file mode 100644
index 0000000..7b4af5e
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/test/PathAssert.java
@@ -0,0 +1,40 @@
+// ========================================================================
+// 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.test;
+
+import java.io.File;
+
+import junit.framework.Assert;
+
+public class PathAssert
+{
+ public static void assertDirExists(String msg, File path)
+ {
+ assertExists(msg,path);
+ Assert.assertTrue(msg + " path should be a Dir : " + path.getAbsolutePath(),path.isDirectory());
+ }
+
+ public static void assertFileExists(String msg, File path)
+ {
+ assertExists(msg,path);
+ Assert.assertTrue(msg + " path should be a File : " + path.getAbsolutePath(),path.isFile());
+ }
+
+ public static void assertExists(String msg, File path)
+ {
+ Assert.assertTrue(msg + " path should exist: " + path.getAbsolutePath(),path.exists());
+ }
+}
diff --git a/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/test/XmlConfiguredJetty.java b/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/test/XmlConfiguredJetty.java
new file mode 100644
index 0000000..90fc9e4
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/test/java/org/eclipse/jetty/deploy/test/XmlConfiguredJetty.java
@@ -0,0 +1,215 @@
+// ========================================================================
+// 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.test;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import org.eclipse.jetty.http.HttpSchemes;
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.util.IO;
+import org.eclipse.jetty.xml.XmlConfiguration;
+import org.junit.Assert;
+
+/**
+ * Allows for setting up a Jetty server for testing based on XML configuration files.
+ */
+public class XmlConfiguredJetty
+{
+ private List<URL> xmlConfigurations;
+ private Properties properties = new Properties();
+ private Server server;
+ private int serverPort;
+ private String scheme = HttpSchemes.HTTP;
+
+ public XmlConfiguredJetty() throws IOException
+ {
+ String testname = new Throwable().getStackTrace()[1].getClassName();
+
+ xmlConfigurations = new ArrayList<URL>();
+ properties = new Properties();
+
+ File jettyHome = MavenTestingUtils.getTargetTestingDir(testname);
+ // Prepare Jetty.Home (Test) dir
+ jettyHome.mkdirs();
+
+ File logsDir = new File(jettyHome,"logs");
+ logsDir.mkdirs();
+
+ File etcDir = new File(jettyHome,"etc");
+ etcDir.mkdirs();
+ IO.copyFile(MavenTestingUtils.getTestResourceFile("etc/realm.properties"),new File(etcDir,"realm.properties"));
+
+ File webappsDir = new File(jettyHome,"webapps");
+ webappsDir.mkdirs();
+ File tmpDir = new File(MavenTestingUtils.getTargetTestingDir(testname),"tmp");
+ tmpDir.mkdirs();
+
+ // Setup properties
+ System.setProperty("java.io.tmpdir",tmpDir.getAbsolutePath());
+ properties.setProperty("jetty.home",jettyHome.getAbsolutePath());
+ System.setProperty("jetty.home",jettyHome.getAbsolutePath());
+ properties.setProperty("test.basedir",MavenTestingUtils.getBasedir().getAbsolutePath());
+ properties.setProperty("test.resourcesdir",MavenTestingUtils.getTestResourcesDir().getAbsolutePath());
+ properties.setProperty("test.webapps",MavenTestingUtils.getTestResourceDir("webapps").getAbsolutePath());
+ properties.setProperty("test.targetdir",MavenTestingUtils.getTargetDir().getAbsolutePath());
+
+ // Write out configuration for use by ConfigurationManager.
+ File testConfig = MavenTestingUtils.getTargetFile("xml-configured-jetty.properties");
+ FileOutputStream out = new FileOutputStream(testConfig);
+ properties.store(out,"Generated by " + XmlConfiguredJetty.class.getName());
+ }
+
+ public void addConfiguration(File xmlConfigFile) throws MalformedURLException
+ {
+ xmlConfigurations.add(xmlConfigFile.toURI().toURL());
+ }
+
+ public void addConfiguration(String testConfigName) throws MalformedURLException
+ {
+ addConfiguration(MavenTestingUtils.getTestResourceFile(testConfigName));
+ }
+
+ public void addConfiguration(URL xmlConfig)
+ {
+ xmlConfigurations.add(xmlConfig);
+ }
+
+ public String getScheme()
+ {
+ return scheme;
+ }
+
+ public Server getServer()
+ {
+ return server;
+ }
+
+ public int getServerPort()
+ {
+ return serverPort;
+ }
+
+ public URI getServerURI() throws UnknownHostException
+ {
+ StringBuffer uri = new StringBuffer();
+ uri.append(this.scheme).append("://");
+ uri.append(InetAddress.getLocalHost().getHostAddress());
+ uri.append(":").append(this.serverPort);
+ return URI.create(uri.toString());
+ }
+
+ @SuppressWarnings("unchecked")
+ public void load() throws Exception
+ {
+ XmlConfiguration last = null;
+ Object[] obj = new Object[this.xmlConfigurations.size()];
+
+ // Configure everything
+ for (int i = 0; i < this.xmlConfigurations.size(); i++)
+ {
+ URL configURL = this.xmlConfigurations.get(i);
+ XmlConfiguration configuration = new XmlConfiguration(configURL);
+ if (last != null)
+ {
+ configuration.getIdMap().putAll(last.getIdMap());
+ }
+ configuration.setProperties(properties);
+ obj[i] = configuration.configure();
+ last = configuration;
+ }
+
+ // Test for Server Instance.
+ Server foundServer = null;
+ int serverCount = 0;
+ for (int i = 0; i < this.xmlConfigurations.size(); i++)
+ {
+ if (obj[i] instanceof Server)
+ {
+ if (obj[i].equals(foundServer))
+ {
+ // Identical server instance found
+ break;
+ }
+ foundServer = (Server)obj[i];
+ serverCount++;
+ }
+ }
+
+ if (serverCount <= 0)
+ {
+ throw new Exception("Load failed to configure a " + Server.class.getName());
+ }
+
+ Assert.assertEquals("Server load count",1,serverCount);
+
+ this.server = foundServer;
+ this.server.setGracefulShutdown(10);
+
+ }
+
+ public void setProperty(String key, String value)
+ {
+ properties.setProperty(key,value);
+ }
+
+ public void setScheme(String scheme)
+ {
+ this.scheme = scheme;
+ }
+
+ public void start() throws Exception
+ {
+ Assert.assertNotNull("Server should not be null (failed load?)",server);
+
+ server.start();
+
+ // Find the active server port.
+ this.serverPort = (-1);
+ Connector connectors[] = server.getConnectors();
+ for (int i = 0; i < connectors.length; i++)
+ {
+ Connector connector = connectors[i];
+ if (connector.getLocalPort() > 0)
+ {
+ this.serverPort = connector.getLocalPort();
+ break;
+ }
+ }
+
+ Assert.assertTrue("Server Port is between 1 and 65535. Actually <" + serverPort + ">",(1 <= this.serverPort) && (this.serverPort <= 65535));
+
+ // Uncomment to have server start and continue to run (without exiting)
+ // System.out.printf("Listening to port %d%n",this.serverPort);
+ // server.join();
+ }
+
+ public void stop() throws Exception
+ {
+ server.stop();
+ }
+}
diff --git a/jetty-deploy-manager-graph/src/test/resources/contexts/logcommon.xml b/jetty-deploy-manager-graph/src/test/resources/contexts/logcommon.xml
new file mode 100644
index 0000000..6da9c12
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/test/resources/contexts/logcommon.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+ <Set name="contextPath">/logcommon</Set>
+ <Set name="war">
+ <Property name="test.webapps" default="." />/logcommon.war
+ </Set>
+</Configure>
diff --git a/jetty-deploy-manager-graph/src/test/resources/etc/realm.properties b/jetty-deploy-manager-graph/src/test/resources/etc/realm.properties
new file mode 100644
index 0000000..cbf905d
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/test/resources/etc/realm.properties
@@ -0,0 +1,21 @@
+#
+# This file defines users passwords and roles for a HashUserRealm
+#
+# The format is
+# <username>: <password>[,<rolename> ...]
+#
+# Passwords may be clear text, obfuscated or checksummed. The class
+# org.eclipse.util.Password should be used to generate obfuscated
+# passwords or password checksums
+#
+# If DIGEST Authentication is used, the password must be in a recoverable
+# format, either plain text or OBF:.
+#
+jetty: MD5:164c88b302622e17050af52c89945d44,user
+admin: CRYPT:adpexzg3FUZAk,server-administrator,content-administrator,admin
+other: OBF:1xmk1w261u9r1w1c1xmq,user
+plain: plain,user
+user: password,user
+
+# This entry is for digest auth. The credential is a MD5 hash of username:realmname:password
+digest: MD5:6e120743ad67abfbc385bc2bb754e297,user
diff --git a/jetty-deploy-manager-graph/src/test/resources/etc/webdefault.xml b/jetty-deploy-manager-graph/src/test/resources/etc/webdefault.xml
new file mode 100644
index 0000000..35a5a9b
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/test/resources/etc/webdefault.xml
@@ -0,0 +1,404 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!-- ===================================================================== -->
+<!-- This file contains the default descriptor for web applications. -->
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<!-- The intent of this descriptor is to include jetty specific or common -->
+<!-- configuration for all webapps. If a context has a webdefault.xml -->
+<!-- descriptor, it is applied before the contexts own web.xml file -->
+<!-- -->
+<!-- A context may be assigned a default descriptor by: -->
+<!-- + Calling WebApplicationContext.setDefaultsDescriptor -->
+<!-- + Passed an arg to addWebApplications -->
+<!-- -->
+<!-- This file is used both as the resource within the jetty.jar (which is -->
+<!-- used as the default if no explicit defaults descriptor is set) and it -->
+<!-- is copied to the etc directory of the Jetty distro and explicitly -->
+<!-- by the jetty.xml file. -->
+<!-- -->
+<!-- ===================================================================== -->
+<web-app
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+ metadata-complete="true"
+ version="2.5">
+
+ <description>
+ Default web.xml file.
+ This file is applied to a Web application before it's own WEB_INF/web.xml file
+ </description>
+
+
+ <!-- ==================================================================== -->
+ <!-- Context params to control Session Cookies -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <!-- UNCOMMENT TO ACTIVATE
+ <context-param>
+ <param-name>org.eclipse.jetty.servlet.SessionDomain</param-name>
+ <param-value>127.0.0.1</param-value>
+ </context-param>
+
+ <context-param>
+ <param-name>org.eclipse.jetty.servlet.SessionPath</param-name>
+ <param-value>/</param-value>
+ </context-param>
+
+ <context-param>
+ <param-name>org.eclipse.jetty.servlet.MaxAge</param-name>
+ <param-value>-1</param-value>
+ </context-param>
+ -->
+
+
+ <!-- ==================================================================== -->
+ <!-- The default servlet. -->
+ <!-- This servlet, normally mapped to /, provides the handling for static -->
+ <!-- content, OPTIONS and TRACE methods for the context. -->
+ <!-- The following initParameters are supported: -->
+ <!-- -->
+ <!-- acceptRanges If true, range requests and responses are -->
+ <!-- supported -->
+ <!-- -->
+ <!-- dirAllowed If true, directory listings are returned if no -->
+ <!-- welcome file is found. Else 403 Forbidden. -->
+ <!-- -->
+ <!-- welcomeServlets If true, attempt to dispatch to welcome files -->
+ <!-- that are servlets, if no matching static -->
+ <!-- resources can be found. -->
+ <!-- -->
+ <!-- redirectWelcome If true, redirect welcome file requests -->
+ <!-- else use request dispatcher forwards -->
+ <!-- -->
+ <!-- gzip If set to true, then static content will be served-->
+ <!-- as gzip content encoded if a matching resource is -->
+ <!-- found ending with ".gz" -->
+ <!-- -->
+ <!-- resoureBase Can be set to replace the context resource base -->
+ <!-- -->
+ <!-- relativeResourceBase -->
+ <!-- Set with a pathname relative to the base of the -->
+ <!-- servlet context root. Useful for only serving -->
+ <!-- static content from only specific subdirectories. -->
+ <!-- -->
+ <!-- useFileMappedBuffer -->
+ <!-- If set to true (the default), a memory mapped -->
+ <!-- file buffer will be used to serve static content -->
+ <!-- when using an NIO connector. Setting this value -->
+ <!-- to false means that a direct buffer will be used -->
+ <!-- instead. If you are having trouble with Windows -->
+ <!-- file locking, set this to false. -->
+ <!-- -->
+ <!-- cacheControl If set, all static content will have this value -->
+ <!-- set as the cache-control header. -->
+ <!-- -->
+ <!-- maxCacheSize Maximum size of the static resource cache -->
+ <!-- -->
+ <!-- maxCachedFileSize Maximum size of any single file in the cache -->
+ <!-- -->
+ <!-- maxCachedFiles Maximum number of files in the cache -->
+ <!-- -->
+ <!-- cacheType "nio", "bio" or "both" to determine the type(s) -->
+ <!-- of resource cache. A bio cached buffer may be used-->
+ <!-- by nio but is not as efficient as a nio buffer. -->
+ <!-- An nio cached buffer may not be used by bio. -->
+ <!-- -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <servlet>
+ <servlet-name>default</servlet-name>
+ <servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
+ <init-param>
+ <param-name>acceptRanges</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ <init-param>
+ <param-name>dirAllowed</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ <init-param>
+ <param-name>welcomeServlets</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <init-param>
+ <param-name>redirectWelcome</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <init-param>
+ <param-name>maxCacheSize</param-name>
+ <param-value>256000000</param-value>
+ </init-param>
+ <init-param>
+ <param-name>maxCachedFileSize</param-name>
+ <param-value>10000000</param-value>
+ </init-param>
+ <init-param>
+ <param-name>maxCachedFiles</param-name>
+ <param-value>1000</param-value>
+ </init-param>
+ <init-param>
+ <param-name>cacheType</param-name>
+ <param-value>both</param-value>
+ </init-param>
+ <init-param>
+ <param-name>gzip</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ <init-param>
+ <param-name>useFileMappedBuffer</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ <!--
+ <init-param>
+ <param-name>cacheControl</param-name>
+ <param-value>max-age=3600,public</param-value>
+ </init-param>
+ -->
+ <load-on-startup>0</load-on-startup>
+ </servlet>
+
+ <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
+
+
+ <!-- ==================================================================== -->
+ <!-- JSP Servlet -->
+ <!-- This is the jasper JSP servlet from the jakarta project -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <!-- The JSP page compiler and execution servlet, which is the mechanism -->
+ <!-- used by Glassfish to support JSP pages. Traditionally, this servlet -->
+ <!-- is mapped to URL patterh "*.jsp". This servlet supports the -->
+ <!-- following initialization parameters (default values are in square -->
+ <!-- brackets): -->
+ <!-- -->
+ <!-- checkInterval If development is false and reloading is true, -->
+ <!-- background compiles are enabled. checkInterval -->
+ <!-- is the time in seconds between checks to see -->
+ <!-- if a JSP page needs to be recompiled. [300] -->
+ <!-- -->
+ <!-- compiler Which compiler Ant should use to compile JSP -->
+ <!-- pages. See the Ant documenation for more -->
+ <!-- information. [javac] -->
+ <!-- -->
+ <!-- classdebuginfo Should the class file be compiled with -->
+ <!-- debugging information? [true] -->
+ <!-- -->
+ <!-- classpath What class path should I use while compiling -->
+ <!-- generated servlets? [Created dynamically -->
+ <!-- based on the current web application] -->
+ <!-- Set to ? to make the container explicitly set -->
+ <!-- this parameter. -->
+ <!-- -->
+ <!-- development Is Jasper used in development mode (will check -->
+ <!-- for JSP modification on every access)? [true] -->
+ <!-- -->
+ <!-- enablePooling Determines whether tag handler pooling is -->
+ <!-- enabled [true] -->
+ <!-- -->
+ <!-- fork Tell Ant to fork compiles of JSP pages so that -->
+ <!-- a separate JVM is used for JSP page compiles -->
+ <!-- from the one Tomcat is running in. [true] -->
+ <!-- -->
+ <!-- ieClassId The class-id value to be sent to Internet -->
+ <!-- Explorer when using <jsp:plugin> tags. -->
+ <!-- [clsid:8AD9C840-044E-11D1-B3E9-00805F499D93] -->
+ <!-- -->
+ <!-- javaEncoding Java file encoding to use for generating java -->
+ <!-- source files. [UTF-8] -->
+ <!-- -->
+ <!-- keepgenerated Should we keep the generated Java source code -->
+ <!-- for each page instead of deleting it? [true] -->
+ <!-- -->
+ <!-- logVerbosityLevel The level of detailed messages to be produced -->
+ <!-- by this servlet. Increasing levels cause the -->
+ <!-- generation of more messages. Valid values are -->
+ <!-- FATAL, ERROR, WARNING, INFORMATION, and DEBUG. -->
+ <!-- [WARNING] -->
+ <!-- -->
+ <!-- mappedfile Should we generate static content with one -->
+ <!-- print statement per input line, to ease -->
+ <!-- debugging? [false] -->
+ <!-- -->
+ <!-- -->
+ <!-- reloading Should Jasper check for modified JSPs? [true] -->
+ <!-- -->
+ <!-- suppressSmap Should the generation of SMAP info for JSR45 -->
+ <!-- debugging be suppressed? [false] -->
+ <!-- -->
+ <!-- dumpSmap Should the SMAP info for JSR45 debugging be -->
+ <!-- dumped to a file? [false] -->
+ <!-- False if suppressSmap is true -->
+ <!-- -->
+ <!-- scratchdir What scratch directory should we use when -->
+ <!-- compiling JSP pages? [default work directory -->
+ <!-- for the current web application] -->
+ <!-- -->
+ <!-- tagpoolMaxSize The maximum tag handler pool size [5] -->
+ <!-- -->
+ <!-- xpoweredBy Determines whether X-Powered-By response -->
+ <!-- header is added by generated servlet [false] -->
+ <!-- -->
+ <!-- If you wish to use Jikes to compile JSP pages: -->
+ <!-- Set the init parameter "compiler" to "jikes". Define -->
+ <!-- the property "-Dbuild.compiler.emacs=true" when starting Jetty -->
+ <!-- to cause Jikes to emit error messages in a format compatible with -->
+ <!-- Jasper. -->
+ <!-- If you get an error reporting that jikes can't use UTF-8 encoding, -->
+ <!-- try setting the init parameter "javaEncoding" to "ISO-8859-1". -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <servlet id="jsp">
+ <servlet-name>jsp</servlet-name>
+ <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
+ <init-param>
+ <param-name>logVerbosityLevel</param-name>
+ <param-value>DEBUG</param-value>
+ </init-param>
+ <init-param>
+ <param-name>fork</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <init-param>
+ <param-name>xpoweredBy</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <!--
+ <init-param>
+ <param-name>classpath</param-name>
+ <param-value>?</param-value>
+ </init-param>
+ -->
+ <load-on-startup>0</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>jsp</servlet-name>
+ <url-pattern>*.jsp</url-pattern>
+ <url-pattern>*.jspf</url-pattern>
+ <url-pattern>*.jspx</url-pattern>
+ <url-pattern>*.xsp</url-pattern>
+ <url-pattern>*.JSP</url-pattern>
+ <url-pattern>*.JSPF</url-pattern>
+ <url-pattern>*.JSPX</url-pattern>
+ <url-pattern>*.XSP</url-pattern>
+ </servlet-mapping>
+
+ <!-- ==================================================================== -->
+ <!-- Dynamic Servlet Invoker. -->
+ <!-- This servlet invokes anonymous servlets that have not been defined -->
+ <!-- in the web.xml or by other means. The first element of the pathInfo -->
+ <!-- of a request passed to the envoker is treated as a servlet name for -->
+ <!-- an existing servlet, or as a class name of a new servlet. -->
+ <!-- This servlet is normally mapped to /servlet/* -->
+ <!-- This servlet support the following initParams: -->
+ <!-- -->
+ <!-- nonContextServlets If false, the invoker can only load -->
+ <!-- servlets from the contexts classloader. -->
+ <!-- This is false by default and setting this -->
+ <!-- to true may have security implications. -->
+ <!-- -->
+ <!-- verbose If true, log dynamic loads -->
+ <!-- -->
+ <!-- * All other parameters are copied to the -->
+ <!-- each dynamic servlet as init parameters -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <!-- Uncomment for dynamic invocation
+ <servlet>
+ <servlet-name>invoker</servlet-name>
+ <servlet-class>org.eclipse.jetty.servlet.Invoker</servlet-class>
+ <init-param>
+ <param-name>verbose</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <init-param>
+ <param-name>nonContextServlets</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <init-param>
+ <param-name>dynamicParam</param-name>
+ <param-value>anyValue</param-value>
+ </init-param>
+ <load-on-startup>0</load-on-startup>
+ </servlet>
+
+ <servlet-mapping> <servlet-name>invoker</servlet-name> <url-pattern>/servlet/*</url-pattern> </servlet-mapping>
+ -->
+
+
+
+ <!-- ==================================================================== -->
+ <session-config>
+ <session-timeout>30</session-timeout>
+ </session-config>
+
+ <!-- ==================================================================== -->
+ <!-- Default MIME mappings -->
+ <!-- The default MIME mappings are provided by the mime.properties -->
+ <!-- resource in the org.eclipse.jetty.server.jar file. Additional or modified -->
+ <!-- mappings may be specified here -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <!-- UNCOMMENT TO ACTIVATE
+ <mime-mapping>
+ <extension>mysuffix</extension>
+ <mime-type>mymime/type</mime-type>
+ </mime-mapping>
+ -->
+
+ <!-- ==================================================================== -->
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ <welcome-file>index.htm</welcome-file>
+ <welcome-file>index.jsp</welcome-file>
+ </welcome-file-list>
+
+ <!-- ==================================================================== -->
+ <locale-encoding-mapping-list>
+ <locale-encoding-mapping><locale>ar</locale><encoding>ISO-8859-6</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>be</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>bg</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>ca</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>cs</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>da</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>de</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>el</locale><encoding>ISO-8859-7</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>en</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>es</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>et</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>fi</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>fr</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>hr</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>hu</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>is</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>it</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>iw</locale><encoding>ISO-8859-8</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>ja</locale><encoding>Shift_JIS</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>ko</locale><encoding>EUC-KR</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>lt</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>lv</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>mk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>nl</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>no</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>pl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>pt</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>ro</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>ru</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>sh</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>sk</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>sl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>sq</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>sr</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>sv</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>tr</locale><encoding>ISO-8859-9</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>uk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>zh</locale><encoding>GB2312</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>zh_TW</locale><encoding>Big5</encoding></locale-encoding-mapping>
+ </locale-encoding-mapping-list>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Disable TRACE</web-resource-name>
+ <url-pattern>/</url-pattern>
+ <http-method>TRACE</http-method>
+ </web-resource-collection>
+ <auth-constraint/>
+ </security-constraint>
+
+</web-app>
+
diff --git a/jetty-deploy-manager-graph/src/test/resources/jetty-deploymgr-contexts.xml b/jetty-deploy-manager-graph/src/test/resources/jetty-deploymgr-contexts.xml
new file mode 100644
index 0000000..e917ca9
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/test/resources/jetty-deploymgr-contexts.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
+
+<Configure id="Server" class="org.eclipse.jetty.server.Server">
+
+ <Call name="addLifeCycle">
+ <Arg>
+ <New id="DeploymentManager" class="org.eclipse.jetty.deploy.DeploymentManager">
+ <Set name="contexts">
+ <Ref id="Contexts" />
+ </Set>
+ <Set name="configurationManager">
+ <New class="org.eclipse.jetty.deploy.support.FileConfigurationManager">
+ <Set name="file">
+ <Property name="test.targetdir" default="target" />/xml-configured-jetty.properties
+ </Set>
+ </New>
+ </Set>
+
+ <!-- Lifecycle Bindings -->
+ <Call name="addLifecycleBinding">
+ <Arg>
+ <New class="org.eclipse.jetty.deploy.bindings.DefaultDeployer" />
+ </Arg>
+ </Call>
+ <Call name="addLifecycleBinding">
+ <Arg>
+ <New class="org.eclipse.jetty.deploy.bindings.DefaultUndeployer" />
+ </Arg>
+ </Call>
+ <Call name="addLifecycleBinding">
+ <Arg>
+ <New class="org.eclipse.jetty.deploy.bindings.DefaultStarter" />
+ </Arg>
+ </Call>
+ <Call name="addLifecycleBinding">
+ <Arg>
+ <New class="org.eclipse.jetty.deploy.bindings.DefaultStopper" />
+ </Arg>
+ </Call>
+
+ <!-- Providers of Apps -->
+ <Call name="addAppProvider">
+ <Arg>
+ <New class="org.eclipse.jetty.deploy.providers.ContextsDirAppProvider">
+ <Set name="contextsDir">
+ <Property name="test.resourcesdir" default="src/test/resources" />/contexts
+ </Set>
+ <Set name="scanInterval">0</Set>
+ <Set name="recursive">false</Set>
+ </New>
+ </Arg>
+ </Call>
+
+ </New>
+ </Arg>
+ </Call>
+
+</Configure>
diff --git a/jetty-deploy-manager-graph/src/test/resources/jetty.xml b/jetty-deploy-manager-graph/src/test/resources/jetty.xml
new file mode 100644
index 0000000..d0cb501
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/test/resources/jetty.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
+
+<!-- =============================================================== -->
+<!-- Configure the Jetty Server -->
+<!-- -->
+<!-- Documentation of this file format can be found at: -->
+<!-- http://docs.codehaus.org/display/JETTY/jetty.xml -->
+<!-- -->
+<!-- =============================================================== -->
+
+
+<Configure id="Server" class="org.eclipse.jetty.server.Server">
+ <!-- =========================================================== -->
+ <!-- Server Thread Pool -->
+ <!-- =========================================================== -->
+ <Set name="ThreadPool">
+ <!-- Default queued blocking threadpool
+ -->
+ <New class="org.eclipse.jetty.util.thread.QueuedThreadPool">
+ <Set name="minThreads">10</Set>
+ <Set name="maxThreads">200</Set>
+ </New>
+
+ <!-- Optional Java 5 bounded threadpool with job queue
+ <New class="org.eclipse.thread.concurrent.ThreadPool">
+ <Set name="corePoolSize">50</Set>
+ <Set name="maximumPoolSize">50</Set>
+ </New>
+ -->
+ </Set>
+
+ <!-- =========================================================== -->
+ <!-- Set connectors -->
+ <!-- =========================================================== -->
+
+ <Call name="addConnector">
+ <Arg>
+ <New class="org.eclipse.jetty.server.nio.SelectChannelConnector">
+ <Set name="host"></Set>
+ <Set name="port">0</Set>
+ <Set name="maxIdleTime">300000</Set>
+ <Set name="Acceptors">2</Set>
+ <Set name="statsOn">false</Set>
+ <Set name="confidentialPort">8443</Set>
+ <Set name="lowResourcesConnections">20000</Set>
+ <Set name="lowResourcesMaxIdleTime">5000</Set>
+ </New>
+ </Arg>
+ </Call>
+
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <!-- To add a HTTPS SSL connector -->
+ <!-- mixin jetty-ssl.xml: -->
+ <!-- java -jar start.jar etc/jetty.xml etc/jetty-ssl.xml -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <!-- To add a HTTP blocking connector -->
+ <!-- mixin jetty-bio.xml: -->
+ <!-- java -jar start.jar etc/jetty.xml etc/jetty-bio.xml -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <!-- To allow Jetty to be started from xinetd -->
+ <!-- mixin jetty-xinetd.xml: -->
+ <!-- java -jar start.jar etc/jetty.xml etc/jetty-xinetd.xml -->
+ <!-- -->
+ <!-- See jetty-xinetd.xml for further instructions. -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <!-- =========================================================== -->
+ <!-- Set handler Collection Structure -->
+ <!-- =========================================================== -->
+ <Set name="handler">
+ <New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
+ <Set name="handlers">
+ <Array type="org.eclipse.jetty.server.Handler">
+ <Item>
+ <New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/>
+ </Item>
+ <Item>
+ <New id="DefaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler"/>
+ </Item>
+ <Item>
+ <New id="RequestLog" class="org.eclipse.jetty.server.handler.RequestLogHandler"/>
+ </Item>
+ </Array>
+ </Set>
+ </New>
+ </Set>
+
+ <!-- =========================================================== -->
+ <!-- Configure Authentication Login Service -->
+ <!-- Realms may be configured for the entire server here, or -->
+ <!-- they can be configured for a specific web app in a context -->
+ <!-- configuration (see $(jetty.home)/contexts/test.xml for an -->
+ <!-- example). -->
+ <!-- =========================================================== -->
+ <Call name="addBean">
+ <Arg>
+ <New class="org.eclipse.jetty.security.HashLoginService">
+ <Set name="name">Test Realm</Set>
+ <Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/realm.properties</Set>
+ <Set name="refreshInterval">0</Set>
+ </New>
+ </Arg>
+ </Call>
+
+ <!-- =========================================================== -->
+ <!-- Configure Request Log -->
+ <!-- Request logs may be configured for the entire server here, -->
+ <!-- or they can be configured for a specific web app in a -->
+ <!-- contexts configuration (see $(jetty.home)/contexts/test.xml -->
+ <!-- for an example). -->
+ <!-- =========================================================== -->
+ <Ref id="RequestLog">
+ <Set name="requestLog">
+ <New id="RequestLogImpl" class="org.eclipse.jetty.server.NCSARequestLog">
+ <Set name="filename"><SystemProperty name="jetty.home" default="."/>/logs/yyyy_mm_dd.request.log</Set>
+ <Set name="filenameDateFormat">yyyy_MM_dd</Set>
+ <Set name="retainDays">90</Set>
+ <Set name="append">true</Set>
+ <Set name="extended">false</Set>
+ <Set name="logCookies">false</Set>
+ <Set name="LogTimeZone">GMT</Set>
+ </New>
+ </Set>
+ </Ref>
+
+ <!-- =========================================================== -->
+ <!-- extra options -->
+ <!-- =========================================================== -->
+ <Set name="stopAtShutdown">true</Set>
+ <Set name="sendServerVersion">true</Set>
+ <Set name="sendDateHeader">true</Set>
+ <Set name="gracefulShutdown">1000</Set>
+
+</Configure>
diff --git a/jetty-deploy-manager-graph/src/test/resources/webapps/logcommon.war b/jetty-deploy-manager-graph/src/test/resources/webapps/logcommon.war
new file mode 100644
index 0000000..bac25eb
--- /dev/null
+++ b/jetty-deploy-manager-graph/src/test/resources/webapps/logcommon.war
Binary files differ