Initial import
[jpf-core.git] / src / classes / java / lang / Throwable.java
1 /*
2  * Copyright (C) 2014, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The Java Pathfinder core (jpf-core) platform is licensed under the
7  * Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. 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 package java.lang;
20
21 import java.io.PrintStream;
22 import java.io.PrintWriter;
23
24 /**
25  * barebones model class for java.lang.Throwable
26  * 
27  * the main reason for having one is to defer the stacktrace creation, which
28  * we don't want if all an application does is intercepting a gazillion of
29  * exceptions like NoSuchMethodException
30  */
31 public class Throwable {
32
33   int[] snapshot; // this is an internal array of { globalMethodId, pcOffset } pairs
34   
35   protected Throwable cause; // in case this is a wrapper exception (like InvocationTargetException)
36   
37   protected String detailMessage; // where we keep the context specific info
38     
39   protected StackTraceElement[] stackTrace; // only set on demand, if getStackTrace() is called
40   
41   public Throwable() {
42     try {                                            // Use Class.forName() instead of new StackTraceElement() since the latter creates garbage.
43       Class.forName("java.lang.StackTraceElement");  // Force this class to load here instead of in createStackTrace().
44     } catch (ClassNotFoundException e) {
45       throw new NoClassDefFoundError("java.lang.StackTraceElement");
46     }
47      
48     fillInStackTrace();
49   }
50
51   public Throwable (String msg) {
52     this();
53     detailMessage = msg;
54     cause = this;
55   }
56
57   public Throwable (String msg, Throwable xCause) {
58     this();
59     detailMessage = msg;
60     cause = xCause;
61   }
62
63   public Throwable (Throwable xCause) {
64     this();
65     
66     cause = xCause;
67     if (cause != null){
68       detailMessage = xCause.toString();
69     }
70   }
71
72   public String getMessage() {
73     return detailMessage;
74   }
75   
76   public String getLocalizedMessage() {
77     return detailMessage;
78   }
79
80   public Throwable getCause() {
81     if (cause == this){
82       return null;  // quirky
83     } else {
84       return cause;
85     }
86   }
87
88   // this sets 'snapshot' from the native side
89   public native Throwable fillInStackTrace();
90   
91   // and this turns 'snapshot' into an array of StackTraceElement objects
92   private native StackTraceElement[] createStackTrace();
93   
94   public StackTraceElement[] getStackTrace() {
95     if (stackTrace == null){
96       stackTrace = createStackTrace();
97     }
98     
99     return stackTrace;
100   }
101   
102   public void setStackTrace (StackTraceElement[] st) {
103     stackTrace = st;
104   }
105
106   public synchronized Throwable initCause (Throwable xCause) {
107     if (xCause == this){
108       throw new IllegalArgumentException("self-causation not permitted");
109     }
110     
111     if (cause != this){
112       throw new IllegalStateException("cannot overwrite cause");
113     }
114     
115     cause = xCause;
116     
117     return this;
118   }
119
120   @Override
121   public native String toString();
122   
123   public native void printStackTrace ();
124   
125   // <2do> and lots more of printStackTraces..
126
127   private native String getStackTraceAsString();
128   
129   public void printStackTrace (PrintStream ps){
130     String s = getStackTraceAsString();
131     ps.print(s);
132   }
133   
134   public void printStackTrace (PrintWriter pw){
135     String s = getStackTraceAsString();
136     pw.print(s);    
137   }
138   
139   int getStackTraceDepth(){
140     return (snapshot.length / 2); // snapshot stores the methodId and pc for each StackFrame 
141   }
142 }