Add translations for French and Japanese
[frank.git] / prod / net / jaekl / frank / ErrorHandler.java
1 package net.jaekl.frank;
2
3 import java.io.ByteArrayOutputStream;
4 import java.io.PrintStream;
5 import java.io.PrintWriter;
6 import java.net.SocketTimeoutException;
7 import java.text.MessageFormat;
8 import java.util.Locale;
9
10 import net.jaekl.qd.http.InvalidResponseException;
11
12 public class ErrorHandler {
13         static final String JAVASCRIPT_PART1 =
14                         "<SCRIPT>\n" +
15                         "  var show_hide = function() {\n" +
16                         "  var theDiv = document.getElementById('details');\n" +
17                         "  var theButton = document.getElementById('details_btn');\n" +
18                         "  if (theDiv.style.display === 'block' || theDiv.style.display === '') {\n" +
19                         "    theDiv.style.display = 'none';\n" +
20                         "  theButton.value = '";
21         // insert "show details" text here
22         static final String JAVASCRIPT_PART2 = "';\n" + 
23                         "  }\n" +
24                         "  else {\n" +
25                         "    theDiv.style.display = 'block';\n" +
26                         "    theButton.value = '";
27         // insert "hide details" text here
28         static final String JAVASCRIPT_PART3 = "';\n" + 
29                         "  }\n" +
30                         "}\n" +
31                         "</SCRIPT>";
32         
33         void writeScript(PrintWriter pw, FrankBundle bundle) {
34                 String javaScript = JAVASCRIPT_PART1 +  
35                                         bundle.get(FrankBundle.SHOW_DETAILS) +
36                                         JAVASCRIPT_PART2 +
37                                         bundle.get(FrankBundle.HIDE_DETAILS) +
38                                         JAVASCRIPT_PART3;
39                 
40                 pw.println(javaScript);
41         }
42         
43         void explain(PrintWriter pw, Throwable t, FrankBundle bundle) {
44                 Throwable cause = t;
45                 if (t instanceof FrankException) {
46                         if (null != t.getCause()) {
47                                 cause = t.getCause();
48                         }
49                 }
50                 
51                 pw.println("<P>");
52                 if (cause instanceof InvalidResponseException) {
53                         InvalidResponseException ire = (InvalidResponseException)cause;
54                         
55                         pw.println(bundle.get(FrankBundle.INVALID_RESPONSE));
56                         pw.println("<P ID=\"errtable\">");
57                         pw.println("  <TABLE>");
58                         pw.println("    <TR><TD CLASS=\"head\">" + bundle.get(FrankBundle.URL_CONTACTED) 
59                                         + "</TD><TD>" + ire.getUrl() + "</TD></TR>");
60                         pw.println("    <TR CLASS=\"alt\"><TD CLASS=\"head\">" + bundle.get(FrankBundle.REQUEST_MADE) 
61                                         + "</TD><TD>" + ire.getMethod() + "</TD></TR>");
62                         pw.println("    <TR><TD CLASS=\"head\">" + bundle.get(FrankBundle.ANSWER_RECEIVED) 
63                                         + "</TD><TD>" + ire.getResponse() + "</TD></TR>");
64                         pw.println("  </TABLE>");
65                         pw.println("</P>");
66                         pw.println("<P>" + bundle.get(FrankBundle.MAYBE_SERVER_PROBLEM) + "</P>");
67                 }
68                 else if (cause instanceof SocketTimeoutException) {
69                         pw.println(bundle.get(FrankBundle.SERVER_TIMEOUT));
70                 }
71                 else {
72                         pw.println(bundle.get(FrankBundle.UNEXPECTED_EXCEPTION));
73                 }
74                 pw.println("</P>");
75         }
76         
77         void writeErrorPage(PrintWriter pw, Throwable t, Locale locale) {
78                 Style style = new Style();
79                 ByteArrayOutputStream baos = new ByteArrayOutputStream();
80                 PrintStream ps = new PrintStream(baos);
81                 FrankBundle bundle = FrankBundle.getInst(locale);
82                 
83                 pw.println("<HTML><HEAD>");
84                 pw.println("<TITLE>" + 
85                                 bundle.get(FrankBundle.FRANK) + ": " +
86                                 bundle.get(FrankBundle.ERROR_PAGE) + 
87                                 "</TITLE>");
88                 style.writeStyle(pw);
89                 writeScript(pw, bundle);
90                 pw.println("</HEAD>");
91                 
92                 pw.println("<BODY>");
93                 pw.println("<TABLE ID=\"errhead\" WIDTH=\"100%\"><TR><TD>" +
94                                 bundle.get(FrankBundle.FRANK) + ": " +
95                                 bundle.get(FrankBundle.UNEXPECTED_ERROR) + 
96                                 "</TD></TR></TABLE>");
97                 
98                 explain(pw, t, bundle);
99                 
100                 // Note that, if we cared about security, we would log this stack trace to a
101                 // server log, and only report a cross-reference to the log file back to the 
102                 // end user's browser, to avoid potentially exposing internal info that we 
103                 // don't want to share.
104                 // At least at this point, we don't care (that much), and trade off a 
105                 // potential information leak in favour of reducing our code complexity
106                 // and the administrator's workload.
107                 
108                 pw.println("<P><INPUT TYPE=\"button\" ID=\"details_btn\" VALUE=\"" +
109                                 bundle.get(FrankBundle.SHOW_DETAILS) +
110                                 "\" ONCLICK=\"show_hide();\"/></P>");
111                 pw.println("<P>");
112                 pw.println("<DIV ID=\"details\" STYLE=\"display: none;\"><PRE>");
113                 
114                 t.printStackTrace(ps);
115                 String stackTrace = baos.toString(); 
116                 pw.println(stackTrace);
117                                 
118                 pw.println("</PRE>\n</P>\n</DIV>");
119                 
120                 String returnToMainFormat = bundle.get(FrankBundle.RETURN_TO_MAIN_PAGE);
121                 String returnToMain = MessageFormat.format(returnToMainFormat, "/");
122                 pw.println("<P>" + returnToMain + "</P>");
123                 pw.println("</BODY></HTML>");
124         }
125 }