All Downloads are FREE. Search and download functionalities are using the official Maven repository.

freemarker.ext.servlet.FreemarkerServlet Maven / Gradle / Ivy

There is a newer version: 2.3.32_1
Show newest version
/*
 * Copyright (c) 2003 The Visigoth Software Society. All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowledgement:
 *       "This product includes software developed by the
 *        Visigoth Software Society (http://www.visigoths.org/)."
 *    Alternately, this acknowledgement may appear in the software itself,
 *    if and wherever such third-party acknowledgements normally appear.
 *
 * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the 
 *    project contributors may be used to endorse or promote products derived
 *    from this software without prior written permission. For written
 *    permission, please contact [email protected].
 *
 * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
 *    nor may "FreeMarker" or "Visigoth" appear in their names
 *    without prior written permission of the Visigoth Software Society.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Visigoth Software Society. For more
 * information on the Visigoth Software Society, please see
 * http://www.visigoths.org/
 */

package freemarker.ext.servlet;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.cache.WebappTemplateLoader;
import freemarker.core.Configurable;
import freemarker.ext.jsp.TaglibFactory;
import freemarker.log.Logger;
import freemarker.template.Configuration;
import freemarker.template.ObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.utility.StringUtil;
import java.util.Locale;

/**
 * 

This is a general-purpose FreeMarker view servlet.

* *

The main features are: * *

    * *
  • It makes all request, request parameters, session, and servlet * context attributes available to templates through Request, * RequestParameters, Session, and Application * variables. * *
  • The scope variables are also available via automatic scope discovery. That is, * writing Application.attrName, Session.attrName, * Request.attrName is not mandatory; it's enough to write attrName, * and if no such variable was created in the template, it will search the * variable in Request, and then in Session, * and finally in Application. * *
  • It creates a variable with name JspTaglibs, that can be used * to load JSP taglibs. For example:
    * <#assign tiles=JspTaglibs["/WEB-INF/struts-tiles.tld"]> * *
  • A custom directive named include_page allows you to * include the output of another servlet resource from your servlet container, * just as if you used ServletRequest.getRequestDispatcher(path).include():
    * <@include_page path="/myWebapp/somePage.jsp"/>. You can also * pass parameters to the newly included page by passing a hash named 'params': * <@include_page path="/myWebapp/somePage.jsp" params={lang: "en", q="5"}/>. * By default, the request parameters of the original request (the one being * processed by FreemarkerServlet) are also inherited by the include. You can * explicitly control this inheritance using the 'inherit_params' parameter: * <@include_page path="/myWebapp/somePage.jsp" params={lang: "en", q="5"} inherit_params=false/>. *
* *

The servlet will rethrow the errors occurring during template processing, * wrapped into ServletException, except if the class name of the * class set by the template_exception_handler contains the * substring "Debug". If it contains "Debug", then it * is assumed that the template exception handler prints the error message to the * page, thus FreemarkerServlet will suppress the exception, and * logs the problem with the servlet logger * (javax.servlet.GenericServlet.log(...)). * *

Supported init-params are:

* *
    * *
  • TemplatePath specifies the location of the templates. * By default, this is interpreted as web application directory relative URI.
    * Alternatively, you can prepend it with file:// to indicate a literal * path in the file system (i.e. file:///var/www/project/templates/). * Note that three slashes were used to specify an absolute path.
    * Also, you can prepend it with class://path/to/template/package to * indicate that you want to load templates from the specified package * accessible through the classloader of the servlet.
    * Default value is class:// (that is, the root of the class hierarchy). * Note that this default is different than the default in FreeMarker 1.x, when * it defaulted /, that is to loading from the webapp root directory.
  • * *
  • NoCache if set to true, generates headers in the response * that advise the HTTP client not to cache the returned page. * The default is false.
  • * *
  • ContentType if specified, response uses the specified * Content-type HTTP header. The value may include the charset (e.g. * "text/html; charset=ISO-8859-1"). If not specified, "text/html" * is used. If the charset is not specified in this init-param, then the charset * (encoding) of the actual template file will be used (in the response HTTP header * and for encoding the output stream). Note that this setting can be overridden * on a per-template basis by specifying a custom attribute named * content_type in the attributes parameter of the * <#ftl> directive. *
  • * *
  • The following init-params are supported only for backward compatibility, and * their usage is discouraged: TemplateUpdateInterval, DefaultEncoding, * ObjectWrapper, TemplateExceptionHandler. Use setting init-params such as * object_wrapper instead. * *
  • Any other init-param will be interpreted as Configuration * level setting. See {@link Configuration#setSetting}
  • * *
* * @author Attila Szegedi * @version $Id: FreemarkerServlet.java,v 1.82.2.5 2006/06/21 13:02:01 ddekany Exp $ */ public class FreemarkerServlet extends HttpServlet { private static final Logger logger = Logger.getLogger("freemarker.servlet"); public static final long serialVersionUID = -2440216393145762479L; private static final String INITPARAM_TEMPLATE_PATH = "TemplatePath"; private static final String INITPARAM_NOCACHE = "NoCache"; private static final String INITPARAM_CONTENT_TYPE = "ContentType"; private static final String DEFAULT_CONTENT_TYPE = "text/html"; private static final String INITPARAM_DEBUG = "Debug"; private static final String DEPR_INITPARAM_TEMPLATE_DELAY = "TemplateDelay"; private static final String DEPR_INITPARAM_ENCODING = "DefaultEncoding"; private static final String DEPR_INITPARAM_OBJECT_WRAPPER = "ObjectWrapper"; private static final String DEPR_INITPARAM_WRAPPER_SIMPLE = "simple"; private static final String DEPR_INITPARAM_WRAPPER_BEANS = "beans"; private static final String DEPR_INITPARAM_WRAPPER_JYTHON = "jython"; private static final String DEPR_INITPARAM_TEMPLATE_EXCEPTION_HANDLER = "TemplateExceptionHandler"; private static final String DEPR_INITPARAM_TEMPLATE_EXCEPTION_HANDLER_RETHROW = "rethrow"; private static final String DEPR_INITPARAM_TEMPLATE_EXCEPTION_HANDLER_DEBUG = "debug"; private static final String DEPR_INITPARAM_TEMPLATE_EXCEPTION_HANDLER_HTML_DEBUG = "htmlDebug"; private static final String DEPR_INITPARAM_TEMPLATE_EXCEPTION_HANDLER_IGNORE = "ignore"; private static final String DEPR_INITPARAM_DEBUG = "debug"; public static final String KEY_REQUEST = "Request"; public static final String KEY_INCLUDE = "include_page"; public static final String KEY_REQUEST_PRIVATE = "__FreeMarkerServlet.Request__"; public static final String KEY_REQUEST_PARAMETERS = "RequestParameters"; public static final String KEY_SESSION = "Session"; public static final String KEY_APPLICATION = "Application"; public static final String KEY_APPLICATION_PRIVATE = "__FreeMarkerServlet.Application__"; public static final String KEY_JSP_TAGLIBS = "JspTaglibs"; // Note these names start with dot, so they're essentially invisible from // a freemarker script. private static final String ATTR_REQUEST_MODEL = ".freemarker.Request"; private static final String ATTR_REQUEST_PARAMETERS_MODEL = ".freemarker.RequestParameters"; private static final String ATTR_SESSION_MODEL = ".freemarker.Session"; private static final String ATTR_APPLICATION_MODEL = ".freemarker.Application"; private static final String ATTR_JSP_TAGLIBS_MODEL = ".freemarker.JspTaglibs"; private static final String EXPIRATION_DATE; static { // Generate expiration date that is one year from now in the past GregorianCalendar expiration = new GregorianCalendar(); expiration.roll(Calendar.YEAR, -1); SimpleDateFormat httpDate = new SimpleDateFormat( "EEE, dd MMM yyyy HH:mm:ss z", java.util.Locale.US); EXPIRATION_DATE = httpDate.format(expiration.getTime()); } private String templatePath; private boolean nocache; protected boolean debug; private Configuration config; private ObjectWrapper wrapper; private String contentType; private boolean noCharsetInContentType; public void init() throws ServletException { try { config = createConfiguration(); // Set defaults: config.setTemplateExceptionHandler(TemplateExceptionHandler.HTML_DEBUG_HANDLER); contentType = DEFAULT_CONTENT_TYPE; // Process object_wrapper init-param out of order: wrapper = createObjectWrapper(); if (logger.isDebugEnabled()) { logger.debug("Using object wrapper of class " + wrapper.getClass().getName()); } config.setObjectWrapper(wrapper); // Process TemplatePath init-param out of order: templatePath = getInitParameter(INITPARAM_TEMPLATE_PATH); if (templatePath == null) templatePath = "class://"; config.setTemplateLoader(createTemplateLoader(templatePath)); // Process all other init-params: Enumeration initpnames = getServletConfig().getInitParameterNames(); while (initpnames.hasMoreElements()) { String name = (String) initpnames.nextElement(); String value = getInitParameter(name); if (name == null) { throw new ServletException( "init-param without param-name. " + "Maybe the web.xml is not well-formed?"); } if (value == null) { throw new ServletException( "init-param without param-value. " + "Maybe the web.xml is not well-formed?"); } if (name.equals(DEPR_INITPARAM_OBJECT_WRAPPER) || name.equals(Configurable.OBJECT_WRAPPER_KEY) || name.equals(INITPARAM_TEMPLATE_PATH)) { // ignore: we have already processed these } else if (name.equals(DEPR_INITPARAM_ENCODING)) { // BC if (getInitParameter(Configuration.DEFAULT_ENCODING_KEY) != null) { throw new ServletException( "Conflicting init-params: " + Configuration.DEFAULT_ENCODING_KEY + " and " + DEPR_INITPARAM_ENCODING); } config.setDefaultEncoding(value); } else if (name.equals(DEPR_INITPARAM_TEMPLATE_DELAY)) { // BC if (getInitParameter(Configuration.TEMPLATE_UPDATE_DELAY_KEY) != null) { throw new ServletException( "Conflicting init-params: " + Configuration.TEMPLATE_UPDATE_DELAY_KEY + " and " + DEPR_INITPARAM_TEMPLATE_DELAY); } try { config.setTemplateUpdateDelay(Integer.parseInt(value)); } catch (NumberFormatException e) { // Intentionally ignored } } else if (name.equals(DEPR_INITPARAM_TEMPLATE_EXCEPTION_HANDLER)) { // BC if (getInitParameter(Configurable.TEMPLATE_EXCEPTION_HANDLER_KEY) != null) { throw new ServletException( "Conflicting init-params: " + Configurable.TEMPLATE_EXCEPTION_HANDLER_KEY + " and " + DEPR_INITPARAM_TEMPLATE_EXCEPTION_HANDLER); } if (DEPR_INITPARAM_TEMPLATE_EXCEPTION_HANDLER_RETHROW.equals(value)) { config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); } else if (DEPR_INITPARAM_TEMPLATE_EXCEPTION_HANDLER_DEBUG.equals(value)) { config.setTemplateExceptionHandler(TemplateExceptionHandler.DEBUG_HANDLER); } else if (DEPR_INITPARAM_TEMPLATE_EXCEPTION_HANDLER_HTML_DEBUG.equals(value)) { config.setTemplateExceptionHandler(TemplateExceptionHandler.HTML_DEBUG_HANDLER); } else if (DEPR_INITPARAM_TEMPLATE_EXCEPTION_HANDLER_IGNORE.equals(value)) { config.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER); } else { throw new ServletException( "Invalid value for servlet init-param " + DEPR_INITPARAM_TEMPLATE_EXCEPTION_HANDLER + ": " + value); } } else if (name.equals(INITPARAM_NOCACHE)) { nocache = StringUtil.getYesNo(value); } else if (name.equals(DEPR_INITPARAM_DEBUG)) { // BC if (getInitParameter(INITPARAM_DEBUG) != null) { throw new ServletException( "Conflicting init-params: " + INITPARAM_DEBUG + " and " + DEPR_INITPARAM_DEBUG); } debug = StringUtil.getYesNo(value); } else if (name.equals(INITPARAM_DEBUG)) { debug = StringUtil.getYesNo(value); } else if (name.equals(INITPARAM_CONTENT_TYPE)) { contentType = value; } else { config.setSetting(name, value); } } // while initpnames noCharsetInContentType = true; int i = contentType.toLowerCase().indexOf("charset="); if (i != -1) { char c = ' '; i--; while (i >= 0) { c = contentType.charAt(i); if (!Character.isWhitespace(c)) break; i--; } if (i == -1 || c == ';') { noCharsetInContentType = false; } } } catch (ServletException e) { throw e; } catch (Exception e) { throw new ServletException(e); } } /** * Create the template loader. The default implementation will create a * {@link ClassTemplateLoader} if the template path starts with "class://", * a {@link FileTemplateLoader} if the template path starts with "file://", * and a {@link WebappTemplateLoader} otherwise. * @param templatePath the template path to create a loader for * @return a newly created template loader * @throws IOException */ protected TemplateLoader createTemplateLoader(String templatePath) throws IOException { if (templatePath.startsWith("class://")) { // substring(7) is intentional as we "reuse" the last slash return new ClassTemplateLoader(getClass(), templatePath.substring(7)); } else { if (templatePath.startsWith("file://")) { templatePath = templatePath.substring(7); return new FileTemplateLoader(new File(templatePath)); } else { return new WebappTemplateLoader(this.getServletContext(), templatePath); } } } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { process(request, response); } public void doPost( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { process(request, response); } private void process( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Give chance to subclasses to perform preprocessing if (preprocessRequest(request, response)) { return; } String path = requestUrlToTemplatePath(request); if (debug) { log("Requested template: " + StringUtil.jQuoteNoXSS(path)); } Template template = null; try { template = config.getTemplate( path, deduceLocale(path, request, response)); } catch (FileNotFoundException e) { response.sendError(HttpServletResponse.SC_NOT_FOUND); return; } Object attrContentType = template.getCustomAttribute("content_type"); if(attrContentType != null) { response.setContentType(attrContentType.toString()); } else { if (noCharsetInContentType) { response.setContentType( contentType + "; charset=" + template.getEncoding()); } else { response.setContentType(contentType); } } // Set cache policy setBrowserCachingPolicy(response); ServletContext servletContext = getServletContext(); try { TemplateModel model = createModel(wrapper, servletContext, request, response); // Give subclasses a chance to hook into preprocessing if (preTemplateProcess(request, response, template, model)) { try { // Process the template template.process(model, response.getWriter()); } finally { // Give subclasses a chance to hook into postprocessing postTemplateProcess(request, response, template, model); } } } catch (TemplateException te) { if (config.getTemplateExceptionHandler() .getClass().getName().indexOf("Debug") != -1) { this.log("Error executing FreeMarker template", te); } else { ServletException e = new ServletException( "Error executing FreeMarker template", te); // Attempt to set init cause, but don't freak out if the method // is not available (i.e. pre-1.4 JRE). This is required as the // constructor-passed throwable won't show up automatically in // stack traces. try { e.getClass().getMethod("initCause", new Class[] { Throwable.class }).invoke(e, new Object[] { te }); } catch (Exception ex) { // Can't set init cause, we're probably running on a pre-1.4 // JDK, oh well... } throw e; } } } /** * Returns the locale used for the * {@link Configuration#getTemplate(String, Locale)} call. * The base implementation simply returns the locale setting of the * configuration. Override this method to provide different behaviour, i.e. * to use the locale indicated in the request. */ protected Locale deduceLocale( String templatePath, HttpServletRequest request, HttpServletResponse response) { return config.getLocale(); } protected TemplateModel createModel(ObjectWrapper wrapper, ServletContext servletContext, final HttpServletRequest request, final HttpServletResponse response) throws TemplateModelException { try { AllHttpScopesHashModel params = new AllHttpScopesHashModel(wrapper, servletContext, request); // Create hash model wrapper for servlet context (the application) ServletContextHashModel servletContextModel = (ServletContextHashModel) servletContext.getAttribute( ATTR_APPLICATION_MODEL); if (servletContextModel == null) { servletContextModel = new ServletContextHashModel(this, wrapper); servletContext.setAttribute( ATTR_APPLICATION_MODEL, servletContextModel); TaglibFactory taglibs = new TaglibFactory(servletContext); servletContext.setAttribute( ATTR_JSP_TAGLIBS_MODEL, taglibs); initializeServletContext(request, response); } params.putUnlistedModel(KEY_APPLICATION, servletContextModel); params.putUnlistedModel(KEY_APPLICATION_PRIVATE, servletContextModel); params.putUnlistedModel(KEY_JSP_TAGLIBS, (TemplateModel)servletContext.getAttribute(ATTR_JSP_TAGLIBS_MODEL)); // Create hash model wrapper for session HttpSessionHashModel sessionModel; HttpSession session = request.getSession(false); if(session != null) { sessionModel = (HttpSessionHashModel) session.getAttribute(ATTR_SESSION_MODEL); if (sessionModel == null || sessionModel.isOrphaned(session)) { sessionModel = new HttpSessionHashModel(session, wrapper); initializeSessionAndInstallModel(request, response, sessionModel, session); } } else { sessionModel = new HttpSessionHashModel(this, request, response, wrapper); } params.putUnlistedModel(KEY_SESSION, sessionModel); // Create hash model wrapper for request HttpRequestHashModel requestModel = (HttpRequestHashModel) request.getAttribute(ATTR_REQUEST_MODEL); if (requestModel == null || requestModel.getRequest() != request) { requestModel = new HttpRequestHashModel(request, response, wrapper); request.setAttribute(ATTR_REQUEST_MODEL, requestModel); request.setAttribute( ATTR_REQUEST_PARAMETERS_MODEL, createRequestParametersHashModel(request)); } params.putUnlistedModel(KEY_REQUEST, requestModel); params.putUnlistedModel(KEY_INCLUDE, new IncludePage(request, response)); params.putUnlistedModel(KEY_REQUEST_PRIVATE, requestModel); // Create hash model wrapper for request parameters HttpRequestParametersHashModel requestParametersModel = (HttpRequestParametersHashModel) request.getAttribute( ATTR_REQUEST_PARAMETERS_MODEL); params.putUnlistedModel(KEY_REQUEST_PARAMETERS, requestParametersModel); return params; } catch (ServletException e) { throw new TemplateModelException(e); } catch (IOException e) { throw new TemplateModelException(e); } } void initializeSessionAndInstallModel(HttpServletRequest request, HttpServletResponse response, HttpSessionHashModel sessionModel, HttpSession session) throws ServletException, IOException { session.setAttribute(ATTR_SESSION_MODEL, sessionModel); initializeSession(request, response); } /** * Maps the request URL to a template path that is passed to * {@link Configuration#getTemplate(String, Locale)}. You can override it * (i.e. to provide advanced rewriting capabilities), but you are strongly * encouraged to call the overridden method first, then only modify its * return value. * @param request the currently processed request * @return a String representing the template path */ protected String requestUrlToTemplatePath(HttpServletRequest request) { // First, see if it is an included request String includeServletPath = (String) request.getAttribute("javax.servlet.include.servlet_path"); if(includeServletPath != null) { // Try path info; only if that's null (servlet is mapped to an // URL extension instead of to prefix) use servlet path. String includePathInfo = (String) request.getAttribute("javax.servlet.include.path_info"); return includePathInfo == null ? includeServletPath : includePathInfo; } // Seems that the servlet was not called as the result of a // RequestDispatcher.include(...). Try pathInfo then servletPath again, // only now directly on the request object: String path = request.getPathInfo(); if (path != null) return path; path = request.getServletPath(); if (path != null) return path; // Seems that it is a servlet mapped with prefix, and there was no extra path info. return ""; } /** * Called as the first step in request processing, before the templating mechanism * is put to work. By default does nothing and returns false. This method is * typically overridden to manage serving of non-template resources (i.e. images) * that reside in the template directory. * @param request the HTTP request * @param response the HTTP response * @return true to indicate this method has processed the request entirely, * and that the further request processing should not take place. */ protected boolean preprocessRequest( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { return false; } /** * This method is called from {@link #init()} to create the * FreeMarker configuration object that this servlet will use * for template loading. This is a hook that allows you * to custom-configure the configuration object in a subclass. * The default implementation returns a new {@link Configuration} * instance. */ protected Configuration createConfiguration() { return new Configuration(); } /** * This method is called from {@link #init()} to create the * FreeMarker object wrapper object that this servlet will use * for adapting request, session, and servlet context attributes into * template models.. This is a hook that allows you * to custom-configure the wrapper object in a subclass. * The default implementation returns a wrapper that depends on the value * of ObjectWrapper init parameter. If simple is * specified, {@link ObjectWrapper#SIMPLE_WRAPPER} is used; if jython * is specified, {@link freemarker.ext.jython.JythonWrapper} is used. In * every other case {@link ObjectWrapper#DEFAULT_WRAPPER} is used. */ protected ObjectWrapper createObjectWrapper() { String wrapper = getServletConfig().getInitParameter(DEPR_INITPARAM_OBJECT_WRAPPER); if (wrapper != null) { // BC if (getInitParameter(Configurable.OBJECT_WRAPPER_KEY) != null) { throw new RuntimeException("Conflicting init-params: " + Configurable.OBJECT_WRAPPER_KEY + " and " + DEPR_INITPARAM_OBJECT_WRAPPER); } if (DEPR_INITPARAM_WRAPPER_BEANS.equals(wrapper)) { return ObjectWrapper.BEANS_WRAPPER; } if(DEPR_INITPARAM_WRAPPER_SIMPLE.equals(wrapper)) { return ObjectWrapper.SIMPLE_WRAPPER; } if(DEPR_INITPARAM_WRAPPER_JYTHON.equals(wrapper)) { // Avoiding compile-time dependency on Jython package try { return (ObjectWrapper) Class.forName("freemarker.ext.jython.JythonWrapper") .newInstance(); } catch (InstantiationException e) { throw new InstantiationError(e.getMessage()); } catch (IllegalAccessException e) { throw new IllegalAccessError(e.getMessage()); } catch (ClassNotFoundException e) { throw new NoClassDefFoundError(e.getMessage()); } } // return BeansWrapper.getDefaultInstance(); return ObjectWrapper.DEFAULT_WRAPPER; } else { wrapper = getInitParameter(Configurable.OBJECT_WRAPPER_KEY); if (wrapper == null) { // return BeansWrapper.getDefaultInstance(); return ObjectWrapper.DEFAULT_WRAPPER; } else { try { config.setSetting(Configurable.OBJECT_WRAPPER_KEY, wrapper); } catch (TemplateException e) { throw new RuntimeException(e.toString()); } return config.getObjectWrapper(); } } } protected ObjectWrapper getObjectWrapper() { return wrapper; } protected final String getTemplatePath() { return templatePath; } protected HttpRequestParametersHashModel createRequestParametersHashModel(HttpServletRequest request) { return new HttpRequestParametersHashModel(request); } /** * Called when servlet detects in a request processing that * application-global (that is, ServletContext-specific) attributes are not yet * set. * This is a generic hook you might use in subclasses to perform a specific * action on first request in the context. By default it does nothing. * @param request the actual HTTP request * @param response the actual HTTP response */ protected void initializeServletContext( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } /** * Called when servlet detects in a request processing that session-global * (that is, HttpSession-specific) attributes are not yet set. * This is a generic hook you might use in subclasses to perform a specific * action on first request in the session. By default it does nothing. It * is only invoked on newly created sessions; it is not invoked when a * replicated session is reinstantiated in another servlet container. * * @param request the actual HTTP request * @param response the actual HTTP response */ protected void initializeSession( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } /** * Called before the execution is passed to template.process(). * This is a generic hook you might use in subclasses to perform a specific * action before the template is processed. By default does nothing. * A typical action to perform here is to inject application-specific * objects into the model root * *

Example: Expose the Serlvet context path as "baseDir" for all templates: * *

     *    ((SimpleHash) data).put("baseDir", request.getContextPath() + "/");
     *    return true;
     *
* * @param request the actual HTTP request * @param response the actual HTTP response * @param template the template that will get executed * @param data the data that will be passed to the template. By default this will be * an {@link AllHttpScopesHashModel} (which is a {@link freemarker.template.SimpleHash} subclass). * Thus, you can add new variables to the data-model with the * {@link freemarker.template.SimpleHash#put(String, Object)} subclass) method. * @return true to process the template, false to suppress template processing. */ protected boolean preTemplateProcess( HttpServletRequest request, HttpServletResponse response, Template template, TemplateModel data) throws ServletException, IOException { return true; } /** * Called after the execution returns from template.process(). * This is a generic hook you might use in subclasses to perform a specific * action after the template is processed. It will be invoked even if the * template processing throws an exception. By default does nothing. * @param request the actual HTTP request * @param response the actual HTTP response * @param template the template that was executed * @param data the data that was passed to the template */ protected void postTemplateProcess( HttpServletRequest request, HttpServletResponse response, Template template, TemplateModel data) throws ServletException, IOException { } /** * Returns the {@link freemarker.template.Configuration} object used by this servlet. * Please don't forget that {@link freemarker.template.Configuration} is not thread-safe * when you modify it. */ protected Configuration getConfiguration() { return config; } /** * If the parameter "nocache" was set to true, generate a set of headers * that will advise the HTTP client not to cache the returned page. */ private void setBrowserCachingPolicy(HttpServletResponse res) { if (nocache) { // HTTP/1.1 + IE extensions res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, " + "post-check=0, pre-check=0"); // HTTP/1.0 res.setHeader("Pragma", "no-cache"); // Last resort for those that ignore all of the above res.setHeader("Expires", EXPIRATION_DATE); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy