001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.wicket.protocol.http;
018:
019: import java.io.File;
020: import java.io.FileInputStream;
021: import java.io.FileNotFoundException;
022: import java.io.IOException;
023: import java.io.InputStream;
024: import java.net.MalformedURLException;
025: import java.net.URL;
026: import java.util.Collections;
027: import java.util.Enumeration;
028: import java.util.HashSet;
029: import java.util.Set;
030:
031: import javax.servlet.RequestDispatcher;
032: import javax.servlet.Servlet;
033: import javax.servlet.ServletContext;
034: import javax.servlet.ServletException;
035: import javax.servlet.ServletRequest;
036: import javax.servlet.ServletResponse;
037:
038: import org.apache.wicket.Application;
039: import org.apache.wicket.util.value.ValueMap;
040: import org.slf4j.Logger;
041: import org.slf4j.LoggerFactory;
042:
043: /**
044: * Mock implementation of the servlet context for testing purposes. This
045: * implementation supports all of the standard context methods except that
046: * request dispatching just indicates what is being dispatched to, rather than
047: * doing the actual dispatch.
048: * <p>
049: * The context can be configured with a path parameter that should point to an
050: * absolute directory location that represents the place where the contents of
051: * the WAR bundle are located. Setting this value allows all of the resource
052: * location functionality to work as in a fully functioning web application.
053: * This value is not set then not resource location functionality will work and
054: * instead null will always be returned.
055: *
056: * @author Chris Turner
057: */
058: public class MockServletContext implements ServletContext {
059: private static final Logger log = LoggerFactory
060: .getLogger(MockServletContext.class);
061:
062: private final Application application;
063:
064: private final ValueMap attributes = new ValueMap();
065:
066: private final ValueMap initParameters = new ValueMap();
067:
068: /** Map of mime types */
069: private final ValueMap mimeTypes = new ValueMap();
070:
071: private File webappRoot;
072:
073: /**
074: * Create the mock object. As part of the creation, the context ets the root
075: * directory where web application content is stored. This must be an
076: * ABSOLUTE directory relative to where the tests are being executed. For
077: * example: <code>System.getProperty("user.dir") +
078: * "/src/webapp"</code>
079: *
080: * @param application
081: * The application that this context is for
082: * @param path
083: * The path to the root of the web application
084: */
085: public MockServletContext(final Application application,
086: final String path) {
087: this .application = application;
088:
089: webappRoot = null;
090: if (path != null) {
091: webappRoot = new File(path);
092: if (!webappRoot.exists() || !webappRoot.isDirectory()) {
093: log
094: .warn("WARNING: The webapp root directory is invalid: "
095: + path);
096: webappRoot = null;
097: }
098: }
099:
100: // assume we're running in maven or an eclipse project created by maven,
101: // so the sessions directory will be created inside the target directory,
102: // and will be cleaned up with a mvn clean
103:
104: File file = new File("target/work/");
105: file.mkdirs();
106: attributes.put("javax.servlet.context.tempdir", file);
107:
108: mimeTypes.put("html", "text/html");
109: mimeTypes.put("htm", "text/html");
110: mimeTypes.put("css", "text/css");
111: mimeTypes.put("xml", "text/xml");
112: mimeTypes.put("js", "text/plain");
113: mimeTypes.put("gif", "image/gif");
114: mimeTypes.put("jpg", "image/jpeg");
115: mimeTypes.put("png", "image/png");
116: }
117:
118: /**
119: * Add an init parameter.
120: *
121: * @param name
122: * The parameter name
123: * @param value
124: * The parameter value
125: */
126: public void addInitParameter(final String name, final String value) {
127: initParameters.put(name, value);
128: }
129:
130: // Configuration methods
131:
132: /**
133: * Add a new recognised mime type.
134: *
135: * @param fileExtension
136: * The file extension (e.g. "jpg")
137: * @param mimeType
138: * The mime type (e.g. "image/jpeg")
139: */
140: public void addMimeType(final String fileExtension,
141: final String mimeType) {
142: mimeTypes.put(fileExtension, mimeType);
143: }
144:
145: /**
146: * Get an attribute with the given name.
147: *
148: * @param name
149: * The attribute name
150: * @return The value, or null
151: */
152: public Object getAttribute(final String name) {
153: return attributes.get(name);
154: }
155:
156: /**
157: * Get all of the attribute names.
158: *
159: * @return The attribute names
160: */
161: public Enumeration getAttributeNames() {
162: return Collections.enumeration(attributes.keySet());
163: }
164:
165: // ServletContext interface methods
166:
167: /**
168: * Get the context for the given URL path
169: *
170: * @param name
171: * The url path
172: * @return Always returns this
173: */
174: public ServletContext getContext(String name) {
175: return this ;
176: }
177:
178: /**
179: * Get the init parameter with the given name.
180: *
181: * @param name
182: * The name
183: * @return The parameter, or null if no such parameter
184: */
185: public String getInitParameter(final String name) {
186: return initParameters.getString(name);
187: }
188:
189: /**
190: * Get the name of all of the init parameters.
191: *
192: * @return The init parameter names
193: */
194: public Enumeration getInitParameterNames() {
195: return Collections.enumeration(initParameters.keySet());
196: }
197:
198: /**
199: * @return Always 2
200: */
201: public int getMajorVersion() {
202: return 2;
203: }
204:
205: /**
206: * Get the mime type for the given file. Uses a hardcoded map of mime types
207: * set at initialisation time.
208: *
209: * @param name
210: * The name to get the mime type for
211: * @return The mime type
212: */
213: public String getMimeType(final String name) {
214: int index = name.lastIndexOf('.');
215: if (index == -1 || index == (name.length() - 1)) {
216: return null;
217: } else {
218: return mimeTypes.getString(name.substring(index + 1));
219: }
220: }
221:
222: /**
223: * @return Always 3
224: */
225: public int getMinorVersion() {
226: return 3;
227: }
228:
229: /**
230: * Wicket does not use the RequestDispatcher, so this implementation just
231: * returns a dummy value.
232: *
233: * @param name
234: * The name of the servlet or JSP
235: * @return The dispatcher
236: */
237: public RequestDispatcher getNamedDispatcher(final String name) {
238: return getRequestDispatcher(name);
239: }
240:
241: /**
242: * Get the real file path of the given resource name.
243: *
244: * @param name
245: * The name
246: * @return The real path or null
247: */
248: public String getRealPath(String name) {
249: if (webappRoot == null) {
250: return null;
251: }
252:
253: if (name.startsWith("/")) {
254: name = name.substring(1);
255: }
256:
257: File f = new File(webappRoot, name);
258: if (!f.exists()) {
259: return null;
260: } else {
261: return f.getPath();
262: }
263: }
264:
265: /**
266: * Wicket does not use the RequestDispatcher, so this implementation just
267: * returns a dummy value.
268: *
269: * @param name
270: * The name of the resource to get the dispatcher for
271: * @return The dispatcher
272: */
273: public RequestDispatcher getRequestDispatcher(final String name) {
274: return new RequestDispatcher() {
275: public void forward(ServletRequest servletRequest,
276: ServletResponse servletResponse) throws IOException {
277: servletResponse.getWriter().write(
278: "FORWARD TO RESOURCE: " + name);
279: }
280:
281: public void include(ServletRequest servletRequest,
282: ServletResponse servletResponse) throws IOException {
283: servletResponse.getWriter().write(
284: "INCLUDE OF RESOURCE: " + name);
285: }
286: };
287: }
288:
289: /**
290: * Get the URL for a particular resource that is relative to the web app
291: * root directory.
292: *
293: * @param name
294: * The name of the resource to get
295: * @return The resource, or null if resource not found
296: * @throws MalformedURLException
297: * If the URL is invalid
298: */
299: public URL getResource(String name) throws MalformedURLException {
300: if (webappRoot == null) {
301: return null;
302: }
303:
304: if (name.startsWith("/")) {
305: name = name.substring(1);
306: }
307:
308: File f = new File(webappRoot, name);
309: if (!f.exists()) {
310: return null;
311: } else {
312: return f.toURI().toURL();
313: }
314: }
315:
316: /**
317: * Get an input stream for a particular resource that is relative to the web
318: * app root directory.
319: *
320: * @param name
321: * The name of the resource to get
322: * @return The input stream for the resource, or null of resource is not
323: * found
324: */
325: public InputStream getResourceAsStream(String name) {
326: if (webappRoot == null) {
327: return null;
328: }
329:
330: if (name.startsWith("/")) {
331: name = name.substring(1);
332: }
333:
334: File f = new File(webappRoot, name);
335: if (!f.exists()) {
336: return null;
337: } else {
338: try {
339: return new FileInputStream(f);
340: } catch (FileNotFoundException e) {
341: e.printStackTrace();
342: return null;
343: }
344: }
345: }
346:
347: /**
348: * Get the resource paths starting from the web app root directory and then
349: * relative to the the given name.
350: *
351: * @param name
352: * The starting name
353: * @return The set of resource paths at this location
354: */
355: public Set getResourcePaths(String name) {
356: if (webappRoot == null) {
357: return new HashSet();
358: }
359:
360: if (name.startsWith("/")) {
361: name = name.substring(1);
362: }
363: if (name.endsWith("/")) {
364: name = name.substring(0, name.length() - 1);
365: }
366: String[] elements = null;
367: if (name.trim().length() == 0) {
368: elements = new String[0];
369: } else {
370: elements = name.split("/");
371: }
372:
373: File current = webappRoot;
374: for (int i = 0; i < elements.length; i++) {
375: File[] files = current.listFiles();
376: boolean match = false;
377: for (int f = 0; f < files.length; f++) {
378: if (files[f].getName().equals(elements[i])
379: && files[f].isDirectory()) {
380: current = files[f];
381: match = true;
382: break;
383: }
384: }
385: if (!match) {
386: return null;
387: }
388: }
389:
390: File[] files = current.listFiles();
391: Set result = new HashSet();
392: int stripLength = webappRoot.getPath().length();
393: for (int f = 0; f < files.length; f++) {
394: String s = files[f].getPath().substring(stripLength)
395: .replace('\\', '/');
396: if (files[f].isDirectory()) {
397: s = s + "/";
398: }
399: result.add(s);
400: }
401: return result;
402: }
403:
404: /**
405: * Get the server info.
406: *
407: * @return The server info
408: */
409: public String getServerInfo() {
410: return "Wicket Mock Test Environment v1.0";
411: }
412:
413: /**
414: * NOT USED - Servlet Spec requires that this always returns null.
415: *
416: * @param name
417: * Not used
418: * @return null
419: * @throws ServletException
420: * Not used
421: */
422: public Servlet getServlet(String name) throws ServletException {
423: return null;
424: }
425:
426: /**
427: * Return the name of the servlet context.
428: *
429: * @return The name
430: */
431: public String getServletContextName() {
432: return application.getName();
433: }
434:
435: /**
436: * NOT USED - Servlet spec requires that this always returns null.
437: *
438: * @return null
439: */
440: public Enumeration getServletNames() {
441: return null;
442: }
443:
444: /**
445: * NOT USED - Servlet spec requires that this always returns null.
446: *
447: * @return null
448: */
449: public Enumeration getServlets() {
450: return null;
451: }
452:
453: /**
454: * As part of testing we always log to the console.
455: *
456: * @param e
457: * The exception to log
458: * @param msg
459: * The message to log
460: */
461: public void log(Exception e, String msg) {
462: log.error(msg, e);
463: }
464:
465: /**
466: * As part of testing we always log to the console.
467: *
468: * @param msg
469: * The message to log
470: */
471: public void log(String msg) {
472: log.info(msg);
473: }
474:
475: /**
476: * As part of testing we always log to the console.
477: *
478: * @param msg
479: * The message to log
480: * @param cause
481: * The cause exception
482: */
483: public void log(String msg, Throwable cause) {
484: log.error(msg, cause);
485: }
486:
487: /**
488: * Remove an attribute with the given name.
489: *
490: * @param name
491: * The name
492: */
493: public void removeAttribute(final String name) {
494: attributes.remove(name);
495: }
496:
497: /**
498: * Set an attribute.
499: *
500: * @param name
501: * The name of the attribute
502: * @param o
503: * The value
504: */
505: public void setAttribute(final String name, final Object o) {
506: attributes.put(name, o);
507: }
508: }
|