001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.core;
018:
019: /**
020: * Handy class for wrapping checked <code>Exceptions</code> with a root cause.
021: *
022: * <p>This class is <code>abstract</code> to force the programmer to extend
023: * the class. <code>getMessage</code> will include nested exception
024: * information; <code>printStackTrace</code> and other like methods will
025: * delegate to the wrapped exception, if any.
026: *
027: * <p>The similarity between this class and the {@link NestedRuntimeException}
028: * class is unavoidable, as Java forces these two classes to have different
029: * superclasses (ah, the inflexibility of concrete inheritance!).
030: *
031: * @author Rod Johnson
032: * @author Juergen Hoeller
033: * @see #getMessage
034: * @see #printStackTrace
035: * @see NestedRuntimeException
036: */
037: public abstract class NestedCheckedException extends Exception {
038:
039: /** Use serialVersionUID from Spring 1.2 for interoperability */
040: private static final long serialVersionUID = 7100714597678207546L;
041:
042: /**
043: * Construct a <code>NestedCheckedException</code> with the specified detail message.
044: * @param msg the detail message
045: */
046: public NestedCheckedException(String msg) {
047: super (msg);
048: }
049:
050: /**
051: * Construct a <code>NestedCheckedException</code> with the specified detail message
052: * and nested exception.
053: * @param msg the detail message
054: * @param cause the nested exception
055: */
056: public NestedCheckedException(String msg, Throwable cause) {
057: super (msg, cause);
058: }
059:
060: /**
061: * Return the detail message, including the message from the nested exception
062: * if there is one.
063: */
064: public String getMessage() {
065: return NestedExceptionUtils.buildMessage(super .getMessage(),
066: getCause());
067: }
068:
069: /**
070: * Retrieve the innermost cause of this exception, if any.
071: * @return the innermost exception, or <code>null</code> if none
072: */
073: public Throwable getRootCause() {
074: Throwable rootCause = null;
075: Throwable cause = getCause();
076: while (cause != null && cause != rootCause) {
077: rootCause = cause;
078: cause = cause.getCause();
079: }
080: return rootCause;
081: }
082:
083: /**
084: * Retrieve the most specific cause of this exception, that is,
085: * either the innermost cause (root cause) or this exception itself.
086: * <p>Differs from {@link #getRootCause()} in that it falls back
087: * to the present exception if there is no root cause.
088: * @return the most specific cause (never <code>null</code>)
089: * @since 2.0.3
090: */
091: public Throwable getMostSpecificCause() {
092: Throwable rootCause = getRootCause();
093: return (rootCause != null ? rootCause : this );
094: }
095:
096: /**
097: * Check whether this exception contains an exception of the given type:
098: * either it is of the given class itself or it contains a nested cause
099: * of the given type.
100: * @param exType the exception type to look for
101: * @return whether there is a nested exception of the specified type
102: */
103: public boolean contains(Class exType) {
104: if (exType == null) {
105: return false;
106: }
107: if (exType.isInstance(this )) {
108: return true;
109: }
110: Throwable cause = getCause();
111: if (cause == this ) {
112: return false;
113: }
114: if (cause instanceof NestedCheckedException) {
115: return ((NestedCheckedException) cause).contains(exType);
116: } else {
117: while (cause != null) {
118: if (exType.isInstance(cause)) {
119: return true;
120: }
121: if (cause.getCause() == cause) {
122: break;
123: }
124: cause = cause.getCause();
125: }
126: return false;
127: }
128: }
129:
130: }
|