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 }