Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/struts/action/Action.java


1   /*
2    * $Id: Action.java 54929 2004-10-16 16:38:42Z germuska $ 
3    *
4    * Copyright 2000-2004 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.action;
20  
21  import java.util.Locale;
22  
23  import javax.servlet.ServletContext;
24  import javax.servlet.ServletRequest;
25  import javax.servlet.ServletResponse;
26  import javax.servlet.http.HttpServletRequest;
27  import javax.servlet.http.HttpServletResponse;
28  import javax.servlet.http.HttpSession;
29  import javax.sql.DataSource;
30  
31  import org.apache.struts.Globals;
32  import org.apache.struts.config.ModuleConfig;
33  import org.apache.struts.util.MessageResources;
34  import org.apache.struts.util.ModuleUtils;
35  import org.apache.struts.util.RequestUtils;
36  import org.apache.struts.util.TokenProcessor;
37  
38  /**
39   * <p>An <strong>Action</strong> is an adapter between the contents of an incoming
40   * HTTP request and the corresponding business logic that should be executed to
41   * process this request. The controller (RequestProcessor) will select an
42   * appropriate Action for each request, create an instance (if necessary),
43   * and call the <code>execute</code> method.</p>
44   *
45   * <p>Actions must be programmed in a thread-safe manner, because the
46   * controller will share the same instance for multiple simultaneous
47   * requests. This means you should design with the following items in mind:
48   * </p>
49   * <ul>
50   * <li>Instance and static variables MUST NOT be used to store information
51   *     related to the state of a particular request. They MAY be used to
52   *     share global resources across requests for the same action.</li>
53   * <li>Access to other resources (JavaBeans, session variables, etc.) MUST
54   *     be synchronized if those resources require protection. (Generally,
55   *     however, resource classes should be designed to provide their own
56   *     protection where necessary.</li>
57   * </ul>
58   *
59   * <p>When an <code>Action</code> instance is first created, the controller
60   * will call <code>setServlet</code> with a non-null argument to
61   * identify the servlet instance to which this Action is attached.
62   * When the servlet is to be shut down (or restarted), the
63   * <code>setServlet</code> method will be called with a <code>null</code>
64   * argument, which can be used to clean up any allocated resources in use
65   * by this Action.</p>
66   *
67   * @version $Rev: 54929 $ $Date: 2004-10-16 09:38:42 -0700 (Sat, 16 Oct 2004) $
68   */
69  public class Action {
70  
71      /**
72       * <p>An instance of <code>TokenProcessor</code> to use for token functionality.</p>
73       */
74      private static TokenProcessor token = TokenProcessor.getInstance();
75      // :TODO: We can make this variable protected and remove Action's token methods
76      // or leave it private and allow the token methods to delegate their calls.
77  
78  
79      // ----------------------------------------------------- Instance Variables
80  
81  
82      /**
83       * <p>The system default Locale.</p>
84       *
85       * @deprecated Use Locale.getDefault directly.  This will be removed after
86       * Struts 1.2.
87       */
88      protected static Locale defaultLocale = Locale.getDefault();
89      // :TODO: Remove after Struts 1.2
90  
91  
92      /**
93       * <p>The servlet to which we are attached.</p>
94       */
95      protected ActionServlet servlet = null;
96  
97  
98      // ------------------------------------------------------------- Properties
99  
100 
101     /**
102      * <p>Return the servlet instance to which we are attached.</p>
103      */
104     public ActionServlet getServlet() {
105 
106         return (this.servlet);
107 
108     }
109 
110 
111     /**
112      * <p>Set the servlet instance to which we are attached (if
113      * <code>servlet</code> is non-null), or release any allocated resources
114      * (if <code>servlet</code> is null).</p>
115      *
116      * @param servlet The new controller servlet, if any
117      */
118     public void setServlet(ActionServlet servlet) {
119 
120         this.servlet = servlet;
121         // :FIXME: Is this suppose to release resources?
122 
123 
124     }
125 
126 
127     // --------------------------------------------------------- Public Methods
128 
129 
130     /**
131      * <p>Process the specified non-HTTP request, and create the
132      * corresponding non-HTTP response (or forward to another web
133      * component that will create it), with provision for handling
134      * exceptions thrown by the business logic.
135      * Return an {@link ActionForward} instance describing where and how
136      * control should be forwarded, or <code>null</code> if the response has
137      * already been completed.</p>
138      *
139      * <p>The default implementation attempts to forward to the HTTP
140      * version of this method.</p>
141      *
142      * @param mapping The ActionMapping used to select this instance
143      * @param form The optional ActionForm bean for this request (if any)
144      * @param request The non-HTTP request we are processing
145      * @param response The non-HTTP response we are creating
146      *
147      * @exception Exception if the application business logic throws
148      *  an exception.
149      * @since Struts 1.1
150      */
151     public ActionForward execute(
152         ActionMapping mapping,
153         ActionForm form,
154         ServletRequest request,
155         ServletResponse response)
156         throws Exception {
157 
158         try {
159             return execute(
160                 mapping,
161                 form,
162                 (HttpServletRequest) request,
163                 (HttpServletResponse) response);
164 
165         } catch (ClassCastException e) {
166             return null;
167         }
168 
169     }
170 
171 
172     /**
173      * <p>Process the specified HTTP request, and create the corresponding HTTP
174      * response (or forward to another web component that will create it),
175      * with provision for handling exceptions thrown by the business logic.
176      * Return an {@link ActionForward} instance describing where and how
177      * control should be forwarded, or <code>null</code> if the response
178      * has already been completed.</p>
179      *
180      * @param mapping The ActionMapping used to select this instance
181      * @param form The optional ActionForm bean for this request (if any)
182      * @param request The HTTP request we are processing
183      * @param response The HTTP response we are creating
184      *
185      * @exception Exception if the application business logic throws
186      *  an exception
187      * @since Struts 1.1
188      */
189     public ActionForward execute(
190         ActionMapping mapping,
191         ActionForm form,
192         HttpServletRequest request,
193         HttpServletResponse response)
194         throws Exception {
195 
196         return null;
197 
198     }
199 
200 
201     // ---------------------------------------------------- Protected Methods
202 
203 
204   /**
205    * Adds the specified messages keys into the appropriate request
206    * attribute for use by the &lt;html:messages&gt; tag (if
207    * messages="true" is set), if any messages are required.
208    * Initialize the attribute if it has not already been.
209    * Otherwise, ensure that the request attribute is not set.
210    *
211    * @param request   The servlet request we are processing
212    * @param messages  Messages object
213    * @since Struts 1.2.1
214    */
215   protected void addMessages(
216     HttpServletRequest request,
217     ActionMessages messages) {
218 
219     if (messages == null){
220       //  bad programmer! *slap*
221       return;
222     }
223 
224     // get any existing messages from the request, or make a new one
225     ActionMessages requestMessages = (ActionMessages) request.getAttribute(Globals.MESSAGE_KEY);
226     if (requestMessages == null){
227       requestMessages = new ActionMessages();
228     }
229     // add incoming messages
230     requestMessages.add(messages);
231 
232     // if still empty, just wipe it out from the request
233     if (requestMessages.isEmpty()) {
234       request.removeAttribute(Globals.MESSAGE_KEY);
235       return;
236     }
237 
238     // Save the messages
239     request.setAttribute(Globals.MESSAGE_KEY, requestMessages);
240   }
241 
242 
243   /**
244    * Adds the specified errors keys into the appropriate request
245    * attribute for use by the for use by the &lt;html:errors&gt; tag,
246    * if any messages are required.
247    * Initialize the attribute if it has not already been.
248    * Otherwise, ensure that the request attribute is not set.
249    *
250    * @param request   The servlet request we are processing
251    * @param errors  Errors object
252    * @since Struts 1.2.1
253    */
254   protected void addErrors(
255     HttpServletRequest request,
256     ActionMessages errors) {
257 
258     if (errors == null){
259       //  bad programmer! *slap*
260       return;
261     }
262 
263     // get any existing errors from the request, or make a new one
264     ActionMessages requestErrors = (ActionMessages)request.getAttribute(Globals.ERROR_KEY);
265     if (requestErrors == null){
266       requestErrors = new ActionMessages();
267     }
268     // add incoming errors
269     requestErrors.add(errors);
270 
271     // if still empty, just wipe it out from the request
272     if (requestErrors.isEmpty()) {
273       request.removeAttribute(Globals.ERROR_KEY);
274       return;
275     }
276 
277     // Save the errors
278     request.setAttribute(Globals.ERROR_KEY, requestErrors);
279   }
280 
281 
282     /**
283      * <p>Generate a new transaction token, to be used for enforcing a single
284      * request for a particular transaction.</p>
285      *
286      * @param request The request we are processing
287      */
288     protected String generateToken(HttpServletRequest request) {
289         return token.generateToken(request);
290     }
291 
292 
293     /**
294      * <p>Return the default data source for the current module.</p>
295      *
296      * @param request The servlet request we are processing
297      *
298      * @since Struts 1.1
299      */
300     protected DataSource getDataSource(HttpServletRequest request) {
301 
302         return (getDataSource(request, Globals.DATA_SOURCE_KEY));
303 
304     }
305 
306 
307 
308     /**
309      * <p>Return the specified data source for the current module.</p>
310      *
311      * @param request The servlet request we are processing
312      * @param key The key specified in the
313      *  <code>&lt;message-resources&gt;</code> element for the
314      *  requested bundle
315      *
316      * @since Struts 1.1
317      */
318     protected DataSource getDataSource(HttpServletRequest request, String key) {
319 
320         // Identify the current module
321         ServletContext context = getServlet().getServletContext();
322         ModuleConfig moduleConfig =
323             ModuleUtils.getInstance().getModuleConfig(request, context);
324 
325         return (DataSource) context.getAttribute(key + moduleConfig.getPrefix());
326     }
327 
328 
329     /**
330      * Retrieves any existing errors placed in the request by previous actions.  This method could be called instead
331      * of creating a <code>new ActionMessages()<code> at the beginning of an <code>Action<code>
332      * This will prevent saveErrors() from wiping out any existing Errors
333      *
334      * @return the Errors that already exist in the request, or a new ActionMessages object if empty.
335      * @param request The servlet request we are processing
336      * @since Struts 1.2.1
337      */
338     protected ActionMessages getErrors(HttpServletRequest request) {
339         ActionMessages errors =
340             (ActionMessages) request.getAttribute(Globals.ERROR_KEY);
341         if (errors == null) {
342             errors = new ActionMessages();
343         }
344         return errors;
345     }
346 
347 
348     /**
349      * <p>Return the user's currently selected Locale.</p>
350      *
351      * @param request The request we are processing
352      */
353     protected Locale getLocale(HttpServletRequest request) {
354 
355         return RequestUtils.getUserLocale(request, null);
356 
357     }
358 
359 
360   /**
361    * Retrieves any existing messages placed in the request by previous actions.  This method could be called instead
362    * of creating a <code>new ActionMessages()<code> at the beginning of an <code>Action<code>
363    * This will prevent saveMessages() from wiping out any existing Messages
364    *
365    * @return the Messages that already exist in the request, or a new ActionMessages object if empty.
366    * @param request The servlet request we are processing
367      * @since Struts 1.2.1
368    */
369   protected ActionMessages getMessages(HttpServletRequest request) {
370     ActionMessages messages =
371       (ActionMessages) request.getAttribute(Globals.MESSAGE_KEY);
372     if (messages == null) {
373       messages = new ActionMessages();
374     }
375     return messages;
376   }
377 
378 
379     /**
380      * <p>Return the default message resources for the current module.</p>
381      *
382      * @param request The servlet request we are processing
383      * @since Struts 1.1
384      */
385     protected MessageResources getResources(HttpServletRequest request) {
386 
387         return ((MessageResources) request.getAttribute(Globals.MESSAGES_KEY));
388 
389     }
390 
391 
392     /**
393      * <p>Return the specified message resources for the current module.</p>
394      *
395      * @param request The servlet request we are processing
396      * @param key The key specified in the
397      *  <code>&lt;message-resources&gt;</code> element for the
398      *  requested bundle
399      *
400      * @since Struts 1.1
401      */
402     protected MessageResources getResources(
403         HttpServletRequest request,
404         String key) {
405 
406         // Identify the current module
407         ServletContext context = getServlet().getServletContext();
408         ModuleConfig moduleConfig =
409             ModuleUtils.getInstance().getModuleConfig(request, context);
410 
411         // Return the requested message resources instance
412         return (MessageResources) context.getAttribute(
413             key + moduleConfig.getPrefix());
414 
415     }
416 
417 
418     /**
419      * <p>Returns <code>true</code> if the current form's cancel button was
420      * pressed.  This method will check if the <code>Globals.CANCEL_KEY</code>
421      * request attribute has been set, which normally occurs if the cancel
422      * button generated by <strong>CancelTag</strong> was pressed by the user
423      * in the current request.  If <code>true</code>, validation performed
424      * by an <strong>ActionForm</strong>'s <code>validate()</code> method
425      * will have been skipped by the controller servlet.</p>
426      *
427      * @param request The servlet request we are processing
428      * @see org.apache.struts.taglib.html.CancelTag
429      */
430     protected boolean isCancelled(HttpServletRequest request) {
431 
432         return (request.getAttribute(Globals.CANCEL_KEY) != null);
433 
434     }
435 
436 
437     /**
438      * <p>Return <code>true</code> if there is a transaction token stored in
439      * the user's current session, and the value submitted as a request
440      * parameter with this action matches it. Returns <code>false</code>
441      * under any of the following circumstances:</p>
442      * <ul>
443      * <li>No session associated with this request</li>
444      * <li>No transaction token saved in the session</li>
445      * <li>No transaction token included as a request parameter</li>
446      * <li>The included transaction token value does not match the
447      *     transaction token in the user's session</li>
448      * </ul>
449      *
450      * @param request The servlet request we are processing
451      */
452     protected boolean isTokenValid(HttpServletRequest request) {
453 
454         return token.isTokenValid(request, false);
455 
456     }
457 
458 
459     /**
460      * <p>Return <code>true</code> if there is a transaction token stored in
461      * the user's current session, and the value submitted as a request
462      * parameter with this action matches it. Returns <code>false</code>.</p>
463      * <ul>
464      * <li>No session associated with this request</li>
465      * <li>No transaction token saved in the session</li>
466      * <li>No transaction token included as a request parameter</li>
467      * <li>The included transaction token value does not match the
468      *     transaction token in the user's session</li>
469      * </ul>
470      *
471      * @param request The servlet request we are processing
472      * @param reset Should we reset the token after checking it?
473      */
474     protected boolean isTokenValid(HttpServletRequest request, boolean reset) {
475 
476         return token.isTokenValid(request, reset);
477 
478     }
479 
480 
481     /**
482      * <p>Reset the saved transaction token in the user's session. This
483      * indicates that transactional token checking will not be needed
484      * on the next request that is submitted.</p>
485      *
486      * @param request The servlet request we are processing
487      */
488     protected void resetToken(HttpServletRequest request) {
489 
490         token.resetToken(request);
491 
492     }
493 
494 
495     /**
496      * <p>Save the specified error messages keys into the appropriate request
497      * attribute for use by the &lt;html:errors&gt; tag, if any messages
498      * are required. Otherwise, ensure that the request attribute is not
499      * created.</p>
500      *
501      * @param request The servlet request we are processing
502      * @param errors Error messages object
503      * @deprecated Use saveErrors(HttpServletRequest, ActionMessages) instead.
504      * This will be removed after Struts 1.2.
505      */
506     protected void saveErrors(HttpServletRequest request, ActionErrors errors) {
507 
508         this.saveErrors(request,(ActionMessages)errors);
509         // :TODO: Remove after Struts 1.2.
510 
511     }
512 
513 
514     /**
515      * <p>Save the specified error messages keys into the appropriate request
516      * attribute for use by the &lt;html:errors&gt; tag, if any messages
517      * are required. Otherwise, ensure that the request attribute is not
518      * created.</p>
519      *
520      * @param request The servlet request we are processing
521      * @param errors Error messages object
522      * @since Struts 1.2
523      */
524     protected void saveErrors(HttpServletRequest request, ActionMessages errors) {
525 
526         // Remove any error messages attribute if none are required
527         if ((errors == null) || errors.isEmpty()) {
528             request.removeAttribute(Globals.ERROR_KEY);
529             return;
530         }
531 
532         // Save the error messages we need
533         request.setAttribute(Globals.ERROR_KEY, errors);
534 
535     }
536 
537 
538     /**
539      * <p>Save the specified messages keys into the appropriate request
540      * attribute for use by the &lt;html:messages&gt; tag (if
541      * messages="true" is set), if any messages are required. Otherwise,
542      * ensure that the request attribute is not created.</p>
543      *
544      * @param request The servlet request we are processing.
545      * @param messages The messages to save. <code>null</code> or empty
546      * messages removes any existing ActionMessages in the request.
547      *
548      * @since Struts 1.1
549      */
550     protected void saveMessages(
551         HttpServletRequest request,
552         ActionMessages messages) {
553 
554         // Remove any messages attribute if none are required
555         if ((messages == null) || messages.isEmpty()) {
556             request.removeAttribute(Globals.MESSAGE_KEY);
557             return;
558         }
559 
560         // Save the messages we need
561         request.setAttribute(Globals.MESSAGE_KEY, messages);
562     }
563 
564 
565     /**
566      * <p>Save the specified messages keys into the appropriate session
567      * attribute for use by the &lt;html:messages&gt; tag (if
568      * messages="true" is set), if any messages are required. Otherwise,
569      * ensure that the session attribute is not created.</p>
570      *
571      * @param session The session to save the messages in.
572      * @param messages The messages to save. <code>null</code> or empty
573      * messages removes any existing ActionMessages in the session.
574      *
575      * @since Struts 1.2
576      */
577     protected void saveMessages(
578         HttpSession session,
579         ActionMessages messages) {
580 
581         // Remove any messages attribute if none are required
582         if ((messages == null) || messages.isEmpty()) {
583             session.removeAttribute(Globals.MESSAGE_KEY);
584             return;
585         }
586 
587         // Save the messages we need
588         session.setAttribute(Globals.MESSAGE_KEY, messages);
589     }
590 
591 
592     /**
593      * <p>Save a new transaction token in the user's current session, creating
594      * a new session if necessary.</p>
595      *
596      * @param request The servlet request we are processing
597      */
598     protected void saveToken(HttpServletRequest request) {
599         token.saveToken(request);
600     }
601 
602 
603     /**
604      * <p>Set the user's currently selected <code>Locale</code> into their
605      * <code>HttpSession</code>.</p>
606      *
607      * @param request The request we are processing
608      * @param locale The user's selected Locale to be set, or null
609      *  to select the server's default Locale
610      */
611     protected void setLocale(HttpServletRequest request, Locale locale) {
612 
613         HttpSession session = request.getSession();
614         if (locale == null) {
615             locale = Locale.getDefault();
616         }
617         session.setAttribute(Globals.LOCALE_KEY, locale);
618 
619     }
620 
621 }