1 // ========================================================================
2 // Copyright 2004-2008 Mort Bay Consulting Pty. Ltd.
3 // ------------------------------------------------------------------------
4 // Licensed under the Apache 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 // http://www.apache.org/licenses/LICENSE-2.0
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 // ========================================================================
14 package org.mortbay.jetty.testing;
15
16 import java.io.IOException;
17 import java.net.Inet4Address;
18 import java.net.InetAddress;
19 import java.net.URL;
20 import java.util.Enumeration;
21 import java.util.EventListener;
22
23 import org.mortbay.io.ByteArrayBuffer;
24 import org.mortbay.jetty.LocalConnector;
25 import org.mortbay.jetty.Server;
26 import org.mortbay.jetty.bio.SocketConnector;
27 import org.mortbay.jetty.nio.SelectChannelConnector;
28 import org.mortbay.jetty.servlet.Context;
29 import org.mortbay.jetty.servlet.FilterHolder;
30 import org.mortbay.jetty.servlet.ServletHolder;
31 import org.mortbay.util.Attributes;
32
33
34
35 /* ------------------------------------------------------------ */
36 /** Testing support for servlets and filters.
37 *
38 * Allows a programatic setup of a context with servlets and filters for
39 * testing. Raw HTTP requests may be sent to the context and responses received.
40 * To avoid handling raw HTTP see {@link org.mortbay.jetty.testing.HttpTester}.
41 * <pre>
42 * ServletTester tester=new ServletTester();
43 * tester.setContextPath("/context");
44 * tester.addServlet(TestServlet.class, "/servlet/*");
45 * tester.addServlet("org.mortbay.jetty.servlet.DefaultServlet", "/");
46 * tester.start();
47 * String response = tester.getResponses("GET /context/servlet/info HTTP/1.0\r\n\r\n");
48 * </pre>
49 *
50 * @see org.mortbay.jetty.testing.HttpTester
51 * @author gregw
52 *
53 */
54 public class ServletTester
55 {
56 Server _server = new Server();
57 LocalConnector _connector = new LocalConnector();
58 Context _context = new Context(Context.SESSIONS|Context.SECURITY);
59
60 public ServletTester()
61 {
62 try
63 {
64 _server.setSendServerVersion(false);
65 _server.addConnector(_connector);
66 _server.addHandler(_context);
67 }
68 catch (Error e)
69 {
70 throw e;
71 }
72 catch (RuntimeException e)
73 {
74 throw e;
75 }
76 catch (Exception e)
77 {
78 throw new RuntimeException(e);
79 }
80 }
81
82 /* ------------------------------------------------------------ */
83 public void start() throws Exception
84 {
85 _server.start();
86 }
87
88 /* ------------------------------------------------------------ */
89 public void stop() throws Exception
90 {
91 _server.stop();
92 }
93
94 /* ------------------------------------------------------------ */
95 public Context getContext()
96 {
97 return _context;
98 }
99
100 /* ------------------------------------------------------------ */
101 /** Get raw HTTP responses from raw HTTP requests.
102 * Multiple requests and responses may be handled, but only if
103 * persistent connections conditions apply.
104 * @param rawRequests String of raw HTTP requests
105 * @return String of raw HTTP responses
106 * @throws Exception
107 */
108 public String getResponses(String rawRequests) throws Exception
109 {
110 _connector.reopen();
111 String responses = _connector.getResponses(rawRequests);
112 return responses;
113 }
114
115 /* ------------------------------------------------------------ */
116 /** Get raw HTTP responses from raw HTTP requests.
117 * Multiple requests and responses may be handled, but only if
118 * persistent connections conditions apply.
119 * @param rawRequests String of raw HTTP requests
120 * @param connector The connector to handle the responses
121 * @return String of raw HTTP responses
122 * @throws Exception
123 */
124 public String getResponses(String rawRequests, LocalConnector connector) throws Exception
125 {
126 connector.reopen();
127 String responses = connector.getResponses(rawRequests);
128 return responses;
129 }
130
131 /* ------------------------------------------------------------ */
132 /** Get raw HTTP responses from raw HTTP requests.
133 * Multiple requests and responses may be handled, but only if
134 * persistent connections conditions apply.
135 * @param rawRequests String of raw HTTP requests
136 * @return String of raw HTTP responses
137 * @throws Exception
138 */
139 public ByteArrayBuffer getResponses(ByteArrayBuffer rawRequests) throws Exception
140 {
141 _connector.reopen();
142 ByteArrayBuffer responses = _connector.getResponses(rawRequests,false);
143 return responses;
144 }
145
146 /* ------------------------------------------------------------ */
147 /** Get raw HTTP responses from raw HTTP requests.
148 * Multiple requests and responses may be handled, but only if
149 * persistent connections conditions apply.
150 * @param rawRequests String of raw HTTP requests
151 * @param connector The connector to handle the responses
152 * @return String of raw HTTP responses
153 * @throws Exception
154 */
155 public ByteArrayBuffer getResponses(ByteArrayBuffer rawRequests, LocalConnector connector) throws Exception
156 {
157 connector.reopen();
158 ByteArrayBuffer responses = connector.getResponses(rawRequests,false);
159 return responses;
160 }
161
162 /* ------------------------------------------------------------ */
163 /** Create a Socket connector.
164 * This methods adds a socket connector to the server
165 * @param locahost if true, only listen on local host, else listen on all interfaces.
166 * @return A URL to access the server via the socket connector.
167 * @throws Exception
168 */
169 public String createSocketConnector(boolean localhost)
170 throws Exception
171 {
172 synchronized (this)
173 {
174 SelectChannelConnector connector = new SelectChannelConnector();
175 if (localhost)
176 connector.setHost("127.0.0.1");
177 _server.addConnector(connector);
178 if (_server.isStarted())
179 connector.start();
180 else
181 connector.open();
182
183 return "http://"+(localhost?"127.0.0.1":
184 InetAddress.getLocalHost().getHostAddress()
185 )+":"+connector.getLocalPort();
186 }
187 }
188
189 /* ------------------------------------------------------------ */
190 /** Create a Socket connector.
191 * This methods adds a socket connector to the server
192 * @param locahost if true, only listen on local host, else listen on all interfaces.
193 * @return A URL to access the server via the socket connector.
194 * @throws Exception
195 */
196 public LocalConnector createLocalConnector()
197 throws Exception
198 {
199 synchronized (this)
200 {
201 LocalConnector connector = new LocalConnector();
202 _server.addConnector(connector);
203
204 if (_server.isStarted())
205 connector.start();
206
207 return connector;
208 }
209 }
210
211 /* ------------------------------------------------------------ */
212 /**
213 * @param listener
214 * @see org.mortbay.jetty.handler.ContextHandler#addEventListener(java.util.EventListener)
215 */
216 public void addEventListener(EventListener listener)
217 {
218 _context.addEventListener(listener);
219 }
220
221 /* ------------------------------------------------------------ */
222 /**
223 * @param filterClass
224 * @param pathSpec
225 * @param dispatches
226 * @return
227 * @see org.mortbay.jetty.servlet.Context#addFilter(java.lang.Class, java.lang.String, int)
228 */
229 public FilterHolder addFilter(Class filterClass, String pathSpec, int dispatches)
230 {
231 return _context.addFilter(filterClass,pathSpec,dispatches);
232 }
233
234 /* ------------------------------------------------------------ */
235 /**
236 * @param filterClass
237 * @param pathSpec
238 * @param dispatches
239 * @return
240 * @see org.mortbay.jetty.servlet.Context#addFilter(java.lang.String, java.lang.String, int)
241 */
242 public FilterHolder addFilter(String filterClass, String pathSpec, int dispatches)
243 {
244 return _context.addFilter(filterClass,pathSpec,dispatches);
245 }
246
247 /* ------------------------------------------------------------ */
248 /**
249 * @param servlet
250 * @param pathSpec
251 * @return
252 * @see org.mortbay.jetty.servlet.Context#addServlet(java.lang.Class, java.lang.String)
253 */
254 public ServletHolder addServlet(Class servlet, String pathSpec)
255 {
256 return _context.addServlet(servlet,pathSpec);
257 }
258
259 /* ------------------------------------------------------------ */
260 /**
261 * @param className
262 * @param pathSpec
263 * @return
264 * @see org.mortbay.jetty.servlet.Context#addServlet(java.lang.String, java.lang.String)
265 */
266 public ServletHolder addServlet(String className, String pathSpec)
267 {
268 return _context.addServlet(className,pathSpec);
269 }
270
271 /* ------------------------------------------------------------ */
272 /**
273 * @param name
274 * @return
275 * @see org.mortbay.jetty.handler.ContextHandler#getAttribute(java.lang.String)
276 */
277 public Object getAttribute(String name)
278 {
279 return _context.getAttribute(name);
280 }
281
282 /* ------------------------------------------------------------ */
283 /**
284 * @return
285 * @see org.mortbay.jetty.handler.ContextHandler#getAttributeNames()
286 */
287 public Enumeration getAttributeNames()
288 {
289 return _context.getAttributeNames();
290 }
291
292 /* ------------------------------------------------------------ */
293 /**
294 * @return
295 * @see org.mortbay.jetty.handler.ContextHandler#getAttributes()
296 */
297 public Attributes getAttributes()
298 {
299 return _context.getAttributes();
300 }
301
302 /* ------------------------------------------------------------ */
303 /**
304 * @return
305 * @see org.mortbay.jetty.handler.ContextHandler#getResourceBase()
306 */
307 public String getResourceBase()
308 {
309 return _context.getResourceBase();
310 }
311
312 /* ------------------------------------------------------------ */
313 /**
314 * @param name
315 * @param value
316 * @see org.mortbay.jetty.handler.ContextHandler#setAttribute(java.lang.String, java.lang.Object)
317 */
318 public void setAttribute(String name, Object value)
319 {
320 _context.setAttribute(name,value);
321 }
322
323 /* ------------------------------------------------------------ */
324 /**
325 * @param classLoader
326 * @see org.mortbay.jetty.handler.ContextHandler#setClassLoader(java.lang.ClassLoader)
327 */
328 public void setClassLoader(ClassLoader classLoader)
329 {
330 _context.setClassLoader(classLoader);
331 }
332
333 /* ------------------------------------------------------------ */
334 /**
335 * @param contextPath
336 * @see org.mortbay.jetty.handler.ContextHandler#setContextPath(java.lang.String)
337 */
338 public void setContextPath(String contextPath)
339 {
340 _context.setContextPath(contextPath);
341 }
342
343 /* ------------------------------------------------------------ */
344 /**
345 * @param eventListeners
346 * @see org.mortbay.jetty.handler.ContextHandler#setEventListeners(java.util.EventListener[])
347 */
348 public void setEventListeners(EventListener[] eventListeners)
349 {
350 _context.setEventListeners(eventListeners);
351 }
352
353 /* ------------------------------------------------------------ */
354 /**
355 * @param resourceBase
356 * @see org.mortbay.jetty.handler.ContextHandler#setResourceBase(java.lang.String)
357 */
358 public void setResourceBase(String resourceBase)
359 {
360 _context.setResourceBase(resourceBase);
361 }
362
363 }