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 }