Save This Page
Home » struts-1.3.9-src » org.apache.struts » tiles » [javadoc | source]
    1   /*
    2    * $Id: TilesRequestProcessor.java 164703 2005-04-26 01:28:13Z niallp $ 
    3    *
    4    * Copyright 1999-2005 The Apache Software Foundation.
    5    * 
    6    * Licensed under the Apache License, Version 2.0 (the "License");
    7    * you may not use this file except in compliance with the License.
    8    * You may obtain a copy of the License at
    9    * 
   10    *      http://www.apache.org/licenses/LICENSE-2.0
   11    * 
   12    * Unless required by applicable law or agreed to in writing, software
   13    * distributed under the License is distributed on an "AS IS" BASIS,
   14    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   15    * See the License for the specific language governing permissions and
   16    * limitations under the License.
   17    */
   18   
   19   package org.apache.struts.tiles;
   20   
   21   import java.io.IOException;
   22   
   23   import javax.servlet.ServletException;
   24   import javax.servlet.http.HttpServletRequest;
   25   import javax.servlet.http.HttpServletResponse;
   26   
   27   import org.apache.commons.logging.Log;
   28   import org.apache.commons.logging.LogFactory;
   29   import org.apache.struts.action.ActionServlet;
   30   import org.apache.struts.action.RequestProcessor;
   31   import org.apache.struts.config.ForwardConfig;
   32   import org.apache.struts.config.ModuleConfig;
   33   
   34   /**
   35    * <p><strong>RequestProcessor</strong> contains the processing logic that
   36    * the Struts controller servlet performs as it receives each servlet request
   37    * from the container.</p>
   38    * <p>This processor subclasses the Struts RequestProcessor in order to intercept calls to forward
   39    * or include. When such calls are done, the Tiles processor checks if the specified URI
   40    * is a definition name. If true, the definition is retrieved and included. If
   41    * false, the original URI is included or a forward is performed.
   42    * <p>
   43    * Actually, catching is done by overloading the following methods:
   44    * <ul>
   45    * <li>{@link #processForwardConfig(HttpServletRequest,HttpServletResponse,ForwardConfig)}</li>
   46    * <li>{@link #internalModuleRelativeForward(String, HttpServletRequest , HttpServletResponse)}</li>
   47    * <li>{@link #internalModuleRelativeInclude(String, HttpServletRequest , HttpServletResponse)}</li>
   48    * </ul>
   49    * </p>
   50    * @since Struts 1.1
   51    */
   52   public class TilesRequestProcessor extends RequestProcessor {
   53   
   54   	/** 
   55   	 * Definitions factory. 
   56   	 */
   57   	protected DefinitionsFactory definitionsFactory = null;
   58   
   59   	/**
   60   	 * Commons Logging instance.
   61   	 */
   62   	protected static Log log = LogFactory.getLog(TilesRequestProcessor.class);
   63   
   64   	/**
   65   	 * Initialize this request processor instance.
   66   	 *
   67   	 * @param servlet The ActionServlet we are associated with.
   68   	 * @param moduleConfig The ModuleConfig we are associated with.
   69   	 * @throws ServletException If an error occurs during initialization.
   70   	 */
   71   	public void init(ActionServlet servlet, ModuleConfig moduleConfig)
   72   		throws ServletException {
   73   
   74   		super.init(servlet, moduleConfig);
   75   		this.initDefinitionsMapping();
   76   	}
   77   
   78   	/**
   79   	 * Read component instance mapping configuration file.
   80   	 * This is where we read files properties.
   81   	 */
   82   	protected void initDefinitionsMapping() throws ServletException {
   83   		// Retrieve and set factory for this modules
   84   		definitionsFactory =
   85   			(
   86   				(TilesUtilStrutsImpl) TilesUtil
   87   					.getTilesUtil())
   88   					.getDefinitionsFactory(
   89   				getServletContext(),
   90   				moduleConfig);
   91   
   92   		if (definitionsFactory == null) { // problem !
   93   
   94   			log.info(
   95   				"Definition Factory not found for module '"
   96   					+ moduleConfig.getPrefix()
   97   					+ "'. "
   98   					+ "Have you declared the appropriate plugin in struts-config.xml ?");
   99   
  100   			return;
  101   		}
  102   
  103   		log.info(
  104   			"Tiles definition factory found for request processor '"
  105   				+ moduleConfig.getPrefix()
  106   				+ "'.");
  107   
  108   	}
  109   
  110   	/**
  111   	 * Process a Tile definition name.
  112   	 * This method tries to process the parameter <code>definitionName</code> as a definition name.
  113   	 * It returns <code>true</code> if a definition has been processed, or <code>false</code> otherwise.
  114   	 * Parameter <code>contextRelative</code> is not used in this implementation.
  115   	 *
  116   	 * @param definitionName Definition name to insert.
  117   	 * @param contextRelative Is the definition marked contextRelative ?
  118   	 * @param request Current page request.
  119   	 * @param response Current page response.
  120   	 * @return <code>true</code> if the method has processed uri as a definition name, <code>false</code> otherwise.
  121   	 */
  122   	protected boolean processTilesDefinition(
  123   		String definitionName,
  124   		boolean contextRelative,
  125   		HttpServletRequest request,
  126   		HttpServletResponse response)
  127   		throws IOException, ServletException {
  128   
  129   		// Do we do a forward (original behavior) or an include ?
  130   		boolean doInclude = false;
  131   
  132   		// Controller associated to a definition, if any
  133   		Controller controller = null;
  134   
  135   		// Computed uri to include
  136   		String uri = null;
  137   
  138   		ComponentContext tileContext = null;
  139   
  140   		try {
  141   			// Get current tile context if any.
  142   			// If context exist, we will do an include
  143   			tileContext = ComponentContext.getContext(request);
  144   			doInclude = (tileContext != null);
  145   			ComponentDefinition definition = null;
  146   
  147   			// Process tiles definition names only if a definition factory exist,
  148   			// and definition is found.
  149   			if (definitionsFactory != null) {
  150   				// Get definition of tiles/component corresponding to uri.
  151   				try {
  152   					definition =
  153   						definitionsFactory.getDefinition(
  154   							definitionName,
  155   							request,
  156   							getServletContext());
  157   				} catch (NoSuchDefinitionException ex) {
  158   					// Ignore not found
  159   					log.debug("NoSuchDefinitionException " + ex.getMessage());
  160   				}
  161   				if (definition != null) { // We have a definition.
  162   					// We use it to complete missing attribute in context.
  163   					// We also get uri, controller.
  164   					uri = definition.getPath();
  165   					controller = definition.getOrCreateController();
  166   
  167   					if (tileContext == null) {
  168   						tileContext =
  169   							new ComponentContext(definition.getAttributes());
  170   						ComponentContext.setContext(tileContext, request);
  171   
  172   					} else {
  173   						tileContext.addMissing(definition.getAttributes());
  174   					}
  175   				}
  176   			}
  177   
  178   			// Process definition set in Action, if any.
  179   			definition = DefinitionsUtil.getActionDefinition(request);
  180   			if (definition != null) { // We have a definition.
  181   				// We use it to complete missing attribute in context.
  182   				// We also overload uri and controller if set in definition.
  183   				if (definition.getPath() != null) {
  184   					uri = definition.getPath();
  185   				}
  186   
  187   				if (definition.getOrCreateController() != null) {
  188   					controller = definition.getOrCreateController();
  189   				}
  190   
  191   				if (tileContext == null) {
  192   					tileContext =
  193   						new ComponentContext(definition.getAttributes());
  194   					ComponentContext.setContext(tileContext, request);
  195   				} else {
  196   					tileContext.addMissing(definition.getAttributes());
  197   				}
  198   			}
  199   
  200   		} catch (java.lang.InstantiationException ex) {
  201   
  202   			log.error("Can't create associated controller", ex);
  203   
  204   			throw new ServletException(
  205   				"Can't create associated controller",
  206   				ex);
  207   		} catch (DefinitionsFactoryException ex) {
  208   			throw new ServletException(ex);
  209   		}
  210   
  211   		// Have we found a definition ?
  212   		if (uri == null) {
  213   			return false;
  214   		}
  215   
  216   		// Execute controller associated to definition, if any.
  217   		if (controller != null) {
  218   			try {
  219   				controller.execute(
  220   					tileContext,
  221   					request,
  222   					response,
  223   					getServletContext());
  224                       
  225   			} catch (Exception e) {
  226   				throw new ServletException(e); 
  227   			}
  228   		}
  229   
  230   		// If request comes from a previous Tile, do an include.
  231   		// This allows to insert an action in a Tile.
  232   		if (log.isDebugEnabled()) {
  233   			log.debug("uri=" + uri + " doInclude=" + doInclude);
  234   		}
  235           
  236   		if (doInclude) {
  237   			doInclude(uri, request, response);
  238   		} else {
  239   			doForward(uri, request, response); // original behavior
  240   		}
  241   
  242   		return true;
  243   	}
  244   
  245   	/**
  246   	 * Do a forward using request dispatcher.
  247   	 * Uri is a valid uri. If response has already been commited, do an include
  248   	 * instead.
  249   	 * @param uri Uri or Definition name to forward.
  250   	 * @param request Current page request.
  251   	 * @param response Current page response.
  252   	 */
  253   	protected void doForward(
  254   		String uri,
  255   		HttpServletRequest request,
  256   		HttpServletResponse response)
  257   		throws IOException, ServletException {
  258               
  259   		if (response.isCommitted()) {
  260   			this.doInclude(uri, request, response);
  261               
  262   		} else {
  263   			super.doForward(uri, request, response);
  264   		}
  265   	}
  266   
  267   	/**
  268   	 * Overloaded method from Struts' RequestProcessor.
  269   	 * Forward or redirect to the specified destination by the specified
  270   	 * mechanism.
  271   	 * This method catches the Struts' actionForward call. It checks if the
  272   	 * actionForward is done on a Tiles definition name. If true, process the
  273   	 * definition and insert it. If false, call the original parent's method.
  274   	 * @param request The servlet request we are processing.
  275   	 * @param response The servlet response we are creating.
  276   	 * @param forward The ActionForward controlling where we go next.
  277   	 *
  278   	 * @exception IOException if an input/output error occurs.
  279   	 * @exception ServletException if a servlet exception occurs.
  280   	 */
  281   	protected void processForwardConfig(
  282   		HttpServletRequest request,
  283   		HttpServletResponse response,
  284   		ForwardConfig forward)
  285   		throws IOException, ServletException {
  286               
  287   		// Required by struts contract
  288   		if (forward == null) {
  289   			return;
  290   		}
  291   
  292   		if (log.isDebugEnabled()) {
  293   			log.debug(
  294   				"processForwardConfig("
  295   					+ forward.getPath()
  296   					+ ", "
  297   					+ forward.getContextRelative()
  298   					+ ")");
  299   		}
  300           
  301   		// Try to process the definition.
  302   		if (processTilesDefinition(forward.getPath(),
  303   			forward.getContextRelative(),
  304   			request,
  305   			response)) {
  306   			if (log.isDebugEnabled()) {
  307   				log.debug(
  308   					"  '" + forward.getPath() + "' - processed as definition");
  309   			}
  310   			return;
  311   		}
  312           
  313   		if (log.isDebugEnabled()) {
  314   			log.debug("  '" + forward.getPath() + "' - processed as uri");
  315   		}
  316           
  317   		// forward doesn't contain a definition, let parent do processing
  318   		super.processForwardConfig(request, response, forward);
  319   	}
  320   
  321   	/**
  322   	 * Catch the call to a module relative forward.
  323   	 * If the specified uri is a tiles definition name, insert it.
  324   	 * Otherwise, parent processing is called.
  325   	 * Do a module relative forward to specified uri using request dispatcher.
  326   	 * Uri is relative to the current module. The real uri is computed by 
  327        * prefixing the module name.
  328   	 * <strong>This method is used internally and is not part of the public 
  329        * API. It is advised to not use it in subclasses.</strong>
  330   	 * @param uri Module-relative URI to forward to.
  331   	 * @param request Current page request.
  332   	 * @param response Current page response.
  333   	 * @since Struts 1.1
  334   	 */
  335   	protected void internalModuleRelativeForward(
  336   		String uri,
  337   		HttpServletRequest request,
  338   		HttpServletResponse response)
  339   		throws IOException, ServletException {
  340               
  341   		if (processTilesDefinition(uri, false, request, response)) {
  342   			return;
  343   		}
  344   
  345   		super.internalModuleRelativeForward(uri, request, response);
  346   	}
  347   
  348   	/**
  349   	 * Do a module relative include to specified uri using request dispatcher.
  350   	 * Uri is relative to the current module. The real uri is computed by 
  351        * prefixing the module name.
  352   	 * <strong>This method is used internally and is not part of the public 
  353        * API. It is advised to not use it in subclasses.</strong>
  354   	 * @param uri Module-relative URI to forward to.
  355   	 * @param request Current page request.
  356   	 * @param response Current page response.
  357   	 * @since Struts 1.1
  358   	 */
  359   	protected void internalModuleRelativeInclude(
  360   		String uri,
  361   		HttpServletRequest request,
  362   		HttpServletResponse response)
  363   		throws IOException, ServletException {
  364               
  365   		if (processTilesDefinition(uri, false, request, response)) {
  366   			return;
  367   		}
  368   
  369   		super.internalModuleRelativeInclude(uri, request, response);
  370   	}
  371   
  372   	/**
  373   	 * Get associated definition factory.
  374   	 */
  375   	public DefinitionsFactory getDefinitionsFactory() {
  376   		return definitionsFactory;
  377   	}
  378   
  379   }

Save This Page
Home » struts-1.3.9-src » org.apache.struts » tiles » [javadoc | source]