Java tutorial
/* * Copyright 2002-2007 the original author or authors. * * Licensed 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 com.parakhcomputer.web.servlet.view.tiles2; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.tiles.Attribute; import org.apache.tiles.AttributeContext; import org.apache.tiles.TilesContainer; import org.apache.tiles.TilesException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.StringUtils; import org.springframework.web.servlet.support.JstlUtils; import org.springframework.web.servlet.support.RequestContext; import org.springframework.web.util.WebUtils; /** * <p>Used for rendering and processing a dynamic tiles view.</p> * * @author David Winterfeldt */ public class DynamicTilesViewProcessor { final Logger logger = LoggerFactory.getLogger(DynamicTilesViewProcessor.class); /** * Keeps Tiles definition to use once derived. */ private String derivedDefinitionName = null; private String tilesDefinitionName = "mainTemplate"; private String tilesBodyAttributeName = "content"; private String tilesDefinitionDelimiter = "."; /** * Main template name. The default is 'mainTemplate'. * * @param tilesDefinitionName Main template name used to lookup definitions. */ public void setTilesDefinitionName(String tilesDefinitionName) { this.tilesDefinitionName = tilesDefinitionName; } /** * Tiles body attribute name. The default is 'body'. * * @param tilesBodyAttributeName Tiles body attribute name. */ public void setTilesBodyAttributeName(String tilesBodyAttributeName) { this.tilesBodyAttributeName = tilesBodyAttributeName; } /** * Sets Tiles definition delimiter. For example, instead of using * the request 'info/about' to lookup the template definition * 'info/mainTemplate', the default delimiter of '.' * would look for '.info.mainTemplate' * * @param tilesDefinitionDelimiter Optional delimiter to replace '/' in a url. */ public void setTilesDefinitionDelimiter(String tilesDefinitionDelimiter) { this.tilesDefinitionDelimiter = tilesDefinitionDelimiter; } /** * Renders output using Tiles. */ protected void renderMergedOutputModel(String beanName, String url, ServletContext servletContext, HttpServletRequest request, HttpServletResponse response, TilesContainer container) throws Exception { JstlUtils.exposeLocalizationContext(new RequestContext(request, servletContext)); if (!response.isCommitted()) { // Tiles is going to use a forward, but some web containers (e.g. // OC4J 10.1.3) // do not properly expose the Servlet 2.4 forward request // attributes... However, // must not do this on Servlet 2.5 or above, mainly for GlassFish // compatibility. if (servletContext.getMajorVersion() == 2 && servletContext.getMinorVersion() < 5) { WebUtils.exposeForwardRequestAttributes(request); } } String definitionName = startDynamicDefinition(beanName, url, request, response, container); container.render(definitionName, request, response); endDynamicDefinition(definitionName, beanName, request, response, container); } /** * Starts processing the dynamic Tiles definition by creating a temporary definition for rendering. */ protected String startDynamicDefinition(String beanName, String url, HttpServletRequest request, HttpServletResponse response, TilesContainer container) throws TilesException { String definitionName = processTilesDefinitionName(beanName, container, request, response); // create a temporary context and render using the incoming url as the // body attribute if (!definitionName.equals(beanName)) { Attribute attr = new Attribute(); attr.setName(tilesBodyAttributeName); attr.setValue(url); AttributeContext attributeContext = container.startContext(request, response); attributeContext.putAttribute(tilesBodyAttributeName, attr); logger.debug("URL used for Tiles body. url='" + url + "'."); } return definitionName; } /** * Closes the temporary Tiles definition. */ protected void endDynamicDefinition(String definitionName, String beanName, HttpServletRequest request, HttpServletResponse response, TilesContainer container) { if (!definitionName.equals(beanName)) { container.endContext(request, response); } } /** * Processes values to get tiles template definition name. First * a Tiles definition matching the url is checked, then a * url specific template is checked, and then just the * default root definition is used. * * @throws TilesException If no valid Tiles definition is found. */ protected String processTilesDefinitionName(String beanName, TilesContainer container, HttpServletRequest request, HttpServletResponse response) throws TilesException { // if definition already derived use it, otherwise // check if url (bean name) is a template definition, then // check for main template if (derivedDefinitionName != null) { return derivedDefinitionName; } else if (container.isValidDefinition(beanName, request, response)) { derivedDefinitionName = beanName; return beanName; } else { String result = null; StringBuilder sb = new StringBuilder(); int lastIndex = beanName.lastIndexOf("/"); boolean rootDefinition = false; // if delim, tiles def will start with it if (StringUtils.hasLength(tilesDefinitionDelimiter)) { sb.append(tilesDefinitionDelimiter); } // if no '/', then at context root if (lastIndex == -1) { rootDefinition = true; } else { String path = (beanName != null ? beanName.substring(0, lastIndex) : ""); if (StringUtils.hasLength(tilesDefinitionDelimiter)) { path = StringUtils.replace(path, "/", tilesDefinitionDelimiter); } sb.append(path); if (StringUtils.hasLength(tilesDefinitionDelimiter)) { sb.append(tilesDefinitionDelimiter); } } sb.append(tilesDefinitionName); if (container.isValidDefinition(sb.toString(), request, response)) { result = sb.toString(); } else if (!rootDefinition) { String root = null; if (StringUtils.hasLength(tilesDefinitionDelimiter)) { root = tilesDefinitionDelimiter; } root += tilesDefinitionName; if (container.isValidDefinition(root, request, response)) { result = root; } else { throw new TilesException( "No defintion of found for " + "'" + root + "'" + " or '" + sb.toString() + "'"); } } derivedDefinitionName = result; return result; } } }