Java tutorial
/* * $Id: PortletVelocityResult.java 474191 2006-11-13 08:30:40Z mrdon $ * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.struts2.portlet.result; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import javax.portlet.ActionResponse; import javax.portlet.PortletException; import javax.portlet.PortletRequestDispatcher; import javax.servlet.Servlet; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.jsp.JspFactory; import javax.servlet.jsp.PageContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts2.ServletActionContext; import org.apache.struts2.StrutsConstants; import org.apache.struts2.dispatcher.StrutsResultSupport; import org.apache.struts2.portlet.PortletActionConstants; import org.apache.struts2.portlet.context.PortletActionContext; import org.apache.struts2.views.JspSupportServlet; import org.apache.struts2.views.velocity.VelocityManager; import org.apache.velocity.Template; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.context.Context; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.inject.Inject; import com.opensymphony.xwork2.util.ValueStack; /** * <!-- START SNIPPET: description --> * * Using the Servlet container's {@link JspFactory}, this result mocks a JSP * execution environment and then displays a Velocity template that will be * streamed directly to the servlet output. * * <!-- END SNIPPET: description --> <p/><b>This result type takes the * following parameters: </b> * * <!-- START SNIPPET: params --> * * <ul> * * <li><b>location (default) </b>- the location of the template to process. * </li> * * <li><b>parse </b>- true by default. If set to false, the location param * will not be parsed for Ognl expressions.</li> * * </ul> * <p> * This result follows the same rules from {@link StrutsResultSupport}. * </p> * * <!-- END SNIPPET: params --> * * <b>Example: </b> * * <pre> * <!-- START SNIPPET: example --> * <result name="success" type="velocity"> * <param name="location">foo.vm</param> * </result> * <!-- END SNIPPET: example --> * </pre> * */ public class PortletVelocityResult extends StrutsResultSupport { private static final long serialVersionUID = -8241086555872212274L; private static final Log log = LogFactory.getLog(PortletVelocityResult.class); private String defaultEncoding; private VelocityManager velocityManager; public PortletVelocityResult() { super(); } public PortletVelocityResult(String location) { super(location); } @Inject public void setVelocityManager(VelocityManager mgr) { this.velocityManager = mgr; } @Inject(StrutsConstants.STRUTS_I18N_ENCODING) public void setDefaultEncoding(String encoding) { this.defaultEncoding = encoding; } /* (non-Javadoc) * @see org.apache.struts2.dispatcher.StrutsResultSupport#doExecute(java.lang.String, com.opensymphony.xwork2.ActionInvocation) */ public void doExecute(String location, ActionInvocation invocation) throws Exception { if (PortletActionContext.isEvent()) { executeActionResult(location, invocation); } else if (PortletActionContext.isRender()) { executeRenderResult(location, invocation); } } /** * Executes the result * * @param location The location string * @param invocation The action invocation */ private void executeActionResult(String location, ActionInvocation invocation) { ActionResponse res = PortletActionContext.getActionResponse(); // View is rendered outside an action...uh oh... res.setRenderParameter(PortletActionConstants.ACTION_PARAM, "freemarkerDirect"); res.setRenderParameter("location", location); res.setRenderParameter(PortletActionConstants.MODE_PARAM, PortletActionContext.getRequest().getPortletMode().toString()); } /** * Creates a Velocity context from the action, loads a Velocity template and * executes the template. Output is written to the servlet output stream. * * @param finalLocation the location of the Velocity template * @param invocation an encapsulation of the action execution state. * @throws Exception if an error occurs when creating the Velocity context, * loading or executing the template or writing output to the * servlet response stream. */ public void executeRenderResult(String finalLocation, ActionInvocation invocation) throws Exception { prepareServletActionContext(); ValueStack stack = ActionContext.getContext().getValueStack(); HttpServletRequest request = ServletActionContext.getRequest(); HttpServletResponse response = ServletActionContext.getResponse(); JspFactory jspFactory = null; ServletContext servletContext = ServletActionContext.getServletContext(); Servlet servlet = JspSupportServlet.jspSupportServlet; velocityManager.init(servletContext); boolean usedJspFactory = false; PageContext pageContext = (PageContext) ActionContext.getContext().get(ServletActionContext.PAGE_CONTEXT); if (pageContext == null && servlet != null) { jspFactory = JspFactory.getDefaultFactory(); pageContext = jspFactory.getPageContext(servlet, request, response, null, true, 8192, true); ActionContext.getContext().put(ServletActionContext.PAGE_CONTEXT, pageContext); usedJspFactory = true; } try { String encoding = getEncoding(finalLocation); String contentType = getContentType(finalLocation); if (encoding != null) { contentType = contentType + ";charset=" + encoding; } Template t = getTemplate(stack, velocityManager.getVelocityEngine(), invocation, finalLocation, encoding); Context context = createContext(velocityManager, stack, request, response, finalLocation); Writer writer = new OutputStreamWriter(response.getOutputStream(), encoding); response.setContentType(contentType); t.merge(context, writer); // always flush the writer (we used to only flush it if this was a // jspWriter, but someone asked // to do it all the time (WW-829). Since Velocity support is being // deprecated, we'll oblige :) writer.flush(); } catch (Exception e) { log.error("Unable to render Velocity Template, '" + finalLocation + "'", e); throw e; } finally { if (usedJspFactory) { jspFactory.releasePageContext(pageContext); } } return; } /** * Retrieve the content type for this template. <p/>People can override * this method if they want to provide specific content types for specific * templates (eg text/xml). * * @return The content type associated with this template (default * "text/html") */ protected String getContentType(String templateLocation) { return "text/html"; } /** * Retrieve the encoding for this template. <p/>People can override this * method if they want to provide specific encodings for specific templates. * * @return The encoding associated with this template (defaults to the value * of 'struts.i18n.encoding' property) */ protected String getEncoding(String templateLocation) { String encoding = defaultEncoding; if (encoding == null) { encoding = System.getProperty("file.encoding"); } if (encoding == null) { encoding = "UTF-8"; } return encoding; } /** * Given a value stack, a Velocity engine, and an action invocation, this * method returns the appropriate Velocity template to render. * * @param stack the value stack to resolve the location again (when parse * equals true) * @param velocity the velocity engine to process the request against * @param invocation an encapsulation of the action execution state. * @param location the location of the template * @param encoding the charset encoding of the template * @return the template to render * @throws Exception when the requested template could not be found */ protected Template getTemplate(ValueStack stack, VelocityEngine velocity, ActionInvocation invocation, String location, String encoding) throws Exception { if (!location.startsWith("/")) { location = invocation.getProxy().getNamespace() + "/" + location; } Template template = velocity.getTemplate(location, encoding); return template; } /** * Creates the VelocityContext that we'll use to render this page. * * @param velocityManager a reference to the velocityManager to use * @param stack the value stack to resolve the location against (when parse * equals true) * @param location the name of the template that is being used * @return the a minted Velocity context. */ protected Context createContext(VelocityManager velocityManager, ValueStack stack, HttpServletRequest request, HttpServletResponse response, String location) { return velocityManager.createContext(stack, request, response); } /** * Prepares the servlet action context for this request */ private void prepareServletActionContext() throws PortletException, IOException { PortletRequestDispatcher disp = PortletActionContext.getPortletConfig().getPortletContext() .getNamedDispatcher("preparator"); disp.include(PortletActionContext.getRenderRequest(), PortletActionContext.getRenderResponse()); } }