001: package org.apache.torque;
002:
003: /*
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: import java.io.PrintStream;
023: import java.io.PrintWriter;
024: import java.io.StringWriter;
025: import java.util.LinkedList;
026: import java.util.StringTokenizer;
027:
028: /**
029: * This is a base class of runtime exeptions thrown by Torque. <p>
030: *
031: * This class represents a non-checked type exception (see
032: * {@link java.lang.RuntimeException}).
033: * It is intended to ease the debugging by carrying on the information about the
034: * exception which was caught and provoked throwing the current exception.
035: * Catching and rethrowing may occur multiple times, and provided that all
036: * exceptions except the first one are descendands of
037: * <code>TorqueRuntimeException</code>, when the exception is finally printed
038: * out using any of the <code>printStackTrace()</code> methods, the stacktrace
039: * will contain the information about all exceptions thrown and caught on the
040: * way.
041: *
042: * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
043: * @version $Id: TorqueRuntimeException.java 584524 2007-10-14 10:25:43Z tfischer $
044: */
045: public class TorqueRuntimeException extends RuntimeException {
046: /**
047: * Serial version
048: */
049: private static final long serialVersionUID = -2997617341459640541L;
050:
051: /**
052: * Holds the reference to the exception or error that caused
053: * this exception to be thrown.
054: */
055: private Throwable nested = null;
056:
057: /**
058: * Constructs a new <code>TorqueRuntimeException</code> without specified
059: * detail message.
060: */
061: public TorqueRuntimeException() {
062: super ();
063: }
064:
065: /**
066: * Constructs a new <code>TorqueRuntimeException</code> with specified
067: * detail message.
068: *
069: * @param msg the error message.
070: */
071: public TorqueRuntimeException(String msg) {
072: super (msg);
073: }
074:
075: /**
076: * Constructs a new <code>TorqueRuntimeException</code> with specified
077: * nested <code>Throwable</code>.
078: *
079: * @param nested the exception or error that caused this exception
080: * to be thrown.
081: */
082: public TorqueRuntimeException(Throwable nested) {
083: super ();
084: this .nested = nested;
085: }
086:
087: /**
088: * Constructs a new <code>TorqueRuntimeException</code> with specified
089: * detail message and nested <code>Throwable</code>.
090: *
091: * @param msg the error message.
092: * @param nested the exception or error that caused this exception
093: * to be thrown.
094: */
095: public TorqueRuntimeException(String msg, Throwable nested) {
096: super (msg);
097: this .nested = nested;
098: }
099:
100: /**
101: * Prints the stack trace of this exception the the standar error stream.
102: */
103: public void printStackTrace() {
104: synchronized (System.err) {
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: synchronized (out) {
116: PrintWriter pw = new PrintWriter(out, false);
117: printStackTrace(pw);
118: // flush the PrintWriter before it's GCed
119: pw.flush();
120: }
121: }
122:
123: /**
124: * Prints the stack trace of this exception to the specified print writer.
125: *
126: * @param out <code>PrintWriter</code> to use for output.
127: */
128: public void printStackTrace(PrintWriter out) {
129: synchronized (out) {
130: printStackTrace(out, 0);
131: }
132: }
133:
134: /**
135: * Prints the stack trace of this exception skiping a specified number
136: * of stack frames.
137: *
138: * @param out <code>PrintWriter</code> to use for output.
139: * @param skip the numbere of stack frames to skip.
140: */
141: public void printStackTrace(PrintWriter out, int skip) {
142: String[] st = captureStackTrace();
143: if (nested != null) {
144: if (nested instanceof TorqueRuntimeException) {
145: ((TorqueRuntimeException) nested).printStackTrace(out,
146: st.length - 2);
147: } else if (nested instanceof TorqueException) {
148: ((TorqueException) nested).printStackTrace(out);
149: } else {
150: String[] nst = captureStackTrace(nested);
151: for (int i = 0; i < nst.length - st.length + 2; i++) {
152: out.println(nst[i]);
153: }
154: }
155: out.print("rethrown as ");
156: }
157: for (int i = 0; i < st.length - skip; i++) {
158: out.println(st[i]);
159: }
160: }
161:
162: /**
163: * Captures the stack trace associated with this exception.
164: *
165: * @return an array of Strings describing stack frames.
166: */
167: private String[] captureStackTrace() {
168: StringWriter sw = new StringWriter();
169: super .printStackTrace(new PrintWriter(sw, true));
170: return splitStackTrace(sw.getBuffer().toString());
171: }
172:
173: /**
174: * Captures the stack trace associated with a <code>Throwable</code>
175: * object.
176: *
177: * @param t the <code>Throwable</code>.
178: * @return an array of Strings describing stack frames.
179: */
180: private String[] captureStackTrace(Throwable t) {
181: StringWriter sw = new StringWriter();
182: t.printStackTrace(new PrintWriter(sw, true));
183: return splitStackTrace(sw.getBuffer().toString());
184: }
185:
186: /**
187: * Splits the stack trace given as a newline separated string
188: * into an array of stack frames.
189: *
190: * @param stackTrace the stack trace.
191: * @return an array of Strings describing stack frames.
192: */
193: private String[] splitStackTrace(String stackTrace) {
194: String linebreak = System.getProperty("line.separator");
195: StringTokenizer st = new StringTokenizer(stackTrace, linebreak);
196: LinkedList list = new LinkedList();
197: while (st.hasMoreTokens()) {
198: list.add(st.nextToken());
199: }
200: return (String[]) list.toArray(new String[list.size()]);
201: }
202: }
|