KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > struts > chain > servlet > TilesPreProcessor


1 /*
2  * \$Header\$
3  * \$Revision\$
4  * \$Date\$
5  *
6  * Copyright 2004 The Apache Software Foundation.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * 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, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */

20 package org.apache.struts.chain.servlet;
21
22 import java.io.IOException JavaDoc;
23
24 import javax.servlet.RequestDispatcher JavaDoc;
25 import javax.servlet.ServletException JavaDoc;
26 import javax.servlet.http.HttpServletRequest JavaDoc;
27 import javax.servlet.http.HttpServletResponse JavaDoc;
28
29 import org.apache.commons.chain.Command;
30 import org.apache.commons.chain.Context;
31 import org.apache.commons.chain.web.servlet.ServletWebContext;
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34
35 import org.apache.struts.chain.Constants;
36 import org.apache.struts.config.ForwardConfig;
37 import org.apache.struts.tiles.ComponentContext;
38 import org.apache.struts.tiles.ComponentDefinition;
39 import org.apache.struts.tiles.Controller;
40 import org.apache.struts.tiles.FactoryNotFoundException;
41 import org.apache.struts.tiles.DefinitionsUtil;
42 import org.apache.struts.tiles.TilesUtil;
43
44 import org.apache.struts.upload.MultipartRequestWrapper;
45
46
47 /**
48  * <p>Command class intended to perform responsibilities of the
49  * TilesRequestProcessor in Struts 1.1. Does not actually dispatch requests,
50  * but simply prepares the chain context for a later forward as
51  * appropriate. Should be added to a chain before something which
52  * would handle a conventional ForwardConfig.</p>
53  *
54  * <p>This class will never have any effect on the chain unless a
55  * <code>TilesDefinitionFactory</code> can be found; however it does not
56  * consider the absence of a definition factory to be a fatal error; the
57  * command simply returns false and lets the chain continue.</p>
58  *
59  * <p>To initialize the <code>TilesDefinitionFactory</code>, use
60  * <code>org.apache.struts.chain.legacy.TilesPlugin</code>. This class
61  * is a simple extension to <code>org.apache.struts.tiles.TilesPlugin</code>
62  * which simply does not interfere with your choice of <code>RequestProcessor</code>
63  * implementation.
64  * </p>
65  *
66  *
67  */

68 public class TilesPreProcessor implements Command
69 {
70
71
72     // ------------------------------------------------------ Instance Variables
73

74
75     private static final Log log = LogFactory.getLog(TilesPreProcessor.class);
76
77     private String JavaDoc forwardConfigKey = Constants.FORWARD_CONFIG_KEY;
78
79     private String JavaDoc includeKey = Constants.INCLUDE_KEY;
80
81     private String JavaDoc moduleConfigKey = Constants.MODULE_CONFIG_KEY;
82
83
84     // -------------------------------------------------------------- Properties
85

86
87     /**
88      * <p>Return the context attribute key under which the
89      * <code>ForwardConfig</code> for the currently selected application
90      * action is stored.</p>
91      */

92     public String JavaDoc getForwardConfigKey() {
93
94         return (this.forwardConfigKey);
95
96     }
97
98
99     /**
100      * <p>Set the context attribute key under which the
101      * <code>ForwardConfig</code> for the currently selected application
102      * action is stored.</p>
103      *
104      * @param forwardConfigKey The new context attribute key
105      */

106     public void setForwardConfigKey(String JavaDoc forwardConfigKey) {
107
108         this.forwardConfigKey = forwardConfigKey;
109
110     }
111
112
113     /**
114      * <p>Return the context attribute key under which the
115      * include uri for the currently selected application
116      * action is stored.</p>
117      */

118     public String JavaDoc getIncludeKey() {
119
120         return (this.includeKey);
121
122     }
123
124
125     /**
126      * <p>Set the context attribute key under which the
127      * include uri for the currently selected application
128      * action is stored.</p>
129      *
130      * @param includeKey The new context attribute key
131      */

132     public void setIncludeKey(String JavaDoc includeKey) {
133
134         this.includeKey = includeKey;
135
136     }
137
138
139     // ---------------------------------------------------------- Public Methods
140

141
142     /**
143      * <p>If the current <code>ForwardConfig</code> is using "tiles",
144      * perform necessary pre-processing to set up the <code>TilesContext</code>
145      * and substitute a new <code>ForwardConfig</code> which is understandable
146      * to a <code>RequestDispatcher</code>.</p>
147      *
148      * <p>Note that if the command finds a previously existing
149      * <code>ComponentContext</code> in the request, then it
150      * infers that it has been called from within another tile,
151      * so instead of changing the <code>ForwardConfig</code> in the chain
152      * <code>Context</code>, the command uses <code>RequestDispatcher</code>
153      * to <em>include</em> the tile, and returns true, indicating that the processing
154      * chain is complete.</p>
155      *
156      * @param context The <code>Context</code> for the current request
157      *
158      * @return <code>false</code> in most cases, but true if we determine
159      * that we're processing in "include" mode.
160      */

161     public boolean execute(Context context) throws Exception JavaDoc {
162
163         // Is there a Tiles Definition to be processed?
164
ForwardConfig forwardConfig = (ForwardConfig)
165                                       context.get(getForwardConfigKey());
166         if (forwardConfig == null || forwardConfig.getPath() == null)
167         {
168             log.debug("No forwardConfig or no path, so pass to next command.");
169             return (false);
170         }
171
172         ServletWebContext swcontext = (ServletWebContext) context;
173
174         ComponentDefinition definition = null;
175         try
176         {
177             definition = TilesUtil.getDefinition(forwardConfig.getPath(),
178                     swcontext.getRequest(),
179                     swcontext.getContext());
180         }
181         catch (FactoryNotFoundException ex)
182         {
183             // this is not a serious error, so log at low priority
184
log.debug("Tiles DefinitionFactory not found, so pass to next command.");
185             return false;
186         }
187
188         // Do we do a forward (original behavior) or an include ?
189
boolean doInclude = false;
190         ComponentContext tileContext = null;
191
192         // Get current tile context if any.
193
// If context exists, we will do an include
194
tileContext = ComponentContext.getContext(swcontext.getRequest());
195         doInclude = (tileContext != null);
196
197         // Controller associated to a definition, if any
198
Controller controller = null;
199
200         // Computed uri to include
201
String JavaDoc uri = null;
202
203         if (definition != null)
204         {
205             // We have a "forward config" definition.
206
// We use it to complete missing attribute in context.
207
// We also get uri, controller.
208
uri = definition.getPath();
209             controller = definition.getOrCreateController();
210
211             if (tileContext == null) {
212                 tileContext =
213                         new ComponentContext(definition.getAttributes());
214                 ComponentContext.setContext(tileContext, swcontext.getRequest());
215
216             } else {
217                 tileContext.addMissing(definition.getAttributes());
218             }
219         }
220
221         // Process definition set in Action, if any. This may override the
222
// values for uri or controller found using the ForwardConfig, and
223
// may augment the tileContext with additional attributes.
224
// :FIXME: the class DefinitionsUtil is deprecated, but I can't find
225
// the intended alternative to use.
226
definition = DefinitionsUtil.getActionDefinition(swcontext.getRequest());
227         if (definition != null) { // We have a definition.
228
// We use it to complete missing attribute in context.
229
// We also overload uri and controller if set in definition.
230
if (definition.getPath() != null) {
231                     log.debug("Override forward uri "
232                               + uri
233                               + " with action uri "
234                               + definition.getPath());
235                         uri = definition.getPath();
236                 }
237
238                 if (definition.getOrCreateController() != null) {
239                     log.debug("Override forward controller with action controller");
240                         controller = definition.getOrCreateController();
241                 }
242
243                 if (tileContext == null) {
244                         tileContext =
245                                 new ComponentContext(definition.getAttributes());
246                         ComponentContext.setContext(tileContext, swcontext.getRequest());
247                 } else {
248                         tileContext.addMissing(definition.getAttributes());
249                 }
250         }
251
252
253         if (uri == null) {
254             log.debug("no uri computed, so pass to next command");
255             return false;
256         }
257
258         // Execute controller associated to definition, if any.
259
if (controller != null) {
260             log.trace("Execute controller: " + controller);
261             controller.execute(
262                     tileContext,
263                     swcontext.getRequest(),
264                     swcontext.getResponse(),
265                     swcontext.getContext());
266         }
267
268         // If request comes from a previous Tile, do an include.
269
// This allows to insert an action in a Tile.
270

271         if (doInclude) {
272             log.info("Tiles process complete; doInclude with " + uri);
273             doInclude(swcontext, uri);
274             return (true);
275         } else {
276             // create an "instant" forward config which can be used
277
// by an AbstractPerformForward later as if our ForwardConfig
278
// were the one actually returned by an executing Action
279
log.info("Tiles process complete; forward to " + uri);
280             // :FIXME: How do we need to coordinate the "context-relative" value
281
// with other places it might be set. For now, hardcode to true.
282
context.put(getForwardConfigKey(), new ForwardConfig("tiles-chain", uri, false, true));
283             return (false);
284         }
285     }
286
287
288     // ------------------------------------------------------- Protected Methods
289

290     /**
291      * <p>Do an include of specified URI using a <code>RequestDispatcher</code>.</p>
292      *
293      * @param swcontext a chain servlet/web context
294      * @param uri Context-relative URI to include
295      */

296     protected void doInclude(
297         ServletWebContext swcontext,
298         String JavaDoc uri)
299         throws IOException JavaDoc, ServletException JavaDoc {
300
301         HttpServletRequest JavaDoc request = swcontext.getRequest();
302
303         // Unwrap the multipart request, if there is one.
304
if (request instanceof MultipartRequestWrapper) {
305             request = ((MultipartRequestWrapper) request).getRequest();
306         }
307
308         HttpServletResponse JavaDoc response = swcontext.getResponse();
309         RequestDispatcher JavaDoc rd = swcontext.getContext().getRequestDispatcher(uri);
310         if (rd == null) {
311             response.sendError(
312                 HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
313                 "Error getting RequestDispatcher for " + uri);
314             return;
315         }
316         rd.include(request, response);
317     }
318
319
320 }
Popular Tags