1 package org.apache.maven.surefire.util;
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 /*
23 * Copyright 2002-2005 the original author or authors.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
36 */
37
38 import java.io.PrintStream;
39 import java.io.PrintWriter;
40
41 /**
42 * <p>Copied from Spring framework to keep Java 1.3 compatibility.</p>
43 * <p/>
44 * <p>Handy class for wrapping checked Exceptions with a root cause.</p>
45 * <p/>
46 * <p>This time-honored technique is no longer necessary in Java 1.4, which
47 * finally provides built-in support for exception nesting. Thus exceptions in
48 * applications written to use Java 1.4 need not extend this class. To ease
49 * migration, this class mirrors Java 1.4's nested exceptions as closely as possible.
50 * <p/>
51 * <p>Abstract to force the programmer to extend the class. <code>getMessage</code>
52 * will include nested exception information; <code>printStackTrace</code> etc will
53 * delegate to the wrapped exception, if any.
54 * <p/>
55 * <p>The similarity between this class and the NestedRuntimeException class is
56 * unavoidable, as Java forces these two classes to have different superclasses
57 * (ah, the inflexibility of concrete inheritance!).
58 * <p/>
59 * <p>As discussed in
60 * <a href="http://www.amazon.com/exec/obidos/tg/detail/-/0764543857/">Expert One-On-One J2EE Design and
61 * Development</a>, runtime exceptions are often a better alternative to checked exceptions.
62 * However, all exceptions should preserve their stack trace, if caused by a
63 * lower-level exception.
64 *
65 * @author Rod Johnson
66 * @author Juergen Hoeller
67 * @see #getMessage
68 * @see #printStackTrace
69 * @see NestedRuntimeException
70 */
71 public class NestedCheckedException
72 extends Exception
73 {
74
75 /**
76 * Root cause of this nested exception
77 */
78 private Throwable cause;
79
80 /**
81 * Construct a <code>NestedCheckedException</code> with no message or exception
82 */
83 public NestedCheckedException()
84 {
85 super();
86 }
87
88 /**
89 * Construct a <code>NestedCheckedException</code> with the specified detail message.
90 *
91 * @param msg the detail message
92 */
93 public NestedCheckedException( String msg )
94 {
95 super( msg );
96 }
97
98 /**
99 * Construct a <code>NestedCheckedException</code> with the specified detail message
100 * and nested exception.
101 *
102 * @param msg the detail message
103 * @param ex the nested exception
104 */
105 public NestedCheckedException( String msg, Throwable ex )
106 {
107 super( msg );
108 this.cause = ex;
109 }
110
111 /**
112 * Return the nested cause, or <code>null</code> if none.
113 */
114 public Throwable getCause()
115 {
116 // Even if you cannot set the cause of this exception other than through
117 // the constructor, we check for the cause being "this" here, as the cause
118 // could still be set to "this" via reflection: for example, by a remoting
119 // deserializer like Hessian's.
120 return ( this.cause == this ? null : this.cause );
121 }
122
123 /**
124 * Return the detail message, including the message from the nested exception
125 * if there is one.
126 */
127 public String getMessage()
128 {
129 if ( getCause() == null )
130 {
131 return super.getMessage();
132 }
133 else
134 {
135 return super.getMessage() + "; nested exception is " + getCause().getClass().getName() + ": "
136 + getCause().getMessage();
137 }
138 }
139
140 /**
141 * Print the composite message and the embedded stack trace to the specified stream.
142 *
143 * @param ps the print stream
144 */
145 public void printStackTrace( PrintStream ps )
146 {
147 if ( getCause() == null )
148 {
149 super.printStackTrace( ps );
150 }
151 else
152 {
153 ps.println( this );
154 getCause().printStackTrace( ps );
155 }
156 }
157
158 /**
159 * Print the composite message and the embedded stack trace to the specified print writer.
160 *
161 * @param pw the print writer
162 */
163 public void printStackTrace( PrintWriter pw )
164 {
165 if ( getCause() == null )
166 {
167 super.printStackTrace( pw );
168 }
169 else
170 {
171 pw.println( this );
172 getCause().printStackTrace( pw );
173 }
174 }
175
176 /**
177 * Check whether this exception contains an exception of the given class:
178 * either it is of the given class itself or it contains a nested cause
179 * of the given class.
180 * <p>Currently just traverses NestedCheckedException causes. Will use
181 * the JDK 1.4 exception cause mechanism once Spring requires JDK 1.4.
182 *
183 * @param exClass the exception class to look for
184 * @return true if it is contained
185 */
186 public boolean contains( Class exClass )
187 {
188 if ( exClass == null )
189 {
190 return false;
191 }
192 Throwable ex = this;
193 while ( ex != null )
194 {
195 if ( exClass.isInstance( ex ) )
196 {
197 return true;
198 }
199 if ( ex instanceof NestedCheckedException )
200 {
201 // Cast is necessary on JDK 1.3, where Throwable does not
202 // provide a "getCause" method itself.
203 ex = ex.getCause();
204 }
205 else
206 {
207 ex = null;
208 }
209 }
210 return false;
211 }
212
213 }