View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    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      // --- Public Constants --
    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      // ---- Private Methods ----
    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         // Log the user in
    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     // ----- Public Methods ----
    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 }