KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > servletunit > struts > Common


1 // StrutsTestCase - a JUnit extension for testing Struts actions
2
// within the context of the ActionServlet.
3
// Copyright (C) 2002 Deryl Seale
4
//
5
// This library is free software; you can redistribute it and/or
6
// modify it under the terms of the Apache Software License as
7
// published by the Apache Software Foundation; either version 1.1
8
// of the License, or (at your option) any later version.
9
//
10
// This library is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
// Apache Software Foundation Licens for more details.
14
//
15
// You may view the full text here: http://www.apache.org/LICENSE.txt
16

17 package servletunit.struts;
18
19 import junit.framework.AssertionFailedError;
20 import org.apache.struts.action.*;
21 import org.apache.struts.tiles.*;
22 import org.apache.struts.config.ModuleConfig;
23 import org.apache.struts.config.ForwardConfig;
24 import org.apache.struts.config.ActionConfig;
25 import org.apache.struts.Globals;
26 import org.apache.struts.util.RequestUtils;
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.commons.collections.Transformer;
30 import org.apache.commons.collections.iterators.TransformIterator;
31 import org.apache.commons.collections.IteratorUtils;
32
33 import javax.servlet.ServletConfig JavaDoc;
34 import javax.servlet.ServletContext JavaDoc;
35 import javax.servlet.http.HttpServletRequest JavaDoc;
36 import javax.servlet.http.HttpSession JavaDoc;
37 import java.util.Iterator JavaDoc;
38 import java.util.Arrays JavaDoc;
39
40
41 /**
42  * Contains code common to both MockStrutsTestCase and CactusStrutsTestCase.
43  * It's always good to get rid of redundancy!
44  */

45 public class Common {
46
47     protected static final String JavaDoc INCLUDE_SERVLET_PATH = RequestProcessor.INCLUDE_SERVLET_PATH;
48     protected static Log logger = LogFactory.getLog(Common.class);
49
50     /**
51      * Common method to verify action errors and action messages.
52      */

53     protected static void verifyNoActionMessages(HttpServletRequest JavaDoc request, String JavaDoc key, String JavaDoc messageLabel) {
54         if (logger.isTraceEnabled())
55             logger.trace("Entering - request = " + request + ", key = " + key + ", messageLabel = " + messageLabel);
56         ActionMessages messages = (ActionMessages) request.getAttribute(key);
57         if (logger.isDebugEnabled()) {
58             logger.debug("retrieved ActionMessages = " + messages);
59         }
60         if (messages != null) {
61             Iterator iterator = messages.get();
62             if (iterator.hasNext()) {
63                 StringBuffer JavaDoc messageText = new StringBuffer JavaDoc();
64                 while (iterator.hasNext()) {
65                     messageText.append(" \"");
66                     messageText.append(((ActionMessage) iterator.next()).getKey());
67                     messageText.append("\"");
68                 }
69                 throw new AssertionFailedError("was expecting no " + messageLabel + " messages, but received: " + messageText.toString());
70             }
71         }
72         if (logger.isTraceEnabled())
73             logger.trace("Exiting");
74     }
75
76     /**
77      * Common method to verify action errors and action messages.
78      */

79     protected static void verifyActionMessages(HttpServletRequest JavaDoc request, String JavaDoc[] messageNames, String JavaDoc key, String JavaDoc messageLabel) {
80         if (logger.isTraceEnabled())
81             logger.trace("Entering - request = " + request + ", messageNames = " + messageNames + ", key = " + key + ", messageLabel = " + messageLabel);
82
83         ActionMessages messages = (ActionMessages) request.getAttribute(key);
84         if (logger.isDebugEnabled()) {
85             logger.debug("retrieved ActionMessages = " + messages);
86         }
87
88         if (messages == null) {
89             throw new AssertionFailedError("was expecting some " + messageLabel + " messages, but received none.");
90         }
91         /* check length of messages as optimization */
92         else if (messages.size() != messageNames.length) {
93             throw new AssertionFailedError("was expecting " + messageNames.length + " " + messageLabel + " message(s), but received " + messages.size() + " " + messageLabel + " message(s)");
94         }
95         else {
96             /* alphabetize the two lists of message keys and compare them */
97
98             Iterator iter = new TransformIterator( messages.get(),
99                     new Transformer(){
100                         public Object JavaDoc transform( Object JavaDoc input )
101                         {
102                             return ((ActionMessage) input).getKey();
103                         }
104                     } );
105
106             String JavaDoc[] messageKeys = (String JavaDoc[]) IteratorUtils.toArray(iter,String JavaDoc.class );
107
108             Arrays.sort( messageKeys );
109             Arrays.sort( messageNames );
110
111             for ( int i = 0; i < messageNames.length;i++) {
112                 if ( !messageNames[i].equals(messageKeys[i])) {
113                     StringBuffer JavaDoc mks = new StringBuffer JavaDoc();
114                     StringBuffer JavaDoc mns = new StringBuffer JavaDoc();
115
116                     for ( int j = 0; j < messageKeys.length; j++) mks.append( messageKeys[j] + " " );
117                     for ( int k = 0; k < messageNames.length; k++) mns.append( messageNames[k] + " " );
118
119                     throw new AssertionFailedError("received " + messageLabel + " messages: (" + mks + ") but expected (" + mns + ")");
120                 }
121             }
122         }
123         if (logger.isTraceEnabled())
124             logger.trace("verifyActionMessages()");
125     }
126
127
128     /**
129      * Retrieves a forward uri for tile - this is required for applications
130      * using the tiles framework, since the actual forward URI must
131      * be fetched from the tile definition.
132      */

133     protected static ComponentDefinition getTilesForward(String JavaDoc forwardPath, HttpServletRequest JavaDoc request, ServletContext JavaDoc context, ServletConfig JavaDoc config) {
134
135         if (logger.isTraceEnabled())
136             logger.trace("Entering - forwardPath = " + forwardPath + ", request = " + request + ", context = " + context + ", config = " + config);
137
138         String JavaDoc result = null;
139         try {
140             ComponentDefinition definition;
141             ComponentDefinition actionDefinition;
142
143             // Get definition of tiles/component corresponding to uri.
144
definition = TilesUtil.getDefinition(forwardPath, request, context);
145             if (definition != null) {
146                 if (logger.isDebugEnabled()) {
147                     logger.debug("found tiles definition - '" + forwardPath + "' = '" + result + "'");
148                 }
149             }
150
151             actionDefinition = DefinitionsUtil.getActionDefinition(request);
152             if (actionDefinition != null) {
153                 if (logger.isDebugEnabled()) {
154                     logger.debug("found tiles definition for action - '" + forwardPath + "' = '" + result + "'");
155                 }
156             }
157
158             if (actionDefinition != null) {
159                 if (logger.isDebugEnabled())
160                     logger.debug("definition attributes: " + actionDefinition.getAttributes());
161                 return actionDefinition;
162             } else {
163                 if (logger.isDebugEnabled() && (definition != null))
164                     logger.debug("definition attributes: " + definition.getAttributes());
165                 return definition;
166             }
167         } catch (NoSuchDefinitionException nsde) {
168             if (logger.isTraceEnabled())
169                 logger.trace("Exiting - caught NoSuchDefinitionException");
170             return null;
171         } catch (DefinitionsFactoryException dfe) {
172             if (logger.isTraceEnabled())
173                 logger.trace("Exiting - caught DefinitionsFactoryException");
174             return null;
175         } catch (NullPointerException JavaDoc npe) {
176             // can happen if tiles is not at all used.
177
if (logger.isDebugEnabled()) {
178                 logger.debug("Exiting - caught NullPointerException");
179             }
180             return null;
181         }
182     }
183
184     /**
185      * Verifies that ActionServlet used this logical forward or input mapping with this tile definition.
186      *
187      * @throws AssertionFailedError if the expected and actual tiles definitions do not match.
188      */

189     protected static void verifyTilesForward(String JavaDoc actionPath, String JavaDoc forwardName, String JavaDoc expectedDefinition, boolean isInputPath, HttpServletRequest JavaDoc request, ServletContext JavaDoc context, ServletConfig JavaDoc config) {
190         if (logger.isTraceEnabled())
191             logger.trace("Entering - actionPath = " + actionPath + ", forwardName = " + forwardName + ", expectedDefinition = " + expectedDefinition);
192
193         String JavaDoc definitionName = null;
194
195         if ((forwardName == null) && (isInputPath)) {
196             if (logger.isDebugEnabled()) {
197                 logger.debug("processing an input forward");
198             }
199             forwardName = getActionConfig(actionPath, request, context).getInput();
200             if (logger.isDebugEnabled()) {
201                 logger.debug("retrieved input forward name = " + forwardName);
202             }
203             if (forwardName == null)
204                 throw new AssertionFailedError("Trying to validate against an input mapping, but none is defined for this Action.");
205             ComponentDefinition definition = getTilesForward(forwardName, request, context, config);
206             if (definition != null)
207                 definitionName = definition.getName();
208         }
209
210         if (!isInputPath) {
211             if (logger.isDebugEnabled()) {
212                 logger.debug("processing normal forward");
213             }
214             ForwardConfig expectedForward = findForward(actionPath, forwardName, request, context);
215             if (expectedForward == null)
216                 throw new AssertionFailedError("Cannot find forward '" + forwardName + "' - it is possible that it is not mapped correctly.");
217             forwardName = expectedForward.getPath();
218             if (logger.isDebugEnabled()) {
219                 logger.debug("retrieved forward name = " + forwardName);
220             }
221
222             ComponentDefinition definition = getTilesForward(forwardName, request, context, config);
223             if (definition != null)
224                 definitionName = definition.getName();
225         }
226         if (definitionName == null)
227             throw new AssertionFailedError("Could not find tiles definition mapped to forward '" + forwardName + "'");
228         if (!definitionName.equals(expectedDefinition))
229             throw new AssertionFailedError("Was expecting tiles definition '" + expectedDefinition + "' but received '" + definitionName + "'");
230         if (logger.isTraceEnabled())
231             logger.trace("Exiting");
232     }
233
234     /**
235      * Verifies that ActionServlet used this logical forward or input mapping.
236      *
237      * @throws AssertionFailedError if expected and actual paths do not match.
238      */

239     protected static void verifyForwardPath(String JavaDoc actionPath, String JavaDoc forwardName, String JavaDoc actualForwardPath, boolean isInputPath, HttpServletRequest JavaDoc request, ServletContext JavaDoc context, ServletConfig JavaDoc config) {
240
241         if (logger.isTraceEnabled())
242             logger.trace("Entering - actionPath = " + actionPath + ", forwardName = " + forwardName + ", actualForwardPath = " + actualForwardPath);
243
244         boolean usesTiles = false;
245         boolean useModules = false;
246
247         if ((forwardName == null) && (isInputPath)) {
248             if (logger.isDebugEnabled()) {
249                 logger.debug("processing an input forward");
250             }
251             forwardName = getActionConfig(actionPath, request, context).getInput();
252             if (logger.isDebugEnabled()) {
253                 logger.debug("retrieved input forward name = " + forwardName);
254             }
255             if (forwardName == null)
256                 throw new AssertionFailedError("Trying to validate against an input mapping, but none is defined for this Action.");
257             String JavaDoc tilesForward = null;
258             ComponentDefinition definition = getTilesForward(forwardName, request, context, config);
259             if (definition != null)
260                 tilesForward = definition.getPath();
261             if (tilesForward != null) {
262                 forwardName = tilesForward;
263                 usesTiles = true;
264                 if (logger.isDebugEnabled()) {
265                     logger.debug("retrieved tiles definition for forward = " + forwardName);
266                 }
267             }
268         }
269         if (!isInputPath) {
270             if (logger.isDebugEnabled()) {
271                 logger.debug("processing normal forward");
272             }
273
274             // check for a null forward, now allowed in Struts 1.1
275
if (forwardName == null) {
276                 if (actualForwardPath == null)
277                     return;
278                 else
279                     throw new AssertionFailedError("Expected a null forward from action, but received '" + actualForwardPath + "'");
280             }
281
282             ForwardConfig expectedForward = findForward(actionPath, forwardName, request, context);
283             if (expectedForward == null)
284                 throw new AssertionFailedError("Cannot find forward '" + forwardName + "' - it is possible that it is not mapped correctly.");
285             forwardName = expectedForward.getPath();
286             if (logger.isDebugEnabled()) {
287                 logger.debug("retrieved forward name = " + forwardName);
288             }
289
290             String JavaDoc tilesForward = null;
291             ComponentDefinition definition = getTilesForward(forwardName, request, context, config);
292             if (definition != null)
293                 tilesForward = definition.getPath();
294             if (tilesForward != null) {
295                 forwardName = tilesForward;
296
297                 usesTiles = true;
298                 if (logger.isDebugEnabled()) {
299                     logger.debug("retrieved tiles definition for forward = " + forwardName);
300                 }
301             }
302             // some fowards cross outside modules - check if we need the module
303
// in the path or not.
304
useModules = !expectedForward.getContextRelative ();
305         }
306
307         String JavaDoc moduleName = request.getServletPath() != null ? request.getServletPath() : "";
308         if ((moduleName == null || moduleName.equalsIgnoreCase("")) && request.getAttribute(INCLUDE_SERVLET_PATH) != null)
309             // check to see if this is a MockStrutsTestCase call
310
moduleName = (String JavaDoc) request.getAttribute(INCLUDE_SERVLET_PATH);
311
312         if ((moduleName != null) && (moduleName.length() > 0))
313             moduleName = moduleName.substring(moduleName.indexOf('/'),moduleName.lastIndexOf('/'));
314         else
315             moduleName = "";
316
317         if (!forwardName.startsWith("/"))
318             forwardName = "/" + forwardName;
319
320         if (usesTiles)
321             forwardName = request.getContextPath() + forwardName;
322         else if (useModules || isInputPath)
323             forwardName = request.getContextPath() + moduleName + forwardName;
324         else
325             forwardName = request.getContextPath() + forwardName;
326         if (logger.isDebugEnabled()) {
327             logger.debug("added context path and module name to forward = " + forwardName);
328         }
329         if (actualForwardPath == null) {
330             if (logger.isDebugEnabled()) {
331                 logger.debug("actualForwardPath is null - this usually means it is not mapped properly.");
332             }
333             throw new AssertionFailedError("Was expecting '" + forwardName + "' but it appears the Action has tried to return an ActionForward that is not mapped correctly.");
334         }
335         if (logger.isDebugEnabled()) {
336             logger.debug("expected forward = '" + forwardName + "' - actual forward = '" + actualForwardPath + "'");
337         }
338         if (!forwardName.equals(stripJSessionID(actualForwardPath)))
339             throw new AssertionFailedError("was expecting '" + forwardName + "' but received '" + actualForwardPath + "'");
340         if (logger.isTraceEnabled())
341             logger.trace("Exiting");
342     }
343
344     /**
345      * Strips off *.do from action paths specified as such.
346      */

347     protected static String JavaDoc stripActionPath(String JavaDoc path) {
348         if (logger.isTraceEnabled())
349             logger.trace("Entering - path = " + path);
350         if (path == null)
351             return null;
352
353         int slash = path.lastIndexOf("/");
354         int period = path.lastIndexOf(".");
355         if ((period >= 0) && (period > slash))
356             path = path.substring(0, period);
357         if (logger.isTraceEnabled())
358             logger.trace("Exiting - returning path = " + path);
359         return path;
360     }
361
362     /**
363      * Strip ;jsessionid=<sessionid> from path.
364      * @return stripped path
365      */

366     protected static String JavaDoc stripJSessionID(String JavaDoc path) {
367         if (logger.isTraceEnabled())
368             logger.trace("Entering - path = " + path);
369         if (path == null)
370             return null;
371
372         String JavaDoc pathCopy = path.toLowerCase();
373         int jsess_idx = pathCopy.indexOf(";jsessionid=");
374         if (jsess_idx > 0) {
375             StringBuffer JavaDoc buf = new StringBuffer JavaDoc(path);
376
377             int queryIndex = pathCopy.indexOf("?");
378             // Strip jsessionid from obtained path, but keep query string
379
if (queryIndex > 0)
380                 path = buf.delete(jsess_idx, queryIndex).toString();
381             // Strip jsessionid from obtained path
382
else
383                 path = buf.delete(jsess_idx, buf.length()).toString();
384         }
385         if (logger.isTraceEnabled())
386             logger.trace("Exiting - returning path = " + path);
387         return path;
388     }
389
390     /**
391      * Returns any ActionForm instance stored in the request or session, if available.
392      */

393     protected static ActionForm getActionForm(String JavaDoc actionPath, HttpServletRequest JavaDoc request, ServletContext JavaDoc context) {
394         if (logger.isTraceEnabled())
395             logger.trace("Entering - actionPath = " + actionPath + ", request = " + request + ", context = " + context);
396         ActionForm form;
397         ActionConfig actionConfig = getActionConfig(actionPath, request, context);
398         if ("request".equals(actionConfig.getScope())) {
399             if (logger.isDebugEnabled()) {
400                 logger.debug("looking for form in request scope");
401             }
402             form = (ActionForm) request.getAttribute(actionConfig.getAttribute());
403         } else {
404             if (logger.isDebugEnabled()) {
405                 logger.debug("looking for form in session scope");
406             }
407             HttpSession JavaDoc session = request.getSession();
408             form = (ActionForm) session.getAttribute(actionConfig.getAttribute());
409         }
410         if (logger.isTraceEnabled())
411             logger.trace("Exiting");
412         return form;
413     }
414
415     /**
416      * Returns a ForwardConfig for the given forward name. This method first searches for the forward in the supplied
417      * action mapping. If it is not defined there, or if the mapping is not provided, it searches for it globally.
418      */

419     protected static ForwardConfig findForward(String JavaDoc mappingName, String JavaDoc forwardName, HttpServletRequest JavaDoc request, ServletContext JavaDoc context) {
420         if (logger.isTraceEnabled())
421             logger.trace("Entering - mappingName = " + mappingName + ", forwardName = " + forwardName + ", request = " + request + ", context = " + context);
422         ForwardConfig forward = null;
423         // first, look for forward in mapping (if it's defined)
424
if (mappingName != null) {
425             ActionConfig mapping = getActionConfig(mappingName, request, context);
426             forward = mapping == null ? null : mapping.findForwardConfig(forwardName);
427         }
428         // if it's not there, check for global forwards
429
if (forward == null) {
430             if (logger.isDebugEnabled())
431                 logger.debug("looking for forward globally");
432             ModuleConfig moduleConfig = getModuleConfig(request,context);
433             forward = moduleConfig.findForwardConfig(forwardName);
434         }
435         if (logger.isDebugEnabled()) {
436             logger.debug("retrieved forward = " + forward);
437         }
438         if (logger.isTraceEnabled())
439             logger.trace("Exiting");
440         return forward;
441     }
442
443     /**
444      * Returns the configuration for the given action mapping.
445      */

446     protected static ActionConfig getActionConfig(String JavaDoc mappingName, HttpServletRequest JavaDoc request, ServletContext JavaDoc context) {
447         if (logger.isTraceEnabled())
448             logger.trace("Entering - mappingName = " + mappingName + ", request = " + request + ", context = " + context);
449         ModuleConfig config = getModuleConfig(request, context);
450         ActionMapping actionMapping = (ActionMapping) config.findActionConfig(mappingName);
451         if (logger.isDebugEnabled()) {
452             logger.debug("retrieved mapping = " + actionMapping);
453         }
454         if (logger.isTraceEnabled())
455             logger.trace("Exiting");
456         return actionMapping;
457     }
458
459     /**
460      * Returns the configuration for the current module.
461      */

462     protected static ModuleConfig getModuleConfig(HttpServletRequest JavaDoc request, ServletContext JavaDoc context) {
463         if (logger.isTraceEnabled())
464             logger.trace("Entering - request = " + request + ", context = " + context);
465         if (logger.isDebugEnabled()) {
466             logger.debug("looking for config in request context");
467         }
468         ModuleConfig config = (ModuleConfig) request.getAttribute(Globals.MODULE_KEY);
469         if (config == null) {
470             if (logger.isDebugEnabled()) {
471                 logger.debug("looking for config in application context");
472             }
473             config = (ModuleConfig) context.getAttribute(Globals.MODULE_KEY);
474         }
475         if (logger.isTraceEnabled())
476             logger.trace("Exiting - returning " + config);
477         return config;
478
479     }
480
481     /**
482      * Sets an ActionForm instance in the request.
483      */

484     protected static void setActionForm(ActionForm form, HttpServletRequest JavaDoc request, String JavaDoc actionPath, ServletContext JavaDoc context) {
485         if (logger.isTraceEnabled())
486             logger.trace("Entering - form = " + form + ", request = " + request + ", actionPath = " + actionPath + ", context = " + context);
487
488         if (actionPath == null || actionPath.equalsIgnoreCase(""))
489             throw new IllegalStateException JavaDoc("You must call setRequestPathInfo() before calling setActionForm()!");
490
491         ActionConfig actionConfig = getActionConfig(actionPath, request, context);
492         if (actionConfig == null) {
493             RequestUtils.selectModule(request,context);
494             actionConfig = getActionConfig(actionPath, request, context);
495         }
496
497         if (actionConfig.getScope().equals("request")) {
498             if (logger.isDebugEnabled()) {
499                 logger.debug("setting form in request context");
500             }
501             request.setAttribute(actionConfig.getAttribute(), form);
502         } else {
503             if (logger.isDebugEnabled()) {
504                 logger.debug("setting form in session context");
505             }
506             request.getSession().setAttribute(actionConfig.getAttribute(), form);
507         }
508         if (logger.isTraceEnabled())
509             logger.trace("Exiting");
510     }
511
512 }
513
Popular Tags