View Javadoc

1   package org.apache.velocity.tools.view.jsp.jspimpl;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.IOException;
23  import java.io.PrintWriter;
24  import java.io.Writer;
25  import java.util.Enumeration;
26  import java.util.NoSuchElementException;
27  
28  import javax.el.ELContext;
29  import javax.servlet.RequestDispatcher;
30  import javax.servlet.Servlet;
31  import javax.servlet.ServletConfig;
32  import javax.servlet.ServletContext;
33  import javax.servlet.ServletException;
34  import javax.servlet.ServletRequest;
35  import javax.servlet.ServletResponse;
36  import javax.servlet.http.HttpServletRequest;
37  import javax.servlet.http.HttpServletResponse;
38  import javax.servlet.http.HttpSession;
39  import javax.servlet.jsp.JspWriter;
40  import javax.servlet.jsp.PageContext;
41  
42  import org.apache.velocity.context.Context;
43  import org.apache.velocity.tools.view.ViewContext;
44  
45  /**
46   * Exposes a Velocity {@link Context}, a request and a response as a {@link PageContext}.
47   *
48   */
49  public class VelocityPageContext extends PageContext {
50  
51      /**
52       * The Velocity context.
53       */
54      private Context velocityContext;
55  
56      /**
57       * The writer to use when writing content.
58       */
59      private Writer velocityWriter;
60  
61      /**
62       * The view context.
63       */
64      private ViewContext viewContext;
65  
66      /**
67       * The JSP writer, simulated.
68       */
69      private JspWriter jspWriter;
70  
71      /**
72       * The HTTP request.
73       */
74      private HttpServletRequest request;
75  
76      /**
77       * The HTTP response.
78       */
79      private HttpServletResponse response;
80  
81      /**
82       * Constructor.
83       *
84       * @param velocityContext The Velocity context.
85       * @param velocityWriter The writer to be used when writing content.
86       * @param viewContext The View context.
87       */
88      public VelocityPageContext(Context velocityContext, Writer velocityWriter, ViewContext viewContext)
89      {
90  	    this.velocityContext = velocityContext;
91  	    this.velocityWriter = velocityWriter;
92  	    this.viewContext = viewContext;
93  	    this.request = viewContext.getRequest();
94  	    this.response = viewContext.getResponse();
95          jspWriter = new JspWriterImpl(velocityWriter);
96          velocityContext.put("out", jspWriter);
97      }
98  
99  	@Override
100     public void initialize(Servlet servlet, ServletRequest request,
101             ServletResponse response, String errorPageURL,
102             boolean needsSession, int bufferSize, boolean autoFlush)
103             throws IOException, IllegalStateException, IllegalArgumentException {
104 		// We never call it and we discard this object at the end of the page call.
105     }
106 
107     @Override
108     public void release() {
109 		// We never call it and we discard this object at the end of the page call.
110     }
111 
112     @Override
113     public HttpSession getSession() {
114         return request.getSession(false);
115     }
116 
117     @Override
118     public Object getPage() {
119         return viewContext;
120     }
121 
122     @Override
123     public ServletRequest getRequest() {
124         return request;
125     }
126 
127     @Override
128     public ServletResponse getResponse() {
129         return response;
130     }
131 
132     @Override
133     public Exception getException() {
134         return null;
135     }
136 
137     @Override
138     public ServletConfig getServletConfig() {
139         throw new UnsupportedOperationException("Servlet config is not supported");
140     }
141 
142     @Override
143     public ServletContext getServletContext() {
144         return viewContext.getServletContext();
145     }
146 
147     @Override
148     public void forward(String relativeUrlPath) throws ServletException,
149             IOException {
150         RequestDispatcher dispatcher = request.getRequestDispatcher(relativeUrlPath);
151         if (dispatcher == null) {
152             throw new IllegalArgumentException("Cannot forward to '" +relativeUrlPath + "'");
153         }
154         dispatcher.forward(request, new ExternalWriterHttpServletResponse(response, new PrintWriter(velocityWriter)));
155 
156     }
157 
158     @Override
159     public void include(String relativeUrlPath) throws ServletException,
160             IOException {
161         include(relativeUrlPath, true);
162     }
163 
164     @Override
165     public void include(String relativeUrlPath, boolean flush)
166             throws ServletException, IOException {
167         if (flush) {
168         	velocityWriter.flush();
169         }
170         RequestDispatcher dispatcher = request.getRequestDispatcher(relativeUrlPath);
171         if (dispatcher == null) {
172             throw new IllegalArgumentException("Cannot include '" +relativeUrlPath + "'");
173         }
174         dispatcher.include(request, new ExternalWriterHttpServletResponse(response, new PrintWriter(velocityWriter)));
175     }
176 
177     @Override
178     public void handlePageException(Exception e) throws ServletException,
179             IOException {
180     	handlePageException((Throwable) e);
181     }
182 
183     @Override
184     public void handlePageException(Throwable t) throws ServletException,
185             IOException {
186         if (t instanceof RuntimeException)
187         {
188 	        throw (RuntimeException) t;
189         }
190         if (t instanceof Error)
191         {
192 	        throw (Error) t;
193         }
194         throw new ServletException("Rethrowing unmanaged exception", t);
195     }
196 
197     @Override
198     public void setAttribute(String name, Object value) {
199     	if (name == null) {
200     		throw new NullPointerException("The attribute name is null");
201     	}
202         velocityContext.put(name, value);
203     }
204 
205     @Override
206     public void setAttribute(String name, Object value, int scope) {
207     	if (name == null) {
208     		throw new NullPointerException("The attribute name is null");
209     	}
210         switch (scope)
211         {
212         case PAGE_SCOPE:
213         	velocityContext.put(name, value);
214 	        break;
215         case REQUEST_SCOPE:
216         	request.setAttribute(name, value);
217         	break;
218         case SESSION_SCOPE:
219         	if (value == null) {
220         		HttpSession session = request.getSession(false);
221         		if (session != null) {
222         			session.removeAttribute(name);
223         		}
224         	} else {
225         		HttpSession session = request.getSession();
226         		session.setAttribute(name, value);
227         	}
228         	break;
229         case APPLICATION_SCOPE:
230         	viewContext.getServletContext().setAttribute(name, value);
231         	break;
232         default:
233         	throw new IllegalArgumentException("Invalid scope constant value: " + scope);
234         }
235     }
236 
237     @Override
238     public Object getAttribute(String name) {
239     	if (name == null) {
240     		throw new NullPointerException("The attribute name is null");
241     	}
242         return velocityContext.get(name);
243     }
244 
245     @Override
246     public Object getAttribute(String name, int scope) {
247     	if (name == null) {
248     		throw new NullPointerException("The attribute name is null");
249     	}
250         switch (scope)
251         {
252         case PAGE_SCOPE:
253         	return velocityContext.get(name);
254         case REQUEST_SCOPE:
255         	return request.getAttribute(name);
256         case SESSION_SCOPE:
257     		HttpSession session = request.getSession(false);
258     		if (session != null) {
259     			return session.getAttribute(name);
260     		} else {
261     			return null;
262     		}
263         case APPLICATION_SCOPE:
264         	return viewContext.getServletContext().getAttribute(name);
265         default:
266         	throw new IllegalArgumentException("Invalid scope constant value: " + scope);
267         }
268     }
269 
270     @Override
271     public Object findAttribute(String name) {
272     	if (name == null) {
273     		throw new NullPointerException("The attribute name is null");
274     	}
275     	Object candidate = velocityContext.get(name);
276     	if (candidate == null) {
277     		candidate = request.getAttribute(name);
278     		if (candidate == null) {
279     			HttpSession session = request.getSession(false);
280     			if (session != null) {
281     				candidate = session.getAttribute(name);
282     			}
283     			if (candidate == null) {
284     				candidate = viewContext.getServletContext().getAttribute(name);
285     			}
286     		}
287     	}
288         return candidate;
289     }
290 
291     @Override
292     public void removeAttribute(String name) {
293     	if (name == null) {
294     		throw new NullPointerException("The attribute name is null");
295     	}
296     	velocityContext.remove(name);
297     	request.removeAttribute(name);
298     	HttpSession session = request.getSession(false);
299     	if (session != null) {
300     		session.removeAttribute(name);
301     	}
302     	viewContext.getServletContext().removeAttribute(name);
303     }
304 
305     @Override
306     public void removeAttribute(String name, int scope) {
307     	if (name == null) {
308     		throw new NullPointerException("The attribute name is null");
309     	}
310         switch (scope)
311         {
312         case PAGE_SCOPE:
313         	velocityContext.remove(name);
314 	        break;
315         case REQUEST_SCOPE:
316         	request.removeAttribute(name);
317         	break;
318         case SESSION_SCOPE:
319     		HttpSession session = request.getSession(false);
320     		if (session != null) {
321     			session.removeAttribute(name);
322     		}
323         	break;
324         case APPLICATION_SCOPE:
325         	viewContext.getServletContext().removeAttribute(name);
326         	break;
327         default:
328         	throw new IllegalArgumentException("Invalid scope constant value: " + scope);
329         }
330     }
331 
332     @Override
333     public int getAttributesScope(String name) {
334     	if (name == null) {
335     		throw new NullPointerException("The attribute name is null");
336     	}
337     	if (velocityContext.get(name) != null) {
338     		return PAGE_SCOPE;
339     	}
340 		if (request.getAttribute(name) != null) {
341 			return REQUEST_SCOPE;
342 		}
343 		HttpSession session = request.getSession(false);
344 		if (session != null) {
345 			if (session.getAttribute(name) != null) {
346 				return SESSION_SCOPE;
347 			}
348 		}
349 		if (viewContext.getServletContext().getAttribute(name) != null) {
350 			return APPLICATION_SCOPE;
351 		}
352         return 0;
353     }
354 
355     @SuppressWarnings("unchecked")
356     @Override
357     public Enumeration<String> getAttributeNamesInScope(int scope) {
358         switch (scope)
359         {
360         case PAGE_SCOPE:
361         	return new Enumeration<String>()
362 			{
363 
364         		private int index = 0;
365 
366         		private Object[] keys = velocityContext.getKeys();
367 
368 				public boolean hasMoreElements()
369                 {
370 	                return index < keys.length;
371                 }
372 
373 				public String nextElement()
374                 {
375 	                String retValue = (String) keys[index];
376 	                index++;
377 	                return retValue;
378                 }
379 			};
380         case REQUEST_SCOPE:
381         	return request.getAttributeNames();
382         case SESSION_SCOPE:
383     		HttpSession session = request.getSession(false);
384     		if (session != null) {
385     			return session.getAttributeNames();
386     		}
387     		return new Enumeration<String>()
388 			{
389 
390 				public boolean hasMoreElements()
391                 {
392 	                return false;
393                 }
394 
395 				public String nextElement()
396                 {
397 	                throw new NoSuchElementException("This is an empty enumeration");
398                 }
399 			};
400         case APPLICATION_SCOPE:
401         	return viewContext.getServletContext().getAttributeNames();
402         default:
403         	throw new IllegalArgumentException("Invalid scope constant value: " + scope);
404         }
405     }
406 
407     @Override
408     public JspWriter getOut() {
409         return jspWriter;
410     }
411 
412     @SuppressWarnings("deprecation")
413     @Override
414     public javax.servlet.jsp.el.ExpressionEvaluator getExpressionEvaluator() {
415     	// Really, who cares?
416     	throw new UnsupportedOperationException("This class works only with JSP 2.1");
417     }
418 
419     @SuppressWarnings("deprecation")
420     @Override
421     public javax.servlet.jsp.el.VariableResolver getVariableResolver() {
422     	// Really, who cares?
423     	throw new UnsupportedOperationException("This class works only with JSP 2.1");
424     }
425 
426     @Override
427     public ELContext getELContext() {
428     	// Really, who cares?
429     	throw new UnsupportedOperationException("EL not available at this point");
430     }
431 }