Commit | Line | Data |
---|---|---|
e23ea538 KL |
1 | /* |
2 | * Jexer - Java Text User Interface | |
3 | * | |
4 | * The MIT License (MIT) | |
5 | * | |
6 | * Copyright (C) 2019 Kevin Lamonte | |
7 | * | |
8 | * Permission is hereby granted, free of charge, to any person obtaining a | |
9 | * copy of this software and associated documentation files (the "Software"), | |
10 | * to deal in the Software without restriction, including without limitation | |
11 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
12 | * and/or sell copies of the Software, and to permit persons to whom the | |
13 | * Software is furnished to do so, subject to the following conditions: | |
14 | * | |
15 | * The above copyright notice and this permission notice shall be included in | |
16 | * all copies or substantial portions of the Software. | |
17 | * | |
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
23 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
24 | * DEALINGS IN THE SOFTWARE. | |
25 | * | |
26 | * @author Kevin Lamonte [kevin.lamonte@gmail.com] | |
27 | * @version 1 | |
28 | */ | |
29 | package jexer; | |
30 | ||
31 | import java.io.FileWriter; | |
32 | import java.io.IOException; | |
33 | import java.io.PrintWriter; | |
34 | import java.text.MessageFormat; | |
35 | import java.util.ArrayList; | |
36 | import java.util.Date; | |
37 | import java.util.ResourceBundle; | |
38 | ||
39 | import jexer.bits.CellAttributes; | |
40 | ||
41 | /** | |
42 | * TExceptionDialog displays an exception and its stack trace to the user, | |
43 | * and provides a means to save a troubleshooting report for support. | |
44 | */ | |
45 | public class TExceptionDialog extends TWindow { | |
46 | ||
47 | /** | |
48 | * Translated strings. | |
49 | */ | |
8994e796 | 50 | private static final ResourceBundle i18n = ResourceBundle.getBundle(TExceptionDialog.class.getName()); |
e23ea538 KL |
51 | |
52 | // ------------------------------------------------------------------------ | |
53 | // Constants -------------------------------------------------------------- | |
54 | // ------------------------------------------------------------------------ | |
55 | ||
56 | // ------------------------------------------------------------------------ | |
57 | // Variables -------------------------------------------------------------- | |
58 | // ------------------------------------------------------------------------ | |
59 | ||
60 | /** | |
61 | * The exception. We will actually make it Throwable, for the unlikely | |
62 | * event we catch an Error rather than an Exception. | |
63 | */ | |
64 | private Throwable exception; | |
65 | ||
66 | /** | |
67 | * The exception's stack trace. | |
68 | */ | |
69 | private TList stackTrace; | |
70 | ||
71 | // ------------------------------------------------------------------------ | |
72 | // Constructors ----------------------------------------------------------- | |
73 | // ------------------------------------------------------------------------ | |
74 | ||
75 | /** | |
76 | * Public constructor. | |
77 | * | |
78 | * @param application TApplication that manages this window | |
79 | * @param exception the exception to display | |
80 | */ | |
81 | public TExceptionDialog(final TApplication application, | |
82 | final Throwable exception) { | |
83 | ||
84 | super(application, i18n.getString("windowTitle"), | |
9240f032 | 85 | 1, 1, 78, 22, CENTERED | MODAL); |
e23ea538 KL |
86 | |
87 | this.exception = exception; | |
88 | ||
89 | addLabel(i18n.getString("captionLine1"), 1, 1, | |
90 | "twindow.background.modal"); | |
91 | addLabel(i18n.getString("captionLine2"), 1, 2, | |
92 | "twindow.background.modal"); | |
93 | addLabel(i18n.getString("captionLine3"), 1, 3, | |
94 | "twindow.background.modal"); | |
95 | addLabel(i18n.getString("captionLine4"), 1, 4, | |
96 | "twindow.background.modal"); | |
97 | ||
98 | addLabel(MessageFormat.format(i18n.getString("exceptionString"), | |
99 | exception.getClass().getName(), exception.getMessage()), | |
100 | 2, 6, "ttext", false); | |
101 | ||
102 | ArrayList<String> stackTraceStrings = new ArrayList<String>(); | |
9240f032 | 103 | stackTraceStrings.add(exception.getMessage()); |
e23ea538 KL |
104 | StackTraceElement [] stack = exception.getStackTrace(); |
105 | for (int i = 0; i < stack.length; i++) { | |
106 | stackTraceStrings.add(stack[i].toString()); | |
107 | } | |
9240f032 | 108 | stackTrace = addList(stackTraceStrings, 2, 7, getWidth() - 6, 10); |
e23ea538 KL |
109 | |
110 | // Buttons | |
9240f032 | 111 | addButton(i18n.getString("saveButton"), 21, getHeight() - 4, |
e23ea538 KL |
112 | new TAction() { |
113 | public void DO() { | |
114 | saveToFile(); | |
115 | } | |
116 | }); | |
117 | ||
118 | TButton closeButton = addButton(i18n.getString("closeButton"), | |
9240f032 | 119 | 37, getHeight() - 4, |
e23ea538 KL |
120 | new TAction() { |
121 | public void DO() { | |
122 | // Don't do anything, just close the window. | |
123 | TExceptionDialog.this.close(); | |
124 | } | |
125 | }); | |
126 | ||
127 | // Save this for last: make the close button default action. | |
128 | activate(closeButton); | |
129 | } | |
130 | ||
131 | // ------------------------------------------------------------------------ | |
132 | // TWindow ---------------------------------------------------------------- | |
133 | // ------------------------------------------------------------------------ | |
134 | ||
135 | /** | |
136 | * Draw the exception message background. | |
137 | */ | |
138 | @Override | |
139 | public void draw() { | |
140 | // Draw window and border. | |
141 | super.draw(); | |
142 | ||
143 | CellAttributes boxColor = getTheme().getColor("ttext"); | |
144 | hLineXY(3, 7, getWidth() - 6, ' ', boxColor); | |
145 | } | |
146 | ||
147 | // ------------------------------------------------------------------------ | |
148 | // TExceptionDialog ------------------------------------------------------- | |
149 | // ------------------------------------------------------------------------ | |
150 | ||
151 | /** | |
152 | * Save a troubleshooting report to file. Note that we do NOT translate | |
153 | * the strings within the error report. | |
154 | */ | |
155 | private void saveToFile() { | |
156 | // Prompt for filename. | |
157 | PrintWriter writer = null; | |
158 | try { | |
159 | String filename = fileSaveBox("."); | |
160 | if (filename == null) { | |
161 | // User cancelled, bail out. | |
162 | return; | |
163 | } | |
164 | writer = new PrintWriter(new FileWriter(filename)); | |
165 | writer.write("Date: " + new Date(System.currentTimeMillis()) | |
166 | + "\n"); | |
167 | ||
168 | // System properties | |
169 | writer.write("System properties:\n"); | |
170 | writer.write("-----------------------------------\n"); | |
171 | System.getProperties().store(writer, null); | |
172 | writer.write("-----------------------------------\n"); | |
173 | writer.write("\n"); | |
174 | ||
175 | // The exception we caught | |
176 | writer.write("Caught exception:\n"); | |
177 | writer.write("-----------------------------------\n"); | |
178 | exception.printStackTrace(writer); | |
179 | writer.write("-----------------------------------\n"); | |
180 | writer.write("\n"); | |
181 | // The exception's cause, if it was set | |
182 | if (exception.getCause() != null) { | |
183 | writer.write("Caught exception's cause:\n"); | |
184 | writer.write("-----------------------------------\n"); | |
185 | exception.getCause().printStackTrace(writer); | |
186 | writer.write("-----------------------------------\n"); | |
187 | } | |
188 | writer.write("\n"); | |
189 | ||
190 | // The UI stack trace | |
191 | writer.write("UI stack trace:\n"); | |
192 | writer.write("-----------------------------------\n"); | |
193 | (new Throwable("UI Thread")).printStackTrace(writer); | |
194 | writer.write("-----------------------------------\n"); | |
195 | writer.write("\n"); | |
196 | writer.close(); | |
197 | } catch (IOException e) { | |
198 | messageBox(i18n.getString("errorDialogTitle"), | |
199 | MessageFormat.format(i18n. | |
200 | getString("errorSavingFile"), e.getMessage())); | |
201 | } finally { | |
202 | if (writer != null) { | |
203 | writer.close(); | |
204 | writer = null; | |
205 | } | |
206 | } | |
207 | } | |
208 | } |