1 package servletunit;
2
3 // StrutsTestCase - a JUnit extension for testing Struts actions
4 // within the context of the ActionServlet.
5 // Copyright (C) 2002 Deryl Seale
6 //
7 // This library is free software; you can redistribute it and/or
8 // modify it under the terms of the Apache Software License as
9 // published by the Apache Software Foundation; either version 1.1
10 // of the License, or (at your option) any later version.
11 //
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // Apache Software Foundation Licens for more details.
16 //
17 // You may view the full text here: http://www.apache.org/LICENSE.txt
18
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21
22 import javax.servlet.RequestDispatcher;
23 import javax.servlet.Servlet;
24 import javax.servlet.ServletContext;
25 import javax.servlet.ServletException;
26 import java.io.InputStream;
27 import java.io.File;
28 import java.io.FileInputStream;
29 import java.net.MalformedURLException;
30 import java.net.URL;
31 import java.util.Enumeration;
32 import java.util.Hashtable;
33 import java.util.Set;
34
35 /**
36 * This class simulates a ServletContext.
37 */
38 public class ServletContextSimulator implements ServletContext
39 {
40
41 private Hashtable initParameters;
42 private Hashtable attributes;
43 private RequestDispatcherSimulator dispatcher = null;
44 private static Log logger = LogFactory.getLog( ServletContextSimulator.class );
45 private File contextDirectory;
46
47 public ServletContextSimulator() {
48 this.initParameters = new Hashtable();
49 this.attributes = new Hashtable();
50 }
51
52 /**
53 * Returns the servlet container attribute with the given name,
54 * or <code>null</code> if there is no attribute by that name.
55 * An attribute allows a servlet container to give the
56 * servlet additional information not
57 * already provided by this interface. See your
58 * server documentation for information about its attributes.
59 * A list of supported attributes can be retrieved using
60 * <code>getAttributeNames</code>.
61 *
62 * <p>The attribute is returned as a <code>java.lang.Object</code>
63 * or some subclass.
64 * Attribute names should follow the same convention as package
65 * names. The Java Servlet API specification reserves names
66 * matching <code>java.*</code>, <code>javax.*</code>,
67 * and <code>sun.*</code>.
68 *
69 *
70 * @param name a <code>String</code> specifying the name
71 * of the attribute
72 *
73 * @return an <code>Object</code> containing the value
74 * of the attribute, or <code>null</code>
75 * if no attribute exists matching the given
76 * name
77 *
78 * @see ServletContext#getAttributeNames
79 *
80 */
81 public Object getAttribute(String name)
82 {
83 return attributes.get(name);
84 }
85
86 /**
87 * Returns an <code>Enumeration</code> containing the
88 * attribute names available
89 * within this servlet context. Use the
90 * {@link #getAttribute} method with an attribute name
91 * to get the value of an attribute.
92 *
93 * @return an <code>Enumeration</code> of attribute
94 * names
95 *
96 * @see #getAttribute
97 *
98 */
99 public Enumeration getAttributeNames()
100 {
101 return attributes.keys();
102 }
103
104 /**
105 * Unsupported in this version.
106 */
107 public ServletContext getContext(String uripath)
108 {
109 throw new UnsupportedOperationException("getContext operation is not supported!");
110 }
111
112 /**
113 * Returns a <code>String</code> containing the value of the named
114 * context-wide initialization parameter, or <code>null</code> if the
115 * parameter does not exist.
116 *
117 * <p>This method can make available configuration information useful
118 * to an entire "web application". For example, it can provide a
119 * webmaster's email address or the name of a system that holds
120 * critical data.
121 *
122 * @param s a <code>String</code> containing the name of the
123 * parameter whose value is requested
124 *
125 * @return a <code>String</code> containing at least the
126 * servlet container name and version number
127 *
128 * @see javax.servlet.ServletConfig#getInitParameter
129 */
130 public String getInitParameter(String s)
131 {
132 return (String) initParameters.get(s);
133 }
134
135 /**
136 * Returns the names of the context's initialization parameters as an
137 * <code>Enumeration</code> of <code>String</code> objects, or an
138 * empty <code>Enumeration</code> if the context has no initialization
139 * parameters.
140 *
141 * @return an <code>Enumeration</code> of <code>String</code>
142 * objects containing the names of the context's
143 * initialization parameters
144 *
145 * @see javax.servlet.ServletConfig#getInitParameter
146 */
147 public Enumeration getInitParameterNames()
148 {
149 return initParameters.keys();
150 }
151
152 /**
153 * Sets a named initialization parameter with the supplied
154 * <code>String</code> value.
155 *
156 * @param key a <code>String</code> specifying the name
157 * of the initialization parameter
158 *
159 * @param value a <code>String</code> value for this initialization
160 * parameter
161 *
162 */
163 public void setInitParameter(String key,String value)
164 {
165 initParameters.put(key,value);
166 }
167
168 /**
169 * Returns the major version of the Java Servlet API that this
170 * Web server supports. All implementations that comply
171 * with Version 2.3 must have this method
172 * return the integer 2.
173 *
174 * @return 2
175 *
176 */
177 public int getMajorVersion()
178 {
179 return 2;
180 }
181
182 /**
183 * Unsupported in this version.
184 */
185 public String getMimeType(String file)
186 {
187 throw new UnsupportedOperationException("getMimeType operation is not supported!");
188 }
189
190 /**
191 * Returns the minor version of the Servlet API that this
192 * Web server supports. All implementations that comply
193 * with Version 2.3 must have this method
194 * return the integer 1.
195 *
196 * @return 3
197 *
198 */
199 public int getMinorVersion()
200 {
201 return 3;
202 }
203
204 public RequestDispatcher getNamedDispatcher(String s)
205 {
206 throw new UnsupportedOperationException("getNamedDispatcher operation is not supported!");
207 }
208
209 public String getRealPath(String path)
210 {
211 if ((contextDirectory == null) || (path == null))
212 return null;
213 else
214 return (new File(contextDirectory, path)).getAbsolutePath();
215 }
216
217 /**
218 *
219 * Returns a {@link RequestDispatcher} object that acts
220 * as a wrapper for the resource located at the given path.
221 * A <code>RequestDispatcher</code> object can be used to forward
222 * a request to the resource or to include the resource in a response.
223 * The resource can be dynamic or static.
224 *
225 * <p>The pathname must begin with a "/" and is interpreted as relative
226 * to the current context root. Use <code>getContext</code> to obtain
227 * a <code>RequestDispatcher</code> for resources in foreign contexts.
228 * This method returns <code>null</code> if the <code>ServletContext</code>
229 * cannot return a <code>RequestDispatcher</code>.
230 *
231 * @param urlpath a <code>String</code> specifying the pathname
232 * to the resource
233 *
234 * @return a <code>RequestDispatcher</code> object
235 * that acts as a wrapper for the resource
236 * at the specified path
237 *
238 * @see RequestDispatcher
239 * @see ServletContext#getContext
240 *
241 */
242 public RequestDispatcher getRequestDispatcher(String urlpath)
243 {
244 dispatcher = new RequestDispatcherSimulator(urlpath);
245 return dispatcher;
246 }
247
248 /**
249 * Returns the mock RequestDispatcher object used in this test.
250 * The RequestDispatcherSimulator contains forwarding information
251 * that can be used in test validation.
252 */
253 public RequestDispatcherSimulator getRequestDispatcherSimulator() {
254 return dispatcher;
255 }
256
257 /**
258 * TODO: add appropriate comments
259 */
260 public URL getResource(String path) throws MalformedURLException
261 {
262 try {
263 File file = getResourceAsFile(path);
264
265 if (file.exists()) {
266 return file.toURL();
267 }
268 else {
269 if(!path.startsWith("/")){
270 path = "/" + path;
271 }
272 return this.getClass().getResource(path);
273 }
274 } catch (Exception e) {
275 return null;
276 }
277 }
278
279 /**
280 * Returns the resource located at the named path as
281 * an <code>InputStream</code> object.
282 *
283 * <p>The data in the <code>InputStream</code> can be
284 * of any type or length. The path must be specified according
285 * to the rules given in <code>getResource</code>.
286 * This method returns <code>null</code> if no resource exists at
287 * the specified path.
288 *
289 * <p>Meta-information such as content length and content type
290 * that is available via <code>getResource</code>
291 * method is lost when using this method.
292 *
293 * <p>The servlet container must implement the URL handlers
294 * and <code>URLConnection</code> objects necessary to access
295 * the resource.
296 *
297 * <p>In this mock implementation, this method first looks for
298 * the supplied pathname in the underlying filesystem; if it
299 * does not exist there, the default Java classloader is used.
300 *
301 *
302 * @param path a <code>String</code> specifying the path
303 * to the resource
304 *
305 * @return the <code>InputStream</code> returned to the
306 * servlet, or <code>null</code> if no resource
307 * exists at the specified path
308 *
309 *
310 */
311 public InputStream getResourceAsStream(String path)
312 {
313 try {
314 File file = getResourceAsFile(path);
315
316 if (file.exists()) {
317 return new FileInputStream(file);
318 }
319 else {
320 if(!path.startsWith("/")){
321 path = "/" + path;
322 }
323 return this.getClass().getResourceAsStream(path);
324 }
325 } catch (Exception e) {
326 System.out.println("caught error: " + e);
327 e.printStackTrace();
328 return null;
329 }
330 }
331
332 /**
333 * Attempts to load a resource from the underlying file system
334 * and return a file handle to it.
335 * It first treats the path as an absolute path. If no file is found,
336 * it attempts to treat the path as relative to the context directory.
337 * If no file is found, it attempts to treat the path as relative to
338 * the current directory.
339 * If all these options fail, the returned file will return false()
340 * to calls to File.exists().
341 * @param path the relative or context-relative path to the file
342 * @return the refernce to the file (which may or may not exist)
343 */
344 public File getResourceAsFile(String path){
345 File file = new File(path);
346
347 // If the path is relative then apply the contextDirectory path if it exists.
348 if (!file.exists())
349 {
350 if(!path.startsWith("/")){
351 path = "/" + path;
352 }
353 if((getContextDirectory() != null))
354 {
355 file = new File(getContextDirectory().getAbsolutePath() + path);
356 }else{
357 //try using current directory
358 file = new File(new File(".").getAbsolutePath() + path);
359 }
360 }
361 return file;
362
363 }
364
365 /**
366 * Unsupported in this version.
367 */
368 public Set getResourcePaths()
369 {
370 throw new UnsupportedOperationException("getResourcePaths operation is not supported!");
371 }
372
373 /**
374 * Returns the name and version of the servlet container on which
375 * the servlet is running.
376 *
377 * <p>The form of the returned string is
378 * <i>servername</i>/<i>versionnumber</i>.
379 * For example, the JavaServer Web Development Kit may return the string
380 * <code>JavaServer Web Dev Kit/1.0</code>.
381 *
382 * <p>The servlet container may return other optional information
383 * after the primary string in parentheses, for example,
384 * <code>JavaServer Web Dev Kit/1.0 (JDK 1.1.6; Windows NT 4.0 x86)</code>.
385 *
386 *
387 * @return a <code>String</code> containing at least the
388 * servlet container name and version number
389 *
390 */
391 public String getServerInfo()
392 {
393 return "MockServletEngine/1.9.5";
394 }
395
396 /**
397 * Unsupported in this version.
398 */
399 public Servlet getServlet(String name) throws ServletException
400 {
401 throw new UnsupportedOperationException("getServlet operation is not supported!");
402 }
403
404 /**
405 * Unsupported in this version.
406 */
407 public String getServletContextName()
408 {
409 throw new UnsupportedOperationException("getServletContextName operation is not supported!");
410 }
411
412 /**
413 * Unsupported in this version.
414 */
415 public Enumeration getServletNames()
416 {
417 throw new UnsupportedOperationException("getServletNames operation is not supported!");
418 }
419
420 /**
421 * Unsupported in this version.
422 */
423 public Enumeration getServlets()
424 {
425 throw new UnsupportedOperationException("getServlets operation is not supported!");
426 }
427
428 /**
429 * @deprecated As of Java Servlet API 2.1, use
430 * @link ServletContext.log(String message, Throwable throwable)
431 * instead.
432 *
433 * <p>This method was originally defined to write an
434 * exception's stack trace and an explanatory error message
435 * to the servlet log file.
436 *
437 */
438 public void log(Exception exception, String msg)
439 {
440 logger.info(msg + "\n" + exception.getClass() + " - " + exception.getMessage());
441 }
442
443 /**
444 *
445 * Writes the specified message to a servlet log file, which is usually
446 * an event log. The message provides explanatory information about
447 * an exception or error or an action the servlet engine takes. The name
448 * and type of the servlet log file is specific to the servlet engine.
449 *
450 *
451 * @param msg a <code>String</code> specifying the explanatory
452 * message to be written to the log file
453 *
454 */
455 public void log(String msg)
456 {
457 logger.info(msg);
458 }
459
460 /**
461 * Writes the stack trace and an explanatory message
462 * for a given <code>Throwable</code> exception
463 * to the servlet log file. The name and type of the servlet log
464 * file is specific to the servlet engine, but it is usually an event log.
465 *
466 *
467 * @param message a <code>String</code> that
468 * describes the error or exception
469 *
470 * @param throwable the <code>Throwable</code> error
471 * or exception
472 *
473 */
474 public void log(String message, Throwable throwable)
475 {
476 logger.info(message + "\n" + throwable.getClass() + " - " + throwable.getMessage());
477 }
478
479 /**
480 * Removes the attribute with the given name from
481 * the servlet context. After removal, subsequent calls to
482 * {@link #getAttribute} to retrieve the attribute's value
483 * will return <code>null</code>.
484
485 * <p>If listeners are configured on the <code>ServletContext</code> the
486 * container notifies them accordingly.
487
488 *
489 *
490 * @param name a <code>String</code> specifying the name
491 * of the attribute to be removed
492 *
493 */
494 public void removeAttribute(String name)
495 {
496 attributes.remove(name);
497 }
498
499 /**
500 *
501 * Binds an object to a given attribute name in this servlet context. If
502 * the name specified is already used for an attribute, this
503 * method will replace the attribute with the new to the new attribute.
504 * <p>If listeners are configured on the <code>ServletContext</code> the
505 * container notifies them accordingly.
506 * <p>
507 * If a null value is passed, the effect is the same as calling
508 * <code>removeAttribute()</code>.
509 *
510 * <p>Attribute names should follow the same convention as package
511 * names. The Java Servlet API specification reserves names
512 * matching <code>java.*</code>, <code>javax.*</code>, and
513 * <code>sun.*</code>.
514 *
515 *
516 * @param name a <code>String</code> specifying the name
517 * of the attribute
518 *
519 * @param object an <code>Object</code> representing the
520 * attribute to be bound
521 *
522 *
523 *
524 */
525 public void setAttribute(String name, Object object)
526 {
527 attributes.put(name,object);
528 }
529
530 /**
531 * Unsupported in this version.
532 */
533 public Set getResourcePaths(String path) {
534 throw new UnsupportedOperationException("getResourcePaths operation is not supported!");
535 }
536
537 /**
538 * Sets the absolute context directory to be used in the getRealPath() method.
539 * @param contextDirectory the absolute path of the root context directory for this application.
540 */
541 public void setContextDirectory(File contextDirectory) {
542 this.contextDirectory = contextDirectory;
543 }
544
545 public File getContextDirectory() {
546 return contextDirectory;
547 }
548
549
550 }