001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Dmitry B. Yershov
019: * @version $Revision: 1.1.2.3.4.3 $
020: */package java.lang;
021:
022: import java.io.IOException;
023: import java.io.ObjectOutputStream;
024: import java.io.PrintStream;
025: import java.io.PrintWriter;
026: import java.io.Serializable;
027:
028: import org.apache.harmony.vm.VMStack;
029:
030: /**
031: * @com.intel.drl.spec_ref
032: */
033: public class Throwable implements Serializable {
034:
035: private static final long serialVersionUID = -3042686055658047285L;
036:
037: private Throwable cause = this ;
038:
039: private final String detailMessage;
040:
041: private StackTraceElement[] stackTrace;
042:
043: private transient Class[] stackClasses;
044:
045: private transient Object state;
046:
047: /**
048: * @com.intel.drl.spec_ref
049: */
050: public Throwable() {
051: fillInStackTrace();
052: detailMessage = null;
053: }
054:
055: /**
056: * @com.intel.drl.spec_ref
057: */
058: public Throwable(String message) {
059: fillInStackTrace();
060: this .detailMessage = message;
061: }
062:
063: /**
064: * @com.intel.drl.spec_ref
065: */
066: public Throwable(String message, Throwable cause) {
067: this (message);
068: this .cause = cause;
069: }
070:
071: /**
072: * @com.intel.drl.spec_ref
073: */
074: public Throwable(Throwable cause) {
075: this ((cause == null ? null : cause.toString()), cause);
076: }
077:
078: /**
079: * @com.intel.drl.spec_ref
080: */
081: public Throwable fillInStackTrace() {
082: state = VMStack.getStackState();
083: stackClasses = VMStack.getStackClasses(state);
084: return this ;
085: }
086:
087: /**
088: * @com.intel.drl.spec_ref
089: */
090: public Throwable getCause() {
091: return cause == this ? null : cause;
092: }
093:
094: /**
095: * @com.intel.drl.spec_ref
096: */
097: public String getLocalizedMessage() {
098: return detailMessage;
099: }
100:
101: /**
102: * @com.intel.drl.spec_ref
103: */
104: public String getMessage() {
105: return detailMessage;
106: }
107:
108: /**
109: * @com.intel.drl.spec_ref
110: */
111: public StackTraceElement[] getStackTrace() {
112: return getStackTrace(true);
113: }
114:
115: /**
116: * @com.intel.drl.spec_ref
117: */
118: public Throwable initCause(Throwable initialCause) {
119: if (initialCause == this ) {
120: throw new IllegalArgumentException(
121: "A throwable cannot be its own cause.");
122: }
123: // second call of initCause(Throwable)
124: if (cause != this ) {
125: throw new IllegalStateException(
126: "A cause can be set at most once."
127: + " Illegal attempt to re-set the cause of "
128: + this );
129: }
130: cause = initialCause;
131: return this ;
132: }
133:
134: /**
135: * @com.intel.drl.spec_ref
136: */
137: public void printStackTrace() {
138: System.err.println(makeThrowableString());
139: }
140:
141: /**
142: * @com.intel.drl.spec_ref
143: */
144: public void printStackTrace(PrintStream ps) {
145: ps.println(makeThrowableString());
146: }
147:
148: /**
149: * @com.intel.drl.spec_ref
150: */
151: public void printStackTrace(PrintWriter pw) {
152: pw.println(makeThrowableString());
153: }
154:
155: private void initStackTrace() {
156: if (stackTrace == null) {
157: stackTrace = VMStack.getStackTrace(state);
158: state = null;
159: stackClasses = null;
160: }
161: }
162:
163: private StackTraceElement[] getStackTrace(boolean copyArray) {
164: StackTraceElement[] st;
165: initStackTrace();
166:
167: if (copyArray) {
168: st = new StackTraceElement[stackTrace.length];
169: System.arraycopy(stackTrace, 0, st, 0, stackTrace.length);
170: } else {
171: st = stackTrace;
172: }
173: return st;
174: }
175:
176: private String makeThrowableString() {
177: StringBuffer sb = new StringBuffer();
178: sb.append(toString());
179: if (stackTrace == null) {
180: initStackTrace();
181: }
182: // FIXME stackTrace should never be null here
183: if (stackTrace != null) {
184: for (int i = 0; i < stackTrace.length; i++) {
185: sb.append("\n at ").append(stackTrace[i].toString());
186: }
187: } else {
188: sb.append("\n <no stack trace available>");
189: }
190: //causes
191: Throwable wCause = this ;
192: while (wCause != wCause.getCause() && wCause.getCause() != null) {
193: StackTraceElement[] parentStackTrace = wCause.stackTrace;
194: wCause = wCause.getCause();
195: if (wCause.stackTrace == null) {
196: wCause.initStackTrace();
197: }
198: sb.append("\nCaused by: ").append(wCause.toString());
199: // FIXME wCause.stackTrace should never be null here
200: if (wCause.stackTrace != null
201: && wCause.stackTrace.length != 0) {
202: if (parentStackTrace == null
203: || parentStackTrace.length == 0) {
204: for (int i = 0; i < wCause.stackTrace.length; i++) {
205: sb.append("\n at ").append(
206: wCause.stackTrace[i].toString());
207: }
208: } else {
209: int this Count = wCause.stackTrace.length - 1;
210: int parentCount = parentStackTrace.length - 1;
211: int framesEqual = 0;
212: while (parentCount > -1 && this Count > -1) {
213: if (wCause.stackTrace[this Count]
214: .equals(parentStackTrace[parentCount])) {
215: framesEqual++;
216: this Count--;
217: parentCount--;
218: } else {
219: break;
220: }
221: }
222: if (framesEqual > 1) { //to conform with the spec and the common practice (F1F1EE)
223: framesEqual--;
224: }
225: int len = wCause.stackTrace.length - framesEqual;
226: for (int i = 0; i < len; i++) {
227: sb.append("\n at ").append(
228: wCause.stackTrace[i].toString());
229: }
230: if (framesEqual > 0) {
231: sb.append("\n ... ").append(framesEqual)
232: .append(" more");
233: }
234: }
235: } else {
236: sb.append("\n <no stack trace available>");
237: }
238: }
239: return sb.toString();
240: }
241:
242: /**
243: * @com.intel.drl.spec_ref
244: */
245: public void setStackTrace(StackTraceElement[] stackTrace) {
246: int len = stackTrace.length;
247: StackTraceElement[] st = new StackTraceElement[len];
248: for (int i = 0; i < len; i++) {
249: if (stackTrace[i] == null) {
250: throw new NullPointerException();
251: }
252: st[i] = stackTrace[i];
253: }
254: this .stackTrace = st;
255: }
256:
257: /**
258: * @com.intel.drl.spec_ref
259: */
260: public String toString() {
261: String str = getMessage();
262: return getClass().getName() + (str == null ? "" : ": " + str);
263: }
264:
265: private void writeObject(ObjectOutputStream s) throws IOException {
266: if (stackTrace == null) {
267: initStackTrace();
268: }
269: s.defaultWriteObject();
270: }
271: }
|