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 }