Coverage Report - org.kuali.rice.krad.web.struts.action.KualiRequestProcessor
 
Classes in this File Line Coverage Branch Coverage Complexity
KualiRequestProcessor
0%
0/259
0%
0/168
7.579
KualiRequestProcessor$1
0%
0/27
0%
0/8
7.579
KualiRequestProcessor$WrappedRuntimeException
0%
0/2
N/A
7.579
 
 1  
 /*
 2  
  * Copyright 2005-2007 The Kuali Foundation
 3  
  * 
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License"); you may not use this file except in
 5  
  * compliance with the License. You may obtain a copy of the License at
 6  
  * 
 7  
  * http://www.opensource.org/licenses/ecl2.php
 8  
  * 
 9  
  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS
 10  
  * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
 11  
  * language governing permissions and limitations under the License.
 12  
  */
 13  
 package org.kuali.rice.krad.web.struts.action;
 14  
 
 15  
 import org.apache.commons.lang.StringUtils;
 16  
 import org.apache.log4j.Logger;
 17  
 import org.apache.log4j.MDC;
 18  
 import org.apache.ojb.broker.OptimisticLockException;
 19  
 import org.apache.struts.Globals;
 20  
 import org.apache.struts.action.*;
 21  
 import org.apache.struts.config.FormBeanConfig;
 22  
 import org.apache.struts.config.ForwardConfig;
 23  
 import org.apache.struts.util.RequestUtils;
 24  
 import org.kuali.rice.core.util.RiceConstants;
 25  
 import org.kuali.rice.core.util.RiceKeyConstants;
 26  
 import org.kuali.rice.krad.UserSession;
 27  
 import org.kuali.rice.krad.document.Document;
 28  
 import org.kuali.rice.krad.exception.FileUploadLimitExceededException;
 29  
 import org.kuali.rice.krad.exception.ValidationException;
 30  
 import org.kuali.rice.krad.service.KRADServiceLocatorInternal;
 31  
 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
 32  
 import org.kuali.rice.krad.service.SessionDocumentService;
 33  
 import org.kuali.rice.krad.util.*;
 34  
 import org.kuali.rice.krad.web.EditablePropertiesHistoryHolder;
 35  
 import org.kuali.rice.krad.web.struts.form.KualiDocumentFormBase;
 36  
 import org.kuali.rice.krad.web.struts.form.KualiForm;
 37  
 import org.kuali.rice.krad.web.struts.pojo.PojoForm;
 38  
 import org.springframework.transaction.PlatformTransactionManager;
 39  
 import org.springframework.transaction.TransactionStatus;
 40  
 import org.springframework.transaction.support.TransactionCallback;
 41  
 import org.springframework.transaction.support.TransactionTemplate;
 42  
 import org.springmodules.orm.ojb.OjbOperationException;
 43  
 
 44  
 import javax.servlet.ServletException;
 45  
 import javax.servlet.http.HttpServletRequest;
 46  
 import javax.servlet.http.HttpServletResponse;
 47  
 import javax.servlet.http.HttpSession;
 48  
 import java.io.IOException;
 49  
 
 50  
 /**
 51  
  * This class handles setup of user session and restoring of action form.
 52  
  * 
 53  
  * 
 54  
  */
 55  0
 public class KualiRequestProcessor extends RequestProcessor {
 56  
         
 57  
         private static final String MDC_DOC_ID = "docId";
 58  
         private static final String PREVIOUS_REQUEST_EDITABLE_PROPERTIES_GUID_PARAMETER_NAME = "actionEditablePropertiesGuid";
 59  
 
 60  0
         private static Logger LOG = Logger.getLogger(KualiRequestProcessor.class);
 61  
 
 62  
         private SessionDocumentService sessionDocumentService;
 63  
         private PlatformTransactionManager transactionManager;
 64  
         
 65  
         @Override
 66  
         public void process(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
 67  0
                 if ( LOG.isInfoEnabled() ) {
 68  0
                         LOG.info(new StringBuffer("Started processing request: '").append(request.getRequestURI()).append("' w/ query string: '").append(request.getQueryString()).append("'"));
 69  
                 }
 70  
 
 71  
                 try { 
 72  0
                         strutsProcess(request, response);
 73  0
                 } catch (FileUploadLimitExceededException e) {
 74  0
                         ActionForward actionForward = processException(request, response, e, e.getActionForm(), e.getActionMapping());
 75  0
                         processForwardConfig(request, response, actionForward);
 76  
                 } finally {
 77  0
                         GlobalVariables.setKualiForm(null);
 78  0
                 }
 79  
                         
 80  
                 try {
 81  0
                         ActionForm form = WebUtils.getKualiForm(request);
 82  
                         
 83  0
                         if (form != null && form instanceof KualiDocumentFormBase) {
 84  0
                                 String docId = ((KualiDocumentFormBase) form).getDocId();
 85  0
                                 if (docId != null) { MDC.put(MDC_DOC_ID, docId); }
 86  
                         }
 87  
 
 88  0
                         String refreshCaller = request.getParameter(KRADConstants.REFRESH_CALLER);
 89  0
                         if (form!=null && KualiDocumentFormBase.class.isAssignableFrom(form.getClass()) 
 90  
                                         && !KRADConstants.QUESTION_REFRESH.equalsIgnoreCase(refreshCaller)) {
 91  0
                                 KualiDocumentFormBase docForm = (KualiDocumentFormBase) form;
 92  0
                                 Document document = docForm.getDocument();
 93  0
                                 String docFormKey = docForm.getFormKey();
 94  
 
 95  0
                                 UserSession userSession = (UserSession) request.getSession().getAttribute(KRADConstants.USER_SESSION_KEY);
 96  
 
 97  0
                                 if (WebUtils.isDocumentSession(document, docForm)) {
 98  0
                                         getSessionDocumentService().setDocumentForm(docForm, userSession, request.getRemoteAddr());
 99  
                                 }
 100  
 
 101  0
                                 Boolean exitingDocument = (Boolean) request.getAttribute(KRADConstants.EXITING_DOCUMENT);
 102  
 
 103  0
                                 if (exitingDocument != null && exitingDocument.booleanValue()) {
 104  
                                         // remove KualiDocumentFormBase object from session and
 105  
                                         // table.
 106  0
                                         getSessionDocumentService().purgeDocumentForm(docForm.getDocument().getDocumentNumber(), docFormKey, userSession, request.getRemoteAddr());
 107  
                                 }
 108  
                         }
 109  
 
 110  0
                         if ( LOG.isInfoEnabled() ) {
 111  0
                                 LOG.info(new StringBuffer("Finished processing request: '").append(request.getRequestURI()).append("' w/ query string: '").append(request.getQueryString()).append("'"));
 112  
                         }
 113  
 
 114  
                 } finally {
 115  
                         // MDC docId key is set above, and also during super.process() in the call to processActionForm
 116  0
                         MDC.remove(MDC_DOC_ID);
 117  0
                 }
 118  
 
 119  0
         }
 120  
         
 121  
         @Override
 122  
         protected boolean processPreprocess(HttpServletRequest request, HttpServletResponse response) {
 123  0
         final UserSession session = WebUtils.getUserSessionFromRequest(request);
 124  
         
 125  0
         if (session == null) {
 126  0
                 throw new IllegalStateException("the user session has not been established");
 127  
         }
 128  0
             GlobalVariables.setUserSession(session);
 129  0
             GlobalVariables.clear();
 130  0
                 return true;
 131  
         }
 132  
         
 133  
         /**
 134  
      * <p>Process an <code>HttpServletRequest</code> and create the
 135  
      * corresponding <code>HttpServletResponse</code> or dispatch
 136  
      * to another resource.</p>
 137  
      *
 138  
      * @param request The servlet request we are processing
 139  
      * @param response The servlet response we are creating
 140  
      *
 141  
      * @exception IOException if an input/output error occurs
 142  
      * @exception ServletException if a processing exception occurs
 143  
      */
 144  
     public void strutsProcess(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
 145  
 
 146  
         // Wrap multipart requests with a special wrapper
 147  0
         request = processMultipart(request);
 148  
 
 149  
         // Identify the path component we will use to select a mapping
 150  0
         String path = processPath(request, response);
 151  0
         if (path == null) {
 152  0
             return;
 153  
         }
 154  
         
 155  0
         if (log.isDebugEnabled()) {
 156  0
             log.debug("Processing a '" + request.getMethod() +
 157  
                       "' for path '" + path + "'");
 158  
         }
 159  
 
 160  
         // Select a Locale for the current user if requested
 161  0
         processLocale(request, response);
 162  
 
 163  
         // Set the content type and no-caching headers if requested
 164  0
         processContent(request, response);
 165  0
         processNoCache(request, response);
 166  
 
 167  
         // General purpose preprocessing hook
 168  0
         if (!processPreprocess(request, response)) {
 169  0
             return;
 170  
         }
 171  
         
 172  0
         this.processCachedMessages(request, response);
 173  
 
 174  
         // Identify the mapping for this request
 175  0
         ActionMapping mapping = processMapping(request, response, path);
 176  0
         if (mapping == null) {
 177  0
             return;
 178  
         }
 179  
 
 180  
         // Check for any role required to perform this action
 181  0
         if (!processRoles(request, response, mapping)) {
 182  0
             return;
 183  
         }
 184  
 
 185  0
         processFormActionAndForward(request, response, mapping);
 186  
 
 187  0
     }
 188  
     
 189  
     public void processFormActionAndForward(final HttpServletRequest request, final HttpServletResponse response, final ActionMapping mapping) throws ServletException, IOException {
 190  0
             TransactionTemplate template = new TransactionTemplate(getTransactionManager());
 191  
             try {
 192  0
                         template.execute(new TransactionCallback() {
 193  
                                 @Override
 194  
                                 public Object doInTransaction(TransactionStatus status) {
 195  
                                         try {
 196  
                                                 // Process any ActionForm bean related to this request
 197  0
                                         ActionForm form = processActionForm(request, response, mapping);
 198  0
                                         processPopulate(request, response, form, mapping);
 199  
                                         
 200  
                                         // Validate any fields of the ActionForm bean, if applicable
 201  
                                         try {
 202  0
                                             if (!processValidate(request, response, form, mapping)) {
 203  0
                                                 return null;
 204  
                                             }
 205  0
                                         } catch (InvalidCancelException e) {
 206  0
                                             ActionForward forward = processException(request, response, e, form, mapping);
 207  0
                                             processForwardConfig(request, response, forward);
 208  0
                                             return null;
 209  0
                                         } catch (IOException e) {
 210  0
                                             throw e;
 211  0
                                         } catch (ServletException e) {
 212  0
                                             throw e;
 213  0
                                         }
 214  
                                             
 215  
                                         // Process a forward or include specified by this mapping
 216  0
                                         if (!processForward(request, response, mapping)) {
 217  0
                                             return null;
 218  
                                         }
 219  
                                         
 220  0
                                         if (!processInclude(request, response, mapping)) {
 221  0
                                             return null;
 222  
                                         }
 223  
 
 224  
                                         // Create or acquire the Action instance to process this request
 225  0
                                         Action action = processActionCreate(request, response, mapping);
 226  0
                                         if (action == null) {
 227  0
                                             return null;
 228  
                                         }
 229  
                                                 
 230  
                                             // Call the Action instance itself
 231  0
                                         ActionForward forward = processActionPerform(request, response, action, form, mapping);
 232  
                                 
 233  
                                         // Process the returned ActionForward instance
 234  0
                                         processForwardConfig(request, response, forward);
 235  0
                                         } catch (Exception e) {
 236  
                                                 // the doInTransaction method has no means for
 237  
                                                 // throwing exceptions, so we will wrap the
 238  
                                                 // exception in
 239  
                                                 // a RuntimeException and re-throw. The one caveat
 240  
                                                 // here is that this will always result in
 241  
                                                 // the
 242  
                                                 // transaction being rolled back (since
 243  
                                                 // WrappedRuntimeException is a runtime exception).
 244  0
                                                 throw new WrappedRuntimeException(e);
 245  0
                                         }
 246  0
                                         return null;
 247  
                                 }
 248  
                         });
 249  0
                 } catch (WrappedRuntimeException wre) {
 250  0
                         throw new RuntimeException(wre.getCause());
 251  0
                 }
 252  0
     }
 253  
 
 254  
 
 255  
         /**
 256  
          * This method gets the document number from the request.  The request should have been processed already 
 257  
          * before this is called if it is multipart.  
 258  
          * 
 259  
          * @param request
 260  
          * @return the document number, or null if one can't be found in the request.
 261  
          */
 262  
         private String getDocumentNumber(HttpServletRequest request) {
 263  0
                 String documentNumber = request.getParameter(KRADConstants.DOCUMENT_DOCUMENT_NUMBER);
 264  
 
 265  
                 // from lookup pages.
 266  0
                 if (documentNumber == null) {
 267  0
                         documentNumber = request.getParameter(KRADConstants.DOC_NUM);
 268  
                 }
 269  
                 
 270  0
                 if (documentNumber == null) {
 271  0
                         documentNumber = request.getParameter("documentId");
 272  
                 }
 273  
                 
 274  0
                 return documentNumber;
 275  
         }
 276  
 
 277  
         /**
 278  
          * Hooks into populate process to call form populate method if form is an
 279  
          * instanceof PojoForm.
 280  
          */
 281  
         @Override
 282  
         protected void processPopulate(HttpServletRequest request, HttpServletResponse response, ActionForm form, ActionMapping mapping) throws ServletException {
 283  0
                 if (form instanceof KualiForm) {
 284  
                         // Add the ActionForm to GlobalVariables
 285  
                         // This will allow developers to retrieve both the Document and any
 286  
                         // request parameters that are not
 287  
                         // part of the Form and make them available in ValueFinder classes
 288  
                         // and other places where they are needed.
 289  0
                         GlobalVariables.setKualiForm((KualiForm) form);
 290  
                 }
 291  
 
 292  
                 // if not PojoForm, call struts populate
 293  0
                 if (!(form instanceof PojoForm)) {
 294  0
                         super.processPopulate(request, response, form, mapping);
 295  0
                         return;
 296  
                 }
 297  
                 
 298  0
                 final String previousRequestGuid = request.getParameter(KualiRequestProcessor.PREVIOUS_REQUEST_EDITABLE_PROPERTIES_GUID_PARAMETER_NAME);
 299  
 
 300  0
                 ((PojoForm)form).clearEditablePropertyInformation();
 301  0
                 ((PojoForm)form).registerStrutsActionMappingScope(mapping.getScope());
 302  
                 
 303  0
                 String multipart = mapping.getMultipartClass();
 304  0
                 if (multipart != null) {
 305  0
                         request.setAttribute(Globals.MULTIPART_KEY, multipart);
 306  
                 }
 307  
 
 308  0
                 form.setServlet(this.servlet);
 309  0
                 form.reset(mapping, request);
 310  
 
 311  0
                 ((PojoForm)form).setPopulateEditablePropertiesGuid(previousRequestGuid);
 312  
                 // call populate on ActionForm
 313  0
                 ((PojoForm) form).populate(request);
 314  0
                 request.setAttribute("UnconvertedValues", ((PojoForm) form).getUnconvertedValues().keySet());
 315  0
                 request.setAttribute("UnconvertedHash", ((PojoForm) form).getUnconvertedValues());
 316  0
         }
 317  
 
 318  
         /**
 319  
          * Hooks into validate to catch any errors from the populate, and translate
 320  
          * the ErrorMap to ActionMessages.
 321  
          */
 322  
         @Override
 323  
         protected boolean processValidate(HttpServletRequest request, HttpServletResponse response, ActionForm form, ActionMapping mapping) throws IOException, ServletException, InvalidCancelException {
 324  
 
 325  
                 // skip form validate if we had errors from populate
 326  0
                 if (GlobalVariables.getMessageMap().hasNoErrors()) {
 327  0
                         if (form == null) {
 328  0
                                 return (true);
 329  
                         }
 330  
                         // Was this request cancelled?
 331  0
                         if (request.getAttribute(Globals.CANCEL_KEY) != null) {
 332  0
                                 if (LOG.isDebugEnabled()) {
 333  0
                                         LOG.debug(" Cancelled transaction, skipping validation");
 334  
                                 }
 335  0
                                 return (true);
 336  
                         }
 337  
 
 338  
                         // Has validation been turned off for this mapping?
 339  0
                         if (!mapping.getValidate()) {
 340  0
                                 return (true);
 341  
                         }
 342  
 
 343  
                         // call super to call forms validate
 344  0
                         super.processValidate(request, response, form, mapping);
 345  
                 }
 346  
 
 347  0
                 publishMessages(request);
 348  0
                 if (!GlobalVariables.getMessageMap().hasNoErrors()) {
 349  
                         // Special handling for multipart request
 350  0
                         if (form.getMultipartRequestHandler() != null) {
 351  0
                                 if (LOG.isDebugEnabled()) {
 352  0
                                         LOG.debug("  Rolling back multipart request");
 353  
                                 }
 354  0
                                 form.getMultipartRequestHandler().rollback();
 355  
                         }
 356  
 
 357  
                         // Fix state that could be incorrect because of validation failure
 358  0
                         if (form instanceof PojoForm) {
 359  0
                                 ((PojoForm) form).processValidationFail();
 360  
                         }
 361  
 
 362  
                         // Was an input path (or forward) specified for this mapping?
 363  0
                         String input = mapping.getInput();
 364  0
                         if (input == null) {
 365  0
                                 if (LOG.isDebugEnabled()) {
 366  0
                                         LOG.debug("  Validation failed but no input form available");
 367  
                                 }
 368  0
                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, getInternal().getMessage("noInput", mapping.getPath()));
 369  0
                                 return (false);
 370  
                         }
 371  
 
 372  0
                         if (moduleConfig.getControllerConfig().getInputForward()) {
 373  0
                                 ForwardConfig forward = mapping.findForward(input);
 374  0
                                 processForwardConfig(request, response, forward);
 375  0
                         } else {
 376  0
                                 internalModuleRelativeForward(input, request, response);
 377  
                         }
 378  
 
 379  0
                         return (false);
 380  
                 }
 381  0
                 return true;
 382  
         }
 383  
 
 384  
         /**
 385  
          * Checks for return from a lookup or question, and restores the action form
 386  
          * stored under the request parameter docFormKey.
 387  
          */
 388  
         @Override
 389  
         protected ActionForm processActionForm(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) {
 390  
                 
 391  0
                 String documentNumber = getDocumentNumber(request);
 392  0
                 if (documentNumber != null) { MDC.put(MDC_DOC_ID, documentNumber); }
 393  
                 
 394  0
                 UserSession userSession = (UserSession) request.getSession().getAttribute(KRADConstants.USER_SESSION_KEY);
 395  
 
 396  0
                 String docFormKey = request.getParameter(KRADConstants.DOC_FORM_KEY);
 397  0
                 String methodToCall = request.getParameter(KRADConstants.DISPATCH_REQUEST_PARAMETER);
 398  0
                 String refreshCaller = request.getParameter(KRADConstants.REFRESH_CALLER);
 399  
 //                String searchListRequestKey = request.getParameter(KRADConstants.SEARCH_LIST_REQUEST_KEY);
 400  0
                 String documentWebScope = request.getParameter(KRADConstants.DOCUMENT_WEB_SCOPE);
 401  
 
 402  0
                 if (mapping.getPath().startsWith(KRADConstants.REFRESH_MAPPING_PREFIX) || KRADConstants.RETURN_METHOD_TO_CALL.equalsIgnoreCase(methodToCall) ||
 403  
                                 KRADConstants.QUESTION_REFRESH.equalsIgnoreCase(refreshCaller) || KRADConstants.TEXT_AREA_REFRESH.equalsIgnoreCase(refreshCaller) || KRADConstants
 404  
                 .SESSION_SCOPE.equalsIgnoreCase(documentWebScope)) {
 405  0
                         ActionForm form = null;
 406  
                         // check for search result storage and clear
 407  0
                         GlobalVariables.getUserSession().removeObjectsByPrefix(KRADConstants.SEARCH_LIST_KEY_PREFIX);
 408  
 
 409  
                         // We put different type of forms such as document form, lookup form
 410  
                         // in session but we only store document form in
 411  
                         // database.
 412  0
                         if (userSession.retrieveObject(docFormKey) != null) {
 413  0
                                 LOG.debug("getDecomentForm KualiDocumentFormBase from session");
 414  0
                                 form = (ActionForm) userSession.retrieveObject(docFormKey);
 415  0
                         } else if (StringUtils.isNotBlank(documentNumber)) {
 416  0
                                 form = getSessionDocumentService().getDocumentForm(documentNumber, docFormKey, userSession, request.getRemoteAddr());
 417  
                         }
 418  0
                         request.setAttribute(mapping.getAttribute(), form);
 419  0
                         if (!KRADConstants.SESSION_SCOPE.equalsIgnoreCase(documentWebScope)) {
 420  0
                                 userSession.removeObject(docFormKey);
 421  
                         }
 422  
                         // we should check whether this is a multipart request because we
 423  
                         // could have had a combination of query parameters and a multipart
 424  
                         // request
 425  0
                         String contentType = request.getContentType();
 426  0
                         String method = request.getMethod();
 427  0
                         if (("POST".equalsIgnoreCase(method) && contentType != null && contentType.startsWith("multipart/form-data"))) {
 428  
                                 // this method parses the multipart request and adds new
 429  
                                 // non-file parameters into the request
 430  0
                                 WebUtils.getMultipartParameters(request, null, form, mapping);
 431  
                         }
 432  
                         // The form can be null if the document is not a session document
 433  0
                         if (form != null) {
 434  0
                                 return form;
 435  
                         }
 436  
                 }
 437  
 
 438  
                 // Rice has the ability to limit file upload sizes on a per-form basis,
 439  
                 // so the max upload sizes may be accessed by calling methods on
 440  
                 // PojoFormBase.
 441  
                 // This requires that we are able know the file upload size limit (i.e.
 442  
                 // retrieve a form instance) before we parse a mulitpart request.
 443  0
                 ActionForm form = super.processActionForm(request, response, mapping);
 444  
 
 445  
                 // for sessiondocument with multipart request
 446  0
                 String contentType = request.getContentType();
 447  0
                 String method = request.getMethod();
 448  
 
 449  0
                 if ("GET".equalsIgnoreCase(method) && StringUtils.isNotBlank(methodToCall) && form instanceof PojoForm &&
 450  
                                 ((PojoForm) form).getMethodToCallsToBypassSessionRetrievalForGETRequests().contains(methodToCall)) {
 451  0
                         return createNewActionForm(mapping, request);
 452  
                 }
 453  
                 
 454  
                 // if we have a multipart request, parse it and return the stored form
 455  
                 // from session if the doc form key is not blank. If it is blank, then
 456  
                 // we just return the form
 457  
                 // generated from the superclass processActionForm method. Either way,
 458  
                 // we need to parse the mulitpart request now so that we may determine
 459  
                 // what the value of the doc form key is.
 460  
                 // This is generally against the contract of processActionForm, because
 461  
                 // processPopulate should be responsible for parsing the mulitpart
 462  
                 // request, but we need to parse it now
 463  
                 // to determine the doc form key value.
 464  0
                 if (("POST".equalsIgnoreCase(method) && contentType != null && contentType.startsWith("multipart/form-data"))) {
 465  0
                         WebUtils.getMultipartParameters(request, null, form, mapping);
 466  0
                         docFormKey = request.getParameter(KRADConstants.DOC_FORM_KEY);
 467  0
                         documentWebScope = request.getParameter(KRADConstants.DOCUMENT_WEB_SCOPE);
 468  
 
 469  0
                         documentNumber = getDocumentNumber(request);
 470  
 
 471  0
                         if (KRADConstants.SESSION_SCOPE.equalsIgnoreCase(documentWebScope) ||
 472  
                                         (form instanceof KualiDocumentFormBase && WebUtils.isDocumentSession(((KualiDocumentFormBase) form).getDocument(), (KualiDocumentFormBase) form))) {
 473  
 
 474  0
                                 Object userSessionObject = userSession.retrieveObject(docFormKey);
 475  0
                                 if ( userSessionObject != null &&  userSessionObject instanceof ActionForm ) {
 476  0
                                         LOG.debug("getDocumentForm KualiDocumentFormBase from session");
 477  0
                                         form = (ActionForm) userSessionObject;
 478  
                                 } else {
 479  0
                                         ActionForm tempForm = getSessionDocumentService().getDocumentForm(documentNumber, docFormKey, userSession, request.getRemoteAddr());
 480  0
                                         if ( tempForm != null ) {
 481  0
                                                 form = tempForm;
 482  
                                         }
 483  
                                 }
 484  
 
 485  0
                                 request.setAttribute(mapping.getAttribute(), form);
 486  0
                                 if (form != null) {
 487  0
                                         return form;
 488  
                                 }
 489  
                         }
 490  
                 }
 491  0
                 return form;
 492  
         }
 493  
 
 494  
         /**
 495  
          * Hook into action perform to handle errors in the error map and catch
 496  
          * exceptions.
 497  
          * 
 498  
          * <p>
 499  
          * A transaction is started prior to the execution of the action. This
 500  
          * allows for the action code to execute efficiently without the need for
 501  
          * using PROPAGATION_SUPPORTS in the transaction definitions. The
 502  
          * PROPAGATION_SUPPORTS propagation type does not work well with JTA.
 503  
          */
 504  
         @Override
 505  
         protected ActionForward processActionPerform(final HttpServletRequest request, final HttpServletResponse response, final Action action, final ActionForm form, final ActionMapping mapping) throws IOException, ServletException {
 506  
                 try {
 507  
                         
 508  0
                         ActionForward forward = action.execute(mapping, form, request, response);
 509  
 
 510  0
                         publishMessages(request);
 511  0
                         saveMessages(request);
 512  0
                         saveAuditErrors(request);
 513  
                         
 514  0
                         if (form instanceof PojoForm) {
 515  0
                                 if (((PojoForm)form).getEditableProperties() == null 
 516  
                                                 || ((PojoForm)form).getEditableProperties().isEmpty()) {
 517  0
                                         EditablePropertiesHistoryHolder holder = (EditablePropertiesHistoryHolder) GlobalVariables.getUserSession().getObjectMap().get(
 518  
                             KRADConstants.EDITABLE_PROPERTIES_HISTORY_HOLDER_ATTR_NAME);
 519  0
                                     if (holder == null) {
 520  0
                                             holder = new EditablePropertiesHistoryHolder();
 521  
                                     }
 522  
                                         
 523  0
                                         final String guid = holder.addEditablePropertiesToHistory(((PojoForm)form).getEditableProperties());
 524  0
                                     ((PojoForm)form).setActionEditablePropertiesGuid(guid);
 525  0
                                     GlobalVariables.getUserSession().addObject(KRADConstants.EDITABLE_PROPERTIES_HISTORY_HOLDER_ATTR_NAME, holder);
 526  
                                 }
 527  
                         }
 528  
                         
 529  0
                         return forward;
 530  
 
 531  0
                 } catch (Exception e) {
 532  0
                         if (e instanceof WrappedRuntimeException) {
 533  0
                                 e = (Exception) e.getCause();
 534  
                         }
 535  0
                         if (e instanceof ValidationException) {
 536  
                                 // add a generic error message if there are none
 537  0
                                 if (GlobalVariables.getMessageMap().hasNoErrors()) {
 538  
 
 539  0
                                         GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS, RiceKeyConstants.ERROR_CUSTOM, e.getMessage());
 540  
                                 }
 541  
 
 542  0
                                 if (form instanceof PojoForm) {
 543  0
                                         if (((PojoForm)form).getEditableProperties() == null 
 544  
                                                         || ((PojoForm)form).getEditableProperties().isEmpty()) {
 545  0
                                             EditablePropertiesHistoryHolder holder = (EditablePropertiesHistoryHolder) GlobalVariables.getUserSession().getObjectMap().get(
 546  
                                 KRADConstants.EDITABLE_PROPERTIES_HISTORY_HOLDER_ATTR_NAME);
 547  0
                                         if (holder == null) {
 548  0
                                                 holder = new EditablePropertiesHistoryHolder();
 549  
                                         }
 550  
 
 551  0
                                             final String guid = holder.addEditablePropertiesToHistory(((PojoForm)form).getEditableProperties());
 552  0
                                         ((PojoForm)form).setActionEditablePropertiesGuid(guid);
 553  0
                                         GlobalVariables.getUserSession().addObject(KRADConstants.EDITABLE_PROPERTIES_HISTORY_HOLDER_ATTR_NAME, holder);
 554  
                                         }
 555  
                                 }                        
 556  
                                 // display error messages and return to originating page
 557  0
                                 publishMessages(request);
 558  0
                                 return mapping.findForward(RiceConstants.MAPPING_BASIC);
 559  
                         }
 560  
 
 561  0
                         publishMessages(request);
 562  
 
 563  0
                         return (processException(request, response, e, form, mapping));
 564  
                 }
 565  
         }
 566  
 
 567  
         /**
 568  
          * Adds more detailed logging for unhandled exceptions
 569  
          * 
 570  
          * @see org.apache.struts.action.RequestProcessor#processException(HttpServletRequest,
 571  
          *      HttpServletResponse, Exception, ActionForm, ActionMapping)
 572  
          */
 573  
         @Override
 574  
         protected ActionForward processException(HttpServletRequest request, HttpServletResponse response, Exception exception, ActionForm form, ActionMapping mapping) throws IOException, ServletException {
 575  0
                 ActionForward actionForward = null;
 576  
 
 577  
                 try {
 578  0
                         actionForward = super.processException(request, response, exception, form, mapping);
 579  0
                 } catch (IOException e) {
 580  0
                         logException(e);
 581  0
                         throw e;
 582  0
                 } catch (ServletException e) {
 583  
                         // special case, to make OptimisticLockExceptions easier to read
 584  0
                         Throwable rootCause = e.getRootCause();
 585  0
                         if (rootCause instanceof OjbOperationException) {
 586  0
                                 OjbOperationException ooe = (OjbOperationException) rootCause;
 587  
 
 588  0
                                 Throwable subcause = ooe.getCause();
 589  0
                                 if (subcause instanceof OptimisticLockException) {
 590  0
                                         OptimisticLockException ole = (OptimisticLockException) subcause;
 591  
 
 592  0
                                         StringBuffer message = new StringBuffer(e.getMessage());
 593  
 
 594  0
                                         Object sourceObject = ole.getSourceObject();
 595  0
                                         if (sourceObject != null) {
 596  0
                                                 message.append(" (sourceObject is ");
 597  0
                                                 message.append(sourceObject.getClass().getName());
 598  0
                                                 message.append(")");
 599  
                                         }
 600  
 
 601  0
                                         e = new ServletException(message.toString(), rootCause);
 602  
                                 }
 603  
                         }
 604  
 
 605  0
                         logException(e);
 606  0
                         throw e;
 607  0
                 }
 608  0
                 return actionForward;
 609  
         }
 610  
 
 611  
         private void logException(Exception e) {
 612  0
                 LOG.error("unhandled exception thrown by KualiRequestProcessor.processActionPerform", e);
 613  0
         }
 614  
 
 615  
         /**
 616  
          * Checks for errors in the error map and transforms them to struts action
 617  
          * messages then stores in the request.
 618  
          */
 619  
         private void publishMessages(HttpServletRequest request) {
 620  0
                 MessageMap errorMap = GlobalVariables.getMessageMap();
 621  0
                 if (!errorMap.hasNoErrors()) {
 622  0
                         ErrorContainer errorContainer = new ErrorContainer(errorMap);
 623  
 
 624  0
                         request.setAttribute("ErrorContainer", errorContainer);
 625  0
                         request.setAttribute(Globals.ERROR_KEY, errorContainer.getRequestErrors());
 626  0
                         request.setAttribute("ErrorPropertyList", errorContainer.getErrorPropertyList());
 627  
                 }
 628  
                 
 629  0
                 if (errorMap.hasWarnings()) {
 630  0
                         WarningContainer warningsContainer = new WarningContainer(errorMap);
 631  
                         
 632  0
                         request.setAttribute("WarningContainer", warningsContainer);
 633  0
                         request.setAttribute("WarningActionMessages", warningsContainer.getRequestMessages());
 634  0
                         request.setAttribute("WarningPropertyList", warningsContainer.getMessagePropertyList());
 635  
                 }
 636  
                 
 637  0
                 if (errorMap.hasInfo()) {
 638  0
                         InfoContainer infoContainer = new InfoContainer(errorMap);
 639  
                         
 640  0
                         request.setAttribute("InfoContainer", infoContainer);
 641  0
                         request.setAttribute("InfoActionMessages", infoContainer.getRequestMessages());
 642  0
                         request.setAttribute("InfoPropertyList", infoContainer.getMessagePropertyList());
 643  
                 }
 644  0
         }
 645  
 
 646  
         /**
 647  
          * Checks for messages in GlobalVariables and places list in request
 648  
          * attribute.
 649  
          */
 650  
         private void saveMessages(HttpServletRequest request) {
 651  0
                 if (!GlobalVariables.getMessageList().isEmpty()) {
 652  0
                         request.setAttribute(KRADConstants.GLOBAL_MESSAGES, GlobalVariables.getMessageList().toActionMessages());
 653  
                 }
 654  0
         }
 655  
 
 656  
         /**
 657  
          * Checks for messages in GlobalVariables and places list in request
 658  
          * attribute.
 659  
          */
 660  
         private void saveAuditErrors(HttpServletRequest request) {
 661  0
                 if (!GlobalVariables.getAuditErrorMap().isEmpty()) {
 662  0
                         request.setAttribute(KRADConstants.AUDIT_ERRORS, GlobalVariables.getAuditErrorMap());
 663  
                 }
 664  0
         }
 665  
 
 666  
         /**
 667  
          * A simple exception that allows us to wrap an exception that is thrown out
 668  
          * of a transaction template.
 669  
          */
 670  0
         @SuppressWarnings("serial")
 671  
         private static class WrappedRuntimeException extends RuntimeException {
 672  
                 public WrappedRuntimeException(Exception e) {
 673  0
                         super(e);
 674  0
                 }
 675  
         }
 676  
 
 677  
         /**
 678  
          * @return the sessionDocumentService
 679  
          */
 680  
         public SessionDocumentService getSessionDocumentService() {
 681  0
                 if ( sessionDocumentService == null ) {
 682  0
                         sessionDocumentService = KRADServiceLocatorWeb.getSessionDocumentService();
 683  
                 }
 684  0
                 return this.sessionDocumentService;
 685  
         }
 686  
 
 687  
         /**
 688  
          * @return the transactionManager
 689  
          */
 690  
         public PlatformTransactionManager getTransactionManager() {
 691  0
                 if ( transactionManager == null ) {
 692  0
                         transactionManager = KRADServiceLocatorInternal.getTransactionManager();
 693  
                 }
 694  0
                 return this.transactionManager;
 695  
         }
 696  
         
 697  
         private ActionForm createNewActionForm(ActionMapping mapping, HttpServletRequest request) {
 698  0
         String name = mapping.getName();
 699  0
         FormBeanConfig config = moduleConfig.findFormBeanConfig(name);
 700  0
         if (config == null) {
 701  0
             log.warn("No FormBeanConfig found under '" + name + "'");
 702  0
             return (null);
 703  
         }
 704  0
         ActionForm instance = RequestUtils.createActionForm(config, servlet);
 705  0
         if ("request".equals(mapping.getScope())) {
 706  0
             request.setAttribute(mapping.getAttribute(), instance);
 707  
         } else {
 708  0
             HttpSession session = request.getSession();
 709  0
             session.setAttribute(mapping.getAttribute(), instance);
 710  
         }
 711  0
         return instance;
 712  
         }
 713  
 }