001/** 002 * Copyright 2005-2016 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.kns.web.struts.action; 017 018import org.apache.commons.lang.ObjectUtils; 019import org.apache.commons.lang.StringUtils; 020import org.apache.struts.action.ActionForm; 021import org.apache.struts.action.ActionForward; 022import org.apache.struts.action.ActionMapping; 023import org.apache.struts.actions.DispatchAction; 024import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator; 025import org.kuali.rice.coreservice.framework.parameter.ParameterService; 026import org.kuali.rice.core.api.CoreApiServiceLocator; 027import org.kuali.rice.core.api.encryption.EncryptionService; 028import org.kuali.rice.core.api.util.RiceConstants; 029import org.kuali.rice.kew.api.KewApiConstants; 030import org.kuali.rice.kim.api.KimConstants; 031import org.kuali.rice.kim.api.services.KimApiServiceLocator; 032import org.kuali.rice.kns.document.authorization.DocumentAuthorizerBase; 033import org.kuali.rice.kns.lookup.LookupUtils; 034import org.kuali.rice.kns.service.BusinessObjectAuthorizationService; 035import org.kuali.rice.kns.service.KNSServiceLocator; 036import org.kuali.rice.kns.util.KNSGlobalVariables; 037import org.kuali.rice.kns.util.WebUtils; 038import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase; 039import org.kuali.rice.kns.web.struts.form.KualiForm; 040import org.kuali.rice.kns.web.struts.form.LookupForm; 041import org.kuali.rice.kns.web.struts.form.pojo.PojoForm; 042import org.kuali.rice.kns.web.struts.form.pojo.PojoFormBase; 043import org.kuali.rice.krad.bo.BusinessObject; 044import org.kuali.rice.krad.exception.AuthorizationException; 045import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 046import org.kuali.rice.krad.service.KualiModuleService; 047import org.kuali.rice.krad.service.ModuleService; 048import org.kuali.rice.krad.util.GlobalVariables; 049import org.kuali.rice.krad.util.KRADConstants; 050import org.kuali.rice.krad.util.KRADUtils; 051import org.kuali.rice.krad.util.UrlFactory; 052 053import javax.servlet.http.HttpServletRequest; 054import javax.servlet.http.HttpServletResponse; 055import java.util.Arrays; 056import java.util.Enumeration; 057import java.util.HashMap; 058import java.util.HashSet; 059import java.util.Map; 060import java.util.Properties; 061import java.util.Set; 062 063/** 064 * <p>The base {@link org.apache.struts.action.Action} class for all KNS-based Actions. Extends from the standard 065 * {@link org.apache.struts.actions.DispatchAction} which allows for a <i>methodToCall</i> request parameter to 066 * be used to indicate which method to invoke.</p> 067 * 068 * <p>This Action overrides #execute to set methodToCall for image submits. Also performs other setup 069 * required for KNS framework calls.</p> 070 * 071 * @author Kuali Rice Team (rice.collab@kuali.org) 072 */ 073public abstract class KualiAction extends DispatchAction { 074 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiAction.class); 075 076 private static KualiModuleService kualiModuleService = null; 077 private static BusinessObjectAuthorizationService businessObjectAuthorizationService = null; 078 private static EncryptionService encryptionService = null; 079 private static Boolean OUTPUT_ENCRYPTION_WARNING = null; 080 private static String applicationBaseUrl = null; 081 082 private Set<String> methodToCallsToNotCheckAuthorization = new HashSet<String>(); 083 084 { 085 methodToCallsToNotCheckAuthorization.add( "performLookup" ); 086 methodToCallsToNotCheckAuthorization.add( "performQuestion" ); 087 methodToCallsToNotCheckAuthorization.add( "performQuestionWithInput" ); 088 methodToCallsToNotCheckAuthorization.add( "performQuestionWithInputAgainBecauseOfErrors" ); 089 methodToCallsToNotCheckAuthorization.add( "performQuestionWithoutInput" ); 090 methodToCallsToNotCheckAuthorization.add( "performWorkgroupLookup" ); 091 } 092 093 /** 094 * Entry point to all actions. 095 * 096 * NOTE: No need to hook into execute for handling framework setup anymore. Just implement the methodToCall for the framework 097 * setup, Constants.METHOD_REQUEST_PARAMETER will contain the full parameter, which can be sub stringed for getting framework 098 * parameters. 099 * 100 * @see org.apache.struts.action.Action#execute(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, 101 * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) 102 */ 103 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 104 ActionForward returnForward = null; 105 106 String methodToCall = findMethodToCall(form, request); 107 108 if(isModuleLocked(form, methodToCall, request)) { 109 return mapping.findForward(RiceConstants.MODULE_LOCKED_MAPPING); 110 } 111 112 if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getMethodToCall())) { 113 if (StringUtils.isNotBlank(getImageContext(request, KRADConstants.ANCHOR))) { 114 ((KualiForm) form).setAnchor(getImageContext(request, KRADConstants.ANCHOR)); 115 } 116 else if (StringUtils.isNotBlank(request.getParameter(KRADConstants.ANCHOR))) { 117 ((KualiForm) form).setAnchor(request.getParameter(KRADConstants.ANCHOR)); 118 } 119 else { 120 ((KualiForm) form).setAnchor(KRADConstants.ANCHOR_TOP_OF_FORM); 121 } 122 } 123 // if found methodToCall, pass control to that method, else return the basic forward 124 if (StringUtils.isNotBlank(methodToCall)) { 125 if ( LOG.isDebugEnabled() ) { 126 LOG.debug("methodToCall: '" + methodToCall+"'"); 127 } 128 returnForward = dispatchMethod(mapping, form, request, response, methodToCall); 129 if ( returnForward!=null && returnForward.getRedirect() && returnForward.getName()!=null && returnForward.getName().equals(KRADConstants.KRAD_INITIATED_DOCUMENT_VIEW_NAME)) { 130 return returnForward; 131 } 132 } 133 else { 134 returnForward = defaultDispatch(mapping, form, request, response); 135 } 136 137 // make sure the user can do what they're trying to according to the module that owns the functionality 138 if ( !methodToCallsToNotCheckAuthorization.contains(methodToCall) ) { 139 if ( LOG.isDebugEnabled() ) { 140 LOG.debug( "'" + methodToCall + "' not in set of excempt methods: " + methodToCallsToNotCheckAuthorization); 141 } 142 checkAuthorization(form, methodToCall); 143 } else { 144 if ( LOG.isDebugEnabled() ) { 145 LOG.debug("'" + methodToCall + "' is exempt from auth checks." ); 146 } 147 } 148 149 // Add the ActionForm to GlobalVariables 150 // This will allow developers to retrieve both the Document and any request parameters that are not 151 // part of the Form and make them available in ValueFinder classes and other places where they are needed. 152 if(KNSGlobalVariables.getKualiForm() == null) { 153 KNSGlobalVariables.setKualiForm((KualiForm)form); 154 } 155 156 return returnForward; 157 } 158 159 /** 160 * When no methodToCall is specified, the defaultDispatch method is invoked. Default implementation 161 * returns the "basic" ActionForward. 162 */ 163 protected ActionForward defaultDispatch(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 164 return mapping.findForward(RiceConstants.MAPPING_BASIC); 165 } 166 167 @Override 168 protected ActionForward dispatchMethod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String methodToCall) throws Exception { 169 GlobalVariables.getUserSession().addObject(DocumentAuthorizerBase.USER_SESSION_METHOD_TO_CALL_OBJECT_KEY, methodToCall); 170 return super.dispatchMethod(mapping, form, request, response, methodToCall); 171 } 172 173 protected String findMethodToCall(ActionForm form, HttpServletRequest request) throws Exception { 174 String methodToCall; 175 if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getMethodToCall())) { 176 methodToCall = ((KualiForm) form).getMethodToCall(); 177 } 178 else { 179 // call utility method to parse the methodToCall from the request. 180 methodToCall = WebUtils.parseMethodToCall(form, request); 181 } 182 return methodToCall; 183 } 184 185 /** 186 * Toggles the tab state in the ui 187 * 188 * @param mapping 189 * @param form 190 * @param request 191 * @param response 192 * @return 193 * @throws Exception 194 */ 195 public ActionForward toggleTab(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 196 KualiForm kualiForm = (KualiForm) form; 197 String tabToToggle = getTabToToggle(request); 198 if (StringUtils.isNotBlank(tabToToggle)) { 199 if (kualiForm.getTabState(tabToToggle).equals(KualiForm.TabState.OPEN.name())) { 200 kualiForm.getTabStates().remove(tabToToggle); 201 kualiForm.getTabStates().put(tabToToggle, KualiForm.TabState.CLOSE.name()); 202 } 203 else { 204 kualiForm.getTabStates().remove(tabToToggle); 205 kualiForm.getTabStates().put(tabToToggle, KualiForm.TabState.OPEN.name()); 206 } 207 } 208 209 doProcessingAfterPost( kualiForm, request ); 210 return mapping.findForward(RiceConstants.MAPPING_BASIC); 211 } 212 213 /** 214 * Toggles all tabs to open 215 * 216 * @param mapping 217 * @param form 218 * @param request 219 * @param response 220 * @return 221 * @throws Exception 222 */ 223 public ActionForward showAllTabs(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 224 return this.doTabOpenOrClose(mapping, form, request, response, true); 225 } 226 227 /** 228 * Toggles all tabs to closed 229 * 230 * @param mapping 231 * @param form 232 * @param request 233 * @param response 234 * @return 235 * @throws Exception 236 */ 237 public ActionForward hideAllTabs(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 238 return this.doTabOpenOrClose(mapping, form, request, response, false); 239 } 240 241 /** 242 * 243 * Toggles all tabs to open of closed depending on the boolean flag. 244 * 245 * @param mapping the mapping 246 * @param form the form 247 * @param request the request 248 * @param response the response 249 * @param open whether to open of close the tabs 250 * @return the action forward 251 */ 252 private ActionForward doTabOpenOrClose(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, boolean open) { 253 KualiForm kualiForm = (KualiForm) form; 254 255 Map<String, String> tabStates = kualiForm.getTabStates(); 256 Map<String, String> newTabStates = new HashMap<String, String>(); 257 for (String tabKey: tabStates.keySet()) { 258 newTabStates.put(tabKey, open ? "OPEN" : "CLOSE"); 259 } 260 kualiForm.setTabStates(newTabStates); 261 doProcessingAfterPost( kualiForm, request ); 262 return mapping.findForward(RiceConstants.MAPPING_BASIC); 263 } 264 265 /** 266 * Default refresh method. Called from returning frameworks. 267 * 268 * @param mapping 269 * @param form 270 * @param request 271 * @param response 272 * @return 273 * @throws Exception 274 */ 275 public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 276 return mapping.findForward(RiceConstants.MAPPING_BASIC); 277 } 278 279 280 /** 281 * Parses the method to call attribute to pick off the line number which should be deleted. 282 * 283 * @param request 284 * @return 285 */ 286 protected int getLineToDelete(HttpServletRequest request) { 287 return getSelectedLine(request); 288 } 289 290 /** 291 * Parses the method to call attribute to pick off the line number which should be edited. 292 * 293 * @param request 294 * @return 295 */ 296 protected int getLineToEdit(HttpServletRequest request) { 297 return getSelectedLine(request); 298 } 299 300 /** 301 * Parses the method to call attribute to pick off the line number which should have an action performed on it. 302 * 303 * @param request 304 * @return 305 */ 306 protected int getSelectedLine(HttpServletRequest request) { 307 int selectedLine = -1; 308 String parameterName = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE); 309 if (StringUtils.isNotBlank(parameterName)) { 310 String lineNumber = StringUtils.substringBetween(parameterName, ".line", "."); 311 if (StringUtils.isEmpty(lineNumber)) { 312 return selectedLine; 313 } 314 selectedLine = Integer.parseInt(lineNumber); 315 } 316 317 return selectedLine; 318 } 319 320 /** 321 * Determines which tab was requested to be toggled 322 * 323 * @param request 324 * @return 325 */ 326 protected String getTabToToggle(HttpServletRequest request) { 327 String tabToToggle = ""; 328 String parameterName = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE); 329 if (StringUtils.isNotBlank(parameterName)) { 330 tabToToggle = StringUtils.substringBetween(parameterName, ".tab", "."); 331 } 332 333 return tabToToggle; 334 } 335 336 /** 337 * Retrieves the header tab to navigate to. 338 * 339 * @param request 340 * @return 341 */ 342 protected String getHeaderTabNavigateTo(HttpServletRequest request) { 343 String headerTabNavigateTo = RiceConstants.MAPPING_BASIC; 344 String imageContext = getImageContext(request, KRADConstants.NAVIGATE_TO); 345 if (StringUtils.isNotBlank(imageContext)) { 346 headerTabNavigateTo = imageContext; 347 } 348 return headerTabNavigateTo; 349 } 350 351 /** 352 * Retrieves the header tab dispatch. 353 * 354 * @param request 355 * @return 356 */ 357 protected String getHeaderTabDispatch(HttpServletRequest request) { 358 String headerTabDispatch = null; 359 String imageContext = getImageContext(request, KRADConstants.HEADER_DISPATCH); 360 if (StringUtils.isNotBlank(imageContext)) { 361 headerTabDispatch = imageContext; 362 } 363 else { 364 // In some cases it might be in request params instead 365 headerTabDispatch = request.getParameter(KRADConstants.METHOD_TO_CALL_ATTRIBUTE); 366 } 367 return headerTabDispatch; 368 } 369 370 /** 371 * Retrieves the image context 372 * 373 * @param request 374 * @param contextKey 375 * @return 376 */ 377 protected String getImageContext(HttpServletRequest request, String contextKey) { 378 String imageContext = ""; 379 String parameterName = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE); 380 if (StringUtils.isBlank(parameterName)) { 381 parameterName = request.getParameter("methodToCallPath"); 382 } 383 if (StringUtils.isNotBlank(parameterName)) { 384 imageContext = StringUtils.substringBetween(parameterName, contextKey, "."); 385 } 386 return imageContext; 387 } 388 389 protected String getReturnLocation(HttpServletRequest request, ActionMapping mapping) { 390 String mappingPath = mapping.getPath(); 391 String basePath = getApplicationBaseUrl(); 392 return basePath + ("/lookup".equals(mappingPath) || "/maintenance".equals(mappingPath) || "/multipleValueLookup".equals(mappingPath) ? "/kr" : "") + mappingPath + ".do"; 393 } 394 395 /** 396 * Retrieves the value of a parameter to be passed into the lookup or inquiry frameworks. The default implementation of this method will attempt to look 397 * in the request to determine wheter the appropriate value exists as a request parameter. If not, it will attempt to look through the form object to find 398 * the property. 399 * 400 * @param boClass a class implementing boClass, representing the BO that will be looked up 401 * @param parameterName the name of the parameter 402 * @param parameterValuePropertyName the property (relative to the form object) where the value to be passed into the lookup/inquiry may be found 403 * @param form 404 * @param request 405 * @return 406 */ 407 protected String retrieveLookupParameterValue(Class<? extends BusinessObject> boClass, String parameterName, String parameterValuePropertyName, ActionForm form, HttpServletRequest request) throws Exception { 408 String value; 409 if (StringUtils.contains(parameterValuePropertyName, "'")) { 410 value = StringUtils.replace(parameterValuePropertyName, "'", ""); 411 } else if (request.getParameterMap().containsKey(parameterValuePropertyName)) { 412 value = request.getParameter(parameterValuePropertyName); 413 } else if (request.getParameterMap().containsKey(KewApiConstants.DOCUMENT_ATTRIBUTE_FIELD_PREFIX + parameterValuePropertyName)) { 414 value = request.getParameter(KewApiConstants.DOCUMENT_ATTRIBUTE_FIELD_PREFIX + parameterValuePropertyName); 415 } else { 416 if (form instanceof KualiForm) { 417 value = ((KualiForm) form).retrieveFormValueForLookupInquiryParameters(parameterName, parameterValuePropertyName); 418 } else { 419 if (LOG.isDebugEnabled()) { 420 LOG.debug("Unable to retrieve lookup/inquiry parameter value for parameter name " + parameterName + " parameter value property " + parameterValuePropertyName); 421 } 422 value = null; 423 } 424 } 425 426 if (value != null && boClass != null && getBusinessObjectAuthorizationService().attributeValueNeedsToBeEncryptedOnFormsAndLinks(boClass, parameterName)) { 427 if(CoreApiServiceLocator.getEncryptionService().isEnabled()) { 428 value = getEncryptionService().encrypt(value) + EncryptionService.ENCRYPTION_POST_PREFIX; 429 } 430 } 431 return value; 432 } 433 434 /** 435 * Takes care of storing the action form in the User session and forwarding to the lookup action. 436 * 437 * @param mapping 438 * @param form 439 * @param request 440 * @param response 441 * @return 442 * @throws Exception 443 */ 444 @SuppressWarnings("unchecked") 445 public ActionForward performLookup(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 446 // parse out the important strings from our methodToCall parameter 447 String fullParameter = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE); 448 validateLookupInquiryFullParameter(request, form, fullParameter); 449 450 KualiForm kualiForm = (KualiForm) form; 451 452 // when we return from the lookup, our next request's method to call is going to be refresh 453 kualiForm.registerEditableProperty(KRADConstants.DISPATCH_REQUEST_PARAMETER); 454 455 // parse out the baseLookupUrl if there is one 456 String baseLookupUrl = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM14_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM14_RIGHT_DEL); 457 458 // parse out business object class name for lookup 459 String boClassName = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_BOPARM_LEFT_DEL, KRADConstants.METHOD_TO_CALL_BOPARM_RIGHT_DEL); 460 if (StringUtils.isBlank(boClassName)) { 461 throw new RuntimeException("Illegal call to perform lookup, no business object class name specified."); 462 } 463 Class boClass = null; 464 465 try{ 466 boClass = Class.forName(boClassName); 467 } catch(ClassNotFoundException cnfex){ 468 if ((StringUtils.isNotEmpty(baseLookupUrl) && baseLookupUrl.startsWith(getApplicationBaseUrl() + "/kr/")) 469 || StringUtils.isEmpty(baseLookupUrl)) { 470 throw new IllegalArgumentException("The class (" + boClassName + ") cannot be found by this particular " 471 + "application. " + "ApplicationBaseUrl: " + getApplicationBaseUrl() 472 + " ; baseLookupUrl: " + baseLookupUrl); 473 } else { 474 LOG.info("The class (" + boClassName + ") cannot be found by this particular application. " 475 + "ApplicationBaseUrl: " + getApplicationBaseUrl() + " ; baseLookupUrl: " + baseLookupUrl); 476 } 477 } 478 479 // build the parameters for the lookup url 480 Properties parameters = new Properties(); 481 String conversionFields = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM1_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM1_RIGHT_DEL); 482 if (StringUtils.isNotBlank(conversionFields)) { 483 parameters.put(KRADConstants.CONVERSION_FIELDS_PARAMETER, conversionFields); 484 485 // register each of the destination parameters of the field conversion string as editable 486 String[] fieldConversions = conversionFields.split(KRADConstants.FIELD_CONVERSIONS_SEPARATOR); 487 for (String fieldConversion : fieldConversions) { 488 String destination = fieldConversion.split(KRADConstants.FIELD_CONVERSION_PAIR_SEPARATOR, 2)[1]; 489 kualiForm.registerEditableProperty(destination); 490 } 491 } 492 493 // pass values from form that should be pre-populated on lookup search 494 String parameterFields = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM2_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM2_RIGHT_DEL); 495 if ( LOG.isDebugEnabled() ) { 496 LOG.debug( "fullParameter: " + fullParameter ); 497 LOG.debug( "parameterFields: " + parameterFields ); 498 } 499 if (StringUtils.isNotBlank(parameterFields)) { 500 String[] lookupParams = parameterFields.split(KRADConstants.FIELD_CONVERSIONS_SEPARATOR); 501 if ( LOG.isDebugEnabled() ) { 502 LOG.debug( "lookupParams: " + Arrays.toString(lookupParams) ); 503 } 504 for (String lookupParam : lookupParams) { 505 String[] keyValue = lookupParam.split(KRADConstants.FIELD_CONVERSION_PAIR_SEPARATOR, 2); 506 if (keyValue.length != 2) { 507 throw new RuntimeException("malformed field conversion pair: " + Arrays.toString(keyValue)); 508 } 509 510 String lookupParameterValue = retrieveLookupParameterValue(boClass, keyValue[1], keyValue[0], form, request); 511 if (StringUtils.isNotBlank(lookupParameterValue)) { 512 parameters.put(keyValue[1], lookupParameterValue); 513 } 514 515 if ( LOG.isDebugEnabled() ) { 516 LOG.debug( "keyValue[0]: " + keyValue[0] ); 517 LOG.debug( "keyValue[1]: " + keyValue[1] ); 518 } 519 } 520 } 521 522 // pass values from form that should be read-Only on lookup search 523 String readOnlyFields = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM8_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM8_RIGHT_DEL); 524 if (StringUtils.isNotBlank(readOnlyFields)) { 525 parameters.put(KRADConstants.LOOKUP_READ_ONLY_FIELDS, readOnlyFields); 526 } 527 528 if ( LOG.isDebugEnabled() ) { 529 LOG.debug( "fullParameter: " + fullParameter ); 530 LOG.debug( "readOnlyFields: " + readOnlyFields ); 531 } 532 533 // grab whether or not the "return value" link should be hidden or not 534 String hideReturnLink = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM3_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM3_RIGHT_DEL); 535 if (StringUtils.isNotBlank(hideReturnLink)) { 536 parameters.put(KRADConstants.HIDE_LOOKUP_RETURN_LINK, hideReturnLink); 537 } 538 539 // add the optional extra button source and parameters string 540 String extraButtonSource = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM4_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM4_RIGHT_DEL); 541 if (StringUtils.isNotBlank(extraButtonSource)) { 542 parameters.put(KRADConstants.EXTRA_BUTTON_SOURCE, extraButtonSource); 543 } 544 String extraButtonParams = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM5_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM5_RIGHT_DEL); 545 if (StringUtils.isNotBlank(extraButtonParams)) { 546 parameters.put(KRADConstants.EXTRA_BUTTON_PARAMS, extraButtonParams); 547 } 548 549 String lookupAction = KRADConstants.LOOKUP_ACTION; 550 551 // is this a multi-value return? 552 boolean isMultipleValue = false; 553 String multipleValues = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM6_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM6_RIGHT_DEL); 554 if ((new Boolean(multipleValues).booleanValue())) { 555 parameters.put(KRADConstants.MULTIPLE_VALUE, multipleValues); 556 lookupAction = KRADConstants.MULTIPLE_VALUE_LOOKUP_ACTION; 557 isMultipleValue = true; 558 } 559 560 // the name of the collection being looked up (primarily for multivalue lookups 561 String lookedUpCollectionName = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM11_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM11_RIGHT_DEL); 562 if (StringUtils.isNotBlank(lookedUpCollectionName)) { 563 parameters.put(KRADConstants.LOOKED_UP_COLLECTION_NAME, lookedUpCollectionName); 564 } 565 566 // grab whether or not the "suppress actions" column should be hidden or not 567 String suppressActions = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM7_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM7_RIGHT_DEL); 568 if (StringUtils.isNotBlank(suppressActions)) { 569 parameters.put(KRADConstants.SUPPRESS_ACTIONS, suppressActions); 570 } 571 572 // grab the references that should be refreshed upon returning from the lookup 573 String referencesToRefresh = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM10_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM10_RIGHT_DEL); 574 if (StringUtils.isNotBlank(referencesToRefresh)) { 575 parameters.put(KRADConstants.REFERENCES_TO_REFRESH, referencesToRefresh); 576 } 577 578 // anchor, if it exists 579 if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getAnchor())) { 580 parameters.put(KRADConstants.LOOKUP_ANCHOR, ((KualiForm) form).getAnchor()); 581 } 582 583 // now add required parameters 584 parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, "start"); 585 586 // pass value from form that shows if autoSearch is desired for lookup search 587 String autoSearch = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM9_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM9_RIGHT_DEL); 588 589 if (StringUtils.isNotBlank(autoSearch)) { 590 parameters.put(KRADConstants.LOOKUP_AUTO_SEARCH, autoSearch); 591 if ("YES".equalsIgnoreCase(autoSearch)){ 592 parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, "search"); 593 } 594 } 595 596 parameters.put(KRADConstants.DOC_FORM_KEY, GlobalVariables.getUserSession().addObjectWithGeneratedKey(form)); 597 parameters.put(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, boClassName); 598 599 parameters.put(KRADConstants.RETURN_LOCATION_PARAMETER, getReturnLocation(request, mapping)); 600 601 if (form instanceof KualiDocumentFormBase) { 602 String docNum = ((KualiDocumentFormBase) form).getDocument().getDocumentNumber(); 603 if(docNum != null){ 604 parameters.put(KRADConstants.DOC_NUM, docNum); 605 } 606 }else if(form instanceof LookupForm){ 607 String docNum = ((LookupForm) form).getDocNum(); 608 if(docNum != null){ 609 parameters.put(KRADConstants.DOC_NUM, ((LookupForm) form).getDocNum()); 610 } 611 } 612 613 if (boClass != null) { 614 ModuleService responsibleModuleService = getKualiModuleService().getResponsibleModuleService(boClass); 615 if(responsibleModuleService!=null && responsibleModuleService.isExternalizable(boClass)){ 616 Map<String, String> parameterMap = new HashMap<String, String>(); 617 Enumeration<Object> e = parameters.keys(); 618 while (e.hasMoreElements()) { 619 String paramName = (String) e.nextElement(); 620 parameterMap.put(paramName, parameters.getProperty(paramName)); 621 } 622 return new ActionForward(responsibleModuleService.getExternalizableBusinessObjectLookupUrl(boClass, parameterMap), true); 623 } 624 } 625 626 if (StringUtils.isBlank(baseLookupUrl)) { 627 baseLookupUrl = getApplicationBaseUrl() + "/kr/" + lookupAction; 628 } else { 629 if (isMultipleValue) { 630 LookupUtils.transformLookupUrlToMultiple(baseLookupUrl); 631 } 632 } 633 String lookupUrl = UrlFactory.parameterizeUrl(baseLookupUrl, parameters); 634 return new ActionForward(lookupUrl, true); 635 } 636 637 protected void validateLookupInquiryFullParameter(HttpServletRequest request, ActionForm form, String fullParameter){ 638 PojoFormBase pojoFormBase = (PojoFormBase) form; 639 if(WebUtils.isFormSessionDocument((PojoFormBase) form)){ 640 if(!pojoFormBase.isPropertyEditable(fullParameter)) { 641 throw new RuntimeException("The methodToCallAttribute is not registered as an editable property."); 642 } 643 } 644 } 645 646 @SuppressWarnings("unchecked") 647 public ActionForward performInquiry(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 648 // parse out the important strings from our methodToCall parameter 649 String fullParameter = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE); 650 validateLookupInquiryFullParameter(request, form, fullParameter); 651 652 // when javascript is disabled, the inquiry will appear in the same window as the document. when we close the inquiry, 653 // our next request's method to call is going to be refresh 654 KualiForm kualiForm = (KualiForm) form; 655 kualiForm.registerEditableProperty(KRADConstants.DISPATCH_REQUEST_PARAMETER); 656 657 // parse out business object class name for lookup 658 String boClassName = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_BOPARM_LEFT_DEL, KRADConstants.METHOD_TO_CALL_BOPARM_RIGHT_DEL); 659 if (StringUtils.isBlank(boClassName)) { 660 throw new RuntimeException("Illegal call to perform inquiry, no business object class name specified."); 661 } 662 663 // build the parameters for the inquiry url 664 Properties parameters = new Properties(); 665 parameters.put(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, boClassName); 666 667 parameters.put(KRADConstants.RETURN_LOCATION_PARAMETER, getReturnLocation(request, mapping)); 668 669 // pass values from form that should be pre-populated on inquiry 670 String parameterFields = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM2_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM2_RIGHT_DEL); 671 if ( LOG.isDebugEnabled() ) { 672 LOG.debug( "fullParameter: " + fullParameter ); 673 LOG.debug( "parameterFields: " + parameterFields ); 674 } 675 if (StringUtils.isNotBlank(parameterFields)) { 676 // TODO : create a method for this to be used by both lookup & inquiry ? 677 String[] inquiryParams = parameterFields.split(KRADConstants.FIELD_CONVERSIONS_SEPARATOR); 678 if ( LOG.isDebugEnabled() ) { 679 LOG.debug( "inquiryParams: " + inquiryParams ); 680 } 681 Class<? extends BusinessObject> boClass = (Class<? extends BusinessObject>) Class.forName(boClassName); 682 for (String inquiryParam : inquiryParams) { 683 String[] keyValue = inquiryParam.split(KRADConstants.FIELD_CONVERSION_PAIR_SEPARATOR, 2); 684 685 String inquiryParameterValue = retrieveLookupParameterValue(boClass, keyValue[1], keyValue[0], form, request); 686 if (inquiryParameterValue == null) { 687 parameters.put(keyValue[1], "directInquiryKeyNotSpecified"); 688 } 689 else { 690 parameters.put(keyValue[1], inquiryParameterValue); 691 } 692 693 if ( LOG.isDebugEnabled() ) { 694 LOG.debug( "keyValue[0]: " + keyValue[0] ); 695 LOG.debug( "keyValue[1]: " + keyValue[1] ); 696 } 697 } 698 } 699 parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, "start"); 700 parameters.put(KRADConstants.DOC_FORM_KEY, GlobalVariables.getUserSession().addObjectWithGeneratedKey(form)); 701 String inquiryUrl = null; 702 try { 703 Class.forName(boClassName); 704 inquiryUrl = getApplicationBaseUrl() + "/kr/" + KRADConstants.DIRECT_INQUIRY_ACTION; 705 } catch ( ClassNotFoundException ex ) { 706 // allow inquiry url to be null (and therefore no inquiry link will be displayed) but at least log a warning 707 LOG.warn("Class name does not represent a valid class which this application understands: " + boClassName); 708 } 709 inquiryUrl = UrlFactory.parameterizeUrl(inquiryUrl, parameters); 710 return new ActionForward(inquiryUrl, true); 711 712 } 713 714 /** 715 * This method handles rendering the question component, but without any of the extra error fields 716 * 717 * @param mapping 718 * @param form 719 * @param request 720 * @param response 721 * @param questionId 722 * @param questionText 723 * @param questionType 724 * @param caller 725 * @param context 726 * @return ActionForward 727 * @throws Exception 728 */ 729 protected ActionForward performQuestionWithoutInput(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String questionId, String questionText, String questionType, String caller, String context) throws Exception { 730 return performQuestion(mapping, form, request, response, questionId, questionText, questionType, caller, context, false, "", "", "", ""); 731 } 732 733 /** 734 * Handles rendering a question prompt - without a specified context. 735 * 736 * @param mapping 737 * @param form 738 * @param request 739 * @param response 740 * @param questionId 741 * @param questionText 742 * @param questionType 743 * @param caller 744 * @param context 745 * @return ActionForward 746 * @throws Exception 747 */ 748 protected ActionForward performQuestionWithInput(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String questionId, String questionText, String questionType, String caller, String context) throws Exception { 749 return performQuestion(mapping, form, request, response, questionId, questionText, questionType, caller, context, true, "", "", "", ""); 750 } 751 752 /** 753 * Handles re-rendering a question prompt because of an error on what was submitted. 754 * 755 * @param mapping 756 * @param form 757 * @param request 758 * @param response 759 * @param questionId 760 * @param questionText 761 * @param questionType 762 * @param caller 763 * @param context 764 * @param reason 765 * @param errorKey 766 * @param errorPropertyName 767 * @param errorParameter 768 * @return ActionForward 769 * @throws Exception 770 */ 771 protected ActionForward performQuestionWithInputAgainBecauseOfErrors(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String questionId, String questionText, String questionType, String caller, String context, String reason, String errorKey, String errorPropertyName, String errorParameter) throws Exception { 772 return performQuestion(mapping, form, request, response, questionId, questionText, questionType, caller, context, true, reason, errorKey, errorPropertyName, errorParameter); 773 } 774 775 /** 776 * Handles rendering a question prompt - with a specified context. 777 * 778 * @param mapping 779 * @param form 780 * @param request 781 * @param response 782 * @param questionId 783 * @param questionText 784 * @param questionType 785 * @param caller 786 * @param context 787 * @param showReasonField 788 * @param reason 789 * @param errorKey 790 * @param errorPropertyName 791 * @param errorParameter 792 * @return ActionForward 793 * @throws Exception 794 */ 795 private ActionForward performQuestion(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String questionId, String questionText, String questionType, String caller, String context, boolean showReasonField, String reason, String errorKey, String errorPropertyName, String errorParameter) throws Exception { 796 Properties parameters = new Properties(); 797 798 parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, "start"); 799 parameters.put(KRADConstants.DOC_FORM_KEY, GlobalVariables.getUserSession().addObjectWithGeneratedKey(form)); 800 parameters.put(KRADConstants.CALLING_METHOD, caller); 801 parameters.put(KRADConstants.QUESTION_INST_ATTRIBUTE_NAME, questionId); 802 parameters.put(KRADConstants.QUESTION_IMPL_ATTRIBUTE_NAME, questionType); 803 //parameters.put(KRADConstants.QUESTION_TEXT_ATTRIBUTE_NAME, questionText); 804 parameters.put(KRADConstants.RETURN_LOCATION_PARAMETER, getReturnLocation(request, mapping)); 805 parameters.put(KRADConstants.QUESTION_CONTEXT, context); 806 parameters.put(KRADConstants.QUESTION_SHOW_REASON_FIELD, Boolean.toString(showReasonField)); 807 parameters.put(KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME, reason); 808 parameters.put(KRADConstants.QUESTION_ERROR_KEY, errorKey); 809 parameters.put(KRADConstants.QUESTION_ERROR_PROPERTY_NAME, errorPropertyName); 810 parameters.put(KRADConstants.QUESTION_ERROR_PARAMETER, errorParameter); 811 parameters.put(KRADConstants.QUESTION_ANCHOR, form instanceof KualiForm ? ObjectUtils.toString(((KualiForm) form).getAnchor()) : ""); 812 Object methodToCallAttribute = request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE); 813 if (methodToCallAttribute != null) { 814 parameters.put(KRADConstants.METHOD_TO_CALL_PATH, methodToCallAttribute); 815 ((PojoForm) form).registerEditableProperty(String.valueOf(methodToCallAttribute)); 816 } 817 818 if (form instanceof KualiDocumentFormBase) { 819 String docNum = ((KualiDocumentFormBase) form).getDocument().getDocumentNumber(); 820 if(docNum != null){ 821 parameters.put(KRADConstants.DOC_NUM, ((KualiDocumentFormBase) form) 822 .getDocument().getDocumentNumber()); 823 } 824 } 825 826 // KULRICE-8077: PO Quote Limitation of Only 9 Vendors 827 String questionTextAttributeName = KRADConstants.QUESTION_TEXT_ATTRIBUTE_NAME + questionId; 828 GlobalVariables.getUserSession().addObject(questionTextAttributeName, (Object)questionText); 829 830 String questionUrl = UrlFactory.parameterizeUrl(getApplicationBaseUrl() + "/kr/" + KRADConstants.QUESTION_ACTION, parameters); 831 return new ActionForward(questionUrl, true); 832 } 833 834 835 /** 836 * Takes care of storing the action form in the User session and forwarding to the workflow workgroup lookup action. 837 * 838 * @param mapping 839 * @param form 840 * @param request 841 * @param response 842 * @return 843 * @throws Exception 844 */ 845 public ActionForward performWorkgroupLookup(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 846 String returnUrl = null; 847 if ("/kr".equals(mapping.getModuleConfig().getPrefix())) { 848 returnUrl = getApplicationBaseUrl() + mapping.getModuleConfig().getPrefix() + mapping.getPath() + ".do"; 849 } else { 850 returnUrl = getApplicationBaseUrl() + mapping.getPath() + ".do"; 851 } 852 853 854 String fullParameter = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE); 855 String conversionFields = StringUtils.substringBetween(fullParameter, KRADConstants.METHOD_TO_CALL_PARM1_LEFT_DEL, KRADConstants.METHOD_TO_CALL_PARM1_RIGHT_DEL); 856 857 String deploymentBaseUrl = CoreApiServiceLocator.getKualiConfigurationService().getPropertyValueAsString( 858 KRADConstants.WORKFLOW_URL_KEY); 859 String workgroupLookupUrl = deploymentBaseUrl + "/Lookup.do?lookupableImplServiceName=WorkGroupLookupableImplService&methodToCall=start&docFormKey=" + GlobalVariables.getUserSession().addObjectWithGeneratedKey(form); 860 861 if (conversionFields != null) { 862 workgroupLookupUrl += "&conversionFields=" + conversionFields; 863 } 864 if (form instanceof KualiDocumentFormBase) { 865 workgroupLookupUrl +="&docNum="+ ((KualiDocumentFormBase) form).getDocument().getDocumentNumber(); 866 } 867 868 workgroupLookupUrl += "&returnLocation=" + returnUrl; 869 870 return new ActionForward(workgroupLookupUrl, true); 871 } 872 873 /** 874 * Handles requests that originate via Header Tabs. 875 * 876 * @param mapping 877 * @param form 878 * @param request 879 * @param response 880 * @return 881 * @throws Exception 882 */ 883 public ActionForward headerTab(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 884 // header tab actions can do two things - 1, call into an action and perform what needs to happen in there and 2, forward to 885 // a new location. 886 String headerTabDispatch = getHeaderTabDispatch(request); 887 if (StringUtils.isNotEmpty(headerTabDispatch)) { 888 ActionForward forward = dispatchMethod(mapping, form, request, response, headerTabDispatch); 889 if (GlobalVariables.getMessageMap().getNumberOfPropertiesWithErrors() > 0) { 890 return mapping.findForward(RiceConstants.MAPPING_BASIC); 891 } 892 this.doTabOpenOrClose(mapping, form, request, response, false); 893 if (forward.getRedirect()) { 894 return forward; 895 } 896 } 897 return dispatchMethod(mapping, form, request, response, getHeaderTabNavigateTo(request)); 898 } 899 900 /** 901 * Override this method to provide action-level access controls to the application. 902 * 903 * @param form 904 * @throws AuthorizationException 905 */ 906 protected void checkAuthorization( ActionForm form, String methodToCall) throws AuthorizationException 907 { 908 String principalId = GlobalVariables.getUserSession().getPrincipalId(); 909 Map<String, String> roleQualifier = new HashMap<String, String>(getRoleQualification(form, methodToCall)); 910 Map<String, String> permissionDetails = KRADUtils.getNamespaceAndActionClass(this.getClass()); 911 912 if (!KimApiServiceLocator.getPermissionService().isAuthorizedByTemplate(principalId, 913 KRADConstants.KNS_NAMESPACE, KimConstants.PermissionTemplateNames.USE_SCREEN, permissionDetails, 914 roleQualifier)) 915 { 916 throw new AuthorizationException(GlobalVariables.getUserSession().getPerson().getPrincipalName(), 917 methodToCall, 918 this.getClass().getSimpleName()); 919 } 920 } 921 922 /** 923 * override this method to add data from the form for role qualification in the authorization check 924 */ 925 protected Map<String,String> getRoleQualification(ActionForm form, String methodToCall) { 926 return new HashMap<String,String>(); 927 } 928 929 protected static KualiModuleService getKualiModuleService() { 930 if ( kualiModuleService == null ) { 931 kualiModuleService = KRADServiceLocatorWeb.getKualiModuleService(); 932 } 933 return kualiModuleService; 934 } 935 936 /** 937 * Constant defined to match with TextArea.jsp and updateTextArea function in core.js 938 * <p>Value is textAreaFieldName 939 */ 940 public static final String TEXT_AREA_FIELD_NAME="textAreaFieldName"; 941 /** 942 * Constant defined to match with TextArea.jsp and updateTextArea function in core.js 943 * <p>Value is textAreaFieldLabel 944 */ 945 public static final String TEXT_AREA_FIELD_LABEL="textAreaFieldLabel"; 946 /** 947 * Constant defined to match with TextArea.jsp and updateTextArea function in core.js 948 * <p>Value is textAreaReadOnly 949 */ 950 public static final String TEXT_AREA_READ_ONLY="textAreaReadOnly"; 951 /** 952 * Constant defined to match with TextArea.jsp and updateTextArea function in core.js 953 * <p>Value is textAreaFieldAnchor 954 */ 955 public static final String TEXT_AREA_FIELD_ANCHOR="textAreaFieldAnchor"; 956 /** 957 * Constant defined to match with TextArea.jsp and updateTextArea function in core.js 958 * <p>Value is textAreaFieldAnchor 959 */ 960 public static final String TEXT_AREA_MAX_LENGTH="textAreaMaxLength"; 961 /** 962 * Constant defined to match with TextArea.jsp and updateTextArea function in core.js 963 * <p>Value is htmlFormAction 964 */ 965 public static final String FORM_ACTION="htmlFormAction"; 966 /** 967 * Constant defined to match input parameter from URL and from TextArea.jsp. 968 * <p>Value is methodToCall 969 */ 970 public static final String METHOD_TO_CALL="methodToCall"; 971 /** 972 * Constant defined to match with global forwarding in struts-config.xml 973 * for Text Area Update. 974 * <p>Value is updateTextArea 975 */ 976 public static final String FORWARD_TEXT_AREA_UPDATE="updateTextArea"; 977 /** 978 * Constant defined to match with method to call in TextArea.jsp. 979 * <p>Value is postTextAreaToParent 980 */ 981 public static final String POST_TEXT_AREA_TO_PARENT="postTextAreaToParent"; 982 /** 983 * Constant defined to match with local forwarding in struts-config.xml 984 * for the parent of the Updated Text Area. 985 * <p>Value is forwardNext 986 */ 987 public static final String FORWARD_NEXT="forwardNext"; 988 989 /** 990 * This method is invoked when Java Script is turned off from the web browser. It 991 * setup the information that the update text area requires for copying current text 992 * in the calling page text area and returning to the calling page. The information 993 * is passed to the JSP through Http Request attributes. All other parameters are 994 * forwarded 995 * 996 * @param mapping 997 * @param form 998 * @param request 999 * @param response 1000 * @return 1001 */ 1002 public ActionForward updateTextArea(ActionMapping mapping, 1003 ActionForm form, 1004 HttpServletRequest request, 1005 HttpServletResponse response) { 1006 if (LOG.isTraceEnabled()) { 1007 String lm=String.format("ENTRY %s%n%s", form.getClass().getSimpleName(), 1008 request.getRequestURI()); 1009 LOG.trace(lm); 1010 } 1011 1012 final String[] keyValue = getTextAreaParams(request); 1013 1014 request.setAttribute(TEXT_AREA_FIELD_NAME, keyValue[0]); 1015 request.setAttribute(FORM_ACTION,keyValue[1]); 1016 request.setAttribute(TEXT_AREA_FIELD_LABEL,keyValue[2]); 1017 request.setAttribute(TEXT_AREA_READ_ONLY,keyValue[3]); 1018 request.setAttribute(TEXT_AREA_MAX_LENGTH,keyValue[4]); 1019 if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getAnchor())) { 1020 request.setAttribute(TEXT_AREA_FIELD_ANCHOR,((KualiForm) form).getAnchor()); 1021 } 1022 1023 // Set document related parameter 1024 String docWebScope=(String)request.getAttribute(KRADConstants.DOCUMENT_WEB_SCOPE); 1025 if (docWebScope != null && docWebScope.trim().length() >= 0) { 1026 request.setAttribute(KRADConstants.DOCUMENT_WEB_SCOPE, docWebScope); 1027 } 1028 1029 request.setAttribute(KRADConstants.DOC_FORM_KEY, GlobalVariables.getUserSession().addObjectWithGeneratedKey(form)); 1030 1031 ActionForward forward=mapping.findForward(FORWARD_TEXT_AREA_UPDATE); 1032 1033 if (LOG.isTraceEnabled()) { 1034 String lm=String.format("EXIT %s", (forward==null)?"null":forward.getPath()); 1035 LOG.trace(lm); 1036 } 1037 1038 return forward; 1039 } 1040 1041 /** 1042 * This method takes the {@link org.kuali.rice.krad.util.KRADConstants.METHOD_TO_CALL_ATTRIBUTE} out of the request 1043 * and parses it returning the required fields needed for a text area. The fields returned 1044 * are the following in this order. 1045 * <ol> 1046 * <li>{@link #TEXT_AREA_FIELD_NAME}</li> 1047 * <li>{@link #FORM_ACTION}</li> 1048 * <li>{@link #TEXT_AREA_FIELD_LABEL}</li> 1049 * <li>{@link #TEXT_AREA_READ_ONLY}</li> 1050 * <li>{@link #TEXT_AREA_MAX_LENGTH}</li> 1051 * </ol> 1052 * 1053 * @param request the request to retrieve the textarea parameters 1054 * @return a string array holding the parsed fields 1055 */ 1056 private String[] getTextAreaParams(HttpServletRequest request) { 1057 // parse out the important strings from our methodToCall parameter 1058 String fullParameter = (String) request.getAttribute( 1059 KRADConstants.METHOD_TO_CALL_ATTRIBUTE); 1060 1061 // parse textfieldname:htmlformaction 1062 String parameterFields = StringUtils.substringBetween(fullParameter, 1063 KRADConstants.METHOD_TO_CALL_PARM2_LEFT_DEL, 1064 KRADConstants.METHOD_TO_CALL_PARM2_RIGHT_DEL); 1065 if ( LOG.isDebugEnabled() ) { 1066 LOG.debug( "fullParameter: " + fullParameter ); 1067 LOG.debug( "parameterFields: " + parameterFields ); 1068 } 1069 String[] keyValue = null; 1070 if (StringUtils.isNotBlank(parameterFields)) { 1071 String[] textAreaParams = parameterFields.split( 1072 KRADConstants.FIELD_CONVERSIONS_SEPARATOR); 1073 if ( LOG.isDebugEnabled() ) { 1074 LOG.debug( "lookupParams: " + textAreaParams ); 1075 } 1076 for (final String textAreaParam : textAreaParams) { 1077 keyValue = textAreaParam.split(KRADConstants.FIELD_CONVERSION_PAIR_SEPARATOR, 2); 1078 1079 if ( LOG.isDebugEnabled() ) { 1080 LOG.debug( "keyValue[0]: " + keyValue[0] ); 1081 LOG.debug( "keyValue[1]: " + keyValue[1] ); 1082 LOG.debug( "keyValue[2]: " + keyValue[2] ); 1083 LOG.debug( "keyValue[3]: " + keyValue[3] ); 1084 LOG.debug( "keyValue[4]: " + keyValue[4] ); 1085 } 1086 } 1087 } 1088 1089 return keyValue; 1090 } 1091 1092 /** 1093 * This method is invoked from the TextArea.jsp for posting its value to the parent 1094 * page that called the extended text area page. The invocation is done through 1095 * Struts action. The default forwarding id is RiceContants.MAPPING_BASIC. This 1096 * can be overridden using the parameter key FORWARD_NEXT. 1097 * 1098 * @param mapping 1099 * @param form 1100 * @param request 1101 * @param response 1102 * @return 1103 */ 1104 public ActionForward postTextAreaToParent(ActionMapping mapping, 1105 ActionForm form, 1106 HttpServletRequest request, 1107 HttpServletResponse response) { 1108 1109 if (LOG.isTraceEnabled()) { 1110 String lm=String.format("ENTRY %s%n%s", form.getClass().getSimpleName(), 1111 request.getRequestURI()); 1112 LOG.trace(lm); 1113 } 1114 1115 String forwardingId=request.getParameter(FORWARD_NEXT); 1116 if (forwardingId == null) { 1117 forwardingId=RiceConstants.MAPPING_BASIC; 1118 } 1119 ActionForward forward=mapping.findForward(forwardingId); 1120 1121 if (LOG.isTraceEnabled()) { 1122 String lm=String.format("EXIT %s", (forward==null)?"null":forward.getPath()); 1123 LOG.trace(lm); 1124 } 1125 1126 return forward; 1127 } 1128 1129 /** 1130 * Use to add a methodToCall to the a list which will not have authorization checks. 1131 * This assumes that the call will be redirected (as in the case of a lookup) that will perform 1132 * the authorization. 1133 */ 1134 protected final void addMethodToCallToUncheckedList( String methodToCall ) { 1135 methodToCallsToNotCheckAuthorization.add(methodToCall); 1136 } 1137 1138 /** 1139 * This method does all special processing on a document that should happen on each HTTP post (ie, save, route, approve, etc). 1140 */ 1141 protected void doProcessingAfterPost( KualiForm form, HttpServletRequest request ) { 1142 1143 } 1144 1145 protected BusinessObjectAuthorizationService getBusinessObjectAuthorizationService() { 1146 if (businessObjectAuthorizationService == null) { 1147 businessObjectAuthorizationService = KNSServiceLocator.getBusinessObjectAuthorizationService(); 1148 } 1149 return businessObjectAuthorizationService; 1150 } 1151 1152 protected EncryptionService getEncryptionService() { 1153 if (encryptionService == null) { 1154 encryptionService = CoreApiServiceLocator.getEncryptionService(); 1155 } 1156 return encryptionService; 1157 } 1158 1159 public static String getApplicationBaseUrl() { 1160 if ( applicationBaseUrl == null ) { 1161 applicationBaseUrl = CoreApiServiceLocator.getKualiConfigurationService().getPropertyValueAsString( 1162 KRADConstants.APPLICATION_URL_KEY); 1163 } 1164 return applicationBaseUrl; 1165 } 1166 1167 protected boolean isModuleLocked(ActionForm form, String methodToCall, HttpServletRequest request) { 1168 String boClass = request.getParameter(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE); 1169 ModuleService moduleService = null; 1170 if(StringUtils.isNotBlank(boClass)) { 1171 try { 1172 moduleService = getKualiModuleService().getResponsibleModuleService(Class.forName(boClass)); 1173 } catch (ClassNotFoundException classNotFoundException) { 1174 LOG.warn("BO class not found: " + boClass, classNotFoundException); 1175 } 1176 } else { 1177 moduleService = getKualiModuleService().getResponsibleModuleService(this.getClass()); 1178 } 1179 if(moduleService != null && moduleService.isLocked()) { 1180 String principalId = GlobalVariables.getUserSession().getPrincipalId(); 1181 String namespaceCode = KRADConstants.KUALI_RICE_SYSTEM_NAMESPACE; 1182 String permissionName = KimConstants.PermissionNames.ACCESS_LOCKED_MODULE; 1183 Map<String, String> qualification = getRoleQualification(form, methodToCall); 1184 if(!KimApiServiceLocator.getPermissionService().isAuthorized(principalId, namespaceCode, permissionName, qualification)) { 1185 ParameterService parameterSerivce = CoreFrameworkServiceLocator.getParameterService(); 1186 String messageParamNamespaceCode = moduleService.getModuleConfiguration().getNamespaceCode(); 1187 String messageParamComponentCode = KRADConstants.DetailTypes.ALL_DETAIL_TYPE; 1188 String messageParamName = KRADConstants.SystemGroupParameterNames.OLTP_LOCKOUT_MESSAGE_PARM; 1189 String lockoutMessage = parameterSerivce.getParameterValueAsString(messageParamNamespaceCode, messageParamComponentCode, messageParamName); 1190 1191 if(StringUtils.isBlank(lockoutMessage)) { 1192 String defaultMessageParamName = KRADConstants.SystemGroupParameterNames.OLTP_LOCKOUT_DEFAULT_MESSAGE; 1193 lockoutMessage = parameterSerivce.getParameterValueAsString(KRADConstants.KNS_NAMESPACE, messageParamComponentCode, defaultMessageParamName); 1194 } 1195 request.setAttribute(KRADConstants.MODULE_LOCKED_MESSAGE_REQUEST_PARAMETER, lockoutMessage); 1196 return true; 1197 } 1198 } 1199 return false; 1200 } 1201}