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