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 checked Exceptions with a given root cause.
20   */
21  public abstract class WrappedCheckedException extends Exception {
22  
23  	private static final long serialVersionUID = 615855181745250021L;
24  
25  	/**
26  	 * Construct a WrappedCheckedException with the specified 
27  	 * message.
28  	 * @param message the specific message
29  	 */
30  	public WrappedCheckedException(String message) {
31  		super(message);
32  	}
33  
34  	/**
35  	 * Construct a WrappedCheckedException with the specified 
36  	 * message and wrapped exception.
37  	 * @param message the specific message
38  	 * @param cause the wrapped exception
39  	 */
40  	public WrappedCheckedException(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  	 */
48  	@Override
49  	public String getMessage() {
50  		return constructMessage(super.getMessage(), getCause());
51  	}
52  
53  	/**
54  	 * Constructs an exception String with the given message and incorporating the
55  	 * causing exception
56  	 * @param message The specific message
57  	 * @param cause The causing exception
58  	 * @return The exception String
59  	 */
60  	protected String constructMessage(String message, Throwable cause) {
61  		
62  		if (cause != null) {
63  		
64  			StringBuilder strBuilder = new StringBuilder();
65  			
66  			if (message != null) {
67  				strBuilder.append(message).append(": ");
68  			}
69  			
70  			strBuilder.append("Wrapped exception is {").append(cause);
71  			strBuilder.append("}");
72  			
73  			return strBuilder.toString();
74  			
75  		} else {
76  			return message;
77  		}
78  	}
79  
80  	/**
81  	 * Retrieves the ultimate root cause for this exception, or null
82  	 * @return The root cause
83  	 */
84  	public Throwable getRootCause() {
85  		
86  		Throwable rootCause = null;
87  		Throwable nextCause = getCause();
88  		
89  		while (nextCause != null && !nextCause.equals(rootCause)) {
90  			rootCause = nextCause;
91  			nextCause = nextCause.getCause();
92  		}
93  		
94  		return rootCause;
95  	}
96  
97  	/**
98  	 * Returns the next parent exception of the given type, or null
99  	 * @param exceptionType the exception type to match
100 	 * @param <E> The Exception type
101 	 * @return The matched exception of the target type, or null
102 	 */
103 	public <E extends Exception> E findWrapped(Class<E> exceptionType) {
104 		
105 		if (exceptionType == null) {
106 			return null;
107 		}
108 		
109 		Throwable cause = getCause();
110 		
111 		while (true) {
112 			
113 			if (cause == null) {
114 				return null;
115 			}
116 			
117 			if (exceptionType.isInstance(cause)) {
118 				
119 				@SuppressWarnings("unchecked") E matchedCause = (E) cause;
120 				return matchedCause;
121 			}
122 
123 			if (cause.getCause() == cause) {
124 				return null;
125 			}
126 			
127 			if (cause instanceof WrappedRuntimeException) {
128 				return ((WrappedRuntimeException) cause).findWrapped(exceptionType);
129 			}
130 			if (cause instanceof WrappedCheckedException) {
131 				return ((WrappedCheckedException) cause).findWrapped(exceptionType);
132 			}			
133 			
134 			cause = cause.getCause();
135 		}
136 	}
137 }