Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ExceptionIncident |
|
| 4.5;4.5 |
1 | /* | |
2 | * Copyright 2007-2008 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.exception; | |
17 | ||
18 | import java.io.PrintWriter; | |
19 | import java.io.StringWriter; | |
20 | import java.util.HashMap; | |
21 | import java.util.List; | |
22 | import java.util.Map; | |
23 | ||
24 | import org.apache.log4j.Logger; | |
25 | import org.kuali.rice.kns.service.KNSServiceLocator; | |
26 | ||
27 | /** | |
28 | * This class contains the exception incident information, exception, form and | |
29 | * session user. It is constructed and saved into the HTTP Request for passing to the | |
30 | * jsp when an exception occurs. | |
31 | * | |
32 | * @author Kuali Rice Team (rice.collab@kuali.org) | |
33 | * | |
34 | */ | |
35 | public class ExceptionIncident implements KualiExceptionIncident { | |
36 | 0 | private static final Logger LOG = Logger.getLogger(ExceptionIncident.class); |
37 | public static final String GENERIC_SYSTEM_ERROR_MESSAGE = "The system has" + | |
38 | " encountered an error and is unable to complete your request at this time."+ | |
39 | " Please provide more information regarding this error by completing"+ | |
40 | " this Incident Report."; | |
41 | ||
42 | /** | |
43 | * Basic exception information is initialized and contained in this class instance. | |
44 | * Additional setting and other information can be added when exception is caught. | |
45 | * Also, an JSP is displayed to collect additional user information and the returned | |
46 | * parameters from the JSP can be used to initialize this class instance for | |
47 | * reporting. | |
48 | * <p>Note: The mechanism for passing data to and receiving data from the JSP uses | |
49 | * java.util.Map. Therefore, the exception is not passed to JSP using HttpRequest. | |
50 | * But rather a Map instance. | |
51 | */ | |
52 | 0 | protected Map<String, String> properties=new HashMap<String, String>(); |
53 | ||
54 | /** | |
55 | * This constructs list of key-value pairs from the caught exception and current | |
56 | * settings. | |
57 | * | |
58 | * @param exception Caught exception | |
59 | * @param exceptionNames List of Kuali exception for determining the display exception | |
60 | * message | |
61 | * @param properties Input information when the exception is caught | |
62 | * <p>Example: | |
63 | * <ul> | |
64 | * <li>DOCUMENT_ID</li> | |
65 | * <li>USER_EMAIL</li> | |
66 | * <li>USER_NAME</li> | |
67 | * <li>COMPONENT_NAME</li> | |
68 | * </ul> | |
69 | */ | |
70 | public ExceptionIncident(Exception exception, | |
71 | 0 | Map<String,String> properties) { |
72 | 0 | if (LOG.isTraceEnabled()) { |
73 | 0 | String message=String.format("ENTRY %s%n%s", |
74 | (exception==null)?"null":exception.toString(), | |
75 | (properties==null)?"":properties.toString()); | |
76 | 0 | LOG.trace(message); |
77 | } | |
78 | ||
79 | 0 | initialize(exception, properties); |
80 | ||
81 | 0 | if (LOG.isTraceEnabled()) { |
82 | 0 | String message=String.format("EXIT %s", this.properties); |
83 | 0 | LOG.trace(message); |
84 | } | |
85 | ||
86 | 0 | } |
87 | ||
88 | /** | |
89 | * This constructs an instance of this class from list of name-value pairs. | |
90 | * | |
91 | * @param inputs List of exception information such as | |
92 | * <ul> | |
93 | * <li>DOCUMENT_ID - If it's document form</li> | |
94 | * <li>USER_EMAIL - Session user email</li> | |
95 | * <li>USER_NAME - Session user name</li> | |
96 | * <li>COMPONENT_NAME - Document or lookup or inquiry form</li> | |
97 | * attribute of GlobalVariables</li> | |
98 | * <li>EXCEPTION_REPORT_SUBJECT - Exception error message and current settings</li> | |
99 | * <li>EXCEPTION_MESSAGE - Exception error message</li> | |
100 | * <li>STACK_TRACE - Exception stack trace</li> | |
101 | * <li>DESCRIPTION - Information input by user or blank</li> | |
102 | * </ul> | |
103 | */ | |
104 | 0 | public ExceptionIncident(Map<String, String> inputs) { |
105 | ||
106 | 0 | this.properties=inputs; |
107 | ||
108 | 0 | } |
109 | ||
110 | /** | |
111 | * This method create and populate the internal properties parameter. | |
112 | * | |
113 | * @param thrownException The caught exception | |
114 | * @param inputs Input information when the exception is caught | |
115 | * <p>Example: | |
116 | * <ul> | |
117 | * <li>DOCUMENT_ID</li> | |
118 | * <li>USER_EMAIL</li> | |
119 | * <li>USER_NAME</li> | |
120 | * <li>COMPONENT_NAME</li> | |
121 | * </ul> | |
122 | */ | |
123 | private void initialize(Exception thrownException, Map<String, String> inputs) { | |
124 | 0 | if (LOG.isTraceEnabled()) { |
125 | 0 | String lm=String.format("ENTRY %s%n%s", |
126 | thrownException.getMessage(), | |
127 | (inputs==null)?"null":inputs.toString()); | |
128 | 0 | LOG.trace(lm); |
129 | } | |
130 | ||
131 | 0 | properties=new HashMap<String, String>(); |
132 | // Add all inputs | |
133 | 0 | if (inputs != null) { |
134 | 0 | properties.putAll(inputs); |
135 | } | |
136 | // Add all exception information | |
137 | 0 | properties.putAll(getExceptionInfo(thrownException)); |
138 | ||
139 | 0 | if (LOG.isTraceEnabled()) { |
140 | 0 | String lm=String.format("EXIT %s", properties.toString()); |
141 | 0 | LOG.trace(lm); |
142 | } | |
143 | 0 | } |
144 | ||
145 | /** | |
146 | * This method return list of required information provided by the caught exception. | |
147 | * | |
148 | * @return | |
149 | * <p>Example: | |
150 | * <code> | |
151 | * exceptionSubject, Caught exception message and settings information | |
152 | * exceptionMessage, Caught exception message | |
153 | * displayMessage, Either exception error message or generic exception error message | |
154 | * stackTrace, Exception stack trace here | |
155 | * </code> | |
156 | * | |
157 | */ | |
158 | private Map<String, String> getExceptionInfo(Exception exception) { | |
159 | 0 | if (LOG.isTraceEnabled()) { |
160 | 0 | String message=String.format("ENTRY"); |
161 | 0 | LOG.trace(message); |
162 | } | |
163 | ||
164 | 0 | Map<String, String> map=new HashMap<String, String>(); |
165 | 0 | map.put(EXCEPTION_REPORT_SUBJECT, createReportSubject(exception)); |
166 | 0 | map.put(EXCEPTION_MESSAGE, exception.getMessage()); |
167 | 0 | map.put(DISPLAY_MESSAGE, getDisplayMessage(exception)); |
168 | 0 | map.put(STACK_TRACE, getExceptionStackTrace(exception)); |
169 | 0 | if(exception instanceof KualiException ){ |
170 | 0 | boolean hideIncidentReport = ((KualiException) exception).isHideIncidentReport(); |
171 | 0 | map.put(EXCEPTION_HIDE_INCIDENT_REPORT, String.valueOf(hideIncidentReport)); |
172 | 0 | }else{ |
173 | 0 | map.put(EXCEPTION_HIDE_INCIDENT_REPORT, String.valueOf(false)); |
174 | } | |
175 | ||
176 | 0 | if (LOG.isTraceEnabled()) { |
177 | 0 | String message=String.format("ENTRY %s", map.toString()); |
178 | 0 | LOG.trace(message); |
179 | } | |
180 | ||
181 | 0 | return map; |
182 | } | |
183 | ||
184 | /** | |
185 | * This method compose the exception information that includes | |
186 | * <ul> | |
187 | * <li>environment - Application environment</li> | |
188 | * <li>componentName- Document or lookup or inquiry form</li> | |
189 | * <li>errorMessage - Exception error message</li> | |
190 | * </ul> | |
191 | * <p>Example; | |
192 | * <code> | |
193 | * kr-dev:SomeForm:Some error message | |
194 | * </code> | |
195 | * | |
196 | * @param exception The caught exception | |
197 | * @return | |
198 | */ | |
199 | private String createReportSubject(Exception exception) { | |
200 | 0 | if (LOG.isTraceEnabled()) { |
201 | 0 | String lm=String.format("ENTRY"); |
202 | 0 | LOG.trace(lm); |
203 | } | |
204 | ||
205 | 0 | String env=KNSServiceLocator.getKualiConfigurationService(). |
206 | getPropertyString("environment"); | |
207 | 0 | String format="%s:%s:%s"; |
208 | 0 | String componentName=properties.get(COMPONENT_NAME); |
209 | 0 | String subject=String.format(format, |
210 | env, | |
211 | (componentName==null)?"":componentName, | |
212 | exception.getMessage()); | |
213 | ||
214 | 0 | if (LOG.isTraceEnabled()) { |
215 | 0 | String lm=String.format("EXIT %s", subject); |
216 | 0 | LOG.trace(lm); |
217 | } | |
218 | ||
219 | 0 | return subject; |
220 | } | |
221 | ||
222 | /** | |
223 | * This method compose the exception information that includes | |
224 | * <ul> | |
225 | * <li>documentId - If it's document form</li> | |
226 | * <li>userEmail - Session user email</li> | |
227 | * <li>userName - Session user name</li> | |
228 | * <li>component - Document or lookup or inquiry form</li> | |
229 | * <li>description - Information input by user or blank</li> | |
230 | * <li>errorMessage - Exception error message</li> | |
231 | * <li>stackTrace - Exception stack trace</li> | |
232 | * </ul> | |
233 | * <p>Example; | |
234 | * <code> | |
235 | * documentId: 2942084 | |
236 | * userEmail: someone@somewhere | |
237 | * userName: some name | |
238 | * description: Something went wrong! | |
239 | * component: document | |
240 | * errorMessage: Some error message | |
241 | * stackTrace: Exception stack trace here | |
242 | * </code> | |
243 | * | |
244 | * @return | |
245 | */ | |
246 | private String createReportMessage() { | |
247 | 0 | if (LOG.isTraceEnabled()) { |
248 | 0 | String lm=String.format("ENTRY"); |
249 | 0 | LOG.trace(lm); |
250 | } | |
251 | ||
252 | 0 | String documentId=properties.get(DOCUMENT_ID); |
253 | 0 | String userEmail=properties.get(USER_EMAIL); |
254 | 0 | String uuid=properties.get(UUID); |
255 | 0 | String description=properties.get(DESCRIPTION); |
256 | 0 | String component=properties.get(COMPONENT_NAME); |
257 | 0 | String exceptionMessage=properties.get(EXCEPTION_MESSAGE); |
258 | 0 | String stackTrace=properties.get(STACK_TRACE); |
259 | 0 | String format="Document Id: %s%n"+ |
260 | "User Email: %s%n"+ | |
261 | "Person User Identifier: %s%n"+ | |
262 | "User Input: %s%n"+ | |
263 | "component: %s%n"+ | |
264 | "errorMessage: %s%n"+ | |
265 | "%s%n"; | |
266 | 0 | String message=String.format(format, |
267 | (documentId==null)?"":documentId, | |
268 | (userEmail==null)?"":userEmail, | |
269 | (uuid==null)?"":uuid, | |
270 | (description==null)?"":description, | |
271 | (component==null)?"":component, | |
272 | (exceptionMessage==null)?"":exceptionMessage, | |
273 | (stackTrace==null)?"":stackTrace); | |
274 | ||
275 | 0 | if (LOG.isTraceEnabled()) { |
276 | 0 | String lm=String.format("EXIT %s", message); |
277 | 0 | LOG.trace(lm); |
278 | } | |
279 | ||
280 | 0 | return message; |
281 | } | |
282 | ||
283 | /** | |
284 | * This method return the thrown exception stack trace as string. | |
285 | * | |
286 | * @param thrownException | |
287 | * @return | |
288 | */ | |
289 | public String getExceptionStackTrace(Exception thrownException) { | |
290 | 0 | if (LOG.isTraceEnabled()) { |
291 | 0 | String lm=String.format("ENTRY"); |
292 | 0 | LOG.trace(lm); |
293 | } | |
294 | ||
295 | 0 | StringWriter wrt=new StringWriter(); |
296 | 0 | PrintWriter pw=new PrintWriter(wrt); |
297 | 0 | thrownException.printStackTrace(pw); |
298 | 0 | pw.flush(); |
299 | 0 | String stackTrace=wrt.toString(); |
300 | try { | |
301 | 0 | wrt.close(); |
302 | 0 | pw.close(); |
303 | 0 | } catch (Exception e) { |
304 | 0 | LOG.trace(e.getMessage(), e); |
305 | 0 | } |
306 | ||
307 | 0 | if (LOG.isTraceEnabled()) { |
308 | 0 | String lm=String.format("EXIT %s", stackTrace); |
309 | 0 | LOG.trace(lm); |
310 | } | |
311 | ||
312 | 0 | return stackTrace; |
313 | } | |
314 | ||
315 | /** | |
316 | * This overridden method return the exception if the ixception type is in the | |
317 | * defined list. Otherwise, it returns the GENERIC_SYSTEM_ERROR_MESSAGE. | |
318 | * | |
319 | * @see org.kuali.rice.kns.exception.KualiExceptionIncident#getDisplayMessage(Exception) | |
320 | */ | |
321 | public String getDisplayMessage(Exception exception) { | |
322 | 0 | if (LOG.isTraceEnabled()) { |
323 | 0 | String message=String.format("ENTRY %s", exception.getMessage()); |
324 | 0 | LOG.trace(message); |
325 | } | |
326 | ||
327 | // Create the display message | |
328 | String displayMessage; | |
329 | 0 | if (exception instanceof KualiException) { |
330 | 0 | displayMessage=exception.getMessage(); |
331 | } else { | |
332 | 0 | displayMessage=GENERIC_SYSTEM_ERROR_MESSAGE; |
333 | } | |
334 | ||
335 | 0 | if (LOG.isTraceEnabled()) { |
336 | 0 | String message=String.format("EXIT %s", displayMessage); |
337 | 0 | LOG.trace(message); |
338 | } | |
339 | ||
340 | 0 | return displayMessage; |
341 | } | |
342 | ||
343 | /** | |
344 | * This overridden method returns value of the found property key. Except the | |
345 | * property EXCEPTION_REPORT_MESSAGE | |
346 | * | |
347 | * @see org.kuali.rice.kns.exception.KualiExceptionIncident#getProperty(java.lang.String) | |
348 | */ | |
349 | public String getProperty(String key) { | |
350 | 0 | if (LOG.isTraceEnabled()) { |
351 | 0 | String message=String.format("ENTRY %s", key); |
352 | 0 | LOG.trace(message); |
353 | } | |
354 | ||
355 | String value; | |
356 | 0 | if (key.equals(EXCEPTION_REPORT_MESSAGE) && !properties.containsKey(key)) { |
357 | 0 | value=createReportMessage(); |
358 | 0 | properties.put(EXCEPTION_REPORT_MESSAGE, value); |
359 | } else { | |
360 | 0 | value=properties.get(key); |
361 | } | |
362 | ||
363 | 0 | if (LOG.isTraceEnabled()) { |
364 | 0 | String message=String.format("EXIT %s", value); |
365 | 0 | LOG.trace(message); |
366 | } | |
367 | ||
368 | 0 | return value; |
369 | } | |
370 | ||
371 | /** | |
372 | * This overridden method return current internal properties. | |
373 | * | |
374 | * @see org.kuali.rice.kns.exception.KualiExceptionIncident#toProperties() | |
375 | */ | |
376 | public Map<String, String> toProperties() { | |
377 | 0 | if (LOG.isTraceEnabled()) { |
378 | 0 | String message=String.format("ENTRY"); |
379 | 0 | LOG.trace(message); |
380 | } | |
381 | ||
382 | 0 | if (LOG.isTraceEnabled()) { |
383 | 0 | String message=String.format("EXIT %s", properties.toString()); |
384 | 0 | LOG.trace(message); |
385 | } | |
386 | ||
387 | 0 | return properties; |
388 | } | |
389 | } |