001 // Copyright 2006, 2007, 2008 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry5.test;
016
017 import org.mortbay.http.NCSARequestLog;
018 import org.mortbay.http.SocketListener;
019 import org.mortbay.http.SunJsseListener;
020 import org.mortbay.jetty.Server;
021 import org.mortbay.jetty.servlet.WebApplicationContext;
022
023 import java.io.File;
024 import static java.lang.String.format;
025
026 /**
027 * Used to start up an instance of the Jetty servlet container in-process, as part of an integration test suite. The
028 * started Jetty is reliant on the file <code>src/test/conf/webdefault.xml</code>.
029 *
030 * @see AbstractIntegrationTestSuite
031 */
032 public class JettyRunner
033 {
034 public static final String DEFAULT_CONTEXT_PATH = "/";
035
036 public static final int DEFAULT_PORT = 8080;
037
038 public static final int DEFAULT_SECURE_PORT = 8443;
039
040 private final File workingDir;
041
042 private final String contextPath;
043
044 private final int port;
045
046 private final String warPath;
047
048 private final Server jetty;
049
050 private final String[] virtualHosts;
051
052 /**
053 * Creates and starts a new instance of Jetty. This should be done from a test case setup method.
054 *
055 * @param workingDir current directory (used for any relative files)
056 * @param contextPath the context path for the deployed application
057 * @param port the port number used to access the application
058 * @param warPath the path to the exploded web application (typically, "src/main/webapp")
059 * @param virtualHosts an array with virtual hosts
060 */
061 public JettyRunner(File workingDir, String contextPath, int port, String warPath,
062 String ... virtualHosts)
063 {
064 this.workingDir = workingDir;
065 this.contextPath = contextPath;
066 this.port = port;
067 this.warPath = warPath;
068 this.virtualHosts = virtualHosts;
069
070 jetty = createAndStart();
071 }
072
073 /**
074 * Stops the Jetty instance. This should be called from a test case tear down method.
075 */
076 public void stop()
077 {
078 System.out.printf("Stopping Jetty instance on port %d\n", port);
079
080 try
081 {
082 // Stop immediately and not gracefully.
083 jetty.stop(false);
084
085 while (jetty.isStarted())
086 {
087 Thread.sleep(100);
088 }
089 }
090 catch (Exception ex)
091 {
092 throw new RuntimeException("Error stopping Jetty instance: " + ex.toString(), ex);
093 }
094
095 System.out.println("Jetty instance has stopped.");
096 }
097
098 @Override
099 public String toString()
100 {
101 return format("<JettyRunner %s:%d (%s)>", contextPath, port, warPath);
102 }
103
104
105 private Server createAndStart()
106 {
107 try
108 {
109
110 File warPathFile = new File(warPath);
111
112 String webappPath = warPathFile.isAbsolute()
113 ? warPath
114 : new File(workingDir, this.warPath).getPath();
115 String webDefaults = new File(workingDir, "src/test/conf/webdefault.xml").getPath();
116
117 File keystoreFile = new File(workingDir, "src/test/conf/keystore");
118 String keystore = keystoreFile.getPath();
119
120 System.out.printf("Starting Jetty instance on port %d (%s mapped to %s)\n", port, contextPath, webappPath);
121
122 Server server = new Server();
123
124
125 SocketListener socketListener = new SocketListener();
126 socketListener.setPort(port);
127 server.addListener(socketListener);
128
129 if (keystoreFile.exists())
130 {
131 SunJsseListener secureListener = new SunJsseListener();
132 secureListener.setPort(DEFAULT_SECURE_PORT);
133 secureListener.setKeystore(keystore);
134 secureListener.setPassword("tapestry");
135 secureListener.setKeyPassword("tapestry");
136
137 server.addListener(secureListener);
138 }
139
140 NCSARequestLog log = new NCSARequestLog();
141 server.setRequestLog(log);
142
143 WebApplicationContext context = server.addWebApplication(contextPath, webappPath);
144
145 for (String virtualHost : virtualHosts) {
146 context.addVirtualHost(virtualHost);
147 }
148
149 context.setDefaultsDescriptor(webDefaults);
150
151 server.start();
152
153 return server;
154 }
155 catch (Exception ex)
156 {
157 throw new RuntimeException("Failure starting Jetty instance: " + ex.toString(), ex);
158 }
159 }
160 }