Added: struts/struts2/trunk/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/VelocityDecoratorServlet.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/VelocityDecoratorServlet.java?rev=835248&view=auto ============================================================================== --- struts/struts2/trunk/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/VelocityDecoratorServlet.java (added) +++ struts/struts2/trunk/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/VelocityDecoratorServlet.java Thu Nov 12 06:06:40 2009 @@ -0,0 +1,182 @@ +/** + * <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); + } + +}
Added: struts/struts2/trunk/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/VelocityMapper2DecoratorSelector.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/VelocityMapper2DecoratorSelector.java?rev=835248&view=auto ============================================================================== --- struts/struts2/trunk/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/VelocityMapper2DecoratorSelector.java (added) +++ struts/struts2/trunk/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/VelocityMapper2DecoratorSelector.java Thu Nov 12 06:06:40 2009 @@ -0,0 +1,64 @@ +/* + * $Id: NoneDecoratorMapper.java 651946 2008-04-27 13:41:38Z apetrelli $ + * + * 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.mapper.AbstractDecoratorMapper; +import com.opensymphony.module.sitemesh.Decorator; +import com.opensymphony.module.sitemesh.Page; +import com.opensymphony.module.sitemesh.DecoratorMapper; +import com.opensymphony.sitemesh.DecoratorSelector; +import com.opensymphony.sitemesh.Content; +import com.opensymphony.sitemesh.SiteMeshContext; +import com.opensymphony.sitemesh.compatability.Content2HTMLPage; +import com.opensymphony.sitemesh.compatability.OldDecorator2NewDecorator; +import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext; +import com.opensymphony.sitemesh.webapp.decorator.NoDecorator; + +import javax.servlet.http.HttpServletRequest; + +/** + * Returns a {...@link OldDecorator2NewStrutsVelocityDecorator} decorator + * for a velocity request. + * + * Won't decorate the output if it finds a "decorator" flag in the request + */ +public class VelocityMapper2DecoratorSelector implements DecoratorSelector { + + private final DecoratorMapper decoratorMapper; + + public VelocityMapper2DecoratorSelector(DecoratorMapper decoratorMapper) { + this.decoratorMapper = decoratorMapper; + } + + public com.opensymphony.sitemesh.Decorator selectDecorator(Content content, SiteMeshContext context) { + SiteMeshWebAppContext webAppContext = (SiteMeshWebAppContext) context; + HttpServletRequest request = webAppContext.getRequest(); + Decorator decorator = + decoratorMapper.getDecorator(request, new Content2HTMLPage(content, request)); + if (decorator == null || decorator.getPage() == null) { + return new NoDecorator(); + } else { + return new OldDecorator2NewStrutsVelocityDecorator(decorator); + } + } +} + Modified: struts/struts2/trunk/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/VelocityPageFilter.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/VelocityPageFilter.java?rev=835248&r1=835247&r2=835248&view=diff ============================================================================== --- struts/struts2/trunk/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/VelocityPageFilter.java (original) +++ struts/struts2/trunk/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/VelocityPageFilter.java Thu Nov 12 06:06:40 2009 @@ -18,92 +18,42 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.sitemesh; -import java.io.IOException; -import java.io.PrintWriter; +import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext; +import com.opensymphony.sitemesh.webapp.SiteMeshFilter; +import com.opensymphony.sitemesh.DecoratorSelector; +import com.opensymphony.module.sitemesh.Factory; +import com.opensymphony.module.sitemesh.Config; +import com.opensymphony.xwork2.inject.Inject; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import javax.servlet.*; import org.apache.struts2.views.velocity.VelocityManager; -import org.apache.velocity.Template; -import org.apache.velocity.context.Context; - -import com.opensymphony.module.sitemesh.Decorator; -import com.opensymphony.module.sitemesh.HTMLPage; -import com.opensymphony.module.sitemesh.Page; -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.logging.Logger; -import com.opensymphony.xwork2.util.logging.LoggerFactory; - /** - * Applies Velocity-based decorators - * + * Core Filter for integrating SiteMesh into a Java web application. */ -public class VelocityPageFilter extends TemplatePageFilter { - private static final Logger LOG = LoggerFactory.getLogger(VelocityPageFilter.class); +public class VelocityPageFilter extends SiteMeshFilter { - private static VelocityManager velocityManager; - @Inject(required=false) public static void setVelocityManager(VelocityManager mgr) { - velocityManager = mgr; + OldDecorator2NewStrutsVelocityDecorator.setVelocityManager(mgr); } - - /** - * Applies the decorator, using the relevent contexts - * - * @param page The page - * @param decorator The decorator - * @param req The servlet request - * @param res The servlet response - * @param servletContext The servlet context - * @param ctx The action context for this request, populated with the server state - */ - protected void applyDecorator(Page page, Decorator decorator, - HttpServletRequest req, HttpServletResponse res, - ServletContext servletContext, ActionContext ctx) - throws ServletException, IOException { - - if (velocityManager == null) { - throw new ServletException("Missing freemarker dependency"); - } - - try { - - // init (if needed) - velocityManager.init(servletContext); - - // get encoding - String encoding = getEncoding(); - - // get the template and context - Template template = velocityManager.getVelocityEngine().getTemplate(decorator.getPage(), encoding); - Context context = velocityManager.createContext(ctx.getValueStack(), req, res); - - // put the page in the context - context.put("page", page); - if (page instanceof HTMLPage) { - HTMLPage htmlPage = ((HTMLPage) page); - context.put("head", htmlPage.getHead()); - } - context.put("title",page.getTitle()); - context.put("body",page.getBody()); - - // finally, render it - PrintWriter writer = res.getWriter(); - template.merge(context, writer); - writer.flush(); - } catch (Exception e) { - String msg = "Error applying decorator: " + e.getMessage(); - LOG.error(msg, e); - throw new ServletException(msg, e); - } + + private FilterConfig filterConfig; + + public void init(FilterConfig filterConfig) { + this.filterConfig = filterConfig; + super.init(filterConfig); + } + + protected DecoratorSelector initDecoratorSelector(SiteMeshWebAppContext webAppContext) { + // TODO: Remove heavy coupling on horrible SM2 Factory + Factory factory = Factory.getInstance(new Config(filterConfig)); + factory.refresh(); + return new FreeMarkerMapper2DecoratorSelector(factory.getDecoratorMapper()); } + } +