package org.martingilday.webwork; import com.opensymphony.webwork.ServletActionContext; import com.opensymphony.webwork.dispatcher.WebWorkResultSupport; import com.opensymphony.webwork.views.freemarker.FreemarkerManager; import com.opensymphony.webwork.views.util.ResourceUtil; import com.opensymphony.xwork.ActionContext; import com.opensymphony.xwork.ActionInvocation; import com.opensymphony.xwork.LocaleProvider; import com.opensymphony.xwork.util.OgnlValueStack; import freemarker.template.*; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import java.util.Locale; /** * User: mgilday * Date: May 5, 2007 * Time: 12:48:16 PM * @author CameronBraid * @author MartinGilday */ public class RethrowHandlingFreemarkerResult extends WebWorkResultSupport { private static final long serialVersionUID = -3778230771704661631L; protected ActionInvocation invocation; protected Configuration configuration; protected ObjectWrapper wrapper; /* * webwork results are constructed for each result execeution * * the current context is availible to subclasses via these protected fields */ protected String location; private String pContentType = "text/html"; public void setContentType(String aContentType) { pContentType = aContentType; } /** * allow parameterization of the contentType * the default being text/html * @return the content type */ public String getContentType() { return pContentType; } /** * Execute this result, using the specified template location. *
* The template location has already been interoplated for any variable substitutions * * this method obtains the freemarker configuration and the object wrapper from the provided hooks. * It them implements the template processing workflow by calling the hooks for * preTemplateProcess and postTemplateProcess */ public void doExecute(String location, ActionInvocation invocation) throws IOException, TemplateException { this.location = location; this.invocation = invocation; this.configuration = getConfiguration(); this.wrapper = getObjectWrapper(); if (!location.startsWith("/")) { ActionContext ctx = invocation.getInvocationContext(); HttpServletRequest req = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST); String base = ResourceUtil.getResourceBase(req); location = base + "/" + location; } Template template = configuration.getTemplate(location, deduceLocale()); TemplateModel model = createModel(); // Give subclasses a chance to hook into preprocessing if (preTemplateProcess(template, model)) { try { // Process the template // First, get the writer Writer writer = null; boolean useOutputStream = false; try { writer = getWriter(); } catch (IllegalStateException ise) { // Getting the writer failed, try using getOutputStream() // This can happen on some application servers such as WebLogic 8.1 useOutputStream = true; } StringWriter buffer = new StringWriter(); template.process(model, buffer); if (useOutputStream) { // Then write the contents of the writer to the OutputStream java.io.OutputStream os = ServletActionContext.getResponse().getOutputStream(); os.write(buffer.toString().getBytes()); } else { writer.write(buffer.toString()); } } finally { // Give subclasses a chance to hook into postprocessing postTemplateProcess(template, model); } } } /** * This method is called from {@link #doExecute(String, ActionInvocation)} to obtain the * FreeMarker configuration object that this result will use for template loading. This is a * hook that allows you to custom-configure the configuration object in a subclass, or to fetch * it from an IoC container. * * * The default implementation obtains the configuration from the ConfigurationManager instance. * * @throws freemarker.template.TemplateException * @return the configuration */ protected Configuration getConfiguration() throws TemplateException { return FreemarkerManager.getInstance().getConfiguration(ServletActionContext.getServletContext()); } /** * This method is called from {@link #doExecute(String, ActionInvocation)} to obtain the * FreeMarker object wrapper object that this result will use for adapting objects into template * models. This is a hook that allows you to custom-configure the wrapper object in a subclass. * * * The default implementation returns {@link Configuration#getObjectWrapper()} * * @return the object wrapper */ protected ObjectWrapper getObjectWrapper() { return configuration.getObjectWrapper(); } /** * The default writer writes directly to the response writer. * @return the writer * @throws java.io.IOException */ protected Writer getWriter() throws IOException { return ServletActionContext.getResponse().getWriter(); } /** * Build the instance of the ScopesHashModel, including JspTagLib support * * Objects added to the model are * *