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 }