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.ksb.messaging.web;
017
018 import org.apache.commons.lang.StringUtils;
019 import org.apache.struts.action.ActionErrors;
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.action.ActionMessages;
024 import org.apache.struts.actions.DispatchAction;
025 import org.kuali.rice.core.api.util.RiceConstants;
026 import org.kuali.rice.coreservice.framework.parameter.ParameterService;
027 import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator;
028 import org.kuali.rice.kim.api.KimConstants;
029 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
030 import org.kuali.rice.kns.util.WebUtils;
031 import org.kuali.rice.kns.web.struts.form.KualiForm;
032 import org.kuali.rice.krad.exception.AuthorizationException;
033 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
034 import org.kuali.rice.krad.service.KualiModuleService;
035 import org.kuali.rice.krad.service.ModuleService;
036 import org.kuali.rice.krad.util.GlobalVariables;
037 import org.kuali.rice.krad.util.KRADConstants;
038 import org.kuali.rice.krad.util.KRADUtils;
039
040 import javax.servlet.http.HttpServletRequest;
041 import javax.servlet.http.HttpServletResponse;
042 import java.util.HashMap;
043 import java.util.Iterator;
044 import java.util.Map;
045
046 /**
047 * An abstract super class for all Struts Actions in KEW. Adds some custom
048 * dispatch behavior by extending the Struts DispatchAction.
049 *
050 * @author Kuali Rice Team (rice.collab@kuali.org)
051 */
052 public abstract class KSBAction extends DispatchAction {
053
054 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KSBAction.class);
055
056 @Override
057 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
058
059 checkAuthorization(form, "");
060
061 if(isModuleLocked(form, findMethodToCall(form, request), request)) {
062 return mapping.findForward(RiceConstants.MODULE_LOCKED_MAPPING);
063 }
064
065 try {
066
067
068 ActionMessages messages = null;
069 messages = establishRequiredState(request, form);
070 if (messages != null && !messages.isEmpty()) {
071 // XXX: HACK: FIXME:
072 // obviously this implies that we can't return both ActionErrors
073 // and ActionMessages... :(
074 // probably establishRequiredState should be refactored to have
075 // a generic 'should-we-continue'
076 // boolean return, so that control flow can be more explicitly
077 // specified by the subclass
078 if (messages instanceof ActionErrors) {
079 saveErrors(request, messages);
080 } else {
081 saveMessages(request, messages);
082 }
083 return mapping.findForward("requiredStateError");
084 }
085 LOG.info(request.getQueryString());
086 ActionForward returnForward = null;
087
088 if (request.getParameterMap() != null) {
089 for (Iterator iter = request.getParameterMap().entrySet().iterator(); iter.hasNext();) {
090 String parameterName = (String) ((Map.Entry) iter.next()).getKey();
091 if (parameterName.startsWith("methodToCall.") && parameterName.endsWith(".x")) {
092 String methodToCall = parameterName.substring(parameterName.indexOf("methodToCall.") + 13, parameterName.lastIndexOf(".x"));
093 if (methodToCall != null && methodToCall.length() > 0) {
094 returnForward = this.dispatchMethod(mapping, form, request, response, methodToCall);
095 }
096 }
097 }
098 }
099 if (returnForward == null) {
100 if (request.getParameter("methodToCall") != null && !"".equals(request.getParameter("methodToCall")) && !"execute".equals(request.getParameter("methodToCall"))) {
101 LOG.info("dispatch to methodToCall " + request.getParameter("methodToCall") + " called");
102 returnForward = super.execute(mapping, form, request, response);
103 } else {
104 LOG.info("dispatch to default start methodToCall");
105 returnForward = start(mapping, form, request, response);
106 }
107 }
108
109
110
111 messages = establishFinalState(request, form);
112 if (messages != null && !messages.isEmpty()) {
113 saveMessages(request, messages);
114 return mapping.findForward("finalStateError");
115 }
116 return returnForward;
117 } catch (Exception e) {
118 LOG.error("Error processing action " + mapping.getPath(), e);
119 throw new RuntimeException(e);
120 }
121 }
122
123 protected void checkAuthorization( ActionForm form, String methodToCall) throws AuthorizationException
124 {
125 String principalId = GlobalVariables.getUserSession().getPrincipalId();
126 Map<String, String> roleQualifier = new HashMap<String, String>(getRoleQualification(form, methodToCall));
127 Map<String, String> permissionDetails = KRADUtils.getNamespaceAndActionClass(this.getClass());
128
129 if (!KimApiServiceLocator.getPermissionService().isAuthorizedByTemplate(principalId,
130 KRADConstants.KNS_NAMESPACE, KimConstants.PermissionTemplateNames.USE_SCREEN, permissionDetails,
131 roleQualifier))
132 {
133 throw new AuthorizationException(GlobalVariables.getUserSession().getPrincipalName(),
134 methodToCall,
135 this.getClass().getSimpleName());
136 }
137 }
138
139 /**
140 * override this method to add data from the form for role qualification in the authorization check
141 */
142 protected Map<String,String> getRoleQualification(ActionForm form, String methodToCall) {
143 return new HashMap<String,String>();
144 }
145
146 public abstract ActionForward start(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception;
147
148 public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
149 return start(mapping, form, request, response);
150 }
151
152 public abstract ActionMessages establishRequiredState(HttpServletRequest request, ActionForm form) throws Exception;
153
154 public ActionMessages establishFinalState(HttpServletRequest request, ActionForm form) throws Exception {
155 return null;
156 }
157
158 public ActionForward noOp(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
159 return mapping.findForward("basic");
160 }
161
162 protected static KualiModuleService getKualiModuleService() {
163 return KRADServiceLocatorWeb.getKualiModuleService();
164 }
165
166 protected String findMethodToCall(ActionForm form, HttpServletRequest request) throws Exception {
167 String methodToCall;
168 if (form instanceof KualiForm && StringUtils.isNotEmpty(((KualiForm) form).getMethodToCall())) {
169 methodToCall = ((KualiForm) form).getMethodToCall();
170 }
171 else {
172 // call utility method to parse the methodToCall from the request.
173 methodToCall = WebUtils.parseMethodToCall(form, request);
174 }
175 return methodToCall;
176 }
177
178 protected boolean isModuleLocked(ActionForm form, String methodToCall, HttpServletRequest request) {
179 String boClass = request.getParameter(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE);
180 ModuleService moduleService = null;
181 if(StringUtils.isNotBlank(boClass)) {
182 try {
183 moduleService = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(Class.forName(boClass));
184 } catch (ClassNotFoundException e) {
185 LOG.warn("Module locking mechanism experienced a class not found exception while trying to load " + boClass, e);
186 }
187 } else {
188 moduleService = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(this.getClass());
189 }
190 if(moduleService != null && moduleService.isLocked()) {
191 String principalId = GlobalVariables.getUserSession().getPrincipalId();
192 String namespaceCode = KRADConstants.KUALI_RICE_SYSTEM_NAMESPACE;
193 String permissionName = KimConstants.PermissionNames.ACCESS_LOCKED_MODULE;
194 Map<String, String> permissionDetails = new HashMap<String, String>();
195 Map<String, String> qualification = new HashMap<String, String>(getRoleQualification(form, methodToCall));
196 if(!KimApiServiceLocator.getPermissionService().isAuthorized(principalId, namespaceCode, permissionName, qualification)) {
197 ParameterService parameterSerivce = CoreFrameworkServiceLocator.getParameterService();
198 String messageParamNamespaceCode = moduleService.getModuleConfiguration().getNamespaceCode();
199 String messageParamComponentCode = KRADConstants.DetailTypes.ALL_DETAIL_TYPE;
200 String messageParamName = KRADConstants.SystemGroupParameterNames.OLTP_LOCKOUT_MESSAGE_PARM;
201 String lockoutMessage = parameterSerivce.getParameterValueAsString(messageParamNamespaceCode, messageParamComponentCode, messageParamName);
202
203 if(StringUtils.isBlank(lockoutMessage)) {
204 String defaultMessageParamName = KRADConstants.SystemGroupParameterNames.OLTP_LOCKOUT_DEFAULT_MESSAGE;
205 lockoutMessage = parameterSerivce.getParameterValueAsString(KRADConstants.KNS_NAMESPACE, messageParamComponentCode, defaultMessageParamName);
206 }
207 request.setAttribute(KRADConstants.MODULE_LOCKED_MESSAGE_REQUEST_PARAMETER, lockoutMessage);
208 return true;
209 }
210 }
211 return false;
212 }
213 }