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