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