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: import java.io.IOException;
020: import java.io.PrintStream;
021: import java.io.PrintWriter;
022:
023: /**
024: * Subclass of IOException that properly handles a root cause,
025: * exposing the root cause just like NestedChecked/RuntimeException does.
026: *
027: * <p>The similarity between this class and the NestedChecked/RuntimeException
028: * class is unavoidable, as this class needs to derive from IOException
029: * and cannot derive from NestedCheckedException.
030: *
031: * @author Juergen Hoeller
032: * @since 2.0
033: * @see #getMessage
034: * @see #printStackTrace
035: * @see org.springframework.core.NestedCheckedException
036: * @see org.springframework.core.NestedRuntimeException
037: */
038: public class NestedIOException extends IOException {
039:
040: /** Root cause of this nested exception */
041: private Throwable cause;
042:
043: /**
044: * Construct a <code>NestedIOException</code> with the specified detail message.
045: * @param msg the detail message
046: */
047: public NestedIOException(String msg) {
048: super (msg);
049: }
050:
051: /**
052: * Construct a <code>NestedIOException</code> with the specified detail message
053: * and nested exception.
054: * @param msg the detail message
055: * @param cause the nested exception
056: */
057: public NestedIOException(String msg, Throwable cause) {
058: super (msg);
059: this .cause = cause;
060: }
061:
062: /**
063: * Return the nested cause, or <code>null</code> if none.
064: */
065: public Throwable getCause() {
066: // Even if you cannot set the cause of this exception other than through
067: // the constructor, we check for the cause being "this" here, as the cause
068: // could still be set to "this" via reflection: for example, by a remoting
069: // deserializer like Hessian's.
070: return (this .cause == this ? null : this .cause);
071: }
072:
073: /**
074: * Return the detail message, including the message from the nested exception
075: * if there is one.
076: */
077: public String getMessage() {
078: return NestedExceptionUtils.buildMessage(super .getMessage(),
079: getCause());
080: }
081:
082: /**
083: * Print the composite message and the embedded stack trace to the specified stream.
084: * @param ps the print stream
085: */
086: public void printStackTrace(PrintStream ps) {
087: if (getCause() == null) {
088: super .printStackTrace(ps);
089: } else {
090: ps.println(this );
091: ps.print("Caused by: ");
092: getCause().printStackTrace(ps);
093: }
094: }
095:
096: /**
097: * Print the composite message and the embedded stack trace to the specified print writer.
098: * @param pw the print writer
099: */
100: public void printStackTrace(PrintWriter pw) {
101: if (getCause() == null) {
102: super .printStackTrace(pw);
103: } else {
104: pw.println(this );
105: pw.print("Caused by: ");
106: getCause().printStackTrace(pw);
107: }
108: }
109:
110: }
|