View Javadoc
1   /**
2    * Copyright 2004-2015 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 }