View Javadoc
1   /**
2    * Copyright 2005-2016 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kns.web.struts.action;
17  
18  import org.apache.log4j.Logger;
19  import org.apache.struts.Globals;
20  import org.apache.struts.action.Action;
21  import org.apache.struts.action.ActionForm;
22  import org.apache.struts.action.ActionForward;
23  import org.apache.struts.action.ActionMapping;
24  import org.kuali.rice.core.api.config.property.ConfigContext;
25  import org.kuali.rice.core.api.util.RiceConstants;
26  import org.kuali.rice.kns.util.IncidentReportUtils;
27  import org.kuali.rice.kns.web.struts.form.KualiExceptionIncidentForm;
28  import org.kuali.rice.krad.exception.ExceptionIncident;
29  import org.kuali.rice.krad.exception.KualiExceptionIncident;
30  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
31  import org.kuali.rice.krad.service.KualiExceptionIncidentService;
32  import org.kuali.rice.krad.util.GlobalVariables;
33  import org.kuali.rice.krad.util.KRADConstants;
34  
35  import javax.servlet.http.HttpServletRequest;
36  import javax.servlet.http.HttpServletResponse;
37  import java.util.Enumeration;
38  import java.util.HashMap;
39  import java.util.Map;
40  
41  /**
42   * This is the struts action class for handling the exception for Kuali
43   * applications.
44   *
45   * @deprecated KNS Struts deprecated, use KRAD and the Spring MVC framework.
46   */
47  @Deprecated
48  public class KualiExceptionHandlerAction extends Action {
49  	private static final Logger LOG = Logger
50  			.getLogger(KualiExceptionHandlerAction.class);
51  
52  	private static final String EXCEPTION_TIME_STAMP = "exception-timeStamp";
53  	private static final String EXCEPTION_DOCUMENT_ID = "exception-" + ExceptionIncident.DOCUMENT_ID;
54  	private static final String EXCEPTION_USER_EMAIL = "exception-" + ExceptionIncident.USER_EMAIL;
55  	private static final String EXCEPTION_USER_NAME = "exception-" + ExceptionIncident.USER_NAME;
56  	private static final String EXCEPTION_UUID = "exception-" + ExceptionIncident.UUID;
57  	private static final String EXCEPTION_COMPONENT_NAME = "exception-" + ExceptionIncident.COMPONENT_NAME;
58  	private static final String EXCEPTION_EXCEPTION_REPORT_SUBJECT = "exception-" + ExceptionIncident.EXCEPTION_REPORT_SUBJECT;
59  	private static final String EXCEPTION_EXCEPTION_MESSAGE = "exception-" + ExceptionIncident.EXCEPTION_MESSAGE;
60  	private static final String EXCEPTION_STACK_TRACE = "exception-" + ExceptionIncident.STACK_TRACE;
61  
62  	/**
63  	 * This overridden method dispatches action to be taken based on
64  	 * "methodToCall" parameter. The exception is processed when there is no
65  	 * "methodToCall" specified.
66  	 *
67  	 * @see org.apache.struts.action.Action#execute(org.apache.struts.action.ActionMapping,
68  	 *      org.apache.struts.action.ActionForm,
69  	 *      javax.servlet.http.HttpServletRequest,
70  	 *      javax.servlet.http.HttpServletResponse)
71  	 */
72  	public ActionForward execute(ActionMapping mapping, ActionForm form,
73  			HttpServletRequest request, HttpServletResponse response)
74  			throws Exception {
75  		return executeException(mapping, form, request, response);
76  	}
77  
78  	/**
79  	 * This overridden method processes the exception and post exception (when
80  	 * user either submit/cancel the exception JSP page).
81  	 * <ul>
82  	 * <li>ProcessDefinition application Exception - Exception is stored in Http Request</li>
83  	 * <li>ProcessDefinition exception incident reporting - No exception, only form data</li>
84  	 * </ul>
85  	 *
86  	 * @see org.apache.struts.action.Action#execute(org.apache.struts.action.ActionMapping,
87  	 *      org.apache.struts.action.ActionForm,
88  	 *      javax.servlet.http.HttpServletRequest,
89  	 *      javax.servlet.http.HttpServletResponse)
90  	 */
91  	public ActionForward executeException(ActionMapping mapping,
92  			ActionForm form, HttpServletRequest request,
93  			HttpServletResponse response) throws Exception {
94  
95  		if (LOG.isDebugEnabled()) {
96  			String lm = String.format("ENTRY %s%n%s", form.getClass()
97  					.getSimpleName(), request.getRequestURI());
98  			LOG.debug(lm);
99  		}
100 
101 		// Get exception thrown
102 		Exception e = (Exception) request.getAttribute(Globals.EXCEPTION_KEY);
103 
104 		// Initialize defined action mapping from struts-config
105 		ActionForward returnForward = null;
106 
107 		// In case there is no exception, either a post back after page was
108 		// filled in
109 		// or just an error from directly accessing this struts action
110 		if (e == null) {
111 			if (form instanceof KualiExceptionIncidentForm) {
112 				KualiExceptionIncidentForm formObject = (KualiExceptionIncidentForm) form;
113 				// Manage conditions: submit or cancel
114 				if (!formObject.isCancel()) {
115 					// Locate the post exception handler service. The service id
116 					// is
117 					// defined in the application properties
118 					// Only process the post exception handling when the
119 					// service
120 					// is specified
121 					KualiExceptionIncidentService reporterService = KRADServiceLocatorWeb
122 							.getKualiExceptionIncidentService();
123 					// An instance of the ExceptionIncident is created by
124 					// the
125 					// ExceptionIncidentService
126 					Map reducedMap = new HashMap();
127 					Enumeration<String> names = request.getParameterNames();
128 					while (names.hasMoreElements()) {
129 						String name = names.nextElement();
130 						reducedMap.put(name, request.getParameter(name));
131 					}
132 
133 					// Sensitive data stored in user session
134 					Map<String, Object> userSessionMap = GlobalVariables.getUserSession().getObjectMap();
135 
136 					// Only display if this is the right exception
137 					if(userSessionMap.get("EXCEPTION_TIME_STAMP").toString().equals(reducedMap.get(ExceptionIncident.STACK_TRACE))) {
138 						reducedMap.put(ExceptionIncident.DOCUMENT_ID, userSessionMap.get("EXCEPTION_DOCUMENT_ID").toString());
139 						reducedMap.put(ExceptionIncident.USER_EMAIL, userSessionMap.get("EXCEPTION_USER_EMAIL").toString());
140 						reducedMap.put(ExceptionIncident.USER_NAME, userSessionMap.get("EXCEPTION_USER_NAME").toString());
141 						reducedMap.put(ExceptionIncident.UUID, userSessionMap.get("EXCEPTION_UUID").toString());
142 						reducedMap.put(ExceptionIncident.COMPONENT_NAME, userSessionMap.get("EXCEPTION_COMPONENT_NAME").toString());
143 						reducedMap.put(ExceptionIncident.EXCEPTION_REPORT_SUBJECT, userSessionMap.get("EXCEPTION_EXCEPTION_REPORT_SUBJECT").toString());
144 						reducedMap.put(ExceptionIncident.EXCEPTION_MESSAGE, userSessionMap.get("EXCEPTION_EXCEPTION_MESSAGE").toString());
145 						reducedMap.put(ExceptionIncident.STACK_TRACE, userSessionMap.get("EXCEPTION_STACK_TRACE").toString());
146 
147 					} else {
148 						reducedMap.put(ExceptionIncident.STACK_TRACE,"Not available.");
149 					}
150 
151 					KualiExceptionIncident exceptionIncident = reporterService
152 							.getExceptionIncident(reducedMap);
153 
154 					// Report the incident
155 					reporterService.report(exceptionIncident);
156 				} else {
157 					// Set return after canceling
158 					ActionForward cancelForward = mapping
159 							.findForward(KRADConstants.MAPPING_CANCEL);
160 					if (cancelForward == null) {
161 						cancelForward = returnForward;
162 					} else {
163 						returnForward = cancelForward;
164 					}
165 				}
166 			}
167 		} else {
168 			// ProcessDefinition the received exception from HTTP request
169 			returnForward = processException(mapping, form, request, e);
170 		}
171 
172 		// Not specified, return
173 		if (returnForward == null) {
174 			returnForward = mapping.findForward(KRADConstants.MAPPING_CLOSE);
175 		}
176 
177 		if (LOG.isDebugEnabled()) {
178 			String lm = String.format("EXIT %s",
179 					(returnForward == null) ? "null" : returnForward.getPath());
180 			LOG.debug(lm);
181 		}
182 
183 		return returnForward;
184 	}
185 
186 	/**
187 	 * This method process the caught exception by creating an exception
188 	 * information properties list and forward these properties to the exception
189 	 * incident handler JSP.
190 	 *
191 	 * @param exception
192 	 * @param mapping
193 	 * @param request
194 	 * @param documentId
195 	 *            Id of the document that Struts threw exception during its
196 	 *            processing. null if not the document processing that caused
197 	 *            the exception
198 	 * @return
199 	 * @throws Exception
200 	 */
201 	@SuppressWarnings("unchecked")
202 	protected ActionForward processException(ActionMapping mapping,
203 			ActionForm form, HttpServletRequest request, Exception exception)
204 			throws Exception {
205 		// Only process the exception handling when the service
206 		// is specified
207 		KualiExceptionIncidentService reporterService = KRADServiceLocatorWeb
208 				.getKualiExceptionIncidentService();
209 		// Get exception properties from the Http Request
210 		Map<String, String> properties = (Map<String, String>) request
211 				.getAttribute(IncidentReportUtils.EXCEPTION_PROPERTIES);
212 		// Construct the exception incident object
213 		KualiExceptionIncident ei = reporterService.getExceptionIncident(
214 				exception, properties);
215 
216 		// Add sensitive data to user session
217 		String exceptionTimeStamp = String.valueOf(System.currentTimeMillis());
218 		GlobalVariables.getUserSession().addObject("EXCEPTION_TIME_STAMP", exceptionTimeStamp);
219 		GlobalVariables.getUserSession().addObject("EXCEPTION_DOCUMENT_ID", ei.getProperty(ExceptionIncident.DOCUMENT_ID));
220 		GlobalVariables.getUserSession().addObject("EXCEPTION_USER_EMAIL", ei.getProperty(ExceptionIncident.USER_EMAIL));
221 		GlobalVariables.getUserSession().addObject("EXCEPTION_USER_NAME", ei.getProperty(ExceptionIncident.USER_NAME));
222 		GlobalVariables.getUserSession().addObject("EXCEPTION_UUID", ei.getProperty(ExceptionIncident.UUID));
223 		GlobalVariables.getUserSession().addObject("EXCEPTION_COMPONENT_NAME", ei.getProperty(ExceptionIncident.COMPONENT_NAME));
224 		GlobalVariables.getUserSession().addObject("EXCEPTION_EXCEPTION_REPORT_SUBJECT", ei.getProperty(ExceptionIncident.EXCEPTION_REPORT_SUBJECT));
225 		GlobalVariables.getUserSession().addObject("EXCEPTION_EXCEPTION_MESSAGE", ei.getProperty(ExceptionIncident.EXCEPTION_MESSAGE));
226 		GlobalVariables.getUserSession().addObject("EXCEPTION_STACK_TRACE", ei.getProperty(ExceptionIncident.STACK_TRACE));
227 
228 		// Hide sensitive data from form in production only
229 		if(ConfigContext.getCurrentContextConfig().isProductionEnvironment()) {
230 			Map<String, String> prodProperties = ei.toProperties();
231 			prodProperties.put(ExceptionIncident.DOCUMENT_ID, "");
232 			prodProperties.put(ExceptionIncident.USER_EMAIL, "");
233 			prodProperties.put(ExceptionIncident.USER_NAME, "");
234 			prodProperties.put(ExceptionIncident.UUID, "");
235 			prodProperties.put(ExceptionIncident.COMPONENT_NAME, "");
236 			prodProperties.put(ExceptionIncident.EXCEPTION_REPORT_SUBJECT, "");
237 			prodProperties.put(ExceptionIncident.EXCEPTION_MESSAGE, "");
238 			prodProperties.put(ExceptionIncident.STACK_TRACE, exceptionTimeStamp);
239 			ei = reporterService.getExceptionIncident(
240 					null, prodProperties);
241 		}
242 
243 		// Set full exception properties in Http Request and forward to JSP
244 		request.setAttribute(KualiExceptionHandlerAction.class
245 				.getSimpleName(), ei.toProperties());
246 		return mapping.findForward(RiceConstants.MAPPING_BASIC);
247 	}
248 }