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