Commits

Stephen McKamey committed 78a2317

enabling multiple WARs from command line

  • Participants
  • Parent commits a3ff5f8

Comments (0)

Files changed (16)

 \.iws
 bootstrap/target
 war-bootstrap-archetype/target
+launch.sh
+test.war
 The MIT License
 
-Copyright (c) 2010-2011 Stephen M. McKamey
+Copyright (c) 2010-2012 Stephen M. McKamey
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 	mvn archetype:generate \
 		-DarchetypeGroupId=org.duelengine \
 		-DarchetypeArtifactId=war-bootstrap-archetype \
-		-DarchetypeVersion=0.2.1
+		-DarchetypeVersion=0.3.0
 
 	# build your boostrap
 	# NOTE: replace "bootstrap" with your chosen project name
 
 	# run the resulting WAR on the test bootstrap
 	# NOTE: again replace with your chosen artifact names
-	java -jar bootstrap/target/bootstrap.jar -war path/to/myapp.war -p 8080 -c /myapp --jetty
+	java -jar bootstrap/target/bootstrap.jar -p 8080 --jetty -war /myapp='path/to/myapp.war'

war-bootstrap-archetype/pom.xml

 
 	<groupId>org.duelengine</groupId>
 	<artifactId>war-bootstrap-archetype</artifactId>
-	<version>0.2.2</version>
+	<version>0.3.0</version>
 	<packaging>maven-archetype</packaging>
 
 	<name>WAR Bootstrap Archetype</name>
 					<plugin>
 						<groupId>org.apache.maven.plugins</groupId>
 						<artifactId>maven-gpg-plugin</artifactId>
-						<version>1.1</version>
+						<version>1.4</version>
 						<executions>
 							<execution>
 								<id>sign-artifacts</id>

war-bootstrap-archetype/src/main/resources/archetype-resources/pom.xml

-<?xml version="1.0" encoding="UTF-8"?>
-<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">
-	<modelVersion>4.0.0</modelVersion>
-
-	<groupId>${groupId}</groupId>
-	<artifactId>${artifactId}</artifactId>
-	<version>${version}</version>
-	<packaging>jar</packaging>
-
-	<name>${artifactId} bootstrap</name>
-	<description>Simple WAR bootstrap for quick &amp; dirty testing in various servlet containers.</description>
-
-	<properties>
-		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-
-		<javac.version>1.6</javac.version>
-		<glassfish.version>3.1.1</glassfish.version>
-		<jetty.version>8.0.1.v20110908</jetty.version>
-		<tomcat.version>7.0.21</tomcat.version>
-	</properties>
-
-	<repositories>
-		<repository>
-			<id>repo1_maven_org</id>
-			<name>Maven 2 Repository</name>
-			<url>http://repo1.maven.org/maven2</url>
-		</repository>
-		<repository>
-			<id>glassfish-repository</id>
-			<name>Glassfish Repository</name>
-			<url>http://download.java.net/maven/glassfish</url>
-		</repository>
-		<repository>
-			<id>java.net2</id>
-			<name>Java.net Maven2 Repository</name>
-			<url>http://download.java.net/maven/2</url>
-		</repository>
-	</repositories>
-
-	<dependencies>
-		<!-- NOTE: GlassFish and Tomcat appear to be conflicting.
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+	<modelVersion>4.0.0</modelVersion>
 
-			 order appears to matter and also
+	<groupId>${groupId}</groupId>
+	<artifactId>${artifactId}</artifactId>
+	<version>${version}</version>
+	<packaging>jar</packaging>
 
-			 must set scope to provided if not used -->
-		<dependency>
-			<!-- Jetty 7/8 embedded runtime -->
-			<groupId>org.eclipse.jetty.aggregate</groupId>
-			<artifactId>jetty-all</artifactId>
-			<version>${jetty.version}</version>
-		</dependency>
-		<dependency>
-			<!-- GlassFish 3.1 embedded runtime -->
-			<groupId>org.glassfish.extras</groupId>
-			<artifactId>glassfish-embedded-web</artifactId>
-			<version>${glassfish.version}</version>
-			<scope>provided</scope><!-- comment this for GF3 -->
-		</dependency>
-		<dependency>
-			<!-- Tomcat 7 embedded runtime -->
-			<groupId>org.apache.tomcat.embed</groupId>
-			<artifactId>tomcat-embed-core</artifactId>
-			<version>${tomcat.version}</version>
-			<!--scope>compile</scope--><!-- comment this for TC7 -->
-		</dependency>
-		<dependency>
-			<!-- Tomcat 7 JSP -->
-			<groupId>org.apache.tomcat.embed</groupId>
-			<artifactId>tomcat-embed-jasper</artifactId>
-			<version>${tomcat.version}</version>
-			<scope>compile</scope>
-		</dependency>
-		<dependency>
-			<!-- Tomcat 7 logging -->
-			<groupId>org.apache.tomcat.embed</groupId>
-			<artifactId>tomcat-embed-logging-juli</artifactId>
-			<version>${tomcat.version}</version>
-			<scope>compile</scope>
-		</dependency>
-	</dependencies>
-
-	<build>
-		<finalName>${project.artifactId}</finalName>
-		<plugins>
-
-			<!-- set the main class -->
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-jar-plugin</artifactId>
-				<version>2.3.1</version>
-				<configuration>
-					<archive>
-						<manifest>
-							<addClasspath>true</addClasspath>
-							<mainClass>${package}.Bootstrap</mainClass>
-						</manifest>
-					</archive>
-				</configuration>
-			</plugin>
-
-			<!-- copy all dependencies to target -->
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-dependency-plugin</artifactId>
-				<configuration>
-					<outputDirectory>${project.build.directory}</outputDirectory>
-				</configuration>
-				<executions>
-					<execution>
-						<goals>
-							<goal>copy-dependencies</goal>
-						</goals>
-					</execution>
-				</executions>
-			</plugin>
-		</plugins>
-		<pluginManagement>
-			<plugins>
-				<!-- Java compiler -->
-				<plugin>
-					<artifactId>maven-compiler-plugin</artifactId>
-					<configuration>
-						<source>${javac.version}</source>
-						<target>${javac.version}</target>
-					</configuration>
-				</plugin>
-			</plugins>
-		</pluginManagement>
-	</build>
-</project>
+	<name>${artifactId} bootstrap</name>
+	<description>Simple WAR bootstrap for quick &amp; dirty testing in various servlet containers.</description>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+
+		<glassfish.version>3.1.1</glassfish.version>
+		<jetty.version>8.1.1.v20120215</jetty.version>
+		<tomcat.version>7.0.26</tomcat.version>
+		<javac.version>1.6</javac.version>
+	</properties>
+
+	<repositories>
+		<repository>
+			<id>repo1_maven_org</id>
+			<name>Maven 2 Repository</name>
+			<url>http://repo1.maven.org/maven2</url>
+		</repository>
+		<repository>
+			<id>glassfish-repository</id>
+			<name>Glassfish Repository</name>
+			<url>http://download.java.net/maven/glassfish</url>
+		</repository>
+		<repository>
+			<id>java.net2</id>
+			<name>Java.net Maven2 Repository</name>
+			<url>http://download.java.net/maven/2</url>
+		</repository>
+	</repositories>
+
+	<dependencies>
+		<!-- NOTE: GlassFish and Tomcat appear to be conflicting.
+			 order appears to matter and also
+			 must set scope to provided if not used -->
+		<dependency>
+			<!-- Jetty 7/8 embedded runtime -->
+			<groupId>org.eclipse.jetty.aggregate</groupId>
+			<artifactId>jetty-all</artifactId>
+			<version>${jetty.version}</version>
+		</dependency>
+		<dependency>
+			<!-- GlassFish 3.1 embedded runtime -->
+			<groupId>org.glassfish.extras</groupId>
+			<artifactId>glassfish-embedded-web</artifactId>
+			<version>${glassfish.version}</version>
+			<scope>provided</scope><!-- comment this for GF3 -->
+		</dependency>
+		<dependency>
+			<!-- Tomcat 7 embedded runtime -->
+			<groupId>org.apache.tomcat.embed</groupId>
+			<artifactId>tomcat-embed-core</artifactId>
+			<version>${tomcat.version}</version>
+			<!--scope>compile</scope--><!-- comment this for TC7 -->
+		</dependency>
+		<dependency>
+			<!-- Tomcat 7 JSP -->
+			<groupId>org.apache.tomcat.embed</groupId>
+			<artifactId>tomcat-embed-jasper</artifactId>
+			<version>${tomcat.version}</version>
+			<scope>compile</scope>
+		</dependency>
+		<dependency>
+			<!-- Tomcat 7 logging -->
+			<groupId>org.apache.tomcat.embed</groupId>
+			<artifactId>tomcat-embed-logging-juli</artifactId>
+			<version>${tomcat.version}</version>
+			<scope>compile</scope>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<finalName>${project.artifactId}</finalName>
+		<plugins>
+
+			<!-- set the main class -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-jar-plugin</artifactId>
+				<version>2.4</version>
+				<configuration>
+					<archive>
+						<manifest>
+							<addClasspath>true</addClasspath>
+							<mainClass>${package}.Bootstrap</mainClass>
+						</manifest>
+					</archive>
+				</configuration>
+			</plugin>
+
+			<!-- copy all dependencies to target -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-dependency-plugin</artifactId>
+				<version>2.4</version>
+				<configuration>
+					<outputDirectory>${project.build.directory}</outputDirectory>
+				</configuration>
+				<executions>
+					<execution>
+						<goals>
+							<goal>copy-dependencies</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+		<pluginManagement>
+			<plugins>
+				<!-- Java compiler -->
+				<plugin>
+					<artifactId>maven-compiler-plugin</artifactId>
+					<configuration>
+						<source>${javac.version}</source>
+						<target>${javac.version}</target>
+					</configuration>
+				</plugin>
+
+				<!-- http://wiki.eclipse.org/M2E_plugin_execution_not_covered -->
+				<plugin>
+					<groupId>org.eclipse.m2e</groupId>
+					<artifactId>lifecycle-mapping</artifactId>
+					<version>1.0.0</version>
+					<configuration>
+						<lifecycleMappingMetadata>
+							<pluginExecutions>
+								<pluginExecution>
+									<pluginExecutionFilter>
+										<groupId>org.apache.maven.plugins</groupId>
+										<artifactId>maven-dependency-plugin</artifactId>
+										<versionRange>[$2.4,)</versionRange>
+										<goals>
+											<goal>copy-dependencies</goal>
+										</goals>
+									</pluginExecutionFilter>
+									<action>
+										<execute />
+									</action>
+								</pluginExecution>
+							</pluginExecutions>
+						</lifecycleMappingMetadata>
+					</configuration>
+				</plugin>
+			</plugins>
+		</pluginManagement>
+	</build>
+</project>

war-bootstrap-archetype/src/main/resources/archetype-resources/src/main/java/Bootstrap.java

 package ${package};
 
 import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
 
 public class Bootstrap {
 
 	private static final String SEPARATOR = "========================================";
 	private static final String HELP = "java -jar ${artifactId}.jar${symbol_escape}n"+
-			"  --help       : this help text${symbol_escape}n"+
-			"  -war <path>  : set the name of war (default: ./root.war)${symbol_escape}n" +
-			"  -p <port>    : set the HTTP listening port (default: 8443)${symbol_escape}n"+
-			"  -s <port>    : set the HTTPS listening port (default: none)${symbol_escape}n"+
-			"  -c <context> : set the context path (default: /)";
+			"  --help                 : this help text${symbol_escape}n"+
+			"  -war <context>=<path>  : set the context of war (e.g., /=./root.war)${symbol_escape}n" +
+			"  -p <port>              : set the HTTP listening port (default: 8080)${symbol_escape}n"+
+			"  -s <port>              : set the HTTPS listening port (default: none)${symbol_escape}n" +
+			"  --tomcat               : use Tomcat as servlet container (default)${symbol_escape}n" +
+			"  --jetty                : use Jetty as servlet container${symbol_escape}n" +
+			"  --glassfish            : use GlassFish as servlet container";
 
 	public static void main(String[] args) {
 
-		String warPath = "./root.war";
-		String context = "/";
+		Map<String, String> contexts = new HashMap<String, String>();
 		int port = 8080;
 		int https = -1;
 		ServletServer server = null;
+		try {
+			System.out.println(SEPARATOR);
+			System.out.println("WAR Bootstrap\n");
+			for (int i=0; i<args.length; i++) {
+				String arg = args[i];
+				if ("-p".equals(arg)) {
+					port = Integer.parseInt(args[++i]);
 
-		System.out.println(SEPARATOR);
-		System.out.println("WAR Bootstrap${symbol_escape}n");
-		for (int i=0; i<args.length; i++) {
-			String arg = args[i];
-			if ("-p".equals(arg)) {
-				port = Integer.parseInt(args[++i]);
+				} else if ("-s".equals(arg)) {
+					https = Integer.parseInt(args[++i]);
 
-			} else if ("-s".equals(arg)) {
-				https = Integer.parseInt(args[++i]);
+				} else if ("-war".equals(arg)) {
+					String contextPath;
+					String warPath = args[++i];
+					int delim = warPath.indexOf('=');
+					if (delim < 1) {
+						contextPath = "/";
+					} else {
+						contextPath = warPath.substring(0, delim);
+					}
+					warPath = new File(warPath.substring(delim+1)).getCanonicalPath();
+					contexts.put(contextPath, warPath);
 
-			} else if ("-war".equals(arg)) {
-				warPath = args[++i];
+				} else if ("--glassfish".equalsIgnoreCase(arg)) {
+					server = new GlassFishServletServer();
 
-			} else if ("-c".equals(arg)) {
-				context = args[++i];
+				} else if ("--jetty".equalsIgnoreCase(arg)) {
+					server = new JettyServletServer();
 
-			} else if ("--glassfish".equalsIgnoreCase(arg)) {
-				server = new GlassFishServletServer();
+				} else if ("--tomcat".equalsIgnoreCase(arg)) {
+					server = new TomcatServletServer();
 
-			} else if ("--jetty".equalsIgnoreCase(arg)) {
-				server = new JettyServletServer();
+				} else if ("--help".equalsIgnoreCase(arg)) {
+					System.out.println(HELP);
+					System.out.println(SEPARATOR);
+					return;
 
-			} else if ("--tomcat".equalsIgnoreCase(arg)) {
+				} else {
+					System.out.println(HELP);
+					System.out.println(SEPARATOR);
+					return;
+				}
+			}
+
+			if (server == null) {
 				server = new TomcatServletServer();
+			}
 
-			} else if ("--help".equalsIgnoreCase(arg)) {
-				System.out.println(HELP);
-				System.out.println(SEPARATOR);
-				return;
-
-			} else {
-				System.out.println(HELP);
-				System.out.println(SEPARATOR);
-				return;
-			}
-		}
-
-		if (server == null) {
-			server = new TomcatServletServer();
-		}
-		
-		try {
 			System.out.println(" - servlet container: "+server.getName());
 
-			warPath = new File(warPath).getCanonicalPath();
-
-			System.out.println(" - war path: "+warPath);
-			System.out.println(" - context root: "+context);
+			for (String contextPath : contexts.keySet()) {
+				System.out.println(" - context root: "+contextPath);
+				System.out.println(" - war path: "+contexts.get(contextPath));
+			}
 			if (port > 0) {
 				System.out.println(" - Listening to HTTP on port: "+port);
 			} else {
 			System.out.println(SEPARATOR);
 			System.out.println();
 
-			server.start(warPath, context, port, https);
+			server.start(contexts, port, https);
 
 			System.in.read();
 

war-bootstrap-archetype/src/main/resources/archetype-resources/src/main/java/GlassFishServletServer.java

 package ${package};
 
 import java.io.File;
+import java.util.Map;
+
 import org.glassfish.embeddable.*;
 
 class GlassFishServletServer implements ServletServer {
 		return "GlassFish";
 	}
 
-	public void start(String warPath, String contextPath, int httpPort, int httpsPort) throws Exception {
+	public void start(Map<String, String> contexts, int httpPort, int httpsPort) throws Exception {
 		if (server != null) {
 			throw new IllegalStateException("Web server is already running.");
 		}
 		if (httpPort > 0) {
 			gfProps.setPort("http-listener", httpPort);
 		}
-		if (httpsPort > 0) {
-			gfProps.setPort("https-listener", httpsPort);
+//		if (httpsPort > 0) {
+//			gfProps.setPort("https-listener", httpsPort);
+//		}
+
+		server = GlassFishRuntime.bootstrap().newGlassFish(gfProps);
+
+		for (String contextPath : contexts.keySet()) {
+			File war = new File(contexts.get(contextPath));
+			Deployer deployer = server.getDeployer();
+			deployer.deploy(war, "--name="+war.getName(), "--contextroot="+contextPath, "--force=true");
 		}
 
-		server = GlassFishRuntime.bootstrap().newGlassFish(gfProps);
 		server.start();
-
-		File war = new File(warPath);
-		Deployer deployer = server.getDeployer();
-		deployer.deploy(war, "--name=webapp", "--contextroot="+contextPath, "--force=true");
 	}
 
 	public void stop() throws Exception {

war-bootstrap-archetype/src/main/resources/archetype-resources/src/main/java/JettyServletServer.java

 #set( $symbol_escape = '\' )
 package ${package};
 
-import org.eclipse.jetty.server.*;
-import org.eclipse.jetty.servlet.*;
+import java.util.Map;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.servlet.DefaultServlet;
 import org.eclipse.jetty.webapp.WebAppContext;
 
 class JettyServletServer implements ServletServer {
 		return "Jetty";
 	}
 
-	public void start(String warPath, String contextPath, int httpPort, int httpsPort) throws Exception {
+	public void start(Map<String, String> contexts, int httpPort, int httpsPort) throws Exception {
 		if (server != null) {
 			throw new IllegalStateException("Web server is already running.");
 		}
 
 		server = new Server(httpPort);
 
-		WebAppContext webapp = new WebAppContext();
-		webapp.setContextPath(contextPath);
-		webapp.setWar(warPath);
+		for (String contextPath : contexts.keySet()) {
+			WebAppContext webapp = new WebAppContext();
+			webapp.setContextPath(contextPath);
+			webapp.setWar(contexts.get(contextPath));
 
-		// wire up DefaultServlet for static files
-		webapp.addServlet(DefaultServlet.class, "/*");
+			// wire up DefaultServlet for static files
+			webapp.addServlet(DefaultServlet.class, "/*");
 
-		server.setHandler(webapp);
+			server.setHandler(webapp);
+		}
 		server.start();
 	}
 

war-bootstrap-archetype/src/main/resources/archetype-resources/src/main/java/ServletServer.java

 #set( $symbol_escape = '\' )
 package ${package};
 
+import java.util.Map;
+
 public interface ServletServer {
 
 	String getName();
 
-	void start(String warPath, String context, int httpPort, int httpsPort) throws Exception;
+	void start(Map<String, String> contexts, int httpPort, int httpsPort) throws Exception;
 
 	void stop() throws Exception;
-}
+}

war-bootstrap-archetype/src/main/resources/archetype-resources/src/main/java/TomcatServletServer.java

 package ${package};
 
 import java.io.File;
+import java.util.Map;
+
 import org.apache.catalina.core.StandardContext;
 import org.apache.catalina.startup.ContextConfig;
 import org.apache.catalina.startup.Tomcat;
 		return "Tomcat";
 	}
 
-	public void start(String warPath, String contextPath, int httpPort, int httpsPort) throws Exception {
+	public void start(Map<String, String> contexts, int httpPort, int httpsPort) throws Exception {
 		if (server != null) {
 			throw new IllegalStateException("Web server is already running.");
 		}
 
 		server = new Tomcat();
-		server.setBaseDir(new File(warPath, ".." + File.separatorChar + "tomcat").getCanonicalPath());
+		server.setBaseDir(new File("tomcat").getCanonicalPath());
 		server.setPort(httpPort);
 
 //		server.addWebapp(contextPath, warPath);
 
-        StandardContext ctx = new StandardContext();
-        ctx.setPath(contextPath);
-        ctx.setDocBase(warPath);
+		for (String contextPath : contexts.keySet()) {
+			StandardContext ctx = new StandardContext();
+			ctx.setPath(contextPath);
+			ctx.setDocBase(contexts.get(contextPath));
 
-        ctx.addLifecycleListener(new Tomcat.DefaultWebXmlListener());
-        
-        ContextConfig ctxCfg = new ContextConfig();
-        ctx.addLifecycleListener(ctxCfg);
-        
-        // prevent it from looking ( if it finds one - it'll have dup error )
-        ctxCfg.setDefaultWebXml("org/apache/catalin/startup/NO_DEFAULT_XML");
-        
-        server.getHost().addChild(ctx);
+			ctx.addLifecycleListener(new Tomcat.DefaultWebXmlListener());
+
+			ContextConfig ctxCfg = new ContextConfig();
+			ctx.addLifecycleListener(ctxCfg);
+
+			// prevent it from looking ( if it finds one - it'll have dup error )
+			ctxCfg.setDefaultWebXml("org/apache/catalin/startup/NO_DEFAULT_XML");
+
+			server.getHost().addChild(ctx);
+		}
 
 		server.start();
 	}

war-bootstrap/pom.xml

 
 	<groupId>org.duelengine</groupId>
 	<artifactId>bootstrap</artifactId>
-	<version>0.2.2</version>
+	<version>0.3.0</version>
 	<packaging>jar</packaging>
 
 	<name>WAR Bootstrap</name>
 	<properties>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 
+		<glassfish.version>3.1.1</glassfish.version>
+		<jetty.version>8.1.1.v20120215</jetty.version>
+		<tomcat.version>7.0.26</tomcat.version>
 		<javac.version>1.6</javac.version>
-		<glassfish.version>3.1.1</glassfish.version>
-		<jetty.version>8.0.1.v20110908</jetty.version>
-		<tomcat.version>7.0.21</tomcat.version>
 	</properties>
 
 	<repositories>
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-jar-plugin</artifactId>
-				<version>2.3.1</version>
+				<version>2.4</version>
 				<configuration>
 					<archive>
 						<manifest>
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-dependency-plugin</artifactId>
+				<version>2.4</version>
 				<configuration>
 					<outputDirectory>${project.build.directory}</outputDirectory>
 				</configuration>
 						<target>${javac.version}</target>
 					</configuration>
 				</plugin>
+
+				<!-- http://wiki.eclipse.org/M2E_plugin_execution_not_covered -->
+				<plugin>
+					<groupId>org.eclipse.m2e</groupId>
+					<artifactId>lifecycle-mapping</artifactId>
+					<version>1.0.0</version>
+					<configuration>
+						<lifecycleMappingMetadata>
+							<pluginExecutions>
+								<pluginExecution>
+									<pluginExecutionFilter>
+										<groupId>org.apache.maven.plugins</groupId>
+										<artifactId>maven-dependency-plugin</artifactId>
+										<versionRange>[$2.4,)</versionRange>
+										<goals>
+											<goal>copy-dependencies</goal>
+										</goals>
+									</pluginExecutionFilter>
+									<action>
+										<execute />
+									</action>
+								</pluginExecution>
+							</pluginExecutions>
+						</lifecycleMappingMetadata>
+					</configuration>
+				</plugin>
 			</plugins>
 		</pluginManagement>
 	</build>

war-bootstrap/src/main/java/org/duelengine/bootstrap/Bootstrap.java

 package org.duelengine.bootstrap;
 
 import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
 
 public class Bootstrap {
 
 	private static final String SEPARATOR = "========================================";
 	private static final String HELP = "java -jar bootstrap.jar\n"+
-			"  --help       : this help text\n"+
-			"  -war <path>  : set the name of war (default: ./root.war)\n" +
-			"  -p <port>    : set the HTTP listening port (default: 8443)\n"+
-			"  -s <port>    : set the HTTPS listening port (default: none)\n"+
-			"  -c <context> : set the context path (default: /)";
+			"  --help                 : this help text\n"+
+			"  -war <context>=<path>  : set the context of war (e.g., /=./root.war)\n" +
+			"  -p <port>              : set the HTTP listening port (default: 8080)\n"+
+			"  -s <port>              : set the HTTPS listening port (default: none)\n" +
+			"  --tomcat               : use Tomcat as servlet container (default)\n" +
+			"  --jetty                : use Jetty as servlet container\n" +
+			"  --glassfish            : use GlassFish as servlet container";
 
 	public static void main(String[] args) {
 
-		String warPath = "./root.war";
-		String context = "/";
+		Map<String, String> contexts = new HashMap<String, String>();
 		int port = 8080;
 		int https = -1;
 		ServletServer server = null;
+		try {
+			System.out.println(SEPARATOR);
+			System.out.println("WAR Bootstrap\n");
+			for (int i=0; i<args.length; i++) {
+				String arg = args[i];
+				if ("-p".equals(arg)) {
+					port = Integer.parseInt(args[++i]);
 
-		System.out.println(SEPARATOR);
-		System.out.println("WAR Bootstrap\n");
-		for (int i=0; i<args.length; i++) {
-			String arg = args[i];
-			if ("-p".equals(arg)) {
-				port = Integer.parseInt(args[++i]);
+				} else if ("-s".equals(arg)) {
+					https = Integer.parseInt(args[++i]);
 
-			} else if ("-s".equals(arg)) {
-				https = Integer.parseInt(args[++i]);
+				} else if ("-war".equals(arg)) {
+					String contextPath;
+					String warPath = args[++i];
+					int delim = warPath.indexOf('=');
+					if (delim < 1) {
+						contextPath = "/";
+					} else {
+						contextPath = warPath.substring(0, delim);
+					}
+					warPath = new File(warPath.substring(delim+1)).getCanonicalPath();
+					contexts.put(contextPath, warPath);
 
-			} else if ("-war".equals(arg)) {
-				warPath = args[++i];
+				} else if ("--glassfish".equalsIgnoreCase(arg)) {
+					server = new GlassFishServletServer();
 
-			} else if ("-c".equals(arg)) {
-				context = args[++i];
+				} else if ("--jetty".equalsIgnoreCase(arg)) {
+					server = new JettyServletServer();
 
-			} else if ("--glassfish".equalsIgnoreCase(arg)) {
-				server = new GlassFishServletServer();
+				} else if ("--tomcat".equalsIgnoreCase(arg)) {
+					server = new TomcatServletServer();
 
-			} else if ("--jetty".equalsIgnoreCase(arg)) {
-				server = new JettyServletServer();
+				} else if ("--help".equalsIgnoreCase(arg)) {
+					System.out.println(HELP);
+					System.out.println(SEPARATOR);
+					return;
 
-			} else if ("--tomcat".equalsIgnoreCase(arg)) {
+				} else {
+					System.out.println(HELP);
+					System.out.println(SEPARATOR);
+					return;
+				}
+			}
+
+			if (server == null) {
 				server = new TomcatServletServer();
+			}
 
-			} else if ("--help".equalsIgnoreCase(arg)) {
-				System.out.println(HELP);
-				System.out.println(SEPARATOR);
-				return;
-
-			} else {
-				System.out.println(HELP);
-				System.out.println(SEPARATOR);
-				return;
-			}
-		}
-
-		if (server == null) {
-			server = new TomcatServletServer();
-		}
-		
-		try {
 			System.out.println(" - servlet container: "+server.getName());
 
-			warPath = new File(warPath).getCanonicalPath();
-
-			System.out.println(" - war path: "+warPath);
-			System.out.println(" - context root: "+context);
+			for (String contextPath : contexts.keySet()) {
+				System.out.println(" - context root: "+contextPath);
+				System.out.println(" - war path: "+contexts.get(contextPath));
+			}
 			if (port > 0) {
 				System.out.println(" - Listening to HTTP on port: "+port);
 			} else {
 			System.out.println(SEPARATOR);
 			System.out.println();
 
-			server.start(warPath, context, port, https);
+			server.start(contexts, port, https);
 
 			System.in.read();
 

war-bootstrap/src/main/java/org/duelengine/bootstrap/GlassFishServletServer.java

 package org.duelengine.bootstrap;
 
 import java.io.File;
+import java.util.Map;
+
 import org.glassfish.embeddable.*;
 
 class GlassFishServletServer implements ServletServer {
 		return "GlassFish";
 	}
 
-	public void start(String warPath, String contextPath, int httpPort, int httpsPort) throws Exception {
+	public void start(Map<String, String> contexts, int httpPort, int httpsPort) throws Exception {
 		if (server != null) {
 			throw new IllegalStateException("Web server is already running.");
 		}
 		if (httpPort > 0) {
 			gfProps.setPort("http-listener", httpPort);
 		}
-		if (httpsPort > 0) {
-			gfProps.setPort("https-listener", httpsPort);
+//		if (httpsPort > 0) {
+//			gfProps.setPort("https-listener", httpsPort);
+//		}
+
+		server = GlassFishRuntime.bootstrap().newGlassFish(gfProps);
+
+		for (String contextPath : contexts.keySet()) {
+			File war = new File(contexts.get(contextPath));
+			Deployer deployer = server.getDeployer();
+			deployer.deploy(war, "--name="+war.getName(), "--contextroot="+contextPath, "--force=true");
 		}
 
-		server = GlassFishRuntime.bootstrap().newGlassFish(gfProps);
 		server.start();
-
-		File war = new File(warPath);
-		Deployer deployer = server.getDeployer();
-		deployer.deploy(war, "--name=webapp", "--contextroot="+contextPath, "--force=true");
 	}
 
 	public void stop() throws Exception {

war-bootstrap/src/main/java/org/duelengine/bootstrap/JettyServletServer.java

 package org.duelengine.bootstrap;
 
-import org.eclipse.jetty.server.*;
-import org.eclipse.jetty.servlet.*;
+import java.util.Map;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.servlet.DefaultServlet;
 import org.eclipse.jetty.webapp.WebAppContext;
 
 class JettyServletServer implements ServletServer {
 		return "Jetty";
 	}
 
-	public void start(String warPath, String contextPath, int httpPort, int httpsPort) throws Exception {
+	public void start(Map<String, String> contexts, int httpPort, int httpsPort) throws Exception {
 		if (server != null) {
 			throw new IllegalStateException("Web server is already running.");
 		}
 
 		server = new Server(httpPort);
 
-		WebAppContext webapp = new WebAppContext();
-		webapp.setContextPath(contextPath);
-		webapp.setWar(warPath);
+		for (String contextPath : contexts.keySet()) {
+			WebAppContext webapp = new WebAppContext();
+			webapp.setContextPath(contextPath);
+			webapp.setWar(contexts.get(contextPath));
 
-		// wire up DefaultServlet for static files
-		webapp.addServlet(DefaultServlet.class, "/*");
+			// wire up DefaultServlet for static files
+			webapp.addServlet(DefaultServlet.class, "/*");
 
-		server.setHandler(webapp);
+			server.setHandler(webapp);
+		}
 		server.start();
 	}
 

war-bootstrap/src/main/java/org/duelengine/bootstrap/ServletServer.java

 package org.duelengine.bootstrap;
 
+import java.util.Map;
+
 public interface ServletServer {
 
 	String getName();
 
-	void start(String warPath, String context, int httpPort, int httpsPort) throws Exception;
+	void start(Map<String, String> contexts, int httpPort, int httpsPort) throws Exception;
 
 	void stop() throws Exception;
-}
+}

war-bootstrap/src/main/java/org/duelengine/bootstrap/TomcatServletServer.java

 package org.duelengine.bootstrap;
 
 import java.io.File;
+import java.util.Map;
+
 import org.apache.catalina.core.StandardContext;
 import org.apache.catalina.startup.ContextConfig;
 import org.apache.catalina.startup.Tomcat;
 		return "Tomcat";
 	}
 
-	public void start(String warPath, String contextPath, int httpPort, int httpsPort) throws Exception {
+	public void start(Map<String, String> contexts, int httpPort, int httpsPort) throws Exception {
 		if (server != null) {
 			throw new IllegalStateException("Web server is already running.");
 		}
 
 		server = new Tomcat();
-		server.setBaseDir(new File(warPath, ".." + File.separatorChar + "tomcat").getCanonicalPath());
+		server.setBaseDir(new File("tomcat").getCanonicalPath());
 		server.setPort(httpPort);
 
 //		server.addWebapp(contextPath, warPath);
 
-        StandardContext ctx = new StandardContext();
-        ctx.setPath(contextPath);
-        ctx.setDocBase(warPath);
+		for (String contextPath : contexts.keySet()) {
+			StandardContext ctx = new StandardContext();
+			ctx.setPath(contextPath);
+			ctx.setDocBase(contexts.get(contextPath));
 
-        ctx.addLifecycleListener(new Tomcat.DefaultWebXmlListener());
-        
-        ContextConfig ctxCfg = new ContextConfig();
-        ctx.addLifecycleListener(ctxCfg);
-        
-        // prevent it from looking ( if it finds one - it'll have dup error )
-        ctxCfg.setDefaultWebXml("org/apache/catalin/startup/NO_DEFAULT_XML");
-        
-        server.getHost().addChild(ctx);
+			ctx.addLifecycleListener(new Tomcat.DefaultWebXmlListener());
+
+			ContextConfig ctxCfg = new ContextConfig();
+			ctx.addLifecycleListener(ctxCfg);
+
+			// prevent it from looking ( if it finds one - it'll have dup error )
+			ctxCfg.setDefaultWebXml("org/apache/catalin/startup/NO_DEFAULT_XML");
+
+			server.getHost().addChild(ctx);
+		}
 
 		server.start();
 	}