/** * <p>This is a SiteMesh Velocity view servlet.</p> * * <p>It overrides the SiteMesh servlet to rely on the * Velocity Manager in Struts instead of creating it's * own manager</p> * * 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.sitemesh; import com.opensymphony.module.sitemesh.*; import com.opensymphony.module.sitemesh.util.OutputConverter; import com.opensymphony.xwork2.ActionContext; import org.apache.struts2.ServletActionContext; import org.apache.struts2.StrutsStatics; import org.apache.struts2.dispatcher.Dispatcher; import org.apache.struts2.dispatcher.ng.listener.StrutsListener; import org.apache.struts2.views.velocity.VelocityManager; import org.apache.velocity.Template; import org.apache.velocity.context.Context; import org.apache.velocity.runtime.RuntimeConstants; import org.apache.velocity.tools.view.servlet.VelocityViewServlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.StringWriter; /** * <p>This is a SiteMesh Velocity view servlet.</p> * <p/> * <p>It overrides the SiteMesh servlet to rely on the * Velocity Manager in Struts instead of creating it's * own manager</p> */ public class VelocityDecoratorServlet extends VelocityViewServlet { protected VelocityManager velocityManager; protected String defaultContentType; /** * <p>Initializes servlet, toolbox and Velocity template engine. * Called by the servlet container on loading.</p> * <p/> * <p>NOTE: If no charset is specified in the default.contentType * property (in your velocity.properties) and you have specified * an output.encoding property, then that will be used as the * charset for the default content-type of pages served by this * servlet.</p> * * @param config servlet configuation */ public void init(ServletConfig config) throws ServletException { super.init(config); Dispatcher dispatcher = (Dispatcher) getServletContext().getAttribute(StrutsStatics.SERVLET_DISPATCHER); if (dispatcher == null) throw new IllegalStateException("Unable to find the Dispatcher in the Servlet Context. Is '" + StrutsListener.class.getName() + "' missing in web.xml?"); velocityManager = dispatcher.getContainer().getInstance(VelocityManager.class); velocityManager.init(config.getServletContext()); // do whatever we have to do to init Velocity setVelocityEngine(velocityManager.getVelocityEngine()); toolboxManager = velocityManager.getToolboxManager(); // we can get these now that velocity is initialized defaultContentType = (String) getVelocityProperty(CONTENT_TYPE, DEFAULT_CONTENT_TYPE); String encoding = (String) getVelocityProperty(RuntimeConstants.OUTPUT_ENCODING, DEFAULT_OUTPUT_ENCODING); // For non Latin-1 encodings, ensure that the charset is // included in the Content-Type header. if (!DEFAULT_OUTPUT_ENCODING.equalsIgnoreCase(encoding)) { int index = defaultContentType.lastIndexOf("charset"); if (index < 0) { // the charset specifier is not yet present in header. // append character encoding to default content-type defaultContentType += "; charset=" + encoding; } else { // The user may have configuration issues. getVelocityEngine().warn("VelocityViewServlet: Charset was already " + "specified in the Content-Type property. " + "Output encoding property will be ignored."); } } getVelocityEngine().info("VelocityViewServlet: Default content-type is: " + defaultContentType); } public Template handleRequest(HttpServletRequest request, HttpServletResponse response, Context context) throws Exception { HTMLPage htmlPage = (HTMLPage) request.getAttribute(RequestConstants.PAGE); String template; context.put("base", request.getContextPath()); // For backwards compatability with apps that used the old VelocityDecoratorServlet // that extended VelocityServlet instead of VelocityViewServlet context.put("req", request); context.put("res", response); if (htmlPage == null) { context.put("title", "Title?"); context.put("body", "<p>Body?</p>"); context.put("head", "<!-- head -->"); template = request.getServletPath(); } else { context.put("title", OutputConverter.convert(htmlPage.getTitle())); { StringWriter buffer = new StringWriter(); htmlPage.writeBody(OutputConverter.getWriter(buffer)); context.put("body", buffer.toString()); } { StringWriter buffer = new StringWriter(); htmlPage.writeHead(OutputConverter.getWriter(buffer)); context.put("head", buffer.toString()); } context.put("page", htmlPage); DecoratorMapper decoratorMapper = getDecoratorMapper(); Decorator decorator = decoratorMapper.getDecorator(request, htmlPage); template = decorator.getPage(); } return getTemplate(template); } private DecoratorMapper getDecoratorMapper() { Factory factory = Factory.getInstance(new Config(getServletConfig())); DecoratorMapper decoratorMapper = factory.getDecoratorMapper(); return decoratorMapper; } /** * <p>Creates and returns an initialized Velocity context.</p> * * @param request servlet request from client * @param response servlet reponse to client */ protected Context createContext(HttpServletRequest request, HttpServletResponse response) { Context context = (Context) request.getAttribute(VelocityManager.KEY_VELOCITY_STRUTS_CONTEXT); if (context == null) { ActionContext ctx = ServletActionContext.getActionContext(request); context = velocityManager.createContext(ctx.getValueStack(), request, response); } return context; } /** * Sets the content type of the response. This is available to be overriden * by a derived class. * <p/> * <p>The default implementation is : * <pre> * <p/> * response.setContentType(defaultContentType); * <p/> * </pre> * where defaultContentType is set to the value of the default.contentType * property, or "text/html" if that is not set.</p> * * @param request servlet request from client * @param response servlet reponse to client */ protected void setContentType(HttpServletRequest request, HttpServletResponse response) { response.setContentType(defaultContentType); } }