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