001 package com.mockrunner.mock.web; 002 003 import java.io.IOException; 004 import java.io.Writer; 005 import java.util.Enumeration; 006 import java.util.HashMap; 007 import java.util.Iterator; 008 import java.util.NoSuchElementException; 009 import java.util.Stack; 010 011 import javax.el.ELContext; 012 import javax.servlet.RequestDispatcher; 013 import javax.servlet.Servlet; 014 import javax.servlet.ServletConfig; 015 import javax.servlet.ServletContext; 016 import javax.servlet.ServletException; 017 import javax.servlet.ServletRequest; 018 import javax.servlet.ServletResponse; 019 import javax.servlet.http.HttpServletRequest; 020 import javax.servlet.http.HttpServletResponse; 021 import javax.servlet.http.HttpSession; 022 import javax.servlet.jsp.JspWriter; 023 import javax.servlet.jsp.PageContext; 024 import javax.servlet.jsp.el.ExpressionEvaluator; 025 import javax.servlet.jsp.el.VariableResolver; 026 import javax.servlet.jsp.tagext.BodyContent; 027 028 import com.mockrunner.base.NestedApplicationException; 029 030 /** 031 * Mock implementation of <code>PageContext</code>. 032 * Please note that EL support using the 033 * the <b>Unified Expression Language</b> API is only available, 034 * if the {@link JasperJspFactory} is configured as the default 035 * <code>JspFactory</code>. By default, {@link #getELContext} 036 * returns <code>null</code>. 037 */ 038 //Some methods of this class were copied from org.apache.struts.mock.MockPageContext 039 //and modified 040 public class MockPageContext extends PageContext 041 { 042 protected ServletConfig config; 043 protected ServletRequest request; 044 protected ServletResponse response; 045 private JspWriter jspWriter; 046 private Stack outStack; 047 private Exception exception; 048 private Object page; 049 private HashMap attributes; 050 private ExpressionEvaluator evaluator; 051 private VariableResolver resolver; 052 private ELContext elContext; 053 054 public MockPageContext() 055 { 056 this(null, null, null); 057 } 058 059 public MockPageContext(ServletConfig config, ServletRequest request, ServletResponse response) 060 { 061 this.config = config; 062 this.request = request; 063 jspWriter = new MockJspWriter(); 064 initJspWriterWithResponse(response); 065 outStack = new Stack(); 066 attributes = new HashMap(); 067 evaluator = new MockExpressionEvaluator(); 068 resolver = new MockVariableResolver(); 069 } 070 071 private void initJspWriterWithResponse(ServletResponse response) 072 { 073 this.response = response; 074 if((null != response) && (response instanceof HttpServletResponse)) 075 { 076 try 077 { 078 jspWriter = new MockJspWriter((HttpServletResponse)response); 079 } 080 catch(IOException exc) 081 { 082 throw new NestedApplicationException(exc); 083 } 084 } 085 } 086 087 /** 088 * This method allows to set custom implementations 089 * of <code>JspWriter</code>. Per default, {@link MockJspWriter} 090 * is used. 091 * @param jspWriter the <code>JspWriter</code> 092 */ 093 public void setJspWriter(JspWriter jspWriter) 094 { 095 this.jspWriter = jspWriter; 096 } 097 098 public void setPage(Object page) 099 { 100 this.page = page; 101 } 102 103 /** 104 * Sets the <code>ServletConfig</code>. 105 * @param config the <code>ServletConfig</code> 106 */ 107 public void setServletConfig(ServletConfig config) 108 { 109 this.config = config; 110 } 111 112 /** 113 * Sets the <code>ServletRequest</code>. 114 * @param request the <code>ServletRequest</code> 115 */ 116 public void setServletRequest(ServletRequest request) 117 { 118 this.request = request; 119 } 120 121 /** 122 * Sets the <code>ServletResponse</code>. 123 * @param response the <code>ServletResponse</code> 124 */ 125 public void setServletResponse(ServletResponse response) 126 { 127 this.response = response; 128 initJspWriterWithResponse(response); 129 } 130 131 public void setException(Exception exception) 132 { 133 this.exception = exception; 134 } 135 136 public Object findAttribute(String name) 137 { 138 Object value = getAttribute(name, PageContext.PAGE_SCOPE); 139 if(value == null) 140 { 141 value = getAttribute(name, PageContext.REQUEST_SCOPE); 142 } 143 if(value == null) 144 { 145 value = getAttribute(name, PageContext.SESSION_SCOPE); 146 } 147 if(value == null) 148 { 149 value = getAttribute(name, PageContext.APPLICATION_SCOPE); 150 } 151 return value; 152 } 153 154 public Object getAttribute(String name) 155 { 156 return getAttribute(name, PageContext.PAGE_SCOPE); 157 } 158 159 public Object getAttribute(String name, int scope) 160 { 161 if(scope == PageContext.PAGE_SCOPE) 162 { 163 return attributes.get(name); 164 } 165 else if(scope == PageContext.REQUEST_SCOPE) 166 { 167 if(null == request) return null; 168 return request.getAttribute(name); 169 } 170 else if(scope == PageContext.SESSION_SCOPE) 171 { 172 if(null == getSession()) return null; 173 return getSession().getAttribute(name); 174 } 175 else if(scope == PageContext.APPLICATION_SCOPE) 176 { 177 if(null == getServletContext()) return null; 178 return getServletContext().getAttribute(name); 179 } 180 else 181 { 182 throw new IllegalArgumentException("Invalid scope " + scope); 183 } 184 } 185 186 public void removeAttribute(String name) 187 { 188 int scope = getAttributesScope(name); 189 if (scope != 0) 190 { 191 removeAttribute(name, scope); 192 } 193 } 194 195 public void removeAttribute(String name, int scope) 196 { 197 if(scope == PageContext.PAGE_SCOPE) 198 { 199 attributes.remove(name); 200 } 201 else if(scope == PageContext.REQUEST_SCOPE) 202 { 203 if(request != null) 204 { 205 request.removeAttribute(name); 206 } 207 } 208 else if(scope == PageContext.SESSION_SCOPE) 209 { 210 if(getSession() != null) 211 { 212 getSession().removeAttribute(name); 213 } 214 } 215 else if(scope == PageContext.APPLICATION_SCOPE) 216 { 217 if(getServletContext() != null) 218 { 219 getServletContext().removeAttribute(name); 220 } 221 } 222 else 223 { 224 throw new IllegalArgumentException("Invalid scope " + scope); 225 } 226 } 227 228 public void setAttribute(String name, Object value) 229 { 230 setAttribute(name, value, PageContext.PAGE_SCOPE); 231 } 232 233 234 public void setAttribute(String name, Object value, int scope) 235 { 236 if(scope == PageContext.PAGE_SCOPE) 237 { 238 attributes.put(name, value); 239 } 240 else if(scope == PageContext.REQUEST_SCOPE) 241 { 242 if(request != null) 243 { 244 request.setAttribute(name, value); 245 } 246 } 247 else if(scope == PageContext.SESSION_SCOPE) 248 { 249 if(getSession() != null) 250 { 251 getSession().setAttribute(name, value); 252 } 253 } 254 else if(scope == PageContext.APPLICATION_SCOPE) 255 { 256 if(getServletContext() != null) 257 { 258 getServletContext().setAttribute(name, value); 259 } 260 } 261 else 262 { 263 throw new IllegalArgumentException("Invalid scope " + scope); 264 } 265 } 266 267 public int getAttributesScope(String name) 268 { 269 if(getAttribute(name, PageContext.PAGE_SCOPE) != null) 270 { 271 return PageContext.PAGE_SCOPE; 272 } 273 else if(getAttribute(name, PageContext.REQUEST_SCOPE) != null) 274 { 275 return PageContext.REQUEST_SCOPE; 276 } 277 else if(getAttribute(name, PageContext.SESSION_SCOPE) != null) 278 { 279 return PageContext.SESSION_SCOPE; 280 } 281 else if(getAttribute(name, PageContext.APPLICATION_SCOPE) != null) 282 { 283 return PageContext.APPLICATION_SCOPE; 284 } 285 return 0; 286 } 287 288 public Enumeration getAttributeNamesInScope(int scope) 289 { 290 if(scope == PageContext.PAGE_SCOPE) 291 { 292 return new WrappedEnumeration(attributes.keySet().iterator()); 293 } 294 else if(scope == PageContext.REQUEST_SCOPE) 295 { 296 if(request == null) return new NullEnumeration(); 297 return request.getAttributeNames(); 298 } 299 else if(scope == PageContext.SESSION_SCOPE) 300 { 301 if(getSession() == null) return new NullEnumeration(); 302 return getSession().getAttributeNames(); 303 } 304 else if(scope == PageContext.APPLICATION_SCOPE) 305 { 306 if(getServletContext() == null) return new NullEnumeration(); 307 return getServletContext().getAttributeNames(); 308 } 309 else 310 { 311 throw new IllegalArgumentException("Invalid scope " + scope); 312 } 313 } 314 315 public JspWriter getOut() 316 { 317 return jspWriter; 318 } 319 320 public Exception getException() 321 { 322 return exception; 323 } 324 325 public Object getPage() 326 { 327 return page; 328 } 329 330 public ServletRequest getRequest() 331 { 332 return request; 333 } 334 335 public ServletResponse getResponse() 336 { 337 return response; 338 } 339 340 public ServletConfig getServletConfig() 341 { 342 return config; 343 } 344 345 public ServletContext getServletContext() 346 { 347 if(null == config) return null; 348 return config.getServletContext(); 349 } 350 351 352 public HttpSession getSession() 353 { 354 if(null == request) return null; 355 return ((HttpServletRequest)request).getSession(); 356 } 357 358 public void handlePageException(Exception exc) 359 { 360 361 } 362 363 public void handlePageException(Throwable thr) 364 { 365 366 } 367 368 public void forward(String path) throws ServletException, IOException 369 { 370 if(null != request) 371 { 372 RequestDispatcher dispatcher = request.getRequestDispatcher(path); 373 if(null != dispatcher) 374 { 375 dispatcher.forward(request, response); 376 } 377 } 378 } 379 380 public void include(String path) throws ServletException, IOException 381 { 382 if(null != request) 383 { 384 RequestDispatcher dispatcher = request.getRequestDispatcher(path); 385 if(null != dispatcher) 386 { 387 dispatcher.include(request, response); 388 } 389 } 390 } 391 392 public void include(String path, boolean flush) throws ServletException, IOException 393 { 394 if(flush) 395 { 396 jspWriter.flush(); 397 } 398 include(path); 399 } 400 401 public void initialize(Servlet servlet, ServletRequest request, 402 ServletResponse response, String errorPageURL, 403 boolean needsSession, int bufferSize, 404 boolean autoFlush) 405 { 406 this.config = servlet.getServletConfig(); 407 this.request = request; 408 this.response = response; 409 jspWriter = new MockJspWriter(); 410 outStack = new Stack(); 411 attributes = new HashMap(); 412 } 413 414 public JspWriter popBody() 415 { 416 jspWriter = (JspWriter)outStack.pop(); 417 return jspWriter; 418 } 419 420 public BodyContent pushBody() 421 { 422 outStack.push(jspWriter); 423 jspWriter = new MockBodyContent(jspWriter); 424 return (BodyContent)jspWriter; 425 } 426 427 public JspWriter pushBody(Writer writer) 428 { 429 outStack.push(jspWriter); 430 jspWriter = new MockJspWriter(writer); 431 return jspWriter; 432 } 433 434 public void release() 435 { 436 jspWriter = new MockJspWriter(); 437 outStack = new Stack(); 438 } 439 440 /** 441 * Sets the expression evaluator. The default expression evaluator 442 * is {@link MockExpressionEvaluator}. 443 * @param evaluator the <code>ExpressionEvaluator</code> 444 */ 445 public void setExpressionEvaluator(ExpressionEvaluator evaluator) 446 { 447 this.evaluator = evaluator; 448 } 449 450 /** 451 * Sets the variable resolver. The default variable resolver 452 * is {@link MockVariableResolver}. 453 * @param resolver the <code>VariableResolver</code> 454 */ 455 public void setVariableResolver(VariableResolver resolver) 456 { 457 this.resolver = resolver; 458 } 459 460 /** 461 * Sets the <code>ELContext</code>. There is no default 462 * <code>ELContext</code>. Configure the {@link JasperJspFactory} 463 * to set one. 464 * @param elContext the <code>ELContext</code> 465 */ 466 public void setELContext(ELContext elContext) 467 { 468 this.elContext = elContext; 469 } 470 471 public ExpressionEvaluator getExpressionEvaluator() 472 { 473 return evaluator; 474 } 475 476 public VariableResolver getVariableResolver() 477 { 478 return resolver; 479 } 480 481 public ELContext getELContext() 482 { 483 return elContext; 484 } 485 486 private class NullEnumeration implements Enumeration 487 { 488 public boolean hasMoreElements() 489 { 490 return false; 491 } 492 493 public Object nextElement() 494 { 495 throw new NoSuchElementException(); 496 } 497 } 498 499 private class WrappedEnumeration implements Enumeration 500 { 501 private Iterator iterator; 502 503 public WrappedEnumeration(Iterator iterator) 504 { 505 this.iterator = iterator; 506 } 507 508 public boolean hasMoreElements() 509 { 510 return iterator.hasNext(); 511 } 512 513 public Object nextElement() 514 { 515 return iterator.next(); 516 } 517 } 518 }