001: /*
002: * Copyright (c) 2003 The Visigoth Software Society. All rights
003: * reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions
007: * are met:
008: *
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: *
012: * 2. Redistributions in binary form must reproduce the above copyright
013: * notice, this list of conditions and the following disclaimer in
014: * the documentation and/or other materials provided with the
015: * distribution.
016: *
017: * 3. The end-user documentation included with the redistribution, if
018: * any, must include the following acknowledgement:
019: * "This product includes software developed by the
020: * Visigoth Software Society (http://www.visigoths.org/)."
021: * Alternately, this acknowledgement may appear in the software itself,
022: * if and wherever such third-party acknowledgements normally appear.
023: *
024: * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the
025: * project contributors may be used to endorse or promote products derived
026: * from this software without prior written permission. For written
027: * permission, please contact visigoths@visigoths.org.
028: *
029: * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
030: * nor may "FreeMarker" or "Visigoth" appear in their names
031: * without prior written permission of the Visigoth Software Society.
032: *
033: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
034: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
035: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
036: * DISCLAIMED. IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
037: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
038: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
039: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
040: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
041: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
042: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
043: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
044: * SUCH DAMAGE.
045: * ====================================================================
046: *
047: * This software consists of voluntary contributions made by many
048: * individuals on behalf of the Visigoth Software Society. For more
049: * information on the Visigoth Software Society, please see
050: * http://www.visigoths.org/
051: */
052:
053: package freemarker.ext.jsp;
054:
055: import freemarker.core.Environment;
056: import freemarker.ext.servlet.FreemarkerServlet;
057: import freemarker.ext.servlet.HttpRequestHashModel;
058: import freemarker.ext.servlet.ServletContextHashModel;
059: import freemarker.ext.util.WrapperTemplateModel;
060: import freemarker.template.AdapterTemplateModel;
061: import freemarker.template.ObjectWrapper;
062: import freemarker.template.TemplateBooleanModel;
063: import freemarker.template.TemplateHashModelEx;
064: import freemarker.template.TemplateModel;
065: import freemarker.template.TemplateModelException;
066: import freemarker.template.TemplateModelIterator;
067: import freemarker.template.TemplateNumberModel;
068: import freemarker.template.TemplateScalarModel;
069: import freemarker.template.utility.UndeclaredThrowableException;
070:
071: import javax.servlet.GenericServlet;
072: import javax.servlet.Servlet;
073: import javax.servlet.ServletConfig;
074: import javax.servlet.ServletContext;
075: import javax.servlet.ServletException;
076: import javax.servlet.ServletRequest;
077: import javax.servlet.ServletResponse;
078: import javax.servlet.http.HttpServletRequest;
079: import javax.servlet.http.HttpServletResponse;
080: import javax.servlet.http.HttpSession;
081: import javax.servlet.jsp.JspWriter;
082: import javax.servlet.jsp.PageContext;
083: import javax.servlet.jsp.tagext.BodyContent;
084: import javax.servlet.jsp.tagext.Tag;
085: import java.io.IOException;
086: import java.util.ArrayList;
087: import java.util.Collections;
088: import java.util.Enumeration;
089: import java.util.List;
090:
091: /**
092: * @version $Id: FreeMarkerPageContext.java,v 1.26.2.2 2006/07/08 14:45:34 ddekany Exp $
093: * @author Attila Szegedi
094: */
095: abstract class FreeMarkerPageContext extends PageContext implements
096: TemplateModel {
097: private static final Class OBJECT_CLASS = Object.class;
098:
099: private final Environment environment;
100: private List tags = new ArrayList();
101: private List outs = new ArrayList();
102: private final GenericServlet servlet;
103: private HttpSession session;
104: private final HttpServletRequest request;
105: private final HttpServletResponse response;
106: private final ObjectWrapper wrapper;
107: private JspWriter jspOut;
108:
109: protected FreeMarkerPageContext() throws TemplateModelException {
110: environment = Environment.getCurrentEnvironment();
111:
112: TemplateModel appModel = environment
113: .getGlobalVariable(FreemarkerServlet.KEY_APPLICATION_PRIVATE);
114: if (!(appModel instanceof ServletContextHashModel)) {
115: appModel = environment
116: .getGlobalVariable(FreemarkerServlet.KEY_APPLICATION);
117: }
118: if (appModel instanceof ServletContextHashModel) {
119: this .servlet = ((ServletContextHashModel) appModel)
120: .getServlet();
121: } else {
122: throw new TemplateModelException(
123: "Could not find an instance of "
124: + ServletContextHashModel.class.getName()
125: + " in the data model under either the name "
126: + FreemarkerServlet.KEY_APPLICATION_PRIVATE
127: + " or "
128: + FreemarkerServlet.KEY_APPLICATION);
129: }
130:
131: TemplateModel requestModel = environment
132: .getGlobalVariable(FreemarkerServlet.KEY_REQUEST_PRIVATE);
133: if (!(requestModel instanceof HttpRequestHashModel)) {
134: requestModel = environment
135: .getGlobalVariable(FreemarkerServlet.KEY_REQUEST);
136: }
137: if (requestModel instanceof HttpRequestHashModel) {
138: HttpRequestHashModel reqHash = (HttpRequestHashModel) requestModel;
139: this .request = reqHash.getRequest();
140: this .session = request.getSession(false);
141: this .response = reqHash.getResponse();
142: this .wrapper = reqHash.getObjectWrapper();
143: } else {
144: throw new TemplateModelException(
145: "Could not find an instance of "
146: + HttpRequestHashModel.class.getName()
147: + " in the data model under either the name "
148: + FreemarkerServlet.KEY_REQUEST_PRIVATE
149: + " or " + FreemarkerServlet.KEY_REQUEST);
150: }
151:
152: // Register page attributes as per spec
153: setAttribute(REQUEST, request);
154: setAttribute(RESPONSE, response);
155: if (session != null)
156: setAttribute(SESSION, session);
157: setAttribute(PAGE, servlet);
158: setAttribute(CONFIG, servlet.getServletConfig());
159: setAttribute(PAGECONTEXT, this );
160: setAttribute(APPLICATION, servlet.getServletContext());
161: }
162:
163: ObjectWrapper getObjectWrapper() {
164: return wrapper;
165: }
166:
167: public void initialize(Servlet servlet, ServletRequest request,
168: ServletResponse response, String errorPageURL,
169: boolean needsSession, int bufferSize, boolean autoFlush) {
170: throw new UnsupportedOperationException();
171: }
172:
173: public void release() {
174: }
175:
176: public void setAttribute(String name, Object value) {
177: setAttribute(name, value, PAGE_SCOPE);
178: }
179:
180: public void setAttribute(String name, Object value, int scope) {
181: switch (scope) {
182: case PAGE_SCOPE: {
183: try {
184: environment
185: .setGlobalVariable(name, wrapper.wrap(value));
186: break;
187: } catch (TemplateModelException e) {
188: throw new UndeclaredThrowableException(e);
189: }
190: }
191: case REQUEST_SCOPE: {
192: getRequest().setAttribute(name, value);
193: break;
194: }
195: case SESSION_SCOPE: {
196: getSession(true).setAttribute(name, value);
197: break;
198: }
199: case APPLICATION_SCOPE: {
200: getServletContext().setAttribute(name, value);
201: break;
202: }
203: default: {
204: throw new IllegalArgumentException("Invalid scope " + scope);
205: }
206: }
207: }
208:
209: public Object getAttribute(String name) {
210: return getAttribute(name, PAGE_SCOPE);
211: }
212:
213: public Object getAttribute(String name, int scope) {
214: switch (scope) {
215: case PAGE_SCOPE: {
216: try {
217: TemplateModel m = environment.getGlobalNamespace().get(
218: name);
219: if (m instanceof AdapterTemplateModel) {
220: return ((AdapterTemplateModel) m)
221: .getAdaptedObject(OBJECT_CLASS);
222: }
223: if (m instanceof WrapperTemplateModel) {
224: return ((WrapperTemplateModel) m)
225: .getWrappedObject();
226: }
227: if (m instanceof TemplateScalarModel) {
228: return ((TemplateScalarModel) m).getAsString();
229: }
230: if (m instanceof TemplateNumberModel) {
231: return ((TemplateNumberModel) m).getAsNumber();
232: }
233: if (m instanceof TemplateBooleanModel) {
234: return ((TemplateBooleanModel) m).getAsBoolean() ? Boolean.TRUE
235: : Boolean.FALSE;
236: }
237: return m;
238: } catch (TemplateModelException e) {
239: throw new UndeclaredThrowableException(e);
240: }
241: }
242: case REQUEST_SCOPE: {
243: return getRequest().getAttribute(name);
244: }
245: case SESSION_SCOPE: {
246: HttpSession session = getSession(false);
247: if (session == null) {
248: return null;
249: }
250: return session.getAttribute(name);
251: }
252: case APPLICATION_SCOPE: {
253: return getServletContext().getAttribute(name);
254: }
255: default: {
256: throw new IllegalArgumentException("Invalid scope " + scope);
257: }
258: }
259: }
260:
261: public Object findAttribute(String name) {
262: Object retval = getAttribute(name, PAGE_SCOPE);
263: if (retval != null)
264: return retval;
265: retval = getAttribute(name, REQUEST_SCOPE);
266: if (retval != null)
267: return retval;
268: retval = getAttribute(name, SESSION_SCOPE);
269: if (retval != null)
270: return retval;
271: return getAttribute(name, APPLICATION_SCOPE);
272: }
273:
274: public void removeAttribute(String name) {
275: removeAttribute(name, PAGE_SCOPE);
276: removeAttribute(name, REQUEST_SCOPE);
277: removeAttribute(name, SESSION_SCOPE);
278: removeAttribute(name, APPLICATION_SCOPE);
279: }
280:
281: public void removeAttribute(String name, int scope) {
282: switch (scope) {
283: case PAGE_SCOPE: {
284: environment.getGlobalNamespace().remove(name);
285: break;
286: }
287: case REQUEST_SCOPE: {
288: getRequest().removeAttribute(name);
289: break;
290: }
291: case SESSION_SCOPE: {
292: HttpSession session = getSession(false);
293: if (session != null) {
294: session.removeAttribute(name);
295: }
296: break;
297: }
298: case APPLICATION_SCOPE: {
299: getServletContext().removeAttribute(name);
300: break;
301: }
302: default: {
303: throw new IllegalArgumentException("Invalid scope: "
304: + scope);
305: }
306: }
307: }
308:
309: public int getAttributesScope(String name) {
310: if (getAttribute(name, PAGE_SCOPE) != null)
311: return PAGE_SCOPE;
312: if (getAttribute(name, REQUEST_SCOPE) != null)
313: return REQUEST_SCOPE;
314: if (getAttribute(name, SESSION_SCOPE) != null)
315: return SESSION_SCOPE;
316: if (getAttribute(name, APPLICATION_SCOPE) != null)
317: return APPLICATION_SCOPE;
318: return 0;
319: }
320:
321: public Enumeration getAttributeNamesInScope(int scope) {
322: switch (scope) {
323: case PAGE_SCOPE: {
324: try {
325: return new TemplateHashModelExEnumeration(environment
326: .getGlobalNamespace());
327: } catch (TemplateModelException e) {
328: throw new UndeclaredThrowableException(e);
329: }
330: }
331: case REQUEST_SCOPE: {
332: return getRequest().getAttributeNames();
333: }
334: case SESSION_SCOPE: {
335: HttpSession session = getSession(false);
336: if (session != null) {
337: return session.getAttributeNames();
338: }
339: return Collections.enumeration(Collections.EMPTY_SET);
340: }
341: case APPLICATION_SCOPE: {
342: return getServletContext().getAttributeNames();
343: }
344: default: {
345: throw new IllegalArgumentException("Invalid scope " + scope);
346: }
347: }
348: }
349:
350: public JspWriter getOut() {
351: return jspOut;
352: }
353:
354: private HttpSession getSession(boolean create) {
355: if (session == null) {
356: session = request.getSession(create);
357: if (session != null) {
358: setAttribute(SESSION, session);
359: }
360: }
361: return session;
362: }
363:
364: public HttpSession getSession() {
365: return getSession(false);
366: }
367:
368: public Object getPage() {
369: return servlet;
370: }
371:
372: public ServletRequest getRequest() {
373: return request;
374: }
375:
376: public ServletResponse getResponse() {
377: return response;
378: }
379:
380: public Exception getException() {
381: throw new UnsupportedOperationException();
382: }
383:
384: public ServletConfig getServletConfig() {
385: return servlet.getServletConfig();
386: }
387:
388: public ServletContext getServletContext() {
389: return servlet.getServletContext();
390: }
391:
392: public void forward(String url) throws ServletException,
393: IOException {
394: //TODO: make sure this is 100% correct by looking at Jasper output
395: request.getRequestDispatcher(url).forward(request, response);
396: }
397:
398: public void include(String url) throws ServletException,
399: IOException {
400: //TODO: make sure this is 100% correct by looking at Jasper output
401: request.getRequestDispatcher(url).include(request, response);
402: }
403:
404: public void handlePageException(Exception e) {
405: throw new UnsupportedOperationException();
406: }
407:
408: public void handlePageException(Throwable e) {
409: throw new UnsupportedOperationException();
410: }
411:
412: public BodyContent pushBody() {
413: BodyContent bc = new TagTransformModel.BodyContentImpl(
414: getOut(), true);
415: pushWriter(bc);
416: return bc;
417: }
418:
419: public JspWriter popBody() {
420: popWriter();
421: return (JspWriter) getAttribute(OUT);
422: }
423:
424: Tag peekTopTag() {
425: return tags.isEmpty() ? null : (Tag) tags.get(tags.size() - 1);
426: }
427:
428: void popTopTag() {
429: tags.remove(tags.size() - 1);
430: }
431:
432: void popWriter() {
433: jspOut = (JspWriter) outs.remove(outs.size() - 1);
434: setAttribute(OUT, jspOut);
435: }
436:
437: void pushTopTag(Tag tag) {
438: tags.add(tag);
439: }
440:
441: void pushWriter(JspWriter out) {
442: outs.add(jspOut);
443: jspOut = out;
444: setAttribute(OUT, jspOut);
445: }
446:
447: private static class TemplateHashModelExEnumeration implements
448: Enumeration {
449: private final TemplateModelIterator it;
450:
451: private TemplateHashModelExEnumeration(
452: TemplateHashModelEx hashEx)
453: throws TemplateModelException {
454: it = hashEx.keys().iterator();
455: }
456:
457: public boolean hasMoreElements() {
458: try {
459: return it.hasNext();
460: } catch (TemplateModelException tme) {
461: throw new UndeclaredThrowableException(tme);
462: }
463: }
464:
465: public Object nextElement() {
466: try {
467: return ((TemplateScalarModel) it.next()).getAsString();
468: } catch (TemplateModelException tme) {
469: throw new UndeclaredThrowableException(tme);
470: }
471: }
472: }
473: }
|