001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.struts.apps.mailreader.actions;
018:
019: import org.apache.commons.beanutils.PropertyUtils;
020: import org.apache.struts.action.ActionForm;
021: import org.apache.struts.action.ActionForward;
022: import org.apache.struts.action.ActionMapping;
023: import org.apache.struts.action.ActionMessage;
024: import org.apache.struts.action.ActionMessages;
025: import org.apache.struts.action.DynaActionForm;
026: import org.apache.struts.apps.mailreader.Constants;
027: import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
028: import org.apache.struts.apps.mailreader.dao.User;
029: import org.apache.struts.apps.mailreader.dao.UserDatabase;
030:
031: import javax.servlet.ServletException;
032: import javax.servlet.http.HttpServletRequest;
033: import javax.servlet.http.HttpServletResponse;
034: import javax.servlet.http.HttpSession;
035: import java.lang.reflect.InvocationTargetException;
036:
037: /**
038: * <p>
039: * Provide an Edit method for retrieving an existing user,
040: * and a Save method for updating or inserting a user.
041: * </p><p>
042: * Both methods utilize a RegistrationForm to obtain or expose User details.
043: * If Save is used to create a user,
044: * additional validations ensure input is nominal.
045: * When a user is created,
046: * Save also handles the initial logon.
047: * </p>
048: */
049: public final class RegistrationAction extends BaseAction {
050:
051: // --- Public Constants --
052:
053: /**
054: * <p>
055: * Name of fromAddress field ["fromAddress"].
056: * </p>
057: */
058: public final static String FROM_ADDRESS = "fromAddress";
059:
060: /**
061: * <p>
062: * Name of fullName field ["fullName"].
063: * </p>
064: */
065: public final static String FULL_NAME = "fullName";
066:
067: /**
068: * <p>
069: * Name of password confirmation field ["password2"].
070: * </p>
071: */
072: public final static String PASSWORD2 = "password2";
073:
074: /**
075: * <p>
076: * Name of replyToAddress field ["replyToAddress"].
077: * </p>
078: */
079: public final static String REPLY_TO_ADDRESS = "replyToAddress";
080:
081: // ---- Private Methods ----
082:
083: /**
084: * <p>
085: * The message prefix to use when populating a Registration Form.
086: * </p>
087: */
088: final String LOG_REGISTRATION_POPULATE = "RegistrationForm.populate";
089:
090: /**
091: * <p>
092: * Helper method to post error message when user already exists.
093: * </p>
094: *
095: * @param username Existing username
096: * @param errors Our ActionMessages collection
097: */
098: private void errorUsernameUnique(String username,
099: ActionMessages errors) {
100: errors.add(USERNAME,
101: new org.apache.struts.action.ActionMessage(
102: "error.username.unique", username));
103: }
104:
105: /**
106: * <p>
107: * Verify input for creating a new user,
108: * create the user, and process the login.
109: * </p>
110: *
111: * @param form The input form
112: * @param request The HttpRequest being served
113: * @param errors The ActionMessages collection for any errors
114: * @return A new User and empty Errors if create succeeds,
115: * or null and Errors if create fails
116: */
117: private User doCreateUser(ActionForm form,
118: HttpServletRequest request, ActionMessages errors) {
119:
120: if (log.isTraceEnabled()) {
121: log.trace(" Perform additional validations on Create");
122: }
123:
124: UserDatabase database = doGetUserDatabase();
125: String username = doGet(form, USERNAME);
126: try {
127: if (database.findUser(username) != null) {
128: errorUsernameUnique(username, errors);
129: }
130: } catch (ExpiredPasswordException e) {
131: errorUsernameUnique(username, errors);
132: errors.add("errors.literal", new ActionMessage(e
133: .getMessage()));
134: }
135:
136: String password = doGet(form, PASSWORD);
137: if ((password == null) || (password.length() < 1)) {
138: errors.add(PASSWORD, new ActionMessage(
139: "error.password.required"));
140:
141: String password2 = doGet(form, PASSWORD2);
142: if ((password2 == null) || (password2.length() < 1)) {
143: errors.add(PASSWORD2, new ActionMessage(
144: "error.password2.required"));
145: }
146: }
147:
148: if (!errors.isEmpty()) {
149: return null;
150: }
151:
152: User user = database.createUser(username);
153:
154: // Log the user in
155: HttpSession session = request.getSession();
156: session.setAttribute(Constants.USER_KEY, user);
157: if (log.isTraceEnabled()) {
158: log.trace(" User: '" + user.getUsername()
159: + "' logged on in session: " + session.getId());
160: }
161:
162: return user;
163: }
164:
165: /**
166: * <p>
167: * Helper method to populate the input form from the User object.
168: * </p>
169: *
170: * @param form Form with incoming values
171: * @param user User object to populate
172: * @throws ServletException On any error
173: */
174: private void doPopulate(ActionForm form, User user)
175: throws ServletException {
176:
177: final String title = Constants.EDIT;
178:
179: if (log.isTraceEnabled()) {
180: log.trace(Constants.LOG_POPULATE_FORM + user);
181: }
182:
183: try {
184: PropertyUtils.copyProperties(form, user);
185: DynaActionForm dyna = (DynaActionForm) form;
186: dyna.set(TASK, title);
187: dyna.set(PASSWORD, null);
188: dyna.set(PASSWORD2, null);
189: } catch (InvocationTargetException e) {
190: Throwable t = e.getTargetException();
191: if (t == null) {
192: t = e;
193: }
194: log.error(LOG_REGISTRATION_POPULATE, t);
195: throw new ServletException(LOG_REGISTRATION_POPULATE, t);
196: } catch (Throwable t) {
197: log.error(LOG_REGISTRATION_POPULATE, t);
198: throw new ServletException(LOG_REGISTRATION_POPULATE, t);
199: }
200: }
201:
202: /**
203: * <p>
204: * Helper method to populate the User object from the input form.
205: * </p>
206: *
207: * @param user User object to populate
208: * @param form Form with incoming values
209: * @throws ServletException On any error
210: */
211: private void doPopulate(User user, ActionForm form)
212: throws ServletException {
213:
214: if (log.isTraceEnabled()) {
215: log.trace(Constants.LOG_POPULATE_USER + user);
216: }
217:
218: try {
219: String oldPassword = user.getPassword();
220: PropertyUtils.copyProperties(user, form);
221: String password = doGet(form, PASSWORD);
222: if ((password == null) || (password.length() < 1)) {
223:
224: user.setPassword(oldPassword);
225: }
226:
227: } catch (InvocationTargetException e) {
228: Throwable t = e.getTargetException();
229: if (t == null) {
230: t = e;
231: }
232:
233: log.error(LOG_REGISTRATION_POPULATE, t);
234: throw new ServletException(LOG_REGISTRATION_POPULATE, t);
235:
236: } catch (Throwable t) {
237: log.error(LOG_REGISTRATION_POPULATE, t);
238: throw new ServletException(LOG_REGISTRATION_POPULATE, t);
239: }
240: }
241:
242: /**
243: * <p>
244: * Validate and clear the transactional token,
245: * creating logging statements as needed.
246: * </p>
247: *
248: * @param request Our HttpServletRequest
249: * @param errors ActionErrors to transfer any messages
250: */
251: private void doValidateToken(HttpServletRequest request,
252: ActionMessages errors) {
253:
254: if (log.isTraceEnabled()) {
255: log.trace(Constants.LOG_TOKEN_CHECK);
256: }
257:
258: if (!isTokenValid(request)) {
259: errors.add(ActionMessages.GLOBAL_MESSAGE,
260: new ActionMessage(Constants.MSG_TRANSACTION_TOKEN));
261: }
262:
263: resetToken(request);
264: }
265:
266: // ----- Public Methods ----
267:
268: /**
269: * <p>
270: * Retrieve the User object to edit or null if the User does not exist,
271: * and set an transactional token to later detect multiple Save commands.
272: * </p>
273: *
274: * @param mapping Our ActionMapping
275: * @param form Our ActionForm
276: * @param request Our HttpServletRequest
277: * @param response Our HttpServletResponse
278: * @return The "Success" result for this mapping
279: * @throws Exception on any error
280: */
281: public ActionForward Edit(ActionMapping mapping, ActionForm form,
282: HttpServletRequest request, HttpServletResponse response)
283: throws Exception {
284:
285: final String method = Constants.EDIT;
286: doLogProcess(mapping, method);
287:
288: HttpSession session = request.getSession();
289: User user = doGetUser(session);
290: boolean updating = (user != null);
291: if (updating) {
292: doPopulate(form, user);
293: }
294:
295: doSaveToken(request);
296: return doFindSuccess(mapping);
297: }
298:
299: /**
300: * <p>
301: * Insert or update a User object to the persistent store.
302: * </p><p>
303: * If a User is not logged in,
304: * then a new User is created and automatically logged in.
305: * Otherwise, the existing User is updated.
306: * </p>
307: *
308: * @param mapping Our ActionMapping
309: * @param form Our ActionForm
310: * @param request Our HttpServletRequest
311: * @param response Our HttpServletResponse
312: * @return The "Success" result for this mapping
313: * @throws Exception on any error
314: */
315: public ActionForward Save(ActionMapping mapping, ActionForm form,
316: HttpServletRequest request, HttpServletResponse response)
317: throws Exception {
318:
319: final String method = Constants.SAVE;
320: doLogProcess(mapping, method);
321:
322: HttpSession session = request.getSession();
323: if (isCancelled(request)) {
324: doCancel(session, method, Constants.SUBSCRIPTION_KEY);
325: return doFindSuccess(mapping);
326: }
327:
328: ActionMessages errors = new ActionMessages();
329: doValidateToken(request, errors);
330:
331: if (!errors.isEmpty()) {
332: return doInputForward(mapping, request, errors);
333: }
334:
335: User user = doGetUser(session);
336: if (user == null) {
337: user = doCreateUser(form, request, errors);
338: if (!errors.isEmpty()) {
339: return doInputForward(mapping, request, errors);
340: }
341: }
342:
343: doPopulate(user, form);
344: doSaveUser(user);
345:
346: return doFindSuccess(mapping);
347: }
348:
349: }
|