1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit;
16
17 import java.io.BufferedReader;
18 import java.io.IOException;
19 import java.io.PrintStream;
20 import java.io.PrintWriter;
21 import java.io.StringReader;
22 import java.io.StringWriter;
23 import java.util.StringTokenizer;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.htmlunit.corejs.javascript.EcmaError;
28 import org.htmlunit.corejs.javascript.JavaScriptException;
29 import org.htmlunit.corejs.javascript.RhinoException;
30 import org.htmlunit.corejs.javascript.WrappedException;
31 import org.htmlunit.html.HtmlPage;
32
33
34
35
36
37
38
39
40
41
42 public class ScriptException extends RuntimeException {
43
44
45 private static final Log LOG = LogFactory.getLog(ScriptException.class);
46
47 private final String scriptSourceCode_;
48 private final HtmlPage page_;
49
50
51
52
53
54
55
56
57
58 public ScriptException(final HtmlPage page, final Throwable throwable,
59 final String scriptSourceCode) {
60 super(getMessageFrom(throwable), throwable);
61 scriptSourceCode_ = scriptSourceCode;
62 page_ = page;
63 }
64
65 private static String getMessageFrom(final Throwable throwable) {
66 if (throwable == null) {
67 return "null";
68 }
69 return throwable.getMessage();
70 }
71
72
73
74
75
76
77 public ScriptException(final HtmlPage page, final Throwable throwable) {
78 this(page, throwable, null);
79 }
80
81
82
83
84
85 @Override
86 public void printStackTrace() {
87 printStackTrace(System.out);
88 }
89
90
91
92
93
94
95
96 @Override
97 public void printStackTrace(final PrintWriter writer) {
98 writer.write(createPrintableStackTrace());
99 }
100
101
102
103
104
105
106
107 @Override
108 public void printStackTrace(final PrintStream stream) {
109 stream.print(createPrintableStackTrace());
110 }
111
112 private String createPrintableStackTrace() {
113 final StringWriter stringWriter = new StringWriter();
114 final PrintWriter printWriter = new PrintWriter(stringWriter);
115
116 printWriter.println("======= EXCEPTION START ========");
117
118 if (getCause() != null) {
119 if (getCause() instanceof EcmaError) {
120 final EcmaError ecmaError = (EcmaError) getCause();
121 printWriter.print("EcmaError: ");
122 printWriter.print("lineNumber=[");
123 printWriter.print(ecmaError.lineNumber());
124 printWriter.print("] column=[");
125 printWriter.print(ecmaError.columnNumber());
126 printWriter.print("] lineSource=[");
127 printWriter.print(getFailingLine());
128 printWriter.print("] name=[");
129 printWriter.print(ecmaError.getName());
130 printWriter.print("] sourceName=[");
131 printWriter.print(ecmaError.sourceName());
132 printWriter.print("] message=[");
133 printWriter.print(ecmaError.getMessage());
134 printWriter.print("]");
135 printWriter.println();
136 }
137 else {
138 printWriter.println("Exception class=[" + getCause().getClass().getName() + "]");
139 }
140 }
141
142 super.printStackTrace(printWriter);
143 if (getCause() instanceof JavaScriptException) {
144 final Object value = ((JavaScriptException) getCause()).getValue();
145
146 printWriter.print("JavaScriptException value = ");
147 if (value instanceof Throwable) {
148 ((Throwable) value).printStackTrace(printWriter);
149 }
150 else {
151 printWriter.println(value);
152 }
153 }
154 else if (getCause() instanceof WrappedException) {
155 final WrappedException wrappedException = (WrappedException) getCause();
156 printWriter.print("WrappedException: ");
157 wrappedException.printStackTrace(printWriter);
158
159 final Throwable innerException = wrappedException.getWrappedException();
160 if (innerException == null) {
161 printWriter.println("Inside wrapped exception: null");
162 }
163 else {
164 printWriter.println("Inside wrapped exception:");
165 innerException.printStackTrace(printWriter);
166 }
167 }
168 else if (getCause() != null) {
169 printWriter.println("Enclosed exception: ");
170 getCause().printStackTrace(printWriter);
171 }
172
173 if (scriptSourceCode_ != null && !scriptSourceCode_.isEmpty()) {
174 printWriter.println("== CALLING JAVASCRIPT ==");
175 printWriter.println(scriptSourceCode_);
176 }
177 printWriter.println("======= EXCEPTION END ========");
178
179 return stringWriter.toString();
180 }
181
182
183
184
185
186 public String getScriptSourceCode() {
187 return scriptSourceCode_;
188 }
189
190
191
192
193
194
195
196
197 public String getFailingLine() {
198 final int lineNumber = getFailingLineNumber();
199 if (lineNumber == -1 || scriptSourceCode_ == null) {
200 return "<no source>";
201 }
202
203 try (BufferedReader reader = new BufferedReader(new StringReader(scriptSourceCode_))) {
204 for (int i = 0; i < lineNumber - 1; i++) {
205 reader.readLine();
206 }
207 return reader.readLine();
208 }
209 catch (final IOException e) {
210
211 LOG.error("Reading scriptSourceCode failed.", e);
212 }
213
214 return "";
215 }
216
217
218
219
220
221
222
223 public int getFailingLineNumber() {
224 if (getCause() instanceof RhinoException) {
225 final RhinoException cause = (RhinoException) getCause();
226 return cause.lineNumber();
227 }
228
229 return -1;
230 }
231
232
233
234
235
236
237
238 public int getFailingColumnNumber() {
239 if (getCause() instanceof RhinoException) {
240 final RhinoException cause = (RhinoException) getCause();
241 return cause.columnNumber();
242 }
243
244 return -1;
245 }
246
247
248
249
250
251
252
253 public HtmlPage getPage() {
254 return page_;
255 }
256
257
258
259
260
261
262 public void printScriptStackTrace(final PrintWriter writer) {
263 final StringWriter stringWriter = new StringWriter();
264 final PrintWriter printWriter = new PrintWriter(stringWriter);
265
266 getCause().printStackTrace(printWriter);
267
268 writer.print(getCause().getMessage());
269 final StringTokenizer st = new StringTokenizer(stringWriter.toString(), "\r\n");
270 while (st.hasMoreTokens()) {
271 final String line = st.nextToken();
272 if (line.contains("at script")) {
273 writer.println();
274 writer.print(line.replaceFirst("at script\\.?", "at "));
275 }
276 }
277 }
278
279 }