Coverage Report - org.kuali.rice.kns.web.struts.action.KualiRequestProcessor
 
Classes in this File Line Coverage Branch Coverage Complexity
KualiRequestProcessor
0%
0/292
0%
0/188
6
KualiRequestProcessor$1
0%
0/9
0%
0/2
6
KualiRequestProcessor$WrappedActionForwardRuntimeException
0%
0/4
N/A
6
KualiRequestProcessor$WrappedRuntimeException
0%
0/2
N/A
6
 
 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 java.io.IOException;
 16  
 
 17  
 import javax.servlet.ServletException;
 18  
 import javax.servlet.http.Cookie;
 19  
 import javax.servlet.http.HttpServletRequest;
 20  
 import javax.servlet.http.HttpServletResponse;
 21  
 import javax.servlet.http.HttpSession;
 22  
 
 23  
 import org.apache.commons.lang.StringUtils;
 24  
 import org.apache.log4j.Logger;
 25  
 import org.apache.log4j.MDC;
 26  
 import org.apache.ojb.broker.OptimisticLockException;
 27  
 import org.apache.struts.Globals;
 28  
 import org.apache.struts.action.Action;
 29  
 import org.apache.struts.action.ActionForm;
 30  
 import org.apache.struts.action.ActionForward;
 31  
 import org.apache.struts.action.ActionMapping;
 32  
 import org.apache.struts.action.InvalidCancelException;
 33  
 import org.apache.struts.action.RequestProcessor;
 34  
 import org.apache.struts.config.FormBeanConfig;
 35  
 import org.apache.struts.config.ForwardConfig;
 36  
 import org.apache.struts.util.RequestUtils;
 37  
 import org.kuali.rice.core.util.RiceConstants;
 38  
 import org.kuali.rice.kew.util.KEWConstants;
 39  
 import org.kuali.rice.kim.bo.entity.KimPrincipal;
 40  
 import org.kuali.rice.kim.bo.types.dto.AttributeSet;
 41  
 import org.kuali.rice.kim.service.IdentityManagementService;
 42  
 import org.kuali.rice.kim.service.KIMServiceLocator;
 43  
 import org.kuali.rice.kim.util.KimConstants;
 44  
 import org.kuali.rice.kns.UserSession;
 45  
 import org.kuali.rice.kns.document.Document;
 46  
 import org.kuali.rice.kns.exception.FileUploadLimitExceededException;
 47  
 import org.kuali.rice.kns.exception.ValidationException;
 48  
 import org.kuali.rice.kns.service.BusinessObjectService;
 49  
 import org.kuali.rice.kns.service.DataDictionaryService;
 50  
 import org.kuali.rice.kns.service.KNSServiceLocator;
 51  
 import org.kuali.rice.kns.service.SessionDocumentService;
 52  
 import org.kuali.rice.kns.util.ErrorContainer;
 53  
 import org.kuali.rice.kns.util.ExceptionUtils;
 54  
 import org.kuali.rice.kns.util.GlobalVariables;
 55  
 import org.kuali.rice.kns.util.Guid;
 56  
 import org.kuali.rice.kns.util.InfoContainer;
 57  
 import org.kuali.rice.kns.util.KNSConstants;
 58  
 import org.kuali.rice.kns.util.MessageMap;
 59  
 import org.kuali.rice.kns.util.RiceKeyConstants;
 60  
 import org.kuali.rice.kns.util.WarningContainer;
 61  
 import org.kuali.rice.kns.util.WebUtils;
 62  
 import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
 63  
 import org.kuali.rice.kns.web.struts.form.KualiForm;
 64  
 import org.kuali.rice.kns.web.struts.pojo.PojoForm;
 65  
 import org.springframework.transaction.PlatformTransactionManager;
 66  
 import org.springframework.transaction.TransactionStatus;
 67  
 import org.springframework.transaction.support.TransactionCallback;
 68  
 import org.springframework.transaction.support.TransactionTemplate;
 69  
 import org.springmodules.orm.ojb.OjbOperationException;
 70  
 
 71  
 /**
 72  
  * This class handles setup of user session and restoring of action form.
 73  
  * 
 74  
  * 
 75  
  */
 76  0
 public class KualiRequestProcessor extends RequestProcessor {
 77  
 
 78  
         private static final String MDC_USER_ALREADY_SET = "userAlreadySet";
 79  
 
 80  
         private static final String MDC_USER = "user";
 81  
 
 82  
         private static final String MDC_DOC_ID = "docId";
 83  
         
 84  
         private static final String PREVIOUS_REQUEST_EDITABLE_PROPERTIES_GUID_PARAMETER_NAME = "actionEditablePropertiesGuid";
 85  
 
 86  0
         private static Logger LOG = Logger.getLogger(KualiRequestProcessor.class);
 87  
 
 88  
         protected SessionDocumentService sessionDocumentService;
 89  
         protected DataDictionaryService dataDictionaryService;
 90  
         protected BusinessObjectService businessObjectService;
 91  
         protected PlatformTransactionManager transactionManager;
 92  
         protected IdentityManagementService identityManagementService;
 93  
         
 94  
         @Override
 95  
         public void process(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
 96  0
                 if ( LOG.isInfoEnabled() ) {
 97  0
                         LOG.info(new StringBuffer("Started processing request: '").append(request.getRequestURI()).append("' w/ query string: '").append(request.getQueryString()).append("'"));
 98  
                 }
 99  
 
 100  
                 try { 
 101  0
                         super.process(request, response);
 102  0
                 } catch (FileUploadLimitExceededException e) {
 103  0
                         ActionForward actionForward = processException(request, response, e, e.getActionForm(), e.getActionMapping());
 104  0
                         processForwardConfig(request, response, actionForward);
 105  0
                 } finally {
 106  0
                         GlobalVariables.setKualiForm(null);
 107  0
                 }
 108  
 
 109  
                 try {
 110  0
                         ActionForm form = WebUtils.getKualiForm(request);
 111  
                         
 112  0
                         if (form != null && form instanceof KualiDocumentFormBase) {
 113  0
                                 String docId = ((KualiDocumentFormBase) form).getDocId();
 114  0
                                 if (docId != null) { MDC.put(MDC_DOC_ID, docId); }
 115  
                         }
 116  
 
 117  0
                         String refreshCaller = request.getParameter(KNSConstants.REFRESH_CALLER);
 118  0
                         if (form!=null && KualiDocumentFormBase.class.isAssignableFrom(form.getClass()) 
 119  
                                         && !KNSConstants.QUESTION_REFRESH.equalsIgnoreCase(refreshCaller)) {
 120  0
                                 KualiDocumentFormBase docForm = (KualiDocumentFormBase) form;
 121  0
                                 Document document = docForm.getDocument();
 122  0
                                 String docFormKey = docForm.getFormKey();
 123  
 
 124  0
                                 UserSession userSession = (UserSession) request.getSession().getAttribute(KNSConstants.USER_SESSION_KEY);
 125  
 
 126  0
                                 if (WebUtils.isDocumentSession(document, docForm)) {
 127  0
                                         getSessionDocumentService().setDocumentForm(docForm, userSession, request.getRemoteAddr());
 128  
                                 }
 129  
 
 130  0
                                 Boolean exitingDocument = (Boolean) request.getAttribute(KNSConstants.EXITING_DOCUMENT);
 131  
 
 132  0
                                 if (exitingDocument != null && exitingDocument.booleanValue()) {
 133  
                                         // remove KualiDocumentFormBase object from session and
 134  
                                         // table.
 135  0
                                         getSessionDocumentService().purgeDocumentForm(docForm.getDocument().getDocumentNumber(), docFormKey, userSession, request.getRemoteAddr());
 136  
                                 }
 137  
                         }
 138  
 
 139  0
                         if ( LOG.isInfoEnabled() ) {
 140  0
                                 LOG.info(new StringBuffer("Finished processing request: '").append(request.getRequestURI()).append("' w/ query string: '").append(request.getQueryString()).append("'"));
 141  
                         }
 142  
 
 143  0
                 } finally {
 144  
                         // MDC docId key is set above, and also during super.process() in the call to processActionForm
 145  0
                         MDC.remove(MDC_DOC_ID);
 146  
                         // MDC user key is set above, although it may have already been set.
 147  0
                         if (MDC.get(MDC_USER_ALREADY_SET) == null) {
 148  0
                                 MDC.remove(MDC_USER);
 149  
                         } else {
 150  0
                                 MDC.remove(MDC_USER_ALREADY_SET);
 151  
                         }
 152  0
                 }
 153  
 
 154  0
         }
 155  
 
 156  
         /**
 157  
          * override of the pre process for all struts requests which will ensure
 158  
          * that we have the appropriate state for user sessions for all of our
 159  
          * requests, also populating the GlobalVariables class with our UserSession
 160  
          * for convenience to the non web layer based classes and implementations
 161  
          */
 162  
         @Override
 163  
         protected boolean processPreprocess(HttpServletRequest request, HttpServletResponse response) {
 164  0
                 UserSession userSession = null;
 165  0
                 if (!isUserSessionEstablished(request)) {
 166  0
                         String principalName = getIdentityManagementService().getAuthenticatedPrincipalName(request);
 167  0
                         if ( StringUtils.isNotBlank(principalName) ) {
 168  0
                                 KimPrincipal principal = getIdentityManagementService().getPrincipalByPrincipalName( principalName );
 169  0
                                 if ( principal != null ) {
 170  0
                                         AttributeSet qualification = new AttributeSet();
 171  0
                                         qualification.put( "principalId", principal.getPrincipalId() );
 172  
                                         // check to see if the given principal is an active principal/entity
 173  0
                                         if ( getIdentityManagementService().isAuthorized( 
 174  
                                                         principal.getPrincipalId(), 
 175  
                                                         KimConstants.KIM_TYPE_DEFAULT_NAMESPACE, 
 176  
                                                         KimConstants.PermissionNames.LOG_IN, 
 177  
                                                         null, 
 178  
                                                         qualification ) ) {
 179  
                                         
 180  
                                                 // This is a temp solution to show KIM AuthN checking existence of Principals.
 181  
                                                 // We may want to move this code to the IdentityService once it is finished.
 182  0
                                                 userSession = new UserSession(principalName);
 183  0
                                                 if ( userSession.getPerson() == null ) {
 184  0
                                                         LOG.warn("Unknown User: " + principalName);
 185  0
                                                         throw new RuntimeException("Invalid User: " + principalName);
 186  
                                                 }
 187  
                                                 
 188  0
                                                 String kualiSessionId = this.getKualiSessionId(request, response);
 189  0
                                                 if (kualiSessionId == null) {
 190  0
                                                         kualiSessionId = new Guid().toString();
 191  0
                                                         response.addCookie(new Cookie(KNSConstants.KUALI_SESSION_ID, kualiSessionId));
 192  
                                                 }
 193  0
                                                 userSession.setKualiSessionId(kualiSessionId);
 194  0
                                         } /* if: principal is active */ else {
 195  0
                                                 LOG.warn("Principal is Inactive: " + principalName);
 196  0
                                                 throw new RuntimeException("You cannot log in, because you are not an active Kuali user.\nPlease ask someone to activate your account, if you need to use Kuali Systems.\nThe user id provided was: " + principalName + ".\n");
 197  
                                         }
 198  0
                                 } /* if: principal is null */ else {
 199  0
                                         LOG.warn("Principal Name not found in IdentityManagementService: " + principalName);
 200  0
                                         throw new RuntimeException("Unknown User: " + principalName);
 201  
                                 }
 202  0
                         } /* if: principalName blank */ else {
 203  0
                                 LOG.error( "Principal Name from the authentication service was blank!" );
 204  0
                                 throw new RuntimeException( "Blank User from AuthenticationService - This should never happen." );
 205  
                         }
 206  0
                 } else {
 207  0
                         userSession = (UserSession) request.getSession().getAttribute(KNSConstants.USER_SESSION_KEY);
 208  
                 }
 209  
                 
 210  0
                 request.getSession().setAttribute(KNSConstants.USER_SESSION_KEY, userSession);
 211  0
                 GlobalVariables.setUserSession(userSession);
 212  0
                 GlobalVariables.clear();
 213  0
                 if ( StringUtils.isNotBlank( request.getParameter(KNSConstants.BACKDOOR_PARAMETER) ) ) {
 214  0
                         if ( !KNSServiceLocator.getKualiConfigurationService().isProductionEnvironment() ) {
 215  0
                                 if ( KNSServiceLocator.getParameterService().getIndicatorParameter(KNSConstants.KUALI_RICE_WORKFLOW_NAMESPACE, KNSConstants.DetailTypes.BACKDOOR_DETAIL_TYPE, KEWConstants.SHOW_BACK_DOOR_LOGIN_IND) ) {
 216  0
                                     userSession.setBackdoorUser(request.getParameter(KNSConstants.BACKDOOR_PARAMETER));
 217  0
                                     org.kuali.rice.kew.web.session.UserSession.getAuthenticatedUser().establishBackdoorWithPrincipalName(request.getParameter(KNSConstants.BACKDOOR_PARAMETER));
 218  
                                 }
 219  
                         }
 220  
                 }
 221  
                 
 222  0
                 if (MDC.get(MDC_USER) != null) {
 223  
                         // abuse the MDC to prevent removing user prematurely if it was set elsewhere (e.g. UserLoginFilter)
 224  0
                         MDC.put(MDC_USER_ALREADY_SET, Boolean.TRUE); 
 225  
                 } else {
 226  0
                         MDC.put(MDC_USER, userSession.getPrincipalId());
 227  
                 }
 228  
                 
 229  0
                 return true;
 230  
         }
 231  
 
 232  
         /**
 233  
          * This method gets the document number from the request.  The request should have been processed already 
 234  
          * before this is called if it is multipart.  
 235  
          * 
 236  
          * @param request
 237  
          * @return the document number, or null if one can't be found in the request.
 238  
          */
 239  
         private String getDocumentNumber(HttpServletRequest request) {
 240  0
                 String documentNumber = request.getParameter(KNSConstants.DOCUMENT_DOCUMENT_NUMBER);
 241  
 
 242  
                 // from lookup pages.
 243  0
                 if (documentNumber == null) {
 244  0
                         documentNumber = request.getParameter(KNSConstants.DOC_NUM);
 245  
                 }
 246  
                 
 247  0
                 if (documentNumber == null) {
 248  0
                         documentNumber = request.getParameter("routeHeaderId");
 249  
                 }
 250  
                 
 251  0
                 return documentNumber;
 252  
         }
 253  
 
 254  
         /**
 255  
          * Checks if the user who made the request has a UserSession established
 256  
          * 
 257  
          * @param request
 258  
          *            the HTTPServletRequest object passed in
 259  
          * @return true if the user session has been established, false otherwise
 260  
          */
 261  
         private boolean isUserSessionEstablished(HttpServletRequest request) {
 262  0
                 boolean result = (request.getSession().getAttribute(KNSConstants.USER_SESSION_KEY) != null);
 263  0
                 return result;
 264  
         }
 265  
 
 266  
         /**
 267  
          * Hooks into populate process to call form populate method if form is an
 268  
          * instanceof PojoForm.
 269  
          */
 270  
         @Override
 271  
         protected void processPopulate(HttpServletRequest request, HttpServletResponse response, ActionForm form, ActionMapping mapping) throws ServletException {
 272  0
                 if (form instanceof KualiForm) {
 273  
                         // Add the ActionForm to GlobalVariables
 274  
                         // This will allow developers to retrieve both the Document and any
 275  
                         // request parameters that are not
 276  
                         // part of the Form and make them available in ValueFinder classes
 277  
                         // and other places where they are needed.
 278  0
                         GlobalVariables.setKualiForm((KualiForm) form);
 279  
                 }
 280  
 
 281  
                 // if not PojoForm, call struts populate
 282  0
                 if (!(form instanceof PojoForm)) {
 283  0
                         super.processPopulate(request, response, form, mapping);
 284  0
                         return;
 285  
                 }
 286  
                 
 287  0
                 final String previousRequestGuid = request.getParameter(KualiRequestProcessor.PREVIOUS_REQUEST_EDITABLE_PROPERTIES_GUID_PARAMETER_NAME);
 288  
 
 289  0
                 ((PojoForm)form).clearEditablePropertyInformation();
 290  0
                 ((PojoForm)form).registerStrutsActionMappingScope(mapping.getScope());
 291  
                 
 292  0
                 String multipart = mapping.getMultipartClass();
 293  0
                 if (multipart != null) {
 294  0
                         request.setAttribute(Globals.MULTIPART_KEY, multipart);
 295  
                 }
 296  
 
 297  0
                 form.setServlet(this.servlet);
 298  0
                 form.reset(mapping, request);
 299  
 
 300  0
                 ((PojoForm)form).setPopulateEditablePropertiesGuid(previousRequestGuid);
 301  
                 // call populate on ActionForm
 302  0
                 ((PojoForm) form).populate(request);
 303  0
                 request.setAttribute("UnconvertedValues", ((PojoForm) form).getUnconvertedValues().keySet());
 304  0
                 request.setAttribute("UnconvertedHash", ((PojoForm) form).getUnconvertedValues());
 305  0
         }
 306  
 
 307  
         /**
 308  
          * Hooks into validate to catch any errors from the populate, and translate
 309  
          * the ErrorMap to ActionMessages.
 310  
          */
 311  
         @Override
 312  
         protected boolean processValidate(HttpServletRequest request, HttpServletResponse response, ActionForm form, ActionMapping mapping) throws IOException, ServletException, InvalidCancelException {
 313  
 
 314  
                 // skip form validate if we had errors from populate
 315  0
                 if (GlobalVariables.getMessageMap().hasNoErrors()) {
 316  0
                         if (form == null) {
 317  0
                                 return (true);
 318  
                         }
 319  
                         // Was this request cancelled?
 320  0
                         if (request.getAttribute(Globals.CANCEL_KEY) != null) {
 321  0
                                 if (LOG.isDebugEnabled()) {
 322  0
                                         LOG.debug(" Cancelled transaction, skipping validation");
 323  
                                 }
 324  0
                                 return (true);
 325  
                         }
 326  
 
 327  
                         // Has validation been turned off for this mapping?
 328  0
                         if (!mapping.getValidate()) {
 329  0
                                 return (true);
 330  
                         }
 331  
 
 332  
                         // call super to call forms validate
 333  0
                         super.processValidate(request, response, form, mapping);
 334  
                 }
 335  
 
 336  0
                 publishMessages(request);
 337  0
                 if (!GlobalVariables.getMessageMap().hasNoErrors()) {
 338  
                         // Special handling for multipart request
 339  0
                         if (form.getMultipartRequestHandler() != null) {
 340  0
                                 if (LOG.isDebugEnabled()) {
 341  0
                                         LOG.debug("  Rolling back multipart request");
 342  
                                 }
 343  0
                                 form.getMultipartRequestHandler().rollback();
 344  
                         }
 345  
 
 346  
                         // Fix state that could be incorrect because of validation failure
 347  0
                         if (form instanceof PojoForm)
 348  0
                                 ((PojoForm) form).processValidationFail();
 349  
 
 350  
                         // Was an input path (or forward) specified for this mapping?
 351  0
                         String input = mapping.getInput();
 352  0
                         if (input == null) {
 353  0
                                 if (LOG.isDebugEnabled()) {
 354  0
                                         LOG.debug("  Validation failed but no input form available");
 355  
                                 }
 356  0
                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, getInternal().getMessage("noInput", mapping.getPath()));
 357  0
                                 return (false);
 358  
                         }
 359  
 
 360  0
                         if (moduleConfig.getControllerConfig().getInputForward()) {
 361  0
                                 ForwardConfig forward = mapping.findForward(input);
 362  0
                                 processForwardConfig(request, response, forward);
 363  0
                         } else {
 364  0
                                 internalModuleRelativeForward(input, request, response);
 365  
                         }
 366  
 
 367  0
                         return (false);
 368  
                 } else {
 369  0
                         return true;
 370  
                 }
 371  
 
 372  
         }
 373  
 
 374  
         /**
 375  
          * Checks for return from a lookup or question, and restores the action form
 376  
          * stored under the request parameter docFormKey.
 377  
          */
 378  
         @Override
 379  
         protected ActionForm processActionForm(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) {
 380  
                 
 381  0
                 String documentNumber = getDocumentNumber(request);
 382  0
                 if (documentNumber != null) { MDC.put(MDC_DOC_ID, documentNumber); }
 383  
                 
 384  0
                 UserSession userSession = (UserSession) request.getSession().getAttribute(KNSConstants.USER_SESSION_KEY);
 385  
 
 386  0
                 String docFormKey = request.getParameter(KNSConstants.DOC_FORM_KEY);
 387  0
                 String methodToCall = request.getParameter(KNSConstants.DISPATCH_REQUEST_PARAMETER);
 388  0
                 String refreshCaller = request.getParameter(KNSConstants.REFRESH_CALLER);
 389  
 //                String searchListRequestKey = request.getParameter(KNSConstants.SEARCH_LIST_REQUEST_KEY);
 390  0
                 String documentWebScope = request.getParameter(KNSConstants.DOCUMENT_WEB_SCOPE);
 391  
 
 392  0
                 if (mapping.getPath().startsWith(KNSConstants.REFRESH_MAPPING_PREFIX) || KNSConstants.RETURN_METHOD_TO_CALL.equalsIgnoreCase(methodToCall) ||
 393  
                                 KNSConstants.QUESTION_REFRESH.equalsIgnoreCase(refreshCaller) || KNSConstants.TEXT_AREA_REFRESH.equalsIgnoreCase(refreshCaller) || KNSConstants.SESSION_SCOPE.equalsIgnoreCase(documentWebScope)) {
 394  0
                         ActionForm form = null;
 395  
                         // check for search result storage and clear
 396  0
                         GlobalVariables.getUserSession().removeObjectsByPrefix(KNSConstants.SEARCH_LIST_KEY_PREFIX);
 397  
 
 398  
                         // We put different type of forms such as document form, lookup form
 399  
                         // in session but we only store document form in
 400  
                         // database.
 401  0
                         if (userSession.retrieveObject(docFormKey) != null) {
 402  0
                                 LOG.debug("getDecomentForm KualiDocumentFormBase from session");
 403  0
                                 form = (ActionForm) userSession.retrieveObject(docFormKey);
 404  
                         } else {
 405  0
                                 form = (ActionForm) getSessionDocumentService().getDocumentForm(documentNumber, docFormKey, userSession, request.getRemoteAddr());
 406  
                         }
 407  0
                         request.setAttribute(mapping.getAttribute(), form);
 408  0
                         if (!KNSConstants.SESSION_SCOPE.equalsIgnoreCase(documentWebScope)) {
 409  0
                                 userSession.removeObject(docFormKey);
 410  
                         }
 411  
                         // we should check whether this is a multipart request because we
 412  
                         // could have had a combination of query parameters and a multipart
 413  
                         // request
 414  0
                         String contentType = request.getContentType();
 415  0
                         String method = request.getMethod();
 416  0
                         if (("POST".equalsIgnoreCase(method) && contentType != null && contentType.startsWith("multipart/form-data"))) {
 417  
                                 // this method parses the multipart request and adds new
 418  
                                 // non-file parameters into the request
 419  0
                                 WebUtils.getMultipartParameters(request, null, form, mapping);
 420  
                         }
 421  
                         // The form can be null if the document is not a session document
 422  0
                         if (form != null) {
 423  0
                                 return form;
 424  
                         }
 425  
                 }
 426  
 
 427  
                 // Rice has the ability to limit file upload sizes on a per-form basis,
 428  
                 // so the max upload sizes may be accessed by calling methods on
 429  
                 // PojoFormBase.
 430  
                 // This requires that we are able know the file upload size limit (i.e.
 431  
                 // retrieve a form instance) before we parse a mulitpart request.
 432  0
                 ActionForm form = super.processActionForm(request, response, mapping);
 433  
 
 434  
                 // for sessiondocument with multipart request
 435  0
                 String contentType = request.getContentType();
 436  0
                 String method = request.getMethod();
 437  
 
 438  0
                 if ("GET".equalsIgnoreCase(method) && StringUtils.isNotBlank(methodToCall) && form instanceof PojoForm &&
 439  
                                 ((PojoForm) form).getMethodToCallsToBypassSessionRetrievalForGETRequests().contains(methodToCall)) {
 440  0
                         return createNewActionForm(mapping, request);
 441  
                 }
 442  
                 
 443  
                 // if we have a multipart request, parse it and return the stored form
 444  
                 // from session if the doc form key is not blank. If it is blank, then
 445  
                 // we just return the form
 446  
                 // generated from the superclass processActionForm method. Either way,
 447  
                 // we need to parse the mulitpart request now so that we may determine
 448  
                 // what the value of the doc form key is.
 449  
                 // This is generally against the contract of processActionForm, because
 450  
                 // processPopulate should be responsible for parsing the mulitpart
 451  
                 // request, but we need to parse it now
 452  
                 // to determine the doc form key value.
 453  0
                 if (("POST".equalsIgnoreCase(method) && contentType != null && contentType.startsWith("multipart/form-data"))) {
 454  0
                         WebUtils.getMultipartParameters(request, null, form, mapping);
 455  0
                         docFormKey = request.getParameter(KNSConstants.DOC_FORM_KEY);
 456  0
                         documentWebScope = request.getParameter(KNSConstants.DOCUMENT_WEB_SCOPE);
 457  
 
 458  0
                         documentNumber = getDocumentNumber(request);
 459  
 
 460  0
                         if (KNSConstants.SESSION_SCOPE.equalsIgnoreCase(documentWebScope) ||
 461  
                                         (form instanceof KualiDocumentFormBase && WebUtils.isDocumentSession(((KualiDocumentFormBase) form).getDocument(), (KualiDocumentFormBase) form))) {
 462  
 
 463  0
                                 Object userSessionObject = userSession.retrieveObject(docFormKey);
 464  0
                                 if ( userSessionObject != null &&  userSessionObject instanceof ActionForm ) {
 465  0
                                         LOG.debug("getDocumentForm KualiDocumentFormBase from session");
 466  0
                                         form = (ActionForm) userSessionObject;
 467  
                                 } else {
 468  0
                                         ActionForm tempForm = (ActionForm)getSessionDocumentService().getDocumentForm(documentNumber, docFormKey, userSession, request.getRemoteAddr());
 469  0
                                         if ( tempForm != null ) {
 470  0
                                                 form = tempForm;
 471  
                                         }
 472  
                                 }
 473  
 
 474  0
                                 request.setAttribute(mapping.getAttribute(), form);
 475  0
                                 if (form != null) {
 476  0
                                         return form;
 477  
                                 }
 478  
                         }
 479  
                 }
 480  0
                 return form;
 481  
         }
 482  
 
 483  
         /**
 484  
          * Hook into action perform to handle errors in the error map and catch
 485  
          * exceptions.
 486  
          * 
 487  
          * <p>
 488  
          * A transaction is started prior to the execution of the action. This
 489  
          * allows for the action code to execute efficiently without the need for
 490  
          * using PROPAGATION_SUPPORTS in the transaction definitions. The
 491  
          * PROPAGATION_SUPPORTS propagation type does not work well with JTA.
 492  
          */
 493  
         @Override
 494  
         protected ActionForward processActionPerform(final HttpServletRequest request, final HttpServletResponse response, final Action action, final ActionForm form, final ActionMapping mapping) throws IOException, ServletException {
 495  
                 try {
 496  0
                         TransactionTemplate template = new TransactionTemplate(getTransactionManager());
 497  0
                         ActionForward forward = null;
 498  
                         try {
 499  0
                                 forward = (ActionForward) template.execute(new TransactionCallback() {
 500  
                                         public Object doInTransaction(TransactionStatus status) {
 501  0
                                                 ActionForward actionForward = null;
 502  
                                                 try {
 503  0
                                                         actionForward = action.execute(mapping, form, request, response);
 504  0
                                                 } catch (Exception e) {
 505  
                                                         // the doInTransaction method has no means for
 506  
                                                         // throwing exceptions, so we will wrap the
 507  
                                                         // exception in
 508  
                                                         // a RuntimeException and re-throw. The one caveat
 509  
                                                         // here is that this will always result in
 510  
                                                         // the
 511  
                                                         // transaction being rolled back (since
 512  
                                                         // WrappedRuntimeException is a runtime exception).
 513  0
                                                         throw new WrappedRuntimeException(e);
 514  0
                                                 }
 515  0
                                                 if (status.isRollbackOnly()) {
 516  
                                                         // this means that the struts action execution
 517  
                                                         // caused the transaction to rollback, we want to
 518  
                                                         // go ahead
 519  
                                                         // and trigger the rollback by throwing an exception
 520  
                                                         // here but then return the action forward
 521  
                                                         // from this method
 522  0
                                                         throw new WrappedActionForwardRuntimeException(actionForward);
 523  
                                                 }
 524  0
                                                 return actionForward;
 525  
                                         }
 526  
                                 });
 527  0
                         } catch (WrappedActionForwardRuntimeException e) {
 528  0
                                 forward = e.getActionForward();
 529  0
                         }
 530  
 
 531  
 
 532  0
                         publishMessages(request);
 533  0
                         saveMessages(request);
 534  0
                         saveAuditErrors(request);
 535  
                         
 536  0
                         if (form instanceof PojoForm) {
 537  0
                                 if (((PojoForm)form).getEditableProperties() == null 
 538  
                                                 || ((PojoForm)form).getEditableProperties().isEmpty()) {
 539  0
                                     final String guid = GlobalVariables.getUserSession().getEditablePropertiesHistoryHolder().addEditablePropertiesToHistory(((PojoForm)form).getEditableProperties());
 540  0
                                     ((PojoForm)form).setActionEditablePropertiesGuid(guid);
 541  
                                 }
 542  
                         }
 543  
                         
 544  0
                         return forward;
 545  
 
 546  0
                 } catch (Exception e) {
 547  0
                         if (e instanceof WrappedRuntimeException) {
 548  0
                                 e = (Exception) e.getCause();
 549  
                         }
 550  0
                         if (e instanceof ValidationException) {
 551  
                                 // add a generic error message if there are none
 552  0
                                 if (GlobalVariables.getMessageMap().hasNoErrors()) {
 553  
 
 554  0
                                         GlobalVariables.getMessageMap().putError(KNSConstants.GLOBAL_ERRORS, RiceKeyConstants.ERROR_CUSTOM, e.getMessage());
 555  
                                 }
 556  
 
 557  0
                                 if (form instanceof PojoForm) {
 558  0
                                         if (((PojoForm)form).getEditableProperties() == null 
 559  
                                                         || ((PojoForm)form).getEditableProperties().isEmpty()) {
 560  0
                                             final String guid = GlobalVariables.getUserSession().getEditablePropertiesHistoryHolder().addEditablePropertiesToHistory(((PojoForm)form).getEditableProperties());
 561  0
                                             ((PojoForm)form).setActionEditablePropertiesGuid(guid);
 562  
                                         }
 563  
                                 }                        
 564  
                                 // display error messages and return to originating page
 565  0
                                 publishMessages(request);
 566  0
                                 return mapping.findForward(RiceConstants.MAPPING_BASIC);
 567  
                         }
 568  
 
 569  0
                         publishMessages(request);
 570  
 
 571  0
                         return (processException(request, response, e, form, mapping));
 572  
                 }
 573  
         }
 574  
 
 575  
         /**
 576  
          * Adds more detailed logging for unhandled exceptions
 577  
          * 
 578  
          * @see org.apache.struts.action.RequestProcessor#processException(HttpServletRequest,
 579  
          *      HttpServletResponse, Exception, ActionForm, ActionMapping)
 580  
          */
 581  
         @Override
 582  
         protected ActionForward processException(HttpServletRequest request, HttpServletResponse response, Exception exception, ActionForm form, ActionMapping mapping) throws IOException, ServletException {
 583  0
                 ActionForward actionForward = null;
 584  
 
 585  
                 try {
 586  0
                         actionForward = super.processException(request, response, exception, form, mapping);
 587  0
                 } catch (IOException e) {
 588  0
                         logException(e);
 589  0
                         throw e;
 590  0
                 } catch (ServletException e) {
 591  
                         // special case, to make OptimisticLockExceptions easier to read
 592  0
                         Throwable rootCause = e.getRootCause();
 593  0
                         if (rootCause instanceof OjbOperationException) {
 594  0
                                 OjbOperationException ooe = (OjbOperationException) rootCause;
 595  
 
 596  0
                                 Throwable subcause = ooe.getCause();
 597  0
                                 if (subcause instanceof OptimisticLockException) {
 598  0
                                         OptimisticLockException ole = (OptimisticLockException) subcause;
 599  
 
 600  0
                                         StringBuffer message = new StringBuffer(e.getMessage());
 601  
 
 602  0
                                         Object sourceObject = ole.getSourceObject();
 603  0
                                         if (sourceObject != null) {
 604  0
                                                 message.append(" (sourceObject is ");
 605  0
                                                 message.append(sourceObject.getClass().getName());
 606  0
                                                 message.append(")");
 607  
                                         }
 608  
 
 609  0
                                         e = new ServletException(message.toString(), rootCause);
 610  
                                 }
 611  
                         }
 612  
 
 613  0
                         logException(e);
 614  0
                         throw e;
 615  0
                 }
 616  0
                 return actionForward;
 617  
         }
 618  
 
 619  
         private void logException(Exception e) {
 620  0
                 LOG.error("unhandled exception thrown by KualiRequestProcessor.processActionPerform");
 621  
 
 622  0
                 if (e.getCause() != null) {
 623  0
                         ExceptionUtils.logStackTrace(LOG, e.getCause());
 624  
                 } else {
 625  0
                         ExceptionUtils.logStackTrace(LOG, e);
 626  
                 }
 627  0
         }
 628  
 
 629  
         /**
 630  
          * Checks for errors in the error map and transforms them to struts action
 631  
          * messages then stores in the request.
 632  
          */
 633  
         private void publishMessages(HttpServletRequest request) {
 634  0
                 MessageMap errorMap = GlobalVariables.getMessageMap();
 635  0
                 if (!errorMap.hasNoErrors()) {
 636  0
                         ErrorContainer errorContainer = new ErrorContainer(errorMap);
 637  
 
 638  0
                         request.setAttribute("ErrorContainer", errorContainer);
 639  0
                         request.setAttribute(Globals.ERROR_KEY, errorContainer.getRequestErrors());
 640  0
                         request.setAttribute("ErrorPropertyList", errorContainer.getErrorPropertyList());
 641  
                 }
 642  
                 
 643  0
                 if (errorMap.hasWarnings()) {
 644  0
                         WarningContainer warningsContainer = new WarningContainer(errorMap);
 645  
                         
 646  0
                         request.setAttribute("WarningContainer", warningsContainer);
 647  0
                         request.setAttribute("WarningActionMessages", warningsContainer.getRequestMessages());
 648  0
                         request.setAttribute("WarningPropertyList", warningsContainer.getMessagePropertyList());
 649  
                 }
 650  
                 
 651  0
                 if (errorMap.hasInfo()) {
 652  0
                         InfoContainer infoContainer = new InfoContainer(errorMap);
 653  
                         
 654  0
                         request.setAttribute("InfoContainer", infoContainer);
 655  0
                         request.setAttribute("InfoActionMessages", infoContainer.getRequestMessages());
 656  0
                         request.setAttribute("InfoPropertyList", infoContainer.getMessagePropertyList());
 657  
                 }
 658  0
         }
 659  
 
 660  
         /**
 661  
          * Checks for messages in GlobalVariables and places list in request
 662  
          * attribute.
 663  
          */
 664  
         private void saveMessages(HttpServletRequest request) {
 665  0
                 if (!GlobalVariables.getMessageList().isEmpty()) {
 666  0
                         request.setAttribute(KNSConstants.GLOBAL_MESSAGES, GlobalVariables.getMessageList().toActionMessages());
 667  
                 }
 668  0
         }
 669  
 
 670  
         /**
 671  
          * Checks for messages in GlobalVariables and places list in request
 672  
          * attribute.
 673  
          */
 674  
         private void saveAuditErrors(HttpServletRequest request) {
 675  0
                 if (!GlobalVariables.getAuditErrorMap().isEmpty()) {
 676  0
                         request.setAttribute(KNSConstants.AUDIT_ERRORS, GlobalVariables.getAuditErrorMap());
 677  
                 }
 678  0
         }
 679  
 
 680  
         /**
 681  
          * A simple exception that allows us to wrap an exception that is thrown out
 682  
          * of a transaction template.
 683  
          */
 684  
         @SuppressWarnings("serial")
 685  
         private static class WrappedRuntimeException extends RuntimeException {
 686  
                 public WrappedRuntimeException(Exception e) {
 687  0
                         super(e);
 688  0
                 }
 689  
         }
 690  
 
 691  0
         @SuppressWarnings("serial")
 692  
         private static class WrappedActionForwardRuntimeException extends RuntimeException {
 693  
                 private ActionForward actionForward;
 694  
 
 695  0
                 public WrappedActionForwardRuntimeException(ActionForward actionForward) {
 696  0
                         this.actionForward = actionForward;
 697  0
                 }
 698  
 
 699  
                 public ActionForward getActionForward() {
 700  0
                         return actionForward;
 701  
                 }
 702  
         }
 703  
 
 704  
         private String getKualiSessionId(HttpServletRequest request, HttpServletResponse response) {
 705  0
                 String kualiSessionId = null;
 706  0
                 Cookie[] cookies = (Cookie[]) request.getCookies();
 707  0
                 if (cookies != null) {
 708  0
                         for (int i = 0; i < cookies.length; i++) {
 709  0
                                 Cookie cookie = cookies[i];
 710  0
                                 if (KNSConstants.KUALI_SESSION_ID.equals(cookie.getName()))
 711  0
                                         kualiSessionId = cookie.getValue();
 712  
                         }
 713  
                 }
 714  0
                 return kualiSessionId;
 715  
         }
 716  
 
 717  
         /**
 718  
          * @return the sessionDocumentService
 719  
          */
 720  
         public SessionDocumentService getSessionDocumentService() {
 721  0
                 if ( sessionDocumentService == null ) {
 722  0
                         sessionDocumentService = KNSServiceLocator.getSessionDocumentService();
 723  
                 }
 724  0
                 return this.sessionDocumentService;
 725  
         }
 726  
 
 727  
         /**
 728  
          * @return the dataDictionaryService
 729  
          */
 730  
         public DataDictionaryService getDataDictionaryService() {
 731  0
                 if ( dataDictionaryService == null ) {
 732  0
                         dataDictionaryService = KNSServiceLocator.getDataDictionaryService();
 733  
                 }
 734  0
                 return this.dataDictionaryService;
 735  
         }
 736  
 
 737  
         /**
 738  
          * @return the businessObjectService
 739  
          */
 740  
         public BusinessObjectService getBusinessObjectService() {
 741  0
                 if ( businessObjectService == null ) {
 742  0
                         businessObjectService = KNSServiceLocator.getBusinessObjectService();
 743  
                 }
 744  0
                 return this.businessObjectService;
 745  
         }
 746  
 
 747  
         /**
 748  
          * @return the transactionManager
 749  
          */
 750  
         public PlatformTransactionManager getTransactionManager() {
 751  0
                 if ( transactionManager == null ) {
 752  0
                         transactionManager = KNSServiceLocator.getTransactionManager();
 753  
                 }
 754  0
                 return this.transactionManager;
 755  
         }
 756  
 
 757  
         
 758  
         public IdentityManagementService getIdentityManagementService() {
 759  0
                 if ( identityManagementService == null ) {
 760  0
                         identityManagementService = KIMServiceLocator.getIdentityManagementService();
 761  
                 }
 762  0
                 return this.identityManagementService;
 763  
         }
 764  
         
 765  
         private ActionForm createNewActionForm(ActionMapping mapping, HttpServletRequest request) {
 766  0
         String name = mapping.getName();
 767  0
         FormBeanConfig config = moduleConfig.findFormBeanConfig(name);
 768  0
         if (config == null) {
 769  0
             log.warn("No FormBeanConfig found under '" + name + "'");
 770  0
             return (null);
 771  
         }
 772  0
         ActionForm instance = RequestUtils.createActionForm(config, servlet);
 773  0
         if ("request".equals(mapping.getScope())) {
 774  0
             request.setAttribute(mapping.getAttribute(), instance);
 775  
         } else {
 776  0
             HttpSession session = request.getSession();
 777  0
             session.setAttribute(mapping.getAttribute(), instance);
 778  
         }
 779  0
         return instance;
 780  
         }
 781  
 }