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