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