View Javadoc
1   /*
2    *  Copyright 2012 Christopher Pheby
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  package org.jadira.cdt.exception;
17  
18  /**
19   * Class for constructing runtime Exceptions with a given root cause.
20   */
21  public abstract class WrappedRuntimeException extends RuntimeException {
22  
23  	private static final long serialVersionUID = 2370572498972367128L;
24  
25  	/**
26  	 * Construct a WrappedRuntimeException with the specified 
27  	 * message.
28  	 * @param message the specific message
29  	 */
30  	public WrappedRuntimeException(String message) {
31  		super(message);
32  	}
33  
34  	/**
35  	 * Construct a WrappedRuntimeException with the specified 
36  	 * message and wrapped exception.
37  	 * @param message the specific message
38  	 * @param cause the wrapped exception
39  	 */
40  	public WrappedRuntimeException(String message, Throwable cause) {
41  		super(message, cause);
42  	}
43  
44  	/**
45  	 * Return the detail message, including the message from the wrapped
46  	 * exception if there is one.
47  	 * @return The message
48  	 */
49  	@Override
50  	public String getMessage() {
51  		return constructMessage(super.getMessage(), getCause());
52  	}
53  
54  	/**
55  	 * Constructs an exception String with the given message and incorporating the
56  	 * causing exception
57  	 * @param message The message
58  	 * @param cause The causing exception
59  	 * @return The exception String
60  	 */
61  	protected String constructMessage(String message, Throwable cause) {
62  		
63  		if (cause != null) {
64  		
65  			StringBuilder strBuilder = new StringBuilder();
66  			
67  			if (message != null) {
68  				strBuilder.append(message).append(": ");
69  			}
70  			
71  			strBuilder.append("Wrapped exception is {").append(cause);
72  			strBuilder.append("}");
73  			
74  			return strBuilder.toString();
75  			
76  		} else {
77  			return message;
78  		}
79  	}
80  
81  	/**
82  	 * Retrieves the ultimate root cause for this exception, or null
83  	 * @return The root cause
84  	 */
85  	public Throwable getRootCause() {
86  		
87  		Throwable rootCause = null;
88  		Throwable nextCause = getCause();
89  		
90  		while (nextCause != null && !nextCause.equals(rootCause)) {
91  			rootCause = nextCause;
92  			nextCause = nextCause.getCause();
93  		}
94  		
95  		return rootCause;
96  	}
97  
98  	/**
99  	 * Returns the next parent exception of the given type, or null
100 	 * @param exceptionType the exception type to match
101 	 * @param <E> The exception type
102 	 * @return The matched exception of the target type, or null
103 	 */
104 	public <E extends Exception> E findWrapped(Class<E> exceptionType) {
105 		
106 		if (exceptionType == null) {
107 			return null;
108 		}
109 		
110 		Throwable cause = getCause();
111 		
112 		while (true) {
113 			
114 			if (cause == null) {
115 				return null;
116 			}
117 			
118 			if (exceptionType.isInstance(cause)) {
119 				
120 				@SuppressWarnings("unchecked") E matchedCause = (E) cause;
121 				return matchedCause;
122 			}
123 			
124 			if (cause.getCause() == cause) {
125 				return null;
126 			}
127 			
128 			if (cause instanceof WrappedRuntimeException) {
129 				return ((WrappedRuntimeException) cause).findWrapped(exceptionType);
130 			}
131 			if (cause instanceof WrappedCheckedException) {
132 				return ((WrappedCheckedException) cause).findWrapped(exceptionType);
133 			}
134 			
135 			cause = cause.getCause();
136 		}
137 	}
138 }