001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/portal/tags/sakai_2-4-1/portal-util/util/src/java/org/sakaiproject/portal/util/ErrorReporter.java $
003: * $Id: ErrorReporter.java 29143 2007-04-19 01:10:38Z ajpoland@iupui.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.portal.util;
021:
022: import java.io.IOException;
023: import java.io.PrintWriter;
024: import java.security.MessageDigest;
025: import java.util.Enumeration;
026:
027: import javax.servlet.ServletException;
028: import javax.servlet.http.HttpServletRequest;
029: import javax.servlet.http.HttpServletResponse;
030: import javax.servlet.http.HttpSession;
031:
032: import org.apache.commons.logging.Log;
033: import org.apache.commons.logging.LogFactory;
034: import org.sakaiproject.component.cover.ServerConfigurationService;
035: import org.sakaiproject.email.cover.EmailService;
036: import org.sakaiproject.event.api.UsageSession;
037: import org.sakaiproject.event.cover.UsageSessionService;
038: import org.sakaiproject.time.api.Time;
039: import org.sakaiproject.time.cover.TimeService;
040: import org.sakaiproject.tool.api.Placement;
041: import org.sakaiproject.tool.cover.SessionManager;
042: import org.sakaiproject.tool.cover.ToolManager;
043: import org.sakaiproject.user.api.User;
044: import org.sakaiproject.user.cover.UserDirectoryService;
045: import org.sakaiproject.util.FormattedText;
046: import org.sakaiproject.util.ResourceLoader;
047:
048: /**
049: * <p>
050: * ErrorReporter helps with end-user formatted error reporting, user feedback
051: * collection, logging and emailing for uncaught throwable based errors.
052: * </p>
053: */
054: public class ErrorReporter {
055: /** Our log (commons). */
056: private static Log M_log = LogFactory.getLog(ErrorReporter.class);
057:
058: /** messages. */
059: private static ResourceLoader rb = new ResourceLoader("portal-util");
060:
061: public ErrorReporter() {
062: }
063:
064: /** Following two methods borrowed from RWikiObjectImpl.java * */
065:
066: private static MessageDigest shatemplate = null;
067:
068: public static String computeSha1(String content) {
069: String digest = "";
070: try {
071: if (shatemplate == null) {
072: shatemplate = MessageDigest.getInstance("SHA");
073: }
074:
075: MessageDigest shadigest = (MessageDigest) shatemplate
076: .clone();
077: byte[] bytedigest = shadigest.digest(content
078: .getBytes("UTF8"));
079: digest = byteArrayToHexStr(bytedigest);
080: } catch (Exception ex) {
081: System.err.println("Unable to create SHA hash of content");
082: ex.printStackTrace();
083: }
084: return digest;
085: }
086:
087: private static String byteArrayToHexStr(byte[] data) {
088: String output = "";
089: String tempStr = "";
090: int tempInt = 0;
091: for (int cnt = 0; cnt < data.length; cnt++) {
092: // Deposit a byte into the 8 lsb of an int.
093: tempInt = data[cnt] & 0xFF;
094: // Get hex representation of the int as a
095: // string.
096: tempStr = Integer.toHexString(tempInt);
097: // Append a leading 0 if necessary so that
098: // each hex string will contain two
099: // characters.
100: if (tempStr.length() == 1)
101: tempStr = "0" + tempStr;
102: // Concatenate the two characters to the
103: // output string.
104: output = output + tempStr;
105: }// end for loop
106: return output.toUpperCase();
107: }// end byteArrayToHexStr
108:
109: /**
110: * Format the full stack trace.
111: *
112: * @param t
113: * The throwable.
114: * @return A display of the full stack trace for the throwable.
115: */
116: protected String getStackTrace(Throwable t) {
117: StackTraceElement[] st = t.getStackTrace();
118: StringBuilder buf = new StringBuilder();
119: if (st != null) {
120: for (int i = 0; i < st.length; i++) {
121: buf.append("\n at "
122: + st[i].getClassName()
123: + "."
124: + st[i].getMethodName()
125: + "("
126: + ((st[i].isNativeMethod()) ? "Native Method"
127: : (st[i].getFileName() + ":" + st[i]
128: .getLineNumber())) + ")");
129: }
130: buf.append("\n");
131: }
132:
133: return buf.toString();
134: }
135:
136: /**
137: * Format a one-level stack trace, just showing the place where the
138: * exception occurred (the first entry in the stack trace).
139: *
140: * @param t
141: * The throwable.
142: * @return A display of the first stack trace entry for the throwable.
143: */
144: protected String getOneTrace(Throwable t) {
145: StackTraceElement[] st = t.getStackTrace();
146: StringBuilder buf = new StringBuilder();
147: if (st != null && st.length > 0) {
148: buf.append("\n at "
149: + st[1].getClassName()
150: + "."
151: + st[1].getMethodName()
152: + "("
153: + ((st[1].isNativeMethod()) ? "Native Method"
154: : (st[1].getFileName() + ":" + st[1]
155: .getLineNumber())) + ")\n");
156: }
157:
158: return buf.toString();
159: }
160:
161: /**
162: * Compute the cause of a throwable, checking for the special
163: * ServletException case, and the points-to-self case.
164: *
165: * @param t
166: * The throwable.
167: * @return The cause of the throwable, or null if there is none.
168: */
169: protected Throwable getCause(Throwable t) {
170: Throwable rv = null;
171:
172: // ServletException is non-standard
173: if (t instanceof ServletException) {
174: rv = ((ServletException) t).getRootCause();
175: }
176:
177: // try for the standard cause
178: if (rv == null)
179: rv = t.getCause();
180:
181: // clear it if the cause is pointing at the throwable
182: if ((rv != null) && (rv == t))
183: rv = null;
184:
185: return rv;
186: }
187:
188: /**
189: * Format a throwable for display: list the various throwables drilling down
190: * the cause, and full stacktrack for the final cause.
191: *
192: * @param t
193: * The throwable.
194: * @return The string display of the throwable.
195: */
196: protected String throwableDisplay(Throwable t) {
197: StringBuilder buf = new StringBuilder();
198: buf.append(t.toString()
199: + ((getCause(t) == null) ? (getStackTrace(t))
200: : getOneTrace(t)));
201: while (getCause(t) != null) {
202: t = getCause(t);
203: buf.append("caused by: ");
204: buf.append(t.toString()
205: + ((getCause(t) == null) ? (getStackTrace(t))
206: : getOneTrace(t)));
207: }
208:
209: return buf.toString();
210: }
211:
212: /**
213: * Log and email the error report details.
214: *
215: * @param usageSessionId
216: * The end-user's usage session id.
217: * @param userId
218: * The end-user's user id.
219: * @param time
220: * The time of the error.
221: * @param problem
222: * The stacktrace of the error.
223: * @param problemdigest
224: * The sha1 digest of the stacktrace.
225: * @param requestURI
226: * The request URI.
227: * @param userReport
228: * The end user comments.
229: * @param object
230: * @param placementDisplay
231: */
232: protected void logAndMail(String usageSessionId, String userId,
233: String time, String problem, String problemdigest,
234: String requestURI, String userReport) {
235: logAndMail(usageSessionId, userId, time, problem,
236: problemdigest, requestURI, "", "", userReport);
237: }
238:
239: protected void logAndMail(String usageSessionId, String userId,
240: String time, String problem, String problemdigest,
241: String requestURI, String requestDisplay,
242: String placementDisplay, String userReport) {
243: // log
244: M_log.warn(rb.getString("bugreport.bugreport") + " "
245: + rb.getString("bugreport.user") + ": " + userId + " "
246: + rb.getString("bugreport.usagesession") + ": "
247: + usageSessionId + " " + rb.getString("bugreport.time")
248: + ": " + time + " "
249: + rb.getString("bugreport.usercomment") + ": "
250: + userReport + " "
251: + rb.getString("bugreport.stacktrace") + "\n" + problem
252: + "\n" + placementDisplay + "\n" + requestDisplay);
253:
254: // mail
255: String emailAddr = ServerConfigurationService
256: .getString("portal.error.email");
257:
258: if (emailAddr != null) {
259: String uSessionInfo = "";
260: UsageSession usageSession = UsageSessionService
261: .getSession();
262:
263: if (usageSession != null) {
264: uSessionInfo = rb.getString("bugreport.useragent")
265: + ": " + usageSession.getUserAgent() + "\n"
266: + rb.getString("bugreport.browserid") + ": "
267: + usageSession.getBrowserId() + "\n"
268: + rb.getString("bugreport.ip") + ": "
269: + usageSession.getIpAddress() + "\n";
270: }
271:
272: String pathInfo = "";
273: if (requestURI != null) {
274: pathInfo = rb.getString("bugreport.path") + ": "
275: + requestURI + "\n";
276: }
277:
278: User user = null;
279: String userName = null;
280: String userMail = null;
281: String userEid = null;
282: if (userId != null) {
283: try {
284: user = UserDirectoryService.getUser(userId);
285: userName = user.getDisplayName();
286: userMail = user.getEmail();
287: userEid = user.getEid();
288: } catch (Exception e) {
289: // nothing
290: }
291: }
292:
293: String subject = rb.getString("bugreport.bugreport") + ": "
294: + problemdigest + " / " + usageSessionId;
295:
296: String userComment = "";
297:
298: if (userReport != null) {
299: userComment = rb.getString("bugreport.usercomment")
300: + ":\n\n" + userReport + "\n\n\n";
301: subject = subject + " "
302: + rb.getString("bugreport.commentflag");
303: }
304:
305: String from = "\""
306: + ServerConfigurationService.getString(
307: "ui.service", "Sakai") + "\"<no-reply@"
308: + ServerConfigurationService.getServerName() + ">";
309:
310: String body = rb.getString("bugreport.user")
311: + ": "
312: + userEid
313: + " ("
314: + userName
315: + ")\n"
316: + rb.getString("bugreport.email")
317: + ": "
318: + userMail
319: + "\n"
320: + rb.getString("bugreport.usagesession")
321: + ": "
322: + usageSessionId
323: + "\n"
324: + rb.getString("bugreport.digest")
325: + ": "
326: + problemdigest
327: + "\n"
328: + rb.getString("bugreport.version-sakai")
329: + ": "
330: + ServerConfigurationService
331: .getString("version.sakai")
332: + "\n"
333: + rb.getString("bugreport.version-service")
334: + ": "
335: + ServerConfigurationService
336: .getString("version.service") + "\n"
337: + rb.getString("bugreport.appserver") + ": "
338: + ServerConfigurationService.getServerId() + "\n"
339: + uSessionInfo + pathInfo
340: + rb.getString("bugreport.time") + ": " + time
341: + "\n\n\n" + userComment
342: + rb.getString("bugreport.stacktrace") + ":\n\n"
343: + problem + "\n\n" + placementDisplay + "\n\n"
344: + requestDisplay;
345:
346: EmailService.send(from, emailAddr, subject, body,
347: emailAddr, null, null);
348: }
349: }
350:
351: /**
352: * Handle the inital report of an error, from an uncaught throwable, with a
353: * user display.
354: *
355: * @param req
356: * The request.
357: * @param res
358: * The response.
359: * @param t
360: * The uncaught throwable.
361: */
362: public void report(HttpServletRequest req, HttpServletResponse res,
363: Throwable t) {
364: String headInclude = (String) req
365: .getAttribute("sakai.html.head");
366: String bodyOnload = (String) req
367: .getAttribute("sakai.html.body.onload");
368: Time reportTime = TimeService.newTime();
369: String time = reportTime.toStringLocalDate() + " "
370: + reportTime.toStringLocalTime24();
371: String usageSessionId = UsageSessionService.getSessionId();
372: String userId = SessionManager.getCurrentSessionUserId();
373: String requestDisplay = requestDisplay(req);
374: String placementDisplay = placementDisplay();
375: String problem = throwableDisplay(t);
376: String problemdigest = computeSha1(problem);
377: String postAddr = ServerConfigurationService.getPortalUrl()
378: + "/error-report";
379: String requestURI = req.getRequestURI();
380:
381: if (bodyOnload == null) {
382: bodyOnload = "";
383: } else {
384: bodyOnload = " onload=\"" + bodyOnload + "\"";
385: }
386: try {
387: // headers
388: res.setContentType("text/html; charset=UTF-8");
389: res.addDateHeader("Expires", System.currentTimeMillis()
390: - (1000L * 60L * 60L * 24L * 365L));
391: res.addDateHeader("Last-Modified", System
392: .currentTimeMillis());
393: res
394: .addHeader("Cache-Control",
395: "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0");
396: res.addHeader("Pragma", "no-cache");
397:
398: PrintWriter out = res.getWriter();
399: out
400: .println("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
401: out
402: .println("<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\">");
403: if (headInclude != null) {
404: out.println("<head>");
405: out.println(headInclude);
406: out.println("</head>");
407: }
408: out.println("<body" + bodyOnload + ">");
409: out.println("<div class=\"portletBody\">");
410: out.println("<h3>" + rb.getString("bugreport.error")
411: + "</h3>");
412: out.println("<p>" + rb.getString("bugreport.statement")
413: + "<br /><br /></p>");
414:
415: out.println("<h4>" + rb.getString("bugreport.sendtitle")
416: + "</h4>");
417: out.println("<p>"
418: + rb.getString("bugreport.sendinstructions")
419: + "</p>");
420:
421: out.println("<form action=\"" + postAddr
422: + "\" method=\"POST\">");
423: out
424: .println("<input type=\"hidden\" name=\"problem\" value=\"");
425: out.println(FormattedText.escapeHtml(problem, false));
426: out.println("\">");
427: out
428: .println("<input type=\"hidden\" name=\"problemRequest\" value=\"");
429: out
430: .println(FormattedText.escapeHtml(requestDisplay,
431: false));
432: out.println("\">");
433: out
434: .println("<input type=\"hidden\" name=\"problemPlacement\" value=\"");
435: out.println(FormattedText.escapeHtml(placementDisplay,
436: false));
437: out.println("\">");
438: out
439: .println("<input type=\"hidden\" name=\"problemdigest\" value=\""
440: + FormattedText.escapeHtml(problemdigest,
441: false) + "\">");
442: out
443: .println("<input type=\"hidden\" name=\"session\" value=\""
444: + FormattedText.escapeHtml(usageSessionId,
445: false) + "\">");
446: out.println("<input type=\"hidden\" name=\"user\" value=\""
447: + FormattedText.escapeHtml(userId, false) + "\">");
448: out.println("<input type=\"hidden\" name=\"time\" value=\""
449: + FormattedText.escapeHtml(time, false) + "\">");
450:
451: out
452: .println("<table class=\"itemSummary\" cellspacing=\"5\" cellpadding=\"5\">");
453: out.println("<tbody>");
454: out.println("<tr>");
455: out
456: .println("<td><textarea rows=\"10\" cols=\"60\" name=\"comment\"></textarea></td>");
457: out.println("</tr>");
458: out.println("</tbody>");
459: out.println("</table>");
460: out.println("<div class=\"act\">");
461: out.println("<input type=\"submit\" value=\""
462: + rb.getString("bugreport.sendsubmit") + "\">");
463: out.println("</div>");
464: out.println("</form><br />");
465:
466: out
467: .println("<h4>"
468: + rb.getString("bugreport.recoverytitle")
469: + "</h4>");
470: out.println("<p>"
471: + rb.getString("bugreport.recoveryinstructions")
472: + "");
473: out.println("<ul><li>"
474: + rb.getString("bugreport.recoveryinstructions1")
475: + "</li>");
476: out.println("<li>"
477: + rb.getString("bugreport.recoveryinstructions2")
478: + "</li>");
479: out.println("<li>"
480: + rb.getString("bugreport.recoveryinstructions3")
481: + "</li></ul><br /><br /></p>");
482:
483: out.println("<h4>" + rb.getString("bugreport.detailstitle")
484: + "</h4>");
485: out.println("<p>" + rb.getString("bugreport.detailsnote")
486: + "</p>");
487: out.println("<p><pre>");
488: out.println(FormattedText.escapeHtml(problem, false));
489: out.println();
490: out.println(rb.getString("bugreport.user") + ": "
491: + FormattedText.escapeHtml(userId, false) + "\n");
492: out.println(rb.getString("bugreport.usagesession") + ": "
493: + FormattedText.escapeHtml(usageSessionId, false)
494: + "\n");
495: out.println(rb.getString("bugreport.time") + ": "
496: + FormattedText.escapeHtml(time, false) + "\n");
497: out.println("</pre></p>");
498:
499: out.println("</body>");
500: out.println("</html>");
501:
502: // log and send the preliminary email
503: logAndMail(usageSessionId, userId, time, problem,
504: problemdigest, requestURI, requestDisplay,
505: placementDisplay, null);
506: } catch (Throwable any) {
507: M_log.warn(rb.getString("bugreport.troublereporting"), any);
508: }
509: }
510:
511: private String placementDisplay() {
512: StringBuilder sb = new StringBuilder();
513: try {
514: Placement p = ToolManager.getCurrentPlacement();
515: if (p != null) {
516: sb.append(rb.getString("bugreport.placement")).append(
517: "\n");
518: sb.append(rb.getString("bugreport.placement.id"))
519: .append(p.getToolId()).append("\n");
520: sb.append(rb.getString("bugreport.placement.context"))
521: .append(p.getContext()).append("\n");
522: sb.append(rb.getString("bugreport.placement.title"))
523: .append(p.getTitle()).append("\n");
524: } else {
525: sb.append(rb.getString("bugreport.placement")).append(
526: "\n");
527: sb.append(rb.getString("bugreport.placement.none"))
528: .append("\n");
529: }
530: } catch (Exception ex) {
531: M_log.error("Failed to generate placement display", ex);
532: sb.append("Error " + ex.getMessage());
533: }
534:
535: return sb.toString();
536: }
537:
538: private String requestDisplay(HttpServletRequest request) {
539: StringBuilder sb = new StringBuilder();
540: try {
541: sb.append(rb.getString("bugreport.request")).append("\n");
542: sb.append(rb.getString("bugreport.request.authtype"))
543: .append(request.getAuthType()).append("\n");
544: sb.append(rb.getString("bugreport.request.charencoding"))
545: .append(request.getCharacterEncoding())
546: .append("\n");
547: sb.append(rb.getString("bugreport.request.contentlength"))
548: .append(request.getContentLength()).append("\n");
549: sb.append(rb.getString("bugreport.request.contenttype"))
550: .append(request.getContentType()).append("\n");
551: sb.append(rb.getString("bugreport.request.contextpath"))
552: .append(request.getContextPath()).append("\n");
553: sb.append(rb.getString("bugreport.request.localaddr"))
554: .append(request.getLocalAddr()).append("\n");
555: sb.append(rb.getString("bugreport.request.localname"))
556: .append(request.getLocalName()).append("\n");
557: sb.append(rb.getString("bugreport.request.localport"))
558: .append(request.getLocalPort()).append("\n");
559: sb.append(rb.getString("bugreport.request.method")).append(
560: request.getMethod()).append("\n");
561: sb.append(rb.getString("bugreport.request.pathinfo"))
562: .append(request.getPathInfo()).append("\n");
563: sb.append(rb.getString("bugreport.request.protocol"))
564: .append(request.getProtocol()).append("\n");
565: sb.append(rb.getString("bugreport.request.querystring"))
566: .append(request.getQueryString()).append("\n");
567: sb.append(rb.getString("bugreport.request.remoteaddr"))
568: .append(request.getRemoteAddr()).append("\n");
569: sb.append(rb.getString("bugreport.request.remotehost"))
570: .append(request.getRemoteHost()).append("\n");
571: sb.append(rb.getString("bugreport.request.remoteport"))
572: .append(request.getRemotePort()).append("\n");
573: sb.append(rb.getString("bugreport.request.remoteuser"))
574: .append(request.getRemoteUser()).append("\n");
575: sb.append(
576: rb.getString("bugreport.request.requestedsession"))
577: .append(request.getRequestedSessionId()).append(
578: "\n");
579: sb.append(rb.getString("bugreport.request.requesturl"))
580: .append(request.getRequestURL()).append("\n");
581: sb.append(rb.getString("bugreport.request.scheme")).append(
582: request.getScheme()).append("\n");
583: sb.append(rb.getString("bugreport.request.servername"))
584: .append(request.getServerName()).append("\n");
585: sb.append(rb.getString("bugreport.request.headers"))
586: .append("\n");
587: for (Enumeration e = request.getHeaderNames(); e
588: .hasMoreElements();) {
589: String headerName = (String) e.nextElement();
590: for (Enumeration he = request.getHeaders(headerName); he
591: .hasMoreElements();) {
592: String headerValue = (String) he.nextElement();
593: sb.append(rb.getString("bugreport.request.header"))
594: .append(headerName).append(":").append(
595: headerValue).append("\n");
596: }
597: }
598: sb.append(rb.getString("bugreport.request.parameters"))
599: .append("\n");
600: for (Enumeration e = request.getParameterNames(); e
601: .hasMoreElements();) {
602: String parameterName = (String) e.nextElement();
603: String[] paramvalues = request
604: .getParameterValues(parameterName);
605: for (int i = 0; i < paramvalues.length; i++) {
606: sb
607: .append(
608: rb
609: .getString("bugreport.request.parameter"))
610: .append(parameterName).append(":")
611: .append(i).append(":").append(
612: paramvalues[i]).append("\n");
613: }
614: }
615: sb.append(rb.getString("bugreport.request.attributes"))
616: .append("\n");
617: for (Enumeration e = request.getAttributeNames(); e
618: .hasMoreElements();) {
619: String attributeName = (String) e.nextElement();
620: Object attribute = request.getAttribute(attributeName);
621: sb.append(rb.getString("bugreport.request.attribute"))
622: .append(attributeName).append(":").append(
623: attribute).append("\n");
624: }
625: HttpSession session = request.getSession(false);
626: if (session != null) {
627: sb.append(rb.getString("bugreport.session")).append(
628: "\n");
629: sb.append(rb.getString("bugreport.session.creation"))
630: .append(session.getCreationTime()).append("\n");
631: sb.append(rb.getString("bugreport.session.lastaccess"))
632: .append(session.getLastAccessedTime()).append(
633: "\n");
634: sb
635: .append(
636: rb
637: .getString("bugreport.session.maxinactive"))
638: .append(session.getMaxInactiveInterval())
639: .append("\n");
640: sb.append(rb.getString("bugreport.session.attributes"))
641: .append("\n");
642: for (Enumeration e = session.getAttributeNames(); e
643: .hasMoreElements();) {
644: String attributeName = (String) e.nextElement();
645: Object attribute = session
646: .getAttribute(attributeName);
647: sb
648: .append(
649: rb
650: .getString("bugreport.session.attribute"))
651: .append(attributeName).append(":").append(
652: attribute).append("\n");
653: }
654:
655: }
656: } catch (Exception ex) {
657: M_log.error("Failed to generate request display", ex);
658: sb.append("Error " + ex.getMessage());
659: }
660:
661: return sb.toString();
662: }
663:
664: /**
665: * Accept the user feedback post.
666: *
667: * @param req
668: * The request.
669: * @param res
670: * The response.
671: */
672: public void postResponse(HttpServletRequest req,
673: HttpServletResponse res) {
674: String session = req.getParameter("session");
675: String user = req.getParameter("user");
676: String time = req.getParameter("time");
677: String comment = req.getParameter("comment");
678: String problem = req.getParameter("problem");
679: String problemdigest = req.getParameter("problemdigest");
680: String problemRequest = req.getParameter("problemRequest");
681: String problemPlacement = req.getParameter("problemPlacement");
682:
683: // log and send the followup email
684: logAndMail(session, user, time, problem, problemdigest, null,
685: problemRequest, problemPlacement, comment);
686:
687: // always redirect from a post
688: try {
689: res.sendRedirect(res
690: .encodeRedirectURL(ServerConfigurationService
691: .getPortalUrl()
692: + "/error-reported"));
693: } catch (IOException e) {
694: M_log.warn(rb.getString("bugreport.troubleredirecting"), e);
695: }
696: }
697:
698: /**
699: * Accept the user feedback post.
700: *
701: * @param req
702: * The request.
703: * @param res
704: * The response.
705: */
706: public void thanksResponse(HttpServletRequest req,
707: HttpServletResponse res) {
708: String headInclude = (String) req
709: .getAttribute("sakai.html.head");
710: String bodyOnload = (String) req
711: .getAttribute("sakai.html.body.onload");
712:
713: if (bodyOnload == null) {
714: bodyOnload = "";
715: } else {
716: bodyOnload = " onload=\"" + bodyOnload + "\"";
717: }
718: try {
719: // headers
720: res.setContentType("text/html; charset=UTF-8");
721: res.addDateHeader("Expires", System.currentTimeMillis()
722: - (1000L * 60L * 60L * 24L * 365L));
723: res.addDateHeader("Last-Modified", System
724: .currentTimeMillis());
725: res
726: .addHeader("Cache-Control",
727: "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0");
728: res.addHeader("Pragma", "no-cache");
729:
730: PrintWriter out = res.getWriter();
731: out
732: .println("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
733: out
734: .println("<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\">");
735: if (headInclude != null) {
736: out.println("<head>");
737: out.println(headInclude);
738: out.println("</head>");
739: }
740: out.println("<body" + bodyOnload + ">");
741: out.println("<div class=\"portletBody\">");
742: out.println("<h3>" + rb.getString("bugreport.error")
743: + "</h3>");
744: out.println("<p>" + rb.getString("bugreport.statement")
745: + "<br /><br /></p>");
746:
747: out.println("<h4>" + rb.getString("bugreport.senttitle")
748: + "</h4>");
749: out.println("<p>" + rb.getString("bugreport.sentnote")
750: + "<br /><br /></p>");
751:
752: out
753: .println("<h4>"
754: + rb.getString("bugreport.recoverytitle")
755: + "</h4>");
756: out.println("<p>"
757: + rb.getString("bugreport.recoveryinstructions")
758: + "");
759: out.println("<ul><li>"
760: + rb.getString("bugreport.recoveryinstructions1")
761: + "</li>");
762: out.println("<li>"
763: + rb.getString("bugreport.recoveryinstructions2")
764: + "</li>");
765: out.println("<li>"
766: + rb.getString("bugreport.recoveryinstructions3")
767: + "</li></ul><br /><br /></p>");
768:
769: out.println("</body>");
770: out.println("</html>");
771: } catch (Throwable any) {
772: M_log.warn(rb.getString("bugreport.troublethanks"), any);
773: }
774: }
775: }
|