1   package org.mortbay.jetty.testing;
2   
3   import java.io.IOException;
4   import java.net.Inet4Address;
5   import java.net.InetAddress;
6   import java.net.URL;
7   import java.util.Enumeration;
8   import java.util.EventListener;
9   
10  import org.mortbay.io.ByteArrayBuffer;
11  import org.mortbay.jetty.LocalConnector;
12  import org.mortbay.jetty.Server;
13  import org.mortbay.jetty.bio.SocketConnector;
14  import org.mortbay.jetty.servlet.Context;
15  import org.mortbay.jetty.servlet.FilterHolder;
16  import org.mortbay.jetty.servlet.ServletHolder;
17  import org.mortbay.util.Attributes;
18  
19  
20  
21  /* ------------------------------------------------------------ */
22  /** Testing support for servlets and filters.
23   * 
24   * Allows a programatic setup of a context with servlets and filters for 
25   * testing.  Raw HTTP requests may be sent to the context and responses received.
26   * To avoid handling raw HTTP see {@link org.mortbay.jetty.testing.HttpTester}.
27   * <pre>
28   *      ServletTester tester=new ServletTester();
29   *      tester.setContextPath("/context");
30   *      tester.addServlet(TestServlet.class, "/servlet/*");
31   *      tester.addServlet("org.mortbay.jetty.servlet.DefaultServlet", "/");
32   *      tester.start();
33   *      String response = tester.getResponses("GET /context/servlet/info HTTP/1.0\r\n\r\n");
34   * </pre>
35   * 
36   * @see org.mortbay.jetty.testing.HttpTester
37   * @author gregw
38   *
39   */
40  public class ServletTester
41  {
42      Server _server = new Server();
43      LocalConnector _connector = new LocalConnector();
44      Context _context = new Context(Context.SESSIONS|Context.SECURITY);
45      
46      public ServletTester()
47      {
48          try
49          {
50              _server.setSendServerVersion(false);
51              _server.addConnector(_connector);
52              _server.addHandler(_context);
53          }
54          catch (Error e)
55          {
56              throw e;
57          }
58          catch (RuntimeException e)
59          {
60              throw e;
61          }
62          catch (Exception e)
63          {
64              throw new RuntimeException(e);
65          }
66      }
67  
68      /* ------------------------------------------------------------ */
69      public void start() throws Exception
70      {
71          _server.start();
72      }
73      
74      /* ------------------------------------------------------------ */
75      public void stop() throws Exception
76      {
77          _server.stop();
78      }
79      
80      /* ------------------------------------------------------------ */
81      /** Get raw HTTP responses from raw HTTP requests.
82       * Multiple requests and responses may be handled, but only if
83       * persistent connections conditions apply.
84       * @param rawRequests String of raw HTTP requests
85       * @return String of raw HTTP responses
86       * @throws Exception
87       */
88      public String getResponses(String rawRequests) throws Exception
89      {
90          _connector.reopen();
91          //System.err.println(">>>>\n"+rawRequests);
92          String responses = _connector.getResponses(rawRequests);
93          //System.err.println("<<<<\n"+responses);
94          return responses;
95      }
96  
97      /* ------------------------------------------------------------ */
98      /** Get raw HTTP responses from raw HTTP requests.
99       * Multiple requests and responses may be handled, but only if
100      * persistent connections conditions apply.
101      * @param rawRequests String of raw HTTP requests
102      * @return String of raw HTTP responses
103      * @throws Exception
104      */
105     public ByteArrayBuffer getResponses(ByteArrayBuffer rawRequests) throws Exception
106     {
107         _connector.reopen();
108         ByteArrayBuffer responses = _connector.getResponses(rawRequests,false);
109         return responses;
110     }
111     
112     /* ------------------------------------------------------------ */
113     /** Create a Socket connector.
114      * This methods adds a socket connector to the server
115      * @param locahost if true, only listen on local host, else listen on all interfaces.
116      * @return A URL to access the server via the socket connector.
117      * @throws Exception
118      */
119     public String createSocketConnector(boolean localhost)
120     throws Exception
121     {
122        SocketConnector connector = new SocketConnector();
123        if (localhost)
124            connector.setHost("127.0.0.1");
125        _server.addConnector(connector);
126        if (_server.isStarted())
127            connector.start();
128        else
129            connector.open();
130        
131        return "http://"+(localhost?"127.0.0.1":
132        InetAddress.getLocalHost().getHostAddress()    
133        )+":"+connector.getLocalPort();
134    }
135 
136     /* ------------------------------------------------------------ */
137     /**
138      * @param listener
139      * @see org.mortbay.jetty.handler.ContextHandler#addEventListener(java.util.EventListener)
140      */
141     public void addEventListener(EventListener listener)
142     {
143         _context.addEventListener(listener);
144     }
145 
146     /* ------------------------------------------------------------ */
147     /**
148      * @param filterClass
149      * @param pathSpec
150      * @param dispatches
151      * @return
152      * @see org.mortbay.jetty.servlet.Context#addFilter(java.lang.Class, java.lang.String, int)
153      */
154     public FilterHolder addFilter(Class filterClass, String pathSpec, int dispatches)
155     {
156         return _context.addFilter(filterClass,pathSpec,dispatches);
157     }
158 
159     /* ------------------------------------------------------------ */
160     /**
161      * @param filterClass
162      * @param pathSpec
163      * @param dispatches
164      * @return
165      * @see org.mortbay.jetty.servlet.Context#addFilter(java.lang.String, java.lang.String, int)
166      */
167     public FilterHolder addFilter(String filterClass, String pathSpec, int dispatches)
168     {
169         return _context.addFilter(filterClass,pathSpec,dispatches);
170     }
171 
172     /* ------------------------------------------------------------ */
173     /**
174      * @param servlet
175      * @param pathSpec
176      * @return
177      * @see org.mortbay.jetty.servlet.Context#addServlet(java.lang.Class, java.lang.String)
178      */
179     public ServletHolder addServlet(Class servlet, String pathSpec)
180     {
181         return _context.addServlet(servlet,pathSpec);
182     }
183 
184     /* ------------------------------------------------------------ */
185     /**
186      * @param className
187      * @param pathSpec
188      * @return
189      * @see org.mortbay.jetty.servlet.Context#addServlet(java.lang.String, java.lang.String)
190      */
191     public ServletHolder addServlet(String className, String pathSpec)
192     {
193         return _context.addServlet(className,pathSpec);
194     }
195 
196     /* ------------------------------------------------------------ */
197     /**
198      * @param name
199      * @return
200      * @see org.mortbay.jetty.handler.ContextHandler#getAttribute(java.lang.String)
201      */
202     public Object getAttribute(String name)
203     {
204         return _context.getAttribute(name);
205     }
206 
207     /* ------------------------------------------------------------ */
208     /**
209      * @return
210      * @see org.mortbay.jetty.handler.ContextHandler#getAttributeNames()
211      */
212     public Enumeration getAttributeNames()
213     {
214         return _context.getAttributeNames();
215     }
216 
217     /* ------------------------------------------------------------ */
218     /**
219      * @return
220      * @see org.mortbay.jetty.handler.ContextHandler#getAttributes()
221      */
222     public Attributes getAttributes()
223     {
224         return _context.getAttributes();
225     }
226 
227     /* ------------------------------------------------------------ */
228     /**
229      * @return
230      * @see org.mortbay.jetty.handler.ContextHandler#getResourceBase()
231      */
232     public String getResourceBase()
233     {
234         return _context.getResourceBase();
235     }
236 
237     /* ------------------------------------------------------------ */
238     /**
239      * @param name
240      * @param value
241      * @see org.mortbay.jetty.handler.ContextHandler#setAttribute(java.lang.String, java.lang.Object)
242      */
243     public void setAttribute(String name, Object value)
244     {
245         _context.setAttribute(name,value);
246     }
247 
248     /* ------------------------------------------------------------ */
249     /**
250      * @param classLoader
251      * @see org.mortbay.jetty.handler.ContextHandler#setClassLoader(java.lang.ClassLoader)
252      */
253     public void setClassLoader(ClassLoader classLoader)
254     {
255         _context.setClassLoader(classLoader);
256     }
257 
258     /* ------------------------------------------------------------ */
259     /**
260      * @param contextPath
261      * @see org.mortbay.jetty.handler.ContextHandler#setContextPath(java.lang.String)
262      */
263     public void setContextPath(String contextPath)
264     {
265         _context.setContextPath(contextPath);
266     }
267 
268     /* ------------------------------------------------------------ */
269     /**
270      * @param eventListeners
271      * @see org.mortbay.jetty.handler.ContextHandler#setEventListeners(java.util.EventListener[])
272      */
273     public void setEventListeners(EventListener[] eventListeners)
274     {
275         _context.setEventListeners(eventListeners);
276     }
277 
278     /* ------------------------------------------------------------ */
279     /**
280      * @param resourceBase
281      * @see org.mortbay.jetty.handler.ContextHandler#setResourceBase(java.lang.String)
282      */
283     public void setResourceBase(String resourceBase)
284     {
285         _context.setResourceBase(resourceBase);
286     }
287     
288 }