001: /*
002: * Copyright 2002-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.mock.web;
018:
019: import java.io.File;
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.net.MalformedURLException;
023: import java.net.URL;
024: import java.util.Enumeration;
025: import java.util.Hashtable;
026: import java.util.Properties;
027: import java.util.Set;
028:
029: import javax.servlet.RequestDispatcher;
030: import javax.servlet.Servlet;
031: import javax.servlet.ServletContext;
032:
033: import org.apache.commons.logging.Log;
034: import org.apache.commons.logging.LogFactory;
035:
036: import org.springframework.core.CollectionFactory;
037: import org.springframework.core.io.DefaultResourceLoader;
038: import org.springframework.core.io.Resource;
039: import org.springframework.core.io.ResourceLoader;
040: import org.springframework.util.Assert;
041: import org.springframework.util.ObjectUtils;
042: import org.springframework.web.util.WebUtils;
043:
044: /**
045: * Mock implementation of the {@link javax.servlet.ServletContext} interface.
046: *
047: * <p>Used for testing the Spring web framework; only rarely necessary for testing
048: * application controllers. As long as application components don't explicitly
049: * access the ServletContext, ClassPathXmlApplicationContext or
050: * FileSystemXmlApplicationContext can be used to load the context files for testing,
051: * even for DispatcherServlet context definitions.
052: *
053: * <p>For setting up a full WebApplicationContext in a test environment, you can
054: * use XmlWebApplicationContext (or GenericWebApplicationContext), passing in an
055: * appropriate MockServletContext instance. You might want to configure your
056: * MockServletContext with a FileSystemResourceLoader in that case, to make your
057: * resource paths interpreted as relative file system locations.
058: *
059: * <p>A common setup is to point your JVM working directory to the root of your
060: * web application directory, in combination with filesystem-based resource loading.
061: * This allows to load the context files as used in the web application, with
062: * relative paths getting interpreted correctly. Such a setup will work with both
063: * FileSystemXmlApplicationContext (which will load straight from the file system)
064: * and XmlWebApplicationContext with an underlying MockServletContext (as long as
065: * the MockServletContext has been configured with a FileSystemResourceLoader).
066: *
067: * @author Rod Johnson
068: * @author Juergen Hoeller
069: * @since 1.0.2
070: * @see #MockServletContext(org.springframework.core.io.ResourceLoader)
071: * @see org.springframework.web.context.support.XmlWebApplicationContext
072: * @see org.springframework.web.context.support.GenericWebApplicationContext
073: * @see org.springframework.context.support.ClassPathXmlApplicationContext
074: * @see org.springframework.context.support.FileSystemXmlApplicationContext
075: */
076: public class MockServletContext implements ServletContext {
077:
078: private static final String TEMP_DIR_SYSTEM_PROPERTY = "java.io.tmpdir";
079:
080: private final Log logger = LogFactory.getLog(getClass());
081:
082: private final String resourceBasePath;
083:
084: private final ResourceLoader resourceLoader;
085:
086: private final Properties initParameters = new Properties();
087:
088: private final Hashtable attributes = new Hashtable();
089:
090: private String servletContextName = "MockServletContext";
091:
092: /**
093: * Create a new MockServletContext, using no base path and a
094: * DefaultResourceLoader (i.e. the classpath root as WAR root).
095: * @see org.springframework.core.io.DefaultResourceLoader
096: */
097: public MockServletContext() {
098: this ("", null);
099: }
100:
101: /**
102: * Create a new MockServletContext, using a DefaultResourceLoader.
103: * @param resourceBasePath the WAR root directory (should not end with a slash)
104: * @see org.springframework.core.io.DefaultResourceLoader
105: */
106: public MockServletContext(String resourceBasePath) {
107: this (resourceBasePath, null);
108: }
109:
110: /**
111: * Create a new MockServletContext, using the specified ResourceLoader
112: * and no base path.
113: * @param resourceLoader the ResourceLoader to use (or null for the default)
114: */
115: public MockServletContext(ResourceLoader resourceLoader) {
116: this ("", resourceLoader);
117: }
118:
119: /**
120: * Create a new MockServletContext.
121: * @param resourceBasePath the WAR root directory (should not end with a slash)
122: * @param resourceLoader the ResourceLoader to use (or null for the default)
123: */
124: public MockServletContext(String resourceBasePath,
125: ResourceLoader resourceLoader) {
126: this .resourceBasePath = (resourceBasePath != null ? resourceBasePath
127: : "");
128: this .resourceLoader = (resourceLoader != null ? resourceLoader
129: : new DefaultResourceLoader());
130:
131: // Use JVM temp dir as ServletContext temp dir.
132: String tempDir = System.getProperty(TEMP_DIR_SYSTEM_PROPERTY);
133: if (tempDir != null) {
134: this .attributes.put(WebUtils.TEMP_DIR_CONTEXT_ATTRIBUTE,
135: new File(tempDir));
136: }
137: }
138:
139: /**
140: * Build a full resource location for the given path,
141: * prepending the resource base path of this MockServletContext.
142: * @param path the path as specified
143: * @return the full resource path
144: */
145: protected String getResourceLocation(String path) {
146: if (!path.startsWith("/")) {
147: path = "/" + path;
148: }
149: return this .resourceBasePath + path;
150: }
151:
152: public ServletContext getContext(String name) {
153: throw new UnsupportedOperationException("getContext");
154: }
155:
156: public int getMajorVersion() {
157: return 2;
158: }
159:
160: public int getMinorVersion() {
161: return 4;
162: }
163:
164: public String getMimeType(String filePath) {
165: throw new UnsupportedOperationException("getMimeType");
166: }
167:
168: public Set getResourcePaths(String path) {
169: String actualPath = (path.endsWith("/") ? path : path + "/");
170: Resource resource = this .resourceLoader
171: .getResource(getResourceLocation(actualPath));
172: try {
173: File file = resource.getFile();
174: String[] fileList = file.list();
175: if (ObjectUtils.isEmpty(fileList)) {
176: return null;
177: }
178: Set resourcePaths = CollectionFactory
179: .createLinkedSetIfPossible(fileList.length);
180: for (int i = 0; i < fileList.length; i++) {
181: String resultPath = actualPath + fileList[i];
182: if (resource.createRelative(fileList[i]).getFile()
183: .isDirectory()) {
184: resultPath += "/";
185: }
186: resourcePaths.add(resultPath);
187: }
188: return resourcePaths;
189: } catch (IOException ex) {
190: logger.warn("Couldn't get resource paths for " + resource,
191: ex);
192: return null;
193: }
194: }
195:
196: public URL getResource(String path) throws MalformedURLException {
197: Resource resource = this .resourceLoader
198: .getResource(getResourceLocation(path));
199: if (!resource.exists()) {
200: return null;
201: }
202: try {
203: return resource.getURL();
204: } catch (MalformedURLException ex) {
205: throw ex;
206: } catch (IOException ex) {
207: logger.warn("Couldn't get URL for " + resource, ex);
208: return null;
209: }
210: }
211:
212: public InputStream getResourceAsStream(String path) {
213: Resource resource = this .resourceLoader
214: .getResource(getResourceLocation(path));
215: if (!resource.exists()) {
216: return null;
217: }
218: try {
219: return resource.getInputStream();
220: } catch (IOException ex) {
221: logger
222: .warn("Couldn't open InputStream for " + resource,
223: ex);
224: return null;
225: }
226: }
227:
228: public RequestDispatcher getRequestDispatcher(String path) {
229: if (!path.startsWith("/")) {
230: throw new IllegalArgumentException(
231: "RequestDispatcher path at ServletContext level must start with '/'");
232: }
233: return new MockRequestDispatcher(path);
234: }
235:
236: public RequestDispatcher getNamedDispatcher(String path) {
237: throw new UnsupportedOperationException("getNamedDispatcher");
238: }
239:
240: public Servlet getServlet(String name) {
241: throw new UnsupportedOperationException("getServlet");
242: }
243:
244: public Enumeration getServlets() {
245: throw new UnsupportedOperationException("getServlets");
246: }
247:
248: public Enumeration getServletNames() {
249: throw new UnsupportedOperationException("getServletNames");
250: }
251:
252: public void log(String message) {
253: logger.info(message);
254: }
255:
256: public void log(Exception ex, String message) {
257: logger.info(message, ex);
258: }
259:
260: public void log(String message, Throwable ex) {
261: logger.info(message, ex);
262: }
263:
264: public String getRealPath(String path) {
265: Resource resource = this .resourceLoader
266: .getResource(getResourceLocation(path));
267: try {
268: return resource.getFile().getAbsolutePath();
269: } catch (IOException ex) {
270: logger.warn("Couldn't determine real path of resource "
271: + resource, ex);
272: return null;
273: }
274: }
275:
276: public String getServerInfo() {
277: return "MockServletContext";
278: }
279:
280: public String getInitParameter(String name) {
281: Assert.notNull(name, "Parameter name must not be null");
282: return this .initParameters.getProperty(name);
283: }
284:
285: public void addInitParameter(String name, String value) {
286: Assert.notNull(name, "Parameter name must not be null");
287: this .initParameters.setProperty(name, value);
288: }
289:
290: public Enumeration getInitParameterNames() {
291: return this .initParameters.keys();
292: }
293:
294: public Object getAttribute(String name) {
295: Assert.notNull(name, "Attribute name must not be null");
296: return this .attributes.get(name);
297: }
298:
299: public Enumeration getAttributeNames() {
300: return this .attributes.keys();
301: }
302:
303: public void setAttribute(String name, Object value) {
304: Assert.notNull(name, "Attribute name must not be null");
305: if (value != null) {
306: this .attributes.put(name, value);
307: } else {
308: this .attributes.remove(name);
309: }
310: }
311:
312: public void removeAttribute(String name) {
313: Assert.notNull(name, "Attribute name must not be null");
314: this .attributes.remove(name);
315: }
316:
317: public void setServletContextName(String servletContextName) {
318: this .servletContextName = servletContextName;
319: }
320:
321: public String getServletContextName() {
322: return servletContextName;
323: }
324:
325: }
|