View Javadoc

1   /*
2    * $Id: BaseAction.java 360442 2005-12-31 20:10:04Z husted $
3    *
4    * Copyright 1999-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.apps.mailreader.actions;
20  
21  import org.apache.commons.beanutils.PropertyUtils;
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  import org.apache.struts.action.ActionForm;
25  import org.apache.struts.action.ActionForward;
26  import org.apache.struts.action.ActionMapping;
27  import org.apache.struts.action.ActionMessage;
28  import org.apache.struts.action.ActionMessages;
29  import org.apache.struts.action.DynaActionForm;
30  import org.apache.struts.actions.MappingDispatchAction;
31  import org.apache.struts.apps.mailreader.Constants;
32  import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
33  import org.apache.struts.apps.mailreader.dao.Subscription;
34  import org.apache.struts.apps.mailreader.dao.User;
35  import org.apache.struts.apps.mailreader.dao.UserDatabase;
36  
37  import javax.servlet.ServletException;
38  import javax.servlet.http.HttpServletRequest;
39  import javax.servlet.http.HttpSession;
40  
41  /***
42   * <p>
43   * Base Action for MailReader application.
44   * </p><p>
45   * All the BaseAction helper methods are prefixed with "do"
46   * so that they can be easily distinguished from Struts and Servlet API methods.
47   * BaseAction subclasses may also have prive "do" helpers of their own.
48   * </p><p>
49   * Methods are kept in alphabetical order, to make them easier to find.
50   * </p>
51   *
52   * @version $Rev: 360442 $ $Date: 2005-12-31 13:10:04 -0700 (Sat, 31 Dec 2005) $
53   */
54  public abstract class BaseAction extends MappingDispatchAction {
55  
56      // ---- Fields ----
57  
58      /***
59       * <p>
60       * Name of username field ["username"].
61       * </p>
62       */
63      public static String USERNAME = "username";
64  
65      /***
66       * <p>
67       * Name of password field ["password"].
68       * </p>
69       */
70      public static String PASSWORD = "password";
71  
72      /***
73       * <p>
74       * Name of task field ["task"].
75       * </p>
76       */
77      public final static String TASK = "task";
78  
79      // ---- Protected Variables ----
80  
81      /***
82       * <p>
83       * The <code>Log</code> instance for this application.
84       * </p>
85       */
86      protected Log log = LogFactory.getLog(Constants.PACKAGE);
87  
88      // ---- Protected Methods ----
89  
90      /***
91       * <p>
92       * Store User object in client session.
93       * If user object is null, any existing user object is removed.
94       * </p>
95       *
96       * @param request The request we are processing
97       * @param user    The user object returned from the database
98       */
99      void doCacheUser(HttpServletRequest request, User user) {
100 
101         HttpSession session = request.getSession();
102         session.setAttribute(Constants.USER_KEY, user);
103         if (log.isDebugEnabled()) {
104             log.debug(
105                     "LogonAction: User '"
106                             + user.getUsername()
107                             + "' logged on in session "
108                             + session.getId());
109         }
110     }
111 
112     /***
113      * <p>
114      * Helper method to log event and cancel transaction.
115      * </p>
116      *
117      * @param session Our HttpSession
118      * @param method  Method being processed
119      * @param key     Attrkibute to remove from session, if any
120      */
121     protected void doCancel(HttpSession session, String method, String key) {
122         if (log.isTraceEnabled()) {
123             StringBuffer sb = new StringBuffer(128);
124             sb.append(Constants.LOG_CANCEL);
125             sb.append(method);
126             log.trace(sb.toString());
127         }
128         if (key != null) {
129             session.removeAttribute(key);
130         }
131     }
132 
133     /***
134      * <p>
135      * Return the local or global forward named "failure"
136      * or null if there is no such forward.
137      * </p>
138      *
139      * @param mapping Our ActionMapping
140      * @return Return the mapping named "failure" or null if there is no such mapping.
141      */
142     protected ActionForward doFindFailure(ActionMapping mapping) {
143         if (log.isTraceEnabled()) {
144             log.trace(Constants.LOG_FAILURE);
145         }
146         return mapping.findForward(Constants.FAILURE);
147     }
148 
149     /***
150      * <p>
151      * Return the local or global forward named "logon"
152      * or null if there is no such forward.
153      * </p>
154      *
155      * @param mapping Our ActionMapping
156      * @return Return the mapping named "logon" or null if there is no such mapping.
157      */
158     protected ActionForward doFindLogon(ActionMapping mapping) {
159         if (log.isTraceEnabled()) {
160             log.trace(Constants.LOG_LOGON);
161         }
162         return mapping.findForward(Constants.LOGON);
163     }
164 
165     /***
166      * <p>
167      * Return the mapping labeled "success"
168      * or null if there is no such mapping.
169      * </p>
170      *
171      * @param mapping Our ActionMapping
172      * @return Return the mapping named "success" or null if there is no such
173      *         mapping.
174      */
175     protected ActionForward doFindSuccess(ActionMapping mapping) {
176         if (log.isTraceEnabled()) {
177             log.trace(Constants.LOG_SUCCESS);
178         }
179         return mapping.findForward(Constants.SUCCESS);
180     }
181 
182     /***
183      * <p>
184      * Helper method to fetch a String property from a DynaActionForm.
185      * </p>
186      * <p>
187      * Values are returned trimmed of leading and trailing whitespace.
188      * Zero-length strings are returned as null.
189      * </p>
190      *
191      * @param form     Our DynaActionForm
192      * @param property The name of the property
193      * @return The value or null if an error occurs
194      */
195     protected String doGet(ActionForm form, String property) {
196         String initial;
197         try {
198             initial = (String) PropertyUtils.getSimpleProperty(form, property);
199         } catch (Throwable t) {
200             initial = null;
201         }
202         String value = null;
203         if ((initial != null) && (initial.length() > 0)) {
204             value = initial.trim();
205             if (value.length() == 0) {
206                 value = null;
207             }
208         }
209         return value;
210     }
211 
212     /***
213      * <p>
214      * Obtain the cached Subscription object, if any.
215      * </p>
216      *
217      * @param session Our HttpSession
218      * @return Cached Subscription object or null
219      */
220     protected Subscription doGetSubscription(HttpSession session) {
221         return (Subscription) session.getAttribute(Constants.SUBSCRIPTION_KEY);
222     }
223 
224     /***
225      * <p>
226      * Obtain the cached Subscription object, if any.
227      * </p>
228      *
229      * @param request Our HttpServletRequest
230      * @return Cached Subscription object or null
231      */
232     protected Subscription doGetSubscription(HttpServletRequest request) {
233         HttpSession session = request.getSession();
234         return doGetSubscription(session);
235     }
236 
237     /***
238      * <p>
239      * Confirm user credentials. Post any errors and return User object
240      * (or null).
241      * </p>
242      *
243      * @param database Database in which to look up the user
244      * @param username Username specified on the logon form
245      * @param password Password specified on the logon form
246      * @param errors   ActionMessages queue to passback errors
247      * @return Validated User object or null
248      * @throws org.apache.struts.apps.mailreader.dao.ExpiredPasswordException
249      *          to be handled by Struts exception
250      *          processor via the action-mapping
251      */
252     User doGetUser(UserDatabase database, String username,
253                    String password, ActionMessages errors)
254             throws ExpiredPasswordException {
255 
256         User user = null;
257         if (database == null) {
258             errors.add(
259                     ActionMessages.GLOBAL_MESSAGE,
260                     new ActionMessage("error.database.missing"));
261         } else {
262 
263             if (username.equals("Hermes")) {
264                 throw new ExpiredPasswordException("Hermes");
265             }
266 
267             user = database.findUser(username);
268             if ((user != null) && !user.getPassword().equals(password)) {
269                 user = null;
270             }
271             if (user == null) {
272                 errors.add(
273                         ActionMessages.GLOBAL_MESSAGE,
274                         new ActionMessage("error.password.mismatch"));
275             }
276         }
277 
278         return user;
279     }
280 
281     /***
282      * <p>
283      * Confirm user credentials. Post any errors and return User object
284      * (or null).
285      * </p>
286      *
287      * @param username Username specified on the logon form
288      * @param password Password specified on the logon form
289      * @param errors   ActionMessages queue to passback errors
290      * @return Validated User object or null
291      * @throws org.apache.struts.apps.mailreader.dao.ExpiredPasswordException
292      *          to be handled by Struts exception
293      *          processor via the action-mapping
294      */
295     User doGetUser(String username,
296                    String password, ActionMessages errors)
297             throws ExpiredPasswordException {
298 
299         return doGetUser(doGetUserDatabase(), username, password, errors);
300     }
301 
302     /***
303      * <p>
304      * Return a reference to the UserDatabase
305      * or null if the database is not available.
306      * </p>
307      *
308      * @return a reference to the UserDatabase or null if the database is not
309      *         available
310      */
311     protected UserDatabase doGetUserDatabase() {
312         return (UserDatabase) servlet.getServletContext().getAttribute(
313                 Constants.DATABASE_KEY);
314     }
315 
316     /***
317      * <p>
318      * Helper method to obtain User form session (if any).
319      * </p>
320      *
321      * @param session Our HttpSession
322      * @return User object, or null if there is no user.
323      */
324     protected User doGetUser(HttpSession session) {
325         return (User) session.getAttribute(Constants.USER_KEY);
326     }
327 
328     /***
329      * <p>
330      * Helper method to obtain User form session (if any).
331      * </p>
332      *
333      * @param request Our HttpServletRequest
334      * @return User object, or null if there is no user.
335      */
336     protected User doGetUser(HttpServletRequest request) {
337         HttpSession session = request.getSession();
338         return (User) session.getAttribute(Constants.USER_KEY);
339     }
340 
341     /***
342      * <p>
343      * Save any errors and the transactioonal token, and forward to the
344      * InputForard result.
345      * </p>
346      *
347      * @param mapping Our ActionMapping
348      * @param request Our HttpServletRequest
349      * @param errors  Our ActionMessages collectoin
350      * @return The InputForward for this mappintg
351      */
352     protected ActionForward doInputForward(ActionMapping mapping,
353                                            HttpServletRequest request,
354                                            ActionMessages errors) {
355         this.saveErrors(request, errors);
356         this.saveToken(request);
357         return (mapping.getInputForward());
358     }
359 
360     /***
361      * <p>
362      * Log a "processing" message for an Action.
363      * </p>
364      *
365      * @param mapping Our ActionMapping
366      * @param method  Name of method being processed
367      */
368     protected void doLogProcess(ActionMapping mapping, String method) {
369         if (log.isDebugEnabled()) {
370             StringBuffer sb = new StringBuffer(128);
371             sb.append(" ");
372             sb.append(mapping.getPath());
373             sb.append(":");
374             sb.append(Constants.LOG_PROCESSING);
375             sb.append(method);
376             log.debug(sb.toString());
377         }
378     }
379 
380     /***
381      * <p>
382      * Helper method to log event and save token.
383      * </p>
384      *
385      * @param request Our HttpServletRequest
386      */
387     protected void doSaveToken(HttpServletRequest request) {
388         if (log.isTraceEnabled()) {
389             log.trace(Constants.LOG_TOKEN);
390         }
391         saveToken(request);
392     }
393 
394     /***
395      * <p>
396      * Persist the User object, including subscriptions, to the database.
397      * </p>
398      *
399      * @param user Our User object
400      * @throws javax.servlet.ServletException On any error
401      */
402     protected void doSaveUser(User user) throws ServletException {
403 
404         final String LOG_DATABASE_SAVE_ERROR =
405                 " Unexpected error when saving User: ";
406 
407         try {
408             UserDatabase database = doGetUserDatabase();
409             database.save();
410         } catch (Exception e) {
411             String message = LOG_DATABASE_SAVE_ERROR + user.getUsername();
412             log.error(message, e);
413             throw new ServletException(message, e);
414         }
415     }
416 
417     /***
418      * <p>
419      * Helper method to inject a String property into a DynaActionForm.
420      * </p>
421      *
422      * @param form     Our DynaActionForm
423      * @param property The name of the property
424      * @param value    The value for the property
425      * @return True if the assignment succeeds
426      */
427     protected boolean doSet(ActionForm form, String property, String value) {
428         try {
429             DynaActionForm dyna = (DynaActionForm) form;
430             dyna.set(property, value);
431         } catch (Throwable t) {
432             return false;
433         }
434         return true;
435     }
436 
437 }