1 /*
2 * ========================================================================
3 *
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership.
7 * The ASF licenses this file to You under the Apache License, Version 2.0
8 * (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * ========================================================================
20 */
21 package org.apache.cactus.server;
22
23 import java.io.InputStream;
24
25 import java.lang.reflect.Constructor;
26
27 import java.net.MalformedURLException;
28 import java.net.URL;
29
30 import java.util.Enumeration;
31 import java.util.Hashtable;
32 import java.util.Vector;
33
34 import javax.servlet.RequestDispatcher;
35 import javax.servlet.Servlet;
36 import javax.servlet.ServletContext;
37 import javax.servlet.ServletException;
38
39 import org.apache.cactus.util.ChainedRuntimeException;
40
41 /**
42 * Abstract wrapper around <code>ServletContext</code>. This class provides
43 * a common implementation of the wrapper for the different servlet API. In
44 * addition to implementing the <code>ServletContext</code> interface it
45 * provides additional features helpful for writing unit tests. More
46 * specifically the <code>getRequestDispatcher()</code> method is overrided
47 * to return an request dispatcher wrapper. In addition logs generated by
48 * calls to the <code>log()</code> methods can be retrieved and asserted by
49 * calling the <code>getLogs()</code> method.
50 *
51 * @version $Id: AbstractServletContextWrapper.java 292559 2005-09-29 21:36:43Z kenney $
52 */
53 public abstract class AbstractServletContextWrapper implements ServletContext
54 {
55 /**
56 * The original servlet context object.
57 */
58 protected ServletContext originalContext;
59
60 /**
61 * List of parameters set using the <code>setInitParameter()</code> method.
62 */
63 protected Hashtable initParameters;
64
65 /**
66 * The logs resulting from calling the <code>log()</code> methods.
67 */
68 private Vector logs = new Vector();
69
70 // Constructors -------------------------------------------------------
71
72 /**
73 * @param theOriginalContext the original servlet context object
74 */
75 public AbstractServletContextWrapper(ServletContext theOriginalContext)
76 {
77 this.originalContext = theOriginalContext;
78 this.initParameters = new Hashtable();
79 }
80 /**
81 * @param theOriginalContext object
82 * @return AbstractServletContextWrapper
83 */
84 public static AbstractServletContextWrapper newInstance(ServletContext
85 theOriginalContext)
86 {
87 try
88 {
89 Class clazz = Class.forName(
90 "org.apache.cactus.server.ServletContextWrapper");
91 Object[] args = new Object[] {theOriginalContext};
92
93 Constructor constructor = clazz.getConstructor(new Class[] {
94 ServletContext.class });
95
96 return (AbstractServletContextWrapper)
97 constructor.newInstance(args);
98 }
99 catch (Throwable t)
100 {
101 throw new ChainedRuntimeException(
102 "Failed to create ServletContextWrapper", t);
103 }
104 }
105
106 // New methods ---------------------------------------------------------
107
108 /**
109 * @return the original unmodified config object
110 * @since 1.6
111 */
112 public ServletContext getOriginalContext()
113 {
114 return this.originalContext;
115 }
116
117 /**
118 * Sets a parameter as if it were set in the <code>web.xml</code> file
119 * (using the <context-param> element).
120 *
121 * @param theName the parameter's name
122 * @param theValue the parameter's value
123 */
124 public void setInitParameter(String theName, String theValue)
125 {
126 this.initParameters.put(theName, theValue);
127 }
128
129 /**
130 * Returns all the text logs that have been generated using the
131 * <code>log()</code> methods so that it is possible to easily assert the
132 * content of the logs. This method does not return the exceptions or
133 * throwable sent for logging; it only returns the messages.
134 *
135 * @return the logs as a vector of strings (each string contains the
136 * message that was sent for logging).
137 */
138 public Vector getLogs()
139 {
140 return this.logs;
141 }
142
143 // Overridden methods --------------------------------------------------
144
145 /**
146 * {@inheritDoc}
147 * @see ServletContext#setAttribute(String, Object)
148 */
149 public void setAttribute(String theName, Object theAttribute)
150 {
151 this.originalContext.setAttribute(theName, theAttribute);
152 }
153
154 /**
155 * {@inheritDoc}
156 * @see ServletContext#removeAttribute(String)
157 */
158 public void removeAttribute(String theName)
159 {
160 this.originalContext.removeAttribute(theName);
161 }
162
163 /**
164 * Intercept the log call and add the message to an internal vector of
165 * log messages that can then later be retrieved and asserted by the
166 * test case writer. Note that the throwable is not saved.
167 *
168 * @param theMessage a <code>String</code> that describes the error or
169 * exception
170 * @param theCause the <code>Throwable</code> error or exception
171 *
172 * @see #getLogs()
173 * @see ServletContext#log(String, Throwable)
174 */
175 public void log(String theMessage, Throwable theCause)
176 {
177 if (theMessage != null)
178 {
179 this.logs.addElement(theMessage);
180 }
181
182 this.originalContext.log(theMessage, theCause);
183 }
184
185 /**
186 * Intercept the log call and add the message to an internal vector of
187 * log messages that can then later be retrieved and asserted by the
188 * test case writer. Note that the throwable is not saved.
189 *
190 * @param theMessage a <code>String</code> that describes the error or
191 * exception
192 *
193 * @see #getLogs()
194 * @see ServletContext#log(String)
195 */
196 public void log(String theMessage)
197 {
198 if (theMessage != null)
199 {
200 this.logs.addElement(theMessage);
201 }
202
203 this.originalContext.log(theMessage);
204 }
205
206 /**
207 * Intercept the log call and add the message to an internal vector of
208 * log messages that can then later be retrieved and asserted by the
209 * test case writer. Note that the throwable is not saved.
210 *
211 * @param theException the exception to log
212 * @param theMessage a <code>String</code> that describes the error or
213 * exception
214 *
215 * @see #getLogs()
216 * @see ServletContext#log(Exception, String)
217 *
218 * @deprecated As of Java Servlet API 2.1, use
219 * {@link #log(String message, Throwable throwable)} instead.
220 * This method was originally defined to write an exception's
221 * stack trace and an explanatory error message to the servlet
222 * log file.
223 */
224 public void log(Exception theException, String theMessage)
225 {
226 if (theMessage != null)
227 {
228 this.logs.addElement(theMessage);
229 }
230
231 this.originalContext.log(theException, theMessage);
232 }
233
234 /**
235 * {@inheritDoc}
236 * @see ServletContext#getServlets()
237 */
238 public Enumeration getServlets()
239 {
240 return this.originalContext.getServlets();
241 }
242
243 /**
244 * {@inheritDoc}
245 * @see ServletContext#getServletNames()
246 */
247 public Enumeration getServletNames()
248 {
249 return this.originalContext.getServletNames();
250 }
251
252 /**
253 * {@inheritDoc}
254 * @see ServletContext#getServlet(String)
255 */
256 public Servlet getServlet(String theName) throws ServletException
257 {
258 return this.originalContext.getServlet(theName);
259 }
260
261 /**
262 * {@inheritDoc}
263 * @see ServletContext#getServerInfo()
264 */
265 public String getServerInfo()
266 {
267 return this.originalContext.getServerInfo();
268 }
269
270 /**
271 * {@inheritDoc}
272 * @see ServletContext#getResourceAsStream(String)
273 */
274 public InputStream getResourceAsStream(String thePath)
275 {
276 return this.originalContext.getResourceAsStream(thePath);
277 }
278
279 /**
280 * {@inheritDoc}
281 * @see ServletContext#getResource(String)
282 */
283 public URL getResource(String thePath) throws MalformedURLException
284 {
285 return this.originalContext.getResource(thePath);
286 }
287
288 /**
289 * @param thePath a string specifying the pathname to the resource
290 * @return our request dispatcher wrapper
291 * @see ServletContext#getRequestDispatcher(String)
292 */
293 public RequestDispatcher getRequestDispatcher(String thePath)
294 {
295 RequestDispatcher wrappedDispatcher = null;
296
297 RequestDispatcher originalDispatcher =
298 this.originalContext.getRequestDispatcher(thePath);
299
300 if (originalDispatcher != null)
301 {
302 wrappedDispatcher =
303 new RequestDispatcherWrapper(originalDispatcher);
304 }
305
306 return wrappedDispatcher;
307 }
308
309 /**
310 * @param theName a string specifying the name of a servlet to wrap
311 * @return our request dispatcher wrapper or null if the servlet cannot
312 * be found.
313 * @see ServletContext#getNamedDispatcher(String)
314 */
315 public RequestDispatcher getNamedDispatcher(String theName)
316 {
317 RequestDispatcher wrappedDispatcher = null;
318
319 RequestDispatcher originalDispatcher =
320 this.originalContext.getNamedDispatcher(theName);
321
322 if (originalDispatcher != null)
323 {
324 wrappedDispatcher =
325 new RequestDispatcherWrapper(originalDispatcher);
326 }
327
328 return wrappedDispatcher;
329 }
330
331 /**
332 * {@inheritDoc}
333 * @see ServletContext#getRealPath(String)
334 */
335 public String getRealPath(String thePath)
336 {
337 return this.originalContext.getRealPath(thePath);
338 }
339
340 /**
341 * {@inheritDoc}
342 * @see ServletContext#getMinorVersion()
343 */
344 public int getMinorVersion()
345 {
346 return this.originalContext.getMinorVersion();
347 }
348
349 /**
350 * {@inheritDoc}
351 * @see ServletContext#getMimeType(String)
352 */
353 public String getMimeType(String theFilename)
354 {
355 return this.originalContext.getMimeType(theFilename);
356 }
357
358 /**
359 * {@inheritDoc}
360 * @see ServletContext#getMajorVersion()
361 */
362 public int getMajorVersion()
363 {
364 return this.originalContext.getMajorVersion();
365 }
366
367 /**
368 * @return the union of the parameters defined in the Redirector
369 * <code>web.xml</code> file and the one set using the
370 * <code>setInitParameter()</code> method.
371 */
372 public Enumeration getInitParameterNames()
373 {
374 Vector names = new Vector();
375
376 // Add parameters that were added using setInitParameter()
377 Enumeration en = this.initParameters.keys();
378
379 while (en.hasMoreElements())
380 {
381 String value = (String) en.nextElement();
382
383 names.add(value);
384 }
385
386 // Add parameters from web.xml
387 en = this.originalContext.getInitParameterNames();
388
389 while (en.hasMoreElements())
390 {
391 String value = (String) en.nextElement();
392
393 // Do not add parameters that have been overriden by calling
394 // the setInitParameter() method.
395 if (!names.contains(value))
396 {
397 names.add(value);
398 }
399 }
400
401 return names.elements();
402 }
403
404 /**
405 * @param theName the name of the parameter's value to return
406 * @return the value of the parameter, looking for it first in the list of
407 * parameters set using the <code>setInitParameter()</code> method
408 * and then in those set in <code>web.xml</code>.
409 */
410 public String getInitParameter(String theName)
411 {
412 // Look first in the list of parameters set using the
413 // setInitParameter() method.
414 String value = (String) this.initParameters.get(theName);
415
416 if (value == null)
417 {
418 value = this.originalContext.getInitParameter(theName);
419 }
420
421 return value;
422 }
423
424 /**
425 * @param theUripath a String specifying the context path of another web
426 * application in the container
427 * @return our servlet context wrapper
428 * @see ServletContext#getContext(String)
429 */
430 public ServletContext getContext(String theUripath)
431 {
432 ServletContext context = AbstractServletContextWrapper.newInstance(
433 this.originalContext.getContext(theUripath));
434
435 return context;
436 }
437
438 /**
439 * {@inheritDoc}
440 * @see ServletContext#getAttributeNames()
441 */
442 public Enumeration getAttributeNames()
443 {
444 return this.originalContext.getAttributeNames();
445 }
446
447 /**
448 * {@inheritDoc}
449 * @see ServletContext#getAttribute(String)
450 */
451 public Object getAttribute(String theName)
452 {
453 return this.originalContext.getAttribute(theName);
454 }
455 }