1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.struts.apps.mailreader.actions;
18
19 import org.apache.commons.beanutils.PropertyUtils;
20 import org.apache.struts.action.ActionForm;
21 import org.apache.struts.action.ActionForward;
22 import org.apache.struts.action.ActionMapping;
23 import org.apache.struts.action.ActionMessage;
24 import org.apache.struts.action.ActionMessages;
25 import org.apache.struts.action.DynaActionForm;
26 import org.apache.struts.apps.mailreader.Constants;
27 import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
28 import org.apache.struts.apps.mailreader.dao.User;
29 import org.apache.struts.apps.mailreader.dao.UserDatabase;
30
31 import javax.servlet.ServletException;
32 import javax.servlet.http.HttpServletRequest;
33 import javax.servlet.http.HttpServletResponse;
34 import javax.servlet.http.HttpSession;
35 import java.lang.reflect.InvocationTargetException;
36
37 /**
38 * <p>
39 * Provide an Edit method for retrieving an existing user,
40 * and a Save method for updating or inserting a user.
41 * </p><p>
42 * Both methods utilize a RegistrationForm to obtain or expose User details.
43 * If Save is used to create a user,
44 * additional validations ensure input is nominal.
45 * When a user is created,
46 * Save also handles the initial logon.
47 * </p>
48 */
49 public final class RegistrationAction extends BaseAction {
50
51
52
53 /**
54 * <p>
55 * Name of fromAddress field ["fromAddress"].
56 * </p>
57 */
58 public final static String FROM_ADDRESS = "fromAddress";
59
60 /**
61 * <p>
62 * Name of fullName field ["fullName"].
63 * </p>
64 */
65 public final static String FULL_NAME = "fullName";
66
67 /**
68 * <p>
69 * Name of password confirmation field ["password2"].
70 * </p>
71 */
72 public final static String PASSWORD2 = "password2";
73
74 /**
75 * <p>
76 * Name of replyToAddress field ["replyToAddress"].
77 * </p>
78 */
79 public final static String REPLY_TO_ADDRESS = "replyToAddress";
80
81
82
83 /**
84 * <p>
85 * The message prefix to use when populating a Registration Form.
86 * </p>
87 */
88 final String LOG_REGISTRATION_POPULATE = "RegistrationForm.populate";
89
90 /**
91 * <p>
92 * Helper method to post error message when user already exists.
93 * </p>
94 *
95 * @param username Existing username
96 * @param errors Our ActionMessages collection
97 */
98 private void errorUsernameUnique(String username,
99 ActionMessages errors) {
100 errors.add(
101 USERNAME,
102 new org.apache.struts.action.ActionMessage(
103 "error.username.unique", username));
104 }
105
106 /**
107 * <p>
108 * Verify input for creating a new user,
109 * create the user, and process the login.
110 * </p>
111 *
112 * @param form The input form
113 * @param request The HttpRequest being served
114 * @param errors The ActionMessages collection for any errors
115 * @return A new User and empty Errors if create succeeds,
116 * or null and Errors if create fails
117 */
118 private User doCreateUser(
119 ActionForm form,
120 HttpServletRequest request,
121 ActionMessages errors) {
122
123 if (log.isTraceEnabled()) {
124 log.trace(" Perform additional validations on Create");
125 }
126
127 UserDatabase database = doGetUserDatabase();
128 String username = doGet(form, USERNAME);
129 try {
130 if (database.findUser(username) != null) {
131 errorUsernameUnique(username, errors);
132 }
133 }
134 catch (ExpiredPasswordException e) {
135 errorUsernameUnique(username, errors);
136 errors.add("errors.literal", new ActionMessage(e.getMessage()));
137 }
138
139 String password = doGet(form, PASSWORD);
140 if ((password == null) || (password.length() < 1)) {
141 errors.add(PASSWORD, new ActionMessage("error.password.required"));
142
143 String password2 = doGet(form, PASSWORD2);
144 if ((password2 == null) || (password2.length() < 1)) {
145 errors.add(
146 PASSWORD2,
147 new ActionMessage("error.password2.required"));
148 }
149 }
150
151 if (!errors.isEmpty()) {
152 return null;
153 }
154
155 User user = database.createUser(username);
156
157
158 HttpSession session = request.getSession();
159 session.setAttribute(Constants.USER_KEY, user);
160 if (log.isTraceEnabled()) {
161 log.trace(
162 " User: '"
163 + user.getUsername()
164 + "' logged on in session: "
165 + session.getId());
166 }
167
168 return user;
169 }
170
171 /**
172 * <p>
173 * Helper method to populate the input form from the User object.
174 * </p>
175 *
176 * @param form Form with incoming values
177 * @param user User object to populate
178 * @throws ServletException On any error
179 */
180 private void doPopulate(ActionForm form, User user)
181 throws ServletException {
182
183 final String title = Constants.EDIT;
184
185 if (log.isTraceEnabled()) {
186 log.trace(Constants.LOG_POPULATE_FORM + user);
187 }
188
189 try {
190 PropertyUtils.copyProperties(form, user);
191 DynaActionForm dyna = (DynaActionForm) form;
192 dyna.set(TASK, title);
193 dyna.set(PASSWORD, null);
194 dyna.set(PASSWORD2, null);
195 } catch (InvocationTargetException e) {
196 Throwable t = e.getTargetException();
197 if (t == null) {
198 t = e;
199 }
200 log.error(LOG_REGISTRATION_POPULATE, t);
201 throw new ServletException(LOG_REGISTRATION_POPULATE, t);
202 } catch (Throwable t) {
203 log.error(LOG_REGISTRATION_POPULATE, t);
204 throw new ServletException(LOG_REGISTRATION_POPULATE, t);
205 }
206 }
207
208 /**
209 * <p>
210 * Helper method to populate the User object from the input form.
211 * </p>
212 *
213 * @param user User object to populate
214 * @param form Form with incoming values
215 * @throws ServletException On any error
216 */
217 private void doPopulate(User user, ActionForm form)
218 throws ServletException {
219
220 if (log.isTraceEnabled()) {
221 log.trace(Constants.LOG_POPULATE_USER + user);
222 }
223
224 try {
225 String oldPassword = user.getPassword();
226 PropertyUtils.copyProperties(user, form);
227 String password = doGet(form, PASSWORD);
228 if ((password == null)
229 || (password.length() < 1)) {
230
231 user.setPassword(oldPassword);
232 }
233
234 } catch (InvocationTargetException e) {
235 Throwable t = e.getTargetException();
236 if (t == null) {
237 t = e;
238 }
239
240 log.error(LOG_REGISTRATION_POPULATE, t);
241 throw new ServletException(LOG_REGISTRATION_POPULATE, t);
242
243 } catch (Throwable t) {
244 log.error(LOG_REGISTRATION_POPULATE, t);
245 throw new ServletException(LOG_REGISTRATION_POPULATE, t);
246 }
247 }
248
249 /**
250 * <p>
251 * Validate and clear the transactional token,
252 * creating logging statements as needed.
253 * </p>
254 *
255 * @param request Our HttpServletRequest
256 * @param errors ActionErrors to transfer any messages
257 */
258 private void doValidateToken(HttpServletRequest request,
259 ActionMessages errors) {
260
261 if (log.isTraceEnabled()) {
262 log.trace(Constants.LOG_TOKEN_CHECK);
263 }
264
265 if (!isTokenValid(request)) {
266 errors.add(
267 ActionMessages.GLOBAL_MESSAGE,
268 new ActionMessage(Constants.MSG_TRANSACTION_TOKEN));
269 }
270
271 resetToken(request);
272 }
273
274
275
276 /**
277 * <p>
278 * Retrieve the User object to edit or null if the User does not exist,
279 * and set an transactional token to later detect multiple Save commands.
280 * </p>
281 *
282 * @param mapping Our ActionMapping
283 * @param form Our ActionForm
284 * @param request Our HttpServletRequest
285 * @param response Our HttpServletResponse
286 * @return The "Success" result for this mapping
287 * @throws Exception on any error
288 */
289 public ActionForward Edit(
290 ActionMapping mapping,
291 ActionForm form,
292 HttpServletRequest request,
293 HttpServletResponse response)
294 throws Exception {
295
296 final String method = Constants.EDIT;
297 doLogProcess(mapping, method);
298
299 HttpSession session = request.getSession();
300 User user = doGetUser(session);
301 boolean updating = (user != null);
302 if (updating) {
303 doPopulate(form, user);
304 }
305
306 doSaveToken(request);
307 return doFindSuccess(mapping);
308 }
309
310 /**
311 * <p>
312 * Insert or update a User object to the persistent store.
313 * </p><p>
314 * If a User is not logged in,
315 * then a new User is created and automatically logged in.
316 * Otherwise, the existing User is updated.
317 * </p>
318 *
319 * @param mapping Our ActionMapping
320 * @param form Our ActionForm
321 * @param request Our HttpServletRequest
322 * @param response Our HttpServletResponse
323 * @return The "Success" result for this mapping
324 * @throws Exception on any error
325 */
326 public ActionForward Save(
327 ActionMapping mapping,
328 ActionForm form,
329 HttpServletRequest request,
330 HttpServletResponse response)
331 throws Exception {
332
333 final String method = Constants.SAVE;
334 doLogProcess(mapping, method);
335
336 HttpSession session = request.getSession();
337 if (isCancelled(request)) {
338 doCancel(session, method, Constants.SUBSCRIPTION_KEY);
339 return doFindSuccess(mapping);
340 }
341
342 ActionMessages errors = new ActionMessages();
343 doValidateToken(request, errors);
344
345 if (!errors.isEmpty()) {
346 return doInputForward(mapping, request, errors);
347 }
348
349 User user = doGetUser(session);
350 if (user == null) {
351 user = doCreateUser(form, request, errors);
352 if (!errors.isEmpty()) {
353 return doInputForward(mapping, request, errors);
354 }
355 }
356
357 doPopulate(user, form);
358 doSaveUser(user);
359
360 return doFindSuccess(mapping);
361 }
362
363 }