Dear Wiki user, You have subscribed to a wiki page or wiki category on "Struts Wiki" for change notification.
The following page has been changed by MichaelJouravlev: http://wiki.apache.org/struts/NewTilesTool The comment on the change is: Orphaned; just a big chunk of code. ------------------------------------------------------------------------------ - 16. October 2003 + deleted - A new version of the TilesTool that utilizes the { { { RequestDispatcher } } } to correctly render alternative formats such as JSP. Thus it is now possible to put e.g. JSP resources into Velocity tiles definitions. - - The changes are based on the URL importation logic found in { { { JSTL ImportSupport-tag } } } by Shawn Bayern. - - Note: This version differs from the original in that each velocity tile in a given layout has it's own velocity context - where in the previous version all the velocity tiles in a given layout shared the same velocity context. - - Note: This version is contingent on the very latest build of { { { VelocityViewServlet } } } for rendering JPSs ... older versions will throw { { { IllegalStateExceptions } } }. - - Any comments are welcome on the Velocity Developer's List <velocity-dev@jakarta.apache.org>. - - Marinó A. Jónsson - - ---- - To expand a little more on what Marino said: Mixed tile definitions, based on a velocity template are now possible. - i.e - {{{ - { { { - {{{ <definition name="Vtest" - path="/TableBased.vm"> <!-- note a velocity layout file is used --> - <put name="header" - value="/header.jsp"/> - <put name="footer" - value="/footer.jsp"/> - <put name="body" - value="/center/listThemes.vm"/> - <put name="rail" - value="/rail.xtp"/> - </definition> - } } } - }}} - Matthew Payne - ------------ - {{{ - { { { - /* - {{{ * The Apache Software License, Version 1.1 - * - * Copyright (c) 2003 The Apache Software Foundation. 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 acknowlegement: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowlegement may appear in the software itself, - * if and wherever such third-party acknowlegements normally appear. - * - * 4. The names "The Jakarta Project", "Velocity", and "Apache Software - * Foundation" must not 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 "Apache" - * nor may "Apache" appear in their names without prior written - * permission of the Apache Group. - * - * 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 APACHE SOFTWARE FOUNDATION 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 Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * <http://www.apache.org/>. - */ }}} - - package org.apache.velocity.tools.struts; - - import java.util.Stack; - import java.util.Map; - import java.util.Locale; - import javax.servlet.http.HttpServletRequest; - import javax.servlet.http.HttpServletResponse; - import javax.servlet.http.HttpServletResponseWrapper; - import javax.servlet.http.HttpSession; - import javax.servlet.ServletContext; - import javax.servlet.RequestDispatcher; - import javax.servlet.ServletOutputStream; - import javax.servlet.ServletException; - - import java.io.InputStream; - import java.io.Reader; - import java.io.BufferedReader; - import java.io.StringReader; - import java.io.InputStreamReader; - import java.io.StringWriter; - import java.io.PrintWriter; - import java.io.ByteArrayOutputStream; - import java.io.IOException; - import java.io.UnsupportedEncodingException; - import java.net.URL; - import java.net.URLConnection; - import java.net.HttpURLConnection; - import org.apache.velocity.app.Velocity; - import org.apache.velocity.Template; - - import org.apache.struts.tiles.ComponentContext; - import org.apache.struts.tiles.ComponentDefinition; - import org.apache.struts.tiles.AttributeDefinition; - import org.apache.struts.tiles.DirectStringAttribute; - import org.apache.struts.tiles.DefinitionAttribute; - import org.apache.struts.tiles.DefinitionNameAttribute; - import org.apache.struts.tiles.PathAttribute; - import org.apache.struts.tiles.TilesUtil; - import org.apache.struts.tiles.DefinitionsFactoryException; - import org.apache.struts.tiles.Controller; - - import org.apache.velocity.tools.view.context.ViewContext; - import org.apache.velocity.tools.view.tools.ViewTool; - - /** - {{{ * <p>Title: TilesTool</p> - * <p>Description: A tool to use struts-tiles with Velocity</p> - * <p>Usage: - * - * Just call $tiles.name_of_tile_definition from the template to insert - * the tile. - * - * $tiles.getString("name_of_tile_attribute") fetches a named attribute-value - * from the current tiles-context. - * - * @author <a href="mailto:[EMAIL PROTECTED]">Marino A. Jonsson</a> - * @version $Revision: 1.1 $ $Date: 2003/07/24 04:59:21 $ - */ }}} - public class TilesTool - {{{ implements ViewTool { - - protected ViewContext context; - protected ServletContext application; - protected HttpServletRequest request; - protected HttpServletResponse response; - - protected static final String VALID_SCHEME_CHARS = - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+.-"; - - /** Default character encoding for response. */ - protected static final String DEFAULT_ENCODING = "ISO-8859-1"; - - /** - * A stack to hold ComponentContexts while nested tile-definitions - * are rendered. - */ - protected Stack contextStack; - - /******************************* Constructors ****************************/ - - /** - * Default constructor. Tool must be initialized before use. - */ - public TilesTool() {} - - /** - * Initializes this tool. - * - * @param obj the current ViewContext - * @throws IllegalArgumentException if the param is not a ViewContext - */ - public void init(Object obj) { - if (! (obj instanceof ViewContext)) { - throw new IllegalArgumentException("Tool can only be initialized with a ViewContext"); - } - - this.context = (ViewContext) obj; - this.request = context.getRequest(); - this.response = context.getResponse(); - this.application = context.getServletContext(); - } - - /***************************** View Helpers ******************************/ - - /** - * Fetches a named attribute value from the current tiles-context. - * - * <p>This is functionally equivalent to - * <code><tiles:getAsString name="title" /></code>.</p> - * - * @param name the name of the tiles-attribute to fetch - * @return the attribute value as String - */ - public String getString(String name) { - ComponentContext context = ComponentContext.getContext(request); - Object attrValue = context.getAttribute(name); - if (attrValue == null) { - return null; - } - return attrValue.toString(); - } - - /** - * <p>A generic tiles insert function</p> - * - * <p>This is functionally equivalent to - * <code><tiles:insert attribute="menu" /></code>.</p> - * - * @param attr - can be any of the following: - * AttributeDefinition, - * tile-definition name, - * tile-attribute name, - * regular uri. - * (checked in that order) - * @return the rendered template or value as a String - * @throws Exception on failure - */ - public String get(Object attr) throws Exception { - ComponentContext currentContext = ComponentContext.getContext(request); - Object attrValue = currentContext.getAttribute(attr.toString()); - if (attrValue != null) { - return processObjectValue(attrValue); - } - return processAsDefinitionOrURL(attr.toString()); - } - - /************************** Protected Methods ****************************/ - - /** - * Process an object retrieved as a bean or attribute. - * - * @param value - Object can be a typed attribute, a String, or anything - * else. If typed attribute, use associated type. Otherwise, apply - * toString() on object, and use returned string as a name. - * @throws Exception - Throws by underlying nested call to - * processDefinitionName() - * @return the fully processed value as String - */ - protected String processObjectValue(Object value) throws Exception { - /* First, check if value is one of the Typed Attribute */ - if (value instanceof AttributeDefinition) { - /* We have a type => return appropriate IncludeType */ - return processTypedAttribute( (AttributeDefinition) value); - - } - else if (value instanceof ComponentDefinition) { - return processDefinition( (ComponentDefinition) value); - } - - /* Value must denote a valid String */ - return processAsDefinitionOrURL(value.toString()); - } - - /** - * Process typed attribute according to its type. - * - * @param value Typed attribute to process. - * @return the fully processed attribute value as String. - * @throws Exception - Throws by underlying nested call to processDefinitionName() - */ - protected String processTypedAttribute(AttributeDefinition value) throws Exception { - if (value instanceof DirectStringAttribute) { - return (String) value.getValue(); - - } - else if (value instanceof DefinitionAttribute) { - return processDefinition( (ComponentDefinition) value.getValue()); - - } - else if (value instanceof DefinitionNameAttribute) { - return processAsDefinitionOrURL( (String) value.getValue()); - } - /* else if( value instanceof PathAttribute ) */ - return doInsert( (String) value.getValue(), null, null); - } - - /** - * Try to process name as a definition, or as an URL if not found. - * - * @param name Name to process. - * @return the fully processed definition or URL - * @throws Exception - */ - protected String processAsDefinitionOrURL(String name) throws Exception { - try { - ComponentDefinition definition = - TilesUtil.getDefinition(name, request, application); - if (definition != null) { - return processDefinition(definition); - } - } - catch (DefinitionsFactoryException ex) { - /* silently failed, because we can choose to not define a factory. */ - } - /* no definition found, try as url */ - return processUrl(name); - } - - /** - * End of Process for definition. - * - * @param definition Definition to process. - * @return the fully processed definition. - * @throws Exception from InstantiationException Can't create requested controller - */ - protected String processDefinition(ComponentDefinition definition) throws Exception { - Controller controller = null; - - try { - controller = definition.getOrCreateController(); - - String role = definition.getRole(); - String page = definition.getTemplate(); - - return doInsert(definition.getAttributes(), - page, - role, - controller); - } - catch (InstantiationException ex) { - throw new Exception(ex.getMessage()); - } - } - - /** - * Processes an url - * - * @param url the URI to process. - * @return the rendered template as String. - * @throws Exception - */ - protected String processUrl(String url) throws Exception { - return doInsert(url, null, null); - } - - /** - * Use this if there is no nested tile. - * - * @param page the page to process. - * @param role possible user-role - * @param controller possible tiles-controller - * @return the rendered template as String. - * @throws Exception - */ - protected String doInsert(String page, String role, Controller controller) throws Exception { - if (role != null && !request.isUserInRole(role)) { - return null; - } - - ComponentContext subCompContext = new ComponentContext(); - return doInsert(subCompContext, page, role, controller); - } - - /** - * Use this if there is a nested tile. - * - * @param attributes attributes for the sub-context - * @param page the page to process. - * @param role possible user-role - * @param controller possible tiles-controller - * @return the rendered template as String. - * @throws Exception - */ - protected String doInsert(Map attributes, - String page, - String role, - Controller controller) throws Exception { - if (role != null && !request.isUserInRole(role)) { - return null; - } - - ComponentContext subCompContext = new ComponentContext(attributes); - return doInsert(subCompContext, page, role, controller); - } - - /** - * An extension of the other two doInsert functions - * - * @param subCompContext the sub-context to set in scope when the - * template is rendered. - * @param page the page to process. - * @param role possible user-role - * @param controller possible tiles-controller - * @return the rendered template as String. - * @throws Exception - */ - protected String doInsert(ComponentContext subCompContext, - String page, - String role, - Controller controller) throws Exception { - pushTilesContext(); - try { - ComponentContext.setContext(subCompContext, request); - - /* Call controller if any */ - if (controller != null) { - controller.perform(subCompContext, - request, - response, - application); - } - return this.acquireString(page); - } - finally { - popTilesContext(); - } - } - - /** - * <p>pushes the current tiles context onto the context-stack. - * preserving the context is necessary so that a sub-context can be - * put into request scope and lower level tiles can be rendered</p> - */ - protected void pushTilesContext() { - if (contextStack == null) { - contextStack = new Stack(); - } - contextStack.push(ComponentContext.getContext(request)); - } - - /** - * <p>pops the tiles sub-context off the context-stack after the lower level - * tiles have been rendered</p> - */ - protected void popTilesContext() { - ComponentContext.setContext( (ComponentContext) contextStack.pop(), request); - } }}} - - //----------------------------------------------------------------------------------------------------- - - {{{ //********************************************************************* - // Actual URL importation logic - - private String acquireString(String targetUrl) throws Exception { - - // normalize the URL if we have an HttpServletRequest - - //String sp = ( (HttpServletRequest) request).getServletPath(); - if (!targetUrl.startsWith("/")) - targetUrl = "/" + targetUrl; - //targetUrl = sp.substring(0, sp.lastIndexOf('/')) + targetUrl; - - // from this context, get a dispatcher - RequestDispatcher rd = application.getRequestDispatcher(targetUrl); - if (rd == null) - throw new Exception(targetUrl); - - // include the resource, using our custom wrapper - ImportResponseWrapper irw = new ImportResponseWrapper( (HttpServletResponse) response); - - // spec mandates specific error handling form include() - try { - rd.include(request, irw); - } - catch (IOException ex) { - throw new Exception(ex); - } - catch (RuntimeException ex) { - throw new Exception(ex); - } - catch (ServletException ex) { - Throwable rc = ex.getRootCause(); - if (rc == null) - throw new Exception(ex); - else - throw new Exception(rc); - } - - // disallow inappropriate response codes per JSTL spec - if (irw.getStatus() < 200 || irw.getStatus() > 299) { - throw new Exception(irw.getStatus() + " " + targetUrl); - } - - // recover the response String from our wrapper - return irw.getString(); - } - - /** Wraps responses to allow us to retrieve results as Strings. */ - private class ImportResponseWrapper - extends HttpServletResponseWrapper { - - private StringWriter sw = new StringWriter(); - - /** The HTTP status set by the target. */ - private int status = 200; - - /** Constructs a new ImportResponseWrapper. */ - public ImportResponseWrapper(HttpServletResponse response) { - super(response); - } - - /** Returns a Writer designed to buffer the output. */ - public PrintWriter getWriter() { - return new PrintWriter(sw); - } - - public void setStatus(int status) { - this.status = status; - } - - public int getStatus() { - return status; - } - - public String getString() { - return sw.toString(); - } - } }}} - - } - {{{ } } } - }}} - - --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]