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, 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 config = new MockServletConfig();
070 context = new MockServletContext();
071 setUpDependencies();
072 }
073
074 private void createMockObjectsBasedOn(WebMockObjectFactory factory)
075 {
076 createMockObjectsBasedOn(factory, true);
077 }
078
079 private void createMockObjectsBasedOn(WebMockObjectFactory factory, boolean createNewSession)
080 {
081 createNewMockObjects(createNewSession);
082 if(!createNewSession) session = factory.getMockSession();
083 config = factory.getMockServletConfig();
084 context = factory.getMockServletContext();
085 setUpDependencies();
086 }
087
088 private void createNewMockObjects(boolean createNewSession)
089 {
090 request = new MockHttpServletRequest();
091 response = new MockHttpServletResponse();
092 wrappedRequest = request;
093 wrappedResponse = response;
094 if(createNewSession) session = new MockHttpSession();
095 filterChain = new MockFilterChain();
096 filterConfig = new MockFilterConfig();
097 }
098
099 private void setUpDependencies()
100 {
101 config.setServletContext(context);
102 request.setSession(session);
103 session.setupServletContext(context);
104 pageContext = new MockPageContext(config, request, response);
105 filterConfig.setupServletContext(context);
106 }
107
108 /**
109 * Refreshes the mock objects dependencies. May be called after setting request
110 * and response wrappers.
111 */
112 public void refresh()
113 {
114 pageContext = new MockPageContext(config, wrappedRequest, wrappedResponse);
115 }
116
117 /**
118 * Returns the <code>MockServletConfig</code>
119 * @return the <code>MockServletConfig</code>
120 */
121 public MockServletConfig getMockServletConfig()
122 {
123 return config;
124 }
125
126 /**
127 * Returns the {@link com.mockrunner.mock.web.MockServletContext}.
128 * @return the {@link com.mockrunner.mock.web.MockServletContext}
129 */
130 public MockServletContext getMockServletContext()
131 {
132 return context;
133 }
134
135 /**
136 * Returns the {@link com.mockrunner.mock.web.MockHttpServletRequest}.
137 * @return the {@link com.mockrunner.mock.web.MockHttpServletRequest}
138 */
139 public MockHttpServletRequest getMockRequest()
140 {
141 return request;
142 }
143
144 /**
145 * Returns the {@link com.mockrunner.mock.web.MockHttpServletResponse}.
146 * @return the {@link com.mockrunner.mock.web.MockHttpServletResponse}
147 */
148 public MockHttpServletResponse getMockResponse()
149 {
150 return response;
151 }
152
153 /**
154 * Returns the wrapped <code>HttpServletRequest</code>. If no
155 * wrapper is specified, this method returns the mock request itself.
156 * @return the wrapped <code>HttpServletRequest</code>
157 */
158 public HttpServletRequest getWrappedRequest()
159 {
160 return wrappedRequest;
161 }
162
163 /**
164 * Returns the wrapped <code>HttpServletResponse</code>. If no
165 * wrapper is specified, this method returns the mock response itself.
166 * @return the wrapped <code>HttpServletRequest</code>
167 */
168 public HttpServletResponse getWrappedResponse()
169 {
170 return wrappedResponse;
171 }
172
173 /**
174 * Returns the {@link com.mockrunner.mock.web.MockHttpSession}.
175 * @return the {@link com.mockrunner.mock.web.MockHttpSession}
176 */
177 public MockHttpSession getMockSession()
178 {
179 return session;
180 }
181
182 /**
183 * Returns the {@link com.mockrunner.mock.web.MockHttpSession}.
184 * @return the {@link com.mockrunner.mock.web.MockHttpSession}
185 * @deprecated use {@link #getMockSession}
186 */
187 public MockHttpSession getSession()
188 {
189 return getMockSession();
190 }
191
192 /**
193 * Returns the {@link com.mockrunner.mock.web.MockPageContext}.
194 * @return the {@link com.mockrunner.mock.web.MockPageContext}
195 */
196 public MockPageContext getMockPageContext()
197 {
198 return pageContext;
199 }
200
201 /**
202 * Returns the {@link com.mockrunner.mock.web.MockFilterConfig}.
203 * @return the {@link com.mockrunner.mock.web.MockFilterConfig}
204 */
205 public MockFilterConfig getMockFilterConfig()
206 {
207 return filterConfig;
208 }
209
210 /**
211 * Returns the {@link com.mockrunner.mock.web.MockFilterChain}.
212 * @return the {@link com.mockrunner.mock.web.MockFilterChain}
213 */
214 public MockFilterChain getMockFilterChain()
215 {
216 return filterChain;
217 }
218
219 /**
220 * Can be used to add a request wrapper. All the
221 * test modules are using the wrapped request returned by
222 * {@link #getWrappedRequest}. The method {@link #getMockRequest}
223 * returns the mock request without any wrapper.
224 * Usually the wrapper is of type <code>javax.servlet.http.HttpServletRequestWrapper</code>.
225 * That's not absolutely necessary but the wrapper must define a constructor
226 * that takes a single <code>javax.servlet.http.HttpServletRequest</code> argument
227 * and must implement <code>javax.servlet.http.HttpServletRequest</code>.
228 * @param wrapper the wrapper class
229 */
230 public void addRequestWrapper(Class wrapper)
231 {
232 try
233 {
234 Constructor constructor = wrapper.getConstructor(new Class[] {HttpServletRequest.class});
235 wrappedRequest = (HttpServletRequest)constructor.newInstance(new Object[] {wrappedRequest});
236 }
237 catch(Exception exc)
238 {
239 throw new NestedApplicationException(exc);
240 }
241 }
242
243 /**
244 * Can be used to add a request wrapper.
245 * All the test modules are using the wrapped request returned by
246 * {@link #getWrappedRequest}. The method {@link #getMockRequest}
247 * returns the mock request without any wrapper. Usually the wrapper is
248 * an instance of <code>javax.servlet.http.HttpServletRequestWrapper</code>
249 * and wraps the current request but that's not absolutely necessary.
250 * However, be careful if you want to add custom mock versions of
251 * <code>javax.servlet.http.HttpServletRequest</code>.
252 * @param wrapper the request wrapper
253 */
254 public void addRequestWrapper(HttpServletRequest wrapper)
255 {
256 wrappedRequest = wrapper;
257 }
258
259 /**
260 * Can be used to add a response wrapper. All the
261 * test modules are using the wrapped response returned by
262 * {@link #getWrappedResponse}. The method {@link #getMockResponse}
263 * returns the mock response without any wrapper.
264 * Usually the wrapper is of type <code>javax.servlet.http.HttpServletResponseWrapper</code>.
265 * That's not absolutely necessary but the wrapper must define a constructor
266 * that takes a single <code>javax.servlet.http.HttpServletResponse</code> argument
267 * and must implement <code>javax.servlet.http.HttpServletResponse</code>.
268 * @param wrapper the wrapper class
269 */
270 public void addResponseWrapper(Class wrapper)
271 {
272 try
273 {
274 Constructor constructor = wrapper.getConstructor(new Class[] {HttpServletResponse.class});
275 wrappedResponse = (HttpServletResponse)constructor.newInstance(new Object[] {wrappedResponse});
276 }
277 catch(Exception exc)
278 {
279 throw new NestedApplicationException(exc);
280 }
281 }
282
283 /**
284 * Can be used to add a response wrapper.
285 * All the test modules are using the wrapped response returned by
286 * {@link #getWrappedResponse}. The method {@link #getMockResponse}
287 * returns the mock response without any wrapper. Usually the wrapper is
288 * an instance of <code>javax.servlet.http.HttpServletResponseWrapper</code>
289 * and wraps the current response but that's not absolutely necessary.
290 * However, be careful if you want to add custom mock versions of
291 * <code>javax.servlet.http.HttpServletResponse</code>.
292 * @param wrapper the wrapper
293 */
294 public void addResponseWrapper(HttpServletResponse wrapper)
295 {
296 wrappedResponse = wrapper;
297 }
298 }