001 // Copyright 2006 Howard M. Lewis Ship
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 com.javaforge.tapestry.testng;
016
017 import org.mortbay.jetty.Connector;
018 import org.mortbay.jetty.Server;
019 import org.mortbay.jetty.nio.BlockingChannelConnector;
020 import org.mortbay.jetty.webapp.WebAppContext;
021
022 import static java.lang.String.format;
023
024 /**
025 * A utitilty class for running an instance of the <a
026 * href="http://jetty.mortbay.com/jetty/index.html">Jetty servlet container</a> from within a unit
027 * test. This code is based on the Jetty 6 code base (which is in beta at the time of writing). When
028 * combined with <a href="http://jwebunit.sourceforge.net/">jWebUnit</a>, this allows for basic
029 * <em>integration</em> testing of an application from within a unit test case.
030 *
031 * @author Howard M. Lewis Ship
032 */
033 public class JettyRunner
034 {
035 public static final String DEFAULT_CONTEXT_PATH = "/";
036
037 public static final int DEFAULT_PORT = 80;
038
039 public static final String DEFAULT_WAR_PATH = "src/main/webapp";
040
041 private final String _contextPath;
042
043 private final int _port;
044
045 private final String _warPath;
046
047 private final Server _jetty;
048
049 /**
050 * Creates and starts a new instance of Jetty, using default configuration values. The
051 * contextPath will be /, the port will be 80, the warPath will be src/main/webapp.
052 */
053 public JettyRunner()
054 {
055 this(DEFAULT_CONTEXT_PATH, DEFAULT_PORT, DEFAULT_WAR_PATH);
056 }
057
058 /**
059 * Creates and starts a new instance of Jetty. This should be done from a test case setup
060 * method.
061 *
062 * @param contextPath
063 * the context path for the deployed application
064 * @param port
065 * the port number used to access the application
066 * @param warPath
067 * the path to the exploded web application (typically, "src/main/webapp")
068 */
069 public JettyRunner(String contextPath, int port, String warPath)
070 {
071 _contextPath = contextPath;
072 _port = port;
073 _warPath = warPath;
074
075 _jetty = new Server();
076
077 startJetty();
078 }
079
080 /** Stops the Jetty instance. This should be called from a test case tear down method. */
081 public void stop()
082 {
083 try
084 {
085 _jetty.stop();
086 }
087 catch (Exception ex)
088 {
089 throw new RuntimeException("Error stopping Jetty instance: " + ex.toString(), ex);
090 }
091 }
092
093 @Override
094 public String toString()
095 {
096 return format("<JettyRunner %s:%d (%s)>", _contextPath, _port, _warPath);
097 }
098
099 private void startJetty()
100 {
101 try
102 {
103 BlockingChannelConnector connector = new BlockingChannelConnector();
104 connector.setPort(_port);
105
106 _jetty.setConnectors(new Connector[]
107 { connector });
108
109 WebAppContext context = new WebAppContext();
110
111 context.setContextPath(_contextPath);
112 context.setWar(_warPath);
113
114 _jetty.addHandler(context);
115
116 _jetty.start();
117 }
118 catch (Exception ex)
119 {
120 throw new RuntimeException("Failure starting Jetty instance: " + ex.toString(), ex);
121 }
122 }
123
124 }