1 package org.apache.torque;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.io.PrintStream;
20 import java.io.PrintWriter;
21 import java.io.StringWriter;
22 import java.util.LinkedList;
23 import java.util.StringTokenizer;
24
25 /***
26 * This is a base class of runtime exeptions thrown by Torque. <p>
27 *
28 * This class represents a non-checked type exception (see
29 * {@link java.lang.RuntimeException}).
30 * It is intended to ease the debugging by carrying on the information about the
31 * exception which was caught and provoked throwing the current exception.
32 * Catching and rethrowing may occur multiple times, and provided that all
33 * exceptions except the first one are descendands of
34 * <code>TorqueRuntimeException</code>, when the exception is finally printed
35 * out using any of the <code>printStackTrace()</code> methods, the stacktrace
36 * will contain the information about all exceptions thrown and caught on the
37 * way.
38 *
39 * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
40 * @version $Id: TorqueRuntimeException.java 239630 2005-08-24 12:25:32Z henning $
41 */
42 public class TorqueRuntimeException
43 extends RuntimeException
44 {
45 /***
46 * Holds the reference to the exception or error that caused
47 * this exception to be thrown.
48 */
49 private Throwable nested = null;
50
51 /***
52 * Constructs a new <code>TorqueRuntimeException</code> without specified
53 * detail message.
54 */
55 public TorqueRuntimeException()
56 {
57 super();
58 }
59
60 /***
61 * Constructs a new <code>TorqueRuntimeException</code> with specified
62 * detail message.
63 *
64 * @param msg the error message.
65 */
66 public TorqueRuntimeException(String msg)
67 {
68 super(msg);
69 }
70
71 /***
72 * Constructs a new <code>TorqueRuntimeException</code> with specified
73 * nested <code>Throwable</code>.
74 *
75 * @param nested the exception or error that caused this exception
76 * to be thrown.
77 */
78 public TorqueRuntimeException(Throwable nested)
79 {
80 super();
81 this.nested = nested;
82 }
83
84 /***
85 * Constructs a new <code>TorqueRuntimeException</code> with specified
86 * detail message and nested <code>Throwable</code>.
87 *
88 * @param msg the error message.
89 * @param nested the exception or error that caused this exception
90 * to be thrown.
91 */
92 public TorqueRuntimeException(String msg, Throwable nested)
93 {
94 super(msg);
95 this.nested = nested;
96 }
97
98 /***
99 * Prints the stack trace of this exception the the standar error stream.
100 */
101 public void printStackTrace()
102 {
103 synchronized (System.err)
104 {
105 printStackTrace(System.err);
106 }
107 }
108
109 /***
110 * Prints the stack trace of this exception to the specified print stream.
111 *
112 * @param out <code>PrintStream</code> to use for output
113 */
114 public void printStackTrace(PrintStream out)
115 {
116 synchronized (out)
117 {
118 PrintWriter pw = new PrintWriter(out, false);
119 printStackTrace(pw);
120
121 pw.flush();
122 }
123 }
124
125 /***
126 * Prints the stack trace of this exception to the specified print writer.
127 *
128 * @param out <code>PrintWriter</code> to use for output.
129 */
130 public void printStackTrace(PrintWriter out)
131 {
132 synchronized (out)
133 {
134 printStackTrace(out, 0);
135 }
136 }
137
138 /***
139 * Prints the stack trace of this exception skiping a specified number
140 * of stack frames.
141 *
142 * @param out <code>PrintWriter</code> to use for output.
143 * @param skip the numbere of stack frames to skip.
144 */
145 public void printStackTrace(PrintWriter out, int skip)
146 {
147 String[] st = captureStackTrace();
148 if (nested != null)
149 {
150 if (nested instanceof TorqueRuntimeException)
151 {
152 ((TorqueRuntimeException) nested)
153 .printStackTrace(out, st.length - 2);
154 }
155 else if (nested instanceof TorqueException)
156 {
157 ((TorqueException) nested).printStackTrace(out);
158 }
159 else
160 {
161 String[] nst = captureStackTrace(nested);
162 for (int i = 0; i < nst.length - st.length + 2; i++)
163 {
164 out.println(nst[i]);
165 }
166 }
167 out.print("rethrown as ");
168 }
169 for (int i = 0; i < st.length - skip; i++)
170 {
171 out.println(st[i]);
172 }
173 }
174
175 /***
176 * Captures the stack trace associated with this exception.
177 *
178 * @return an array of Strings describing stack frames.
179 */
180 private String[] captureStackTrace()
181 {
182 StringWriter sw = new StringWriter();
183 super.printStackTrace(new PrintWriter(sw, true));
184 return splitStackTrace(sw.getBuffer().toString());
185 }
186
187 /***
188 * Captures the stack trace associated with a <code>Throwable</code>
189 * object.
190 *
191 * @param t the <code>Throwable</code>.
192 * @return an array of Strings describing stack frames.
193 */
194 private String[] captureStackTrace(Throwable t)
195 {
196 StringWriter sw = new StringWriter();
197 t.printStackTrace(new PrintWriter(sw, true));
198 return splitStackTrace(sw.getBuffer().toString());
199 }
200
201 /***
202 * Splits the stack trace given as a newline separated string
203 * into an array of stack frames.
204 *
205 * @param stackTrace the stack trace.
206 * @return an array of Strings describing stack frames.
207 */
208 private String[] splitStackTrace(String stackTrace)
209 {
210 String linebreak = System.getProperty("line.separator");
211 StringTokenizer st = new StringTokenizer(stackTrace, linebreak);
212 LinkedList list = new LinkedList();
213 while (st.hasMoreTokens())
214 {
215 list.add(st.nextToken());
216 }
217 return (String[]) list.toArray(new String[] {});
218 }
219 }