View Javadoc

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