/* * $Id: TilesRequestProcessor.java 682831 2008-08-05 17:50:09Z 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.struts.tiles2; import java.io.IOException; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts.action.ActionServlet; import org.apache.struts.action.RequestProcessor; import org.apache.struts.config.ForwardConfig; import org.apache.struts.config.ModuleConfig; import org.apache.tiles.TilesContainer; import org.apache.tiles.TilesException; import org.apache.tiles.access.TilesAccess; /** * <p><strong>RequestProcessor</strong> contains the processing logic that * the Struts controller servlet performs as it receives each servlet request * from the container.</p> * <p>This processor subclasses the Struts RequestProcessor in order to intercept calls to forward * or include. When such calls are done, the Tiles processor checks if the specified URI * is a definition name. If true, the definition is retrieved and included. If * false, the original URI is included or a forward is performed. * <p> * Actually, catching is done by overloading the following methods: * <ul> * <li>{@link #processForwardConfig(HttpServletRequest,HttpServletResponse,ForwardConfig)}</li> * <li>{@link #internalModuleRelativeForward(String, HttpServletRequest , HttpServletResponse)}</li> * <li>{@link #internalModuleRelativeInclude(String, HttpServletRequest , HttpServletResponse)}</li> * </ul> * </p> * @since Struts 1.1 */ public class TilesRequestProcessor extends RequestProcessor { /** * Commons Logging instance. */ protected static Log log = LogFactory.getLog(TilesRequestProcessor.class); /** * The used servlet context. */ protected ServletContext servletContext; /** * Initialize this request processor instance. * * @param servlet The ActionServlet we are associated with. * @param moduleConfig The ModuleConfig we are associated with. * @throws ServletException If an error occurs during initialization. */ public void init(ActionServlet servlet, ModuleConfig moduleConfig) throws ServletException { super.init(servlet, moduleConfig); } /** * Process a Tile definition name. * This method tries to process the parameter <code>definitionName</code> * as a definition name. * It returns <code>true</code> if a definition has been processed, or * <code>false</code> otherwise. * * @param definitionName Definition name to insert. * @param request Current page request. * @param response Current page response. * @throws IOException If something goes wrong during writing the * definition. * @throws ServletException If something goes wrong during the evaluation * of the definition * @return <code>true</code> if the method has processed uri as a * definition name, <code>false</code> otherwise. */ protected boolean processTilesDefinition( String definitionName, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { TilesContainer container = TilesAccess.getContainer(servlet .getServletContext()); if (container == null) { log.debug("Tiles container not found, so pass to next command."); return false; } boolean retValue = false; if (container.isValidDefinition(definitionName, new Object[] { request, response })) { retValue = true; try { container.render(definitionName, new Object[] { request, response }); } catch (TilesException e) { throw new ServletException("Cannot render definition '" + definitionName + "'"); } } else { // ignore not found if (log.isDebugEnabled()) { log.debug("Cannot find definition '" + definitionName + "'"); } } return retValue; } /** * Do a forward using request dispatcher. * Uri is a valid uri. If response has already been commited, do an include * instead. * @param uri Uri or Definition name to forward. * @param request Current page request. * @param response Current page response. * @throws IOException If something goes wrong during writing the * definition. * @throws ServletException If something goes wrong during the evaluation * of the definition */ protected void doForward( String uri, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (response.isCommitted()) { this.doInclude(uri, request, response); } else { super.doForward(uri, request, response); } } /** * Overloaded method from Struts' RequestProcessor. * Forward or redirect to the specified destination by the specified * mechanism. * This method catches the Struts' actionForward call. It checks if the * actionForward is done on a Tiles definition name. If true, process the * definition and insert it. If false, call the original parent's method. * @param request The servlet request we are processing. * @param response The servlet response we are creating. * @param forward The ActionForward controlling where we go next. * * @exception IOException if an input/output error occurs. * @exception ServletException if a servlet exception occurs. */ protected void processForwardConfig( HttpServletRequest request, HttpServletResponse response, ForwardConfig forward) throws IOException, ServletException { // Required by struts contract if (forward == null) { return; } if (log.isDebugEnabled()) { log.debug( "processForwardConfig(" + forward.getPath() + ")"); } // Try to process the definition. if (processTilesDefinition(forward.getPath(), request, response)) { if (log.isDebugEnabled()) { log.debug( " '" + forward.getPath() + "' - processed as definition"); } return; } if (log.isDebugEnabled()) { log.debug(" '" + forward.getPath() + "' - processed as uri"); } // forward doesn't contain a definition, let parent do processing super.processForwardConfig(request, response, forward); } /** * Catch the call to a module relative forward. * If the specified uri is a tiles definition name, insert it. * Otherwise, parent processing is called. * Do a module relative forward to specified uri using request dispatcher. * Uri is relative to the current module. The real uri is computed by * prefixing the module name. * <strong>This method is used internally and is not part of the public * API. It is advised to not use it in subclasses.</strong> * @param uri Module-relative URI to forward to. * @param request Current page request. * @param response Current page response. * @throws IOException If something goes wrong during writing the * definition. * @throws ServletException If something goes wrong during the evaluation * of the definition * @since Struts 1.1 */ protected void internalModuleRelativeForward( String uri, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (processTilesDefinition(uri, request, response)) { return; } super.internalModuleRelativeForward(uri, request, response); } /** * Do a module relative include to specified uri using request dispatcher. * Uri is relative to the current module. The real uri is computed by * prefixing the module name. * <strong>This method is used internally and is not part of the public * API. It is advised to not use it in subclasses.</strong> * @param uri Module-relative URI to forward to. * @param request Current page request. * @param response Current page response. * @throws IOException If something goes wrong during writing the * definition. * @throws ServletException If something goes wrong during the evaluation * of the definition * @since Struts 1.1 */ protected void internalModuleRelativeInclude( String uri, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (processTilesDefinition(uri, request, response)) { return; } super.internalModuleRelativeInclude(uri, request, response); } }