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    }