View Javadoc
1   /*
2    * $Id$
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  package org.apache.struts.tiles2.commands;
22  
23  import org.apache.commons.chain.Command;
24  import org.apache.struts.chain.contexts.ServletActionContext;
25  import org.apache.struts.config.ForwardConfig;
26  import org.apache.tiles.TilesContainer;
27  import org.apache.tiles.access.TilesAccess;
28  import org.apache.tiles.request.ApplicationContext;
29  import org.apache.tiles.request.Request;
30  import org.apache.tiles.request.jakarta.servlet.ServletRequest;
31  import org.apache.tiles.request.jakarta.servlet.ServletUtil;
32  import org.slf4j.Logger;
33  import org.slf4j.LoggerFactory;
34  
35  /**
36   * Command class intended to perform responsibilities of the
37   * TilesRequestProcessor in Struts 1.1. Does not actually dispatch requests,
38   * but simply prepares the chain context for a later forward as appropriate.
39   * Should be added to a chain before something which would handle a
40   * conventional ForwardConfig.
41   *
42   * <p>This class will never have any effect on the chain unless a
43   * {@code TilesDefinitionFactory} can be found; however it does not consider
44   * the absence of a definition factory to be a fatal error; the command simply
45   * returns false and lets the chain continue.</p>
46   *
47   * <p>To initialize the {@code TilesDefinitionFactory}, use
48   * {@code org.apache.struts.chain.commands.legacy.TilesPlugin}. This class is a
49   * simple extension to {@code org.apache.struts.tiles2.TilesPlugin} which
50   * simply does not interfere with your choice of {@code RequestProcessor}
51   * implementation.</p>
52   */
53  public class TilesPreProcessor implements Command<ServletActionContext> {
54  
55  
56      // ------------------------------------------------------ Instance Variables
57  
58  
59      /**
60       * The {@code Log} instance for this class.
61       */
62      private final Logger log =
63          LoggerFactory.getLogger(TilesPreProcessor.class);
64  
65      // ---------------------------------------------------------- Public Methods
66  
67  
68      /**
69       * If the current {@code ForwardConfig} is using "tiles", perform necessary
70       * pre-processing to set up the {@code TilesContext} and substitute a new
71       * {@code ForwardConfig} which is understandable to a
72       * {@code RequestDispatcher}.
73       *
74       * <p>Note that if the command finds a previously existing
75       * {@code AttributeContext} in the request, then it infers that it has been
76       * called from within another tile, so instead of changing the
77       * {@code ForwardConfig} in the chain {@code Context}, the command uses
78       * {@code RequestDispatcher} to <em>include</em> the tile, and returns
79       * true, indicating that the processing chain is complete.</p>
80       *
81       * @param sacontext The {@code Context} for the current request
82       *
83       * @throws Exception If something goes wrong.
84       *
85       * @return {@code false} in most cases, but true if we determine
86       *         that we're processing in "include" mode.
87       */
88      public boolean execute(ServletActionContext sacontext) throws Exception {
89  
90          // Is there a Tiles Definition to be processed?
91          ForwardConfig forwardConfig = sacontext.getForwardConfig();
92          if (forwardConfig == null || forwardConfig.getPath() == null) {
93              // this is not a serious error, so log at low priority
94              log.debug("No forwardConfig or no path, so pass to next command.");
95              return (false);
96          }
97  
98  
99          ApplicationContext applicationContext = ServletUtil
100                 .getApplicationContext(sacontext.getContext());
101         Request request = new ServletRequest(applicationContext,
102                 sacontext.getRequest(), sacontext.getResponse());
103         TilesContainer container = TilesAccess.getContainer(applicationContext);
104         if (container == null) {
105             log.debug("Tiles container not found, so pass to next command.");
106             return false;
107         }
108 
109         if (container.isValidDefinition(forwardConfig.getPath(), request)) {
110             container.render(forwardConfig.getPath(), request);
111             sacontext.setForwardConfig(null);
112         } else {
113             // ignore not found
114             log.debug("Cannot find definition '{}'", forwardConfig.getPath());
115         }
116 
117         return false;
118     }
119 }