View Javadoc

1   /**
2    * Copyright 2005-2011 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.test.launch;
17  
18  import java.io.File;
19  import java.util.ArrayList;
20  import java.util.List;
21  import java.util.StringTokenizer;
22  
23  import javax.servlet.Servlet;
24  
25  import org.apache.commons.collections.CollectionUtils;
26  import org.apache.commons.lang.builder.ToStringBuilder;
27  import org.eclipse.jetty.server.Server;
28  import org.eclipse.jetty.servlet.ServletContextHandler;
29  import org.eclipse.jetty.servlet.ServletHolder;
30  import org.eclipse.jetty.util.resource.ResourceCollection;
31  import org.eclipse.jetty.webapp.WebAppContext;
32  
33  public class JettyLauncher {
34  	
35  	private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(JettyLauncher.class);
36  	
37      /**
38       * The name of an attribute we set in the ServletContext to indicate to the webapp
39       * that it is running within unit tests, in case it needs to alter its configuration
40       * or behavior.
41       */
42      public static final String JETTYSERVER_TESTMODE_ATTRIB = "JETTYSERVER_TESTMODE";
43  
44  	private int port;
45  	private String contextName;	
46  	private List<String> relativeWebappRoots = new ArrayList<String>();
47  	private Class<? extends Servlet> servletClass;
48  	private Server server;
49  	private ServletContextHandler context;
50  	private boolean failOnContextFailure;
51  
52  	/**
53  	 * Whether we are in test mode
54  	 */
55  	private boolean testMode = false;
56  
57  	public JettyLauncher() {
58  		this(8080);
59  	}
60  
61  	public JettyLauncher(int port) {
62  		this(port, null, null, null);
63  	}
64  
65  	public JettyLauncher(int port, String contextName) {
66  		this(port, contextName, null, null);
67  	}
68  	
69  	public JettyLauncher(int port, String contextName, String relativeWebappRoot) {
70          this(port, contextName, relativeWebappRoot, null);
71  	}	
72  
73      public JettyLauncher(int port, String contextName, Class<? extends Servlet> servletClass) {
74          this(port, contextName, null, servletClass);
75      }   
76  
77      public JettyLauncher(int port, String contextName, String relativeWebappRoots, Class<? extends Servlet> servletClass) {
78          this.port = port;
79          this.contextName = contextName;
80          StringTokenizer tokenizer = new StringTokenizer(relativeWebappRoots, ",");
81          while (tokenizer.hasMoreTokens()) {
82              String relativeWebappRoot = tokenizer.nextToken();
83              this.relativeWebappRoots.add(relativeWebappRoot);
84          }
85          this.servletClass = servletClass;
86      }   
87  
88      public void setTestMode(boolean t) {
89  	    this.testMode = t;
90  	}
91  
92  	public boolean isTestMode() {
93  	    return testMode;
94  	}
95  
96  	public Server getServer() {
97  		return server;
98  	}
99  
100 	public ServletContextHandler getContext() {
101 	    return context;
102 	}
103 
104 	public void start() throws Exception {
105 		server = createServer();
106 		server.start();
107 		if (isFailOnContextFailure() && contextStartupFailed()) {
108 			try {
109 				server.stop();
110 			} catch (Exception e) {
111 				LOG.warn("Failed to stop server after web application startup failure.");
112 			}
113 			throw new Exception("Failed to startup web application context!  Check logs for specific error.");
114 		}
115 	}
116 
117 	public void stop() throws Exception {
118 		server.stop(); 
119 	}
120 
121 	public boolean isStarted() {
122 		return server.isStarted();
123 	}
124 
125 	protected Server createServer() {
126 		Server server = new Server(getPort());
127 		setBaseDirSystemProperty();
128 		if (useWebAppContext()) {
129 			File tmpDir = new File(System.getProperty("basedir") + "/target/jetty-tmp");
130 			tmpDir.mkdirs();
131 			WebAppContext webAppContext = new WebAppContext();
132 			webAppContext.setContextPath(getContextName());
133 			String[] fullRelativeWebappRoots = new String[this.relativeWebappRoots.size()];
134 			for (int i = 0; i < this.relativeWebappRoots.size(); i++) {
135 				String fullRelativeWebappRoot = this.relativeWebappRoots.get(i);
136 				fullRelativeWebappRoots[i] = System.getProperty("basedir") + fullRelativeWebappRoot;
137 				if (LOG.isInfoEnabled()) {
138 					LOG.info("WebAppRoot = " + fullRelativeWebappRoots[i]);
139 				}
140 			}
141 			webAppContext.setBaseResource(new ResourceCollection(fullRelativeWebappRoots));
142 			webAppContext.setTempDirectory(tmpDir);
143 			webAppContext.setAttribute(JETTYSERVER_TESTMODE_ATTRIB, String.valueOf(isTestMode()));
144 			context = webAppContext;
145 			server.setHandler(context);
146 		} else {
147 			ServletContextHandler root = new ServletContextHandler(server,"/",ServletContextHandler.SESSIONS);
148 			root.addServlet(new ServletHolder(servletClass), getContextName());
149 			root.setAttribute(JETTYSERVER_TESTMODE_ATTRIB, String.valueOf(isTestMode()));
150 			context = root;
151 		}
152 		return server;
153 	}
154 
155 	protected void setBaseDirSystemProperty() {
156 		if (System.getProperty("basedir") == null) {
157 			System.setProperty("basedir", System.getProperty("user.dir"));
158 		}
159 	}
160 	
161 	private boolean useWebAppContext() {
162 		return CollectionUtils.isNotEmpty(this.relativeWebappRoots);
163 	}
164 
165 	protected boolean contextStartupFailed() throws Exception {
166         return !context.isAvailable();
167 	}
168 	
169 	public String getContextName() {
170 		if (contextName == null) {
171 			return "/SampleRiceClient";
172 		}
173 		return contextName;
174 	}
175 
176 	public void setContextName(String contextName) {
177 		this.contextName = contextName;
178 	}
179 
180 	public int getPort() {
181 		return port;
182 	}
183 
184 	public void setPort(int port) {
185 		this.port = port;
186 	}
187 	
188 	
189 	public boolean isFailOnContextFailure() {
190 		return this.failOnContextFailure;
191 	}
192 
193 	public void setFailOnContextFailure(boolean failOnContextFailure) {
194 		this.failOnContextFailure = failOnContextFailure;
195 	}
196 
197 	public String toString() {
198 	    return new ToStringBuilder(this).append("port", port)
199 	                                    .append("contextName", contextName)
200 	                                    .append("relativeWebappRoots", relativeWebappRoots)
201                                         .append("servletClass", servletClass)
202 	                                    .toString();
203 	}
204 
205     public static void main(String[] args) {
206         int port = args.length > 0 ? Integer.parseInt(args[0]) : 8080;
207         String contextName = args.length > 1 ? args[1] : null;
208         String relativeWebappRoot = args.length > 2 ? args[2] : null;
209         try {
210             new JettyLauncher(port, contextName, relativeWebappRoot).start();
211         } catch (Exception e) {
212             e.printStackTrace();
213         }
214     }
215 }