View Javadoc

1   package org.apache.torque;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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             // flush the PrintWriter before it's GCed
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 }