001: package com.mockrunner.mock.web;
002:
003: import java.lang.reflect.Constructor;
004:
005: import javax.servlet.http.HttpServletRequest;
006: import javax.servlet.http.HttpServletResponse;
007: import javax.servlet.jsp.JspFactory;
008:
009: import com.mockrunner.base.NestedApplicationException;
010:
011: /**
012: * Used to create all types of web mock objects. Maintains
013: * the necessary dependencies between the mock objects.
014: * If you use the mock objects returned by this
015: * factory in your tests you can be sure that they are all
016: * up to date.
017: */
018: public class WebMockObjectFactory {
019: private HttpServletRequest wrappedRequest;
020: private HttpServletResponse wrappedResponse;
021: private MockHttpServletRequest request;
022: private MockHttpServletResponse response;
023: private MockServletConfig config;
024: private MockServletContext context;
025: private MockHttpSession session;
026: private MockPageContext pageContext;
027: private MockFilterConfig filterConfig;
028: private MockFilterChain filterChain;
029: private JspFactory jspFactory;
030:
031: /**
032: * Creates a new set of mock objects.
033: */
034: public WebMockObjectFactory() {
035: createMockObjects();
036: }
037:
038: /**
039: * Creates a set of mock objects based on another one.
040: * The created mock objects will have their own
041: * request and session objects, but they will share
042: * one <code>ServletContext</code>.
043: * @param factory the other factory
044: * @see com.mockrunner.base.BaseTestCase#createWebMockObjectFactory(WebMockObjectFactory)
045: */
046: public WebMockObjectFactory(WebMockObjectFactory factory) {
047: createMockObjectsBasedOn(factory);
048: }
049:
050: /**
051: * Creates a set of mock objects based on another one.
052: * You can specify, if the created mock objects should
053: * share the same session. They will share one
054: * <code>ServletContext</code> anyway.
055: * @param factory the other factory
056: * @param createNewSession <code>true</code> creates a new session,
057: * <code>false</code> uses the session from factory
058: * @see com.mockrunner.base.BaseTestCase#createWebMockObjectFactory(WebMockObjectFactory, boolean)
059: */
060: public WebMockObjectFactory(WebMockObjectFactory factory,
061: boolean createNewSession) {
062: createMockObjectsBasedOn(factory, createNewSession);
063: }
064:
065: private void createMockObjects() {
066: createNewMockObjects(true);
067: context = createMockServletContext();
068: setUpDependencies();
069: JspFactory.setDefaultFactory(jspFactory);
070: }
071:
072: private void createMockObjectsBasedOn(WebMockObjectFactory factory) {
073: createMockObjectsBasedOn(factory, true);
074: }
075:
076: private void createMockObjectsBasedOn(WebMockObjectFactory factory,
077: boolean createNewSession) {
078: createNewMockObjects(createNewSession);
079: if (!createNewSession)
080: session = factory.getMockSession();
081: context = factory.getMockServletContext();
082: setUpDependencies();
083: JspFactory.setDefaultFactory(jspFactory);
084: }
085:
086: private void createNewMockObjects(boolean createNewSession) {
087: request = createMockRequest();
088: response = createMockResponse();
089: wrappedRequest = request;
090: wrappedResponse = response;
091: if (createNewSession)
092: session = createMockSession();
093: config = createMockServletConfig();
094: filterChain = createMockFilterChain();
095: filterConfig = createMockFilterConfig();
096: jspFactory = createMockJspFactory();
097: }
098:
099: private void setUpDependencies() {
100: config.setServletContext(context);
101: request.setSession(session);
102: session.setupServletContext(context);
103: pageContext = createMockPageContext();
104: pageContext.setServletConfig(config);
105: pageContext.setServletRequest(request);
106: pageContext.setServletResponse(response);
107: filterConfig.setupServletContext(context);
108: setUpJspFactory();
109: }
110:
111: private void setUpJspFactory() {
112: if (jspFactory instanceof MockJspFactory) {
113: ((MockJspFactory) jspFactory).setPageContext(pageContext);
114: }
115: }
116:
117: /**
118: * Sets the default <code>JspFactory</code> by calling
119: * <code>JspFactory.setDefaultFactory()</code>.
120: * @param jspFactory the <code>JspFactory</code>
121: */
122: public void setDefaultJspFactory(JspFactory jspFactory) {
123: JspFactory.setDefaultFactory(jspFactory);
124: this .jspFactory = jspFactory;
125: setUpJspFactory();
126: }
127:
128: /**
129: * Refreshes the mock objects dependencies. May be called after setting request
130: * and response wrappers.
131: */
132: public void refresh() {
133: pageContext = new MockPageContext(config, wrappedRequest,
134: wrappedResponse);
135: setUpJspFactory();
136: }
137:
138: /**
139: * Creates the {@link com.mockrunner.mock.web.MockServletContext} using <code>new</code>.
140: * This method can be overridden to return a subclass of {@link com.mockrunner.mock.web.MockServletContext}.
141: * @return the {@link com.mockrunner.mock.web.MockServletContext}
142: */
143: public MockServletContext createMockServletContext() {
144: return new MockServletContext();
145: }
146:
147: /**
148: * Creates the {@link com.mockrunner.mock.web.MockServletConfig} using <code>new</code>.
149: * This method can be overridden to return a subclass of {@link com.mockrunner.mock.web.MockServletConfig}.
150: * @return the {@link com.mockrunner.mock.web.MockServletConfig}
151: */
152: public MockServletConfig createMockServletConfig() {
153: return new MockServletConfig();
154: }
155:
156: /**
157: * Creates the {@link com.mockrunner.mock.web.MockHttpServletResponse} using <code>new</code>.
158: * This method can be overridden to return a subclass of {@link com.mockrunner.mock.web.MockHttpServletResponse}.
159: * @return the {@link com.mockrunner.mock.web.MockHttpServletResponse}
160: */
161: public MockHttpServletResponse createMockResponse() {
162: return new MockHttpServletResponse();
163: }
164:
165: /**
166: * Creates the {@link com.mockrunner.mock.web.MockHttpServletRequest} using <code>new</code>.
167: * This method can be overridden to return a subclass of {@link com.mockrunner.mock.web.MockHttpServletRequest}.
168: * @return the {@link com.mockrunner.mock.web.MockHttpServletRequest}
169: */
170: public MockHttpServletRequest createMockRequest() {
171: return new MockHttpServletRequest();
172: }
173:
174: /**
175: * Creates the {@link com.mockrunner.mock.web.MockHttpSession} using <code>new</code>.
176: * This method can be overridden to return a subclass of {@link com.mockrunner.mock.web.MockHttpSession}.
177: * @return the {@link com.mockrunner.mock.web.MockHttpSession}
178: */
179: public MockHttpSession createMockSession() {
180: return new MockHttpSession();
181: }
182:
183: /**
184: * Creates the {@link com.mockrunner.mock.web.MockPageContext} using <code>new</code>.
185: * This method can be overridden to return a subclass of {@link com.mockrunner.mock.web.MockPageContext}.
186: * @return the {@link com.mockrunner.mock.web.MockPageContext}
187: */
188: public MockPageContext createMockPageContext() {
189: return new MockPageContext();
190: }
191:
192: /**
193: * Creates the {@link com.mockrunner.mock.web.MockFilterConfig} using <code>new</code>.
194: * This method can be overridden to return a subclass of {@link com.mockrunner.mock.web.MockFilterConfig}.
195: * @return the {@link com.mockrunner.mock.web.MockFilterConfig}
196: */
197: public MockFilterConfig createMockFilterConfig() {
198: return new MockFilterConfig();
199: }
200:
201: /**
202: * Creates the {@link com.mockrunner.mock.web.MockFilterChain} using <code>new</code>.
203: * This method can be overridden to return a subclass of {@link com.mockrunner.mock.web.MockFilterChain}.
204: * @return the {@link com.mockrunner.mock.web.MockFilterChain}
205: */
206: public MockFilterChain createMockFilterChain() {
207: return new MockFilterChain();
208: }
209:
210: /**
211: * Creates the {@link com.mockrunner.mock.web.MockJspFactory} using <code>new</code>.
212: * This method can be overridden to return a subclass of {@link com.mockrunner.mock.web.MockJspFactory}.
213: * @return the {@link com.mockrunner.mock.web.MockJspFactory}
214: */
215: public MockJspFactory createMockJspFactory() {
216: return new MockJspFactory();
217: }
218:
219: /**
220: * Returns the <code>MockServletConfig</code>
221: * @return the <code>MockServletConfig</code>
222: */
223: public MockServletConfig getMockServletConfig() {
224: return config;
225: }
226:
227: /**
228: * Returns the {@link com.mockrunner.mock.web.MockServletContext}.
229: * @return the {@link com.mockrunner.mock.web.MockServletContext}
230: */
231: public MockServletContext getMockServletContext() {
232: return context;
233: }
234:
235: /**
236: * Returns the {@link com.mockrunner.mock.web.MockHttpServletRequest}.
237: * @return the {@link com.mockrunner.mock.web.MockHttpServletRequest}
238: */
239: public MockHttpServletRequest getMockRequest() {
240: return request;
241: }
242:
243: /**
244: * Returns the {@link com.mockrunner.mock.web.MockHttpServletResponse}.
245: * @return the {@link com.mockrunner.mock.web.MockHttpServletResponse}
246: */
247: public MockHttpServletResponse getMockResponse() {
248: return response;
249: }
250:
251: /**
252: * Returns the wrapped <code>HttpServletRequest</code>. If no
253: * wrapper is specified, this method returns the mock request itself.
254: * @return the wrapped <code>HttpServletRequest</code>
255: */
256: public HttpServletRequest getWrappedRequest() {
257: return wrappedRequest;
258: }
259:
260: /**
261: * Returns the wrapped <code>HttpServletResponse</code>. If no
262: * wrapper is specified, this method returns the mock response itself.
263: * @return the wrapped <code>HttpServletRequest</code>
264: */
265: public HttpServletResponse getWrappedResponse() {
266: return wrappedResponse;
267: }
268:
269: /**
270: * Returns the {@link com.mockrunner.mock.web.MockHttpSession}.
271: * @return the {@link com.mockrunner.mock.web.MockHttpSession}
272: */
273: public MockHttpSession getMockSession() {
274: return session;
275: }
276:
277: /**
278: * Returns the {@link com.mockrunner.mock.web.MockHttpSession}.
279: * @return the {@link com.mockrunner.mock.web.MockHttpSession}
280: * @deprecated use {@link #getMockSession}
281: */
282: public MockHttpSession getSession() {
283: return getMockSession();
284: }
285:
286: /**
287: * Returns the {@link com.mockrunner.mock.web.MockPageContext}.
288: * @return the {@link com.mockrunner.mock.web.MockPageContext}
289: */
290: public MockPageContext getMockPageContext() {
291: return pageContext;
292: }
293:
294: /**
295: * Returns the {@link com.mockrunner.mock.web.MockFilterConfig}.
296: * @return the {@link com.mockrunner.mock.web.MockFilterConfig}
297: */
298: public MockFilterConfig getMockFilterConfig() {
299: return filterConfig;
300: }
301:
302: /**
303: * Returns the {@link com.mockrunner.mock.web.MockFilterChain}.
304: * @return the {@link com.mockrunner.mock.web.MockFilterChain}
305: */
306: public MockFilterChain getMockFilterChain() {
307: return filterChain;
308: }
309:
310: /**
311: * Returns the {@link com.mockrunner.mock.web.MockJspFactory}.
312: * If the current <code>JspFactory</code> is not an instance
313: * of {@link com.mockrunner.mock.web.MockJspFactory}, <code>null</code>
314: * will be returned.
315: * @return the {@link com.mockrunner.mock.web.MockJspFactory}
316: */
317: public MockJspFactory getMockJspFactory() {
318: if (jspFactory instanceof MockJspFactory) {
319: return (MockJspFactory) jspFactory;
320: }
321: return null;
322: }
323:
324: /**
325: * Returns the <code>JspFactory</code>.
326: * @return the <code>JspFactory</code>
327: */
328: public JspFactory getJspFactory() {
329: return jspFactory;
330: }
331:
332: /**
333: * Can be used to add a request wrapper. All the
334: * test modules are using the wrapped request returned by
335: * {@link #getWrappedRequest}. The method {@link #getMockRequest}
336: * returns the mock request without any wrapper.
337: * Usually the wrapper is of type <code>javax.servlet.http.HttpServletRequestWrapper</code>.
338: * That's not absolutely necessary but the wrapper must define a constructor
339: * that takes a single <code>javax.servlet.http.HttpServletRequest</code> argument
340: * and must implement <code>javax.servlet.http.HttpServletRequest</code>.
341: * @param wrapper the wrapper class
342: */
343: public void addRequestWrapper(Class wrapper) {
344: try {
345: Constructor constructor = wrapper
346: .getConstructor(new Class[] { HttpServletRequest.class });
347: wrappedRequest = (HttpServletRequest) constructor
348: .newInstance(new Object[] { wrappedRequest });
349: } catch (Exception exc) {
350: throw new NestedApplicationException(exc);
351: }
352: }
353:
354: /**
355: * Can be used to add a request wrapper.
356: * All the test modules are using the wrapped request returned by
357: * {@link #getWrappedRequest}. The method {@link #getMockRequest}
358: * returns the mock request without any wrapper. Usually the wrapper is
359: * an instance of <code>javax.servlet.http.HttpServletRequestWrapper</code>
360: * and wraps the current request but that's not absolutely necessary.
361: * However, be careful if you want to add custom mock versions of
362: * <code>javax.servlet.http.HttpServletRequest</code>.
363: * @param wrapper the request wrapper
364: */
365: public void addRequestWrapper(HttpServletRequest wrapper) {
366: wrappedRequest = wrapper;
367: }
368:
369: /**
370: * Can be used to add a response wrapper. All the
371: * test modules are using the wrapped response returned by
372: * {@link #getWrappedResponse}. The method {@link #getMockResponse}
373: * returns the mock response without any wrapper.
374: * Usually the wrapper is of type <code>javax.servlet.http.HttpServletResponseWrapper</code>.
375: * That's not absolutely necessary but the wrapper must define a constructor
376: * that takes a single <code>javax.servlet.http.HttpServletResponse</code> argument
377: * and must implement <code>javax.servlet.http.HttpServletResponse</code>.
378: * @param wrapper the wrapper class
379: */
380: public void addResponseWrapper(Class wrapper) {
381: try {
382: Constructor constructor = wrapper
383: .getConstructor(new Class[] { HttpServletResponse.class });
384: wrappedResponse = (HttpServletResponse) constructor
385: .newInstance(new Object[] { wrappedResponse });
386: } catch (Exception exc) {
387: throw new NestedApplicationException(exc);
388: }
389: }
390:
391: /**
392: * Can be used to add a response wrapper.
393: * All the test modules are using the wrapped response returned by
394: * {@link #getWrappedResponse}. The method {@link #getMockResponse}
395: * returns the mock response without any wrapper. Usually the wrapper is
396: * an instance of <code>javax.servlet.http.HttpServletResponseWrapper</code>
397: * and wraps the current response but that's not absolutely necessary.
398: * However, be careful if you want to add custom mock versions of
399: * <code>javax.servlet.http.HttpServletResponse</code>.
400: * @param wrapper the wrapper
401: */
402: public void addResponseWrapper(HttpServletResponse wrapper) {
403: wrappedResponse = wrapper;
404: }
405: }
|