001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.mail;
019
020import java.io.PrintStream;
021import java.io.PrintWriter;
022
023/**
024 * Exception thrown when a checked error occurs in commons-email.
025 * <p>
026 * Supports nesting, emulating JDK 1.4 behavior if necessary.
027 * <p>
028 * Adapted from FunctorException in Commons Collections.
029 *
030 * @author jakarta-commons
031 * @since 1.0
032 * @version $Id: EmailException.java 510812 2007-02-23 04:32:22Z dion $
033 */
034public class EmailException
035        extends Exception
036{
037    /** Serializable version identifier */
038    static final long serialVersionUID = 5550674499282474616L;
039
040    /**
041     * Does JDK support nested exceptions?
042     */
043    private static final boolean JDK_SUPPORTS_NESTED;
044
045    static
046    {
047        boolean flag = false;
048
049        try
050        {
051            Throwable.class.getDeclaredMethod("getCause", new Class[0]);
052            flag = true;
053        }
054        catch (NoSuchMethodException ex)
055        {
056            flag = false;
057        }
058
059        JDK_SUPPORTS_NESTED = flag;
060    }
061
062    /**
063     * Root cause of the exception
064     */
065    private final Throwable rootCause;
066
067    /**
068     * Constructs a new <code>EmailException</code> with no
069     * detail message.
070     */
071    public EmailException()
072    {
073        super();
074        this.rootCause = null;
075    }
076
077    /**
078     * Constructs a new <code>EmailException</code> with specified
079     * detail message.
080     *
081     * @param msg  the error message.
082     */
083    public EmailException(String msg)
084    {
085        super(msg);
086        this.rootCause = null;
087    }
088
089    /**
090     * Constructs a new <code>EmailException</code> with specified
091     * nested <code>Throwable</code> root cause.
092     *
093     * @param rootCause  the exception or error that caused this exception
094     *                   to be thrown.
095     */
096    public EmailException(Throwable rootCause)
097    {
098        super((rootCause == null) ? null : rootCause.getMessage());
099        this.rootCause = rootCause;
100    }
101
102    /**
103     * Constructs a new <code>EmailException</code> with specified
104     * detail message and nested <code>Throwable</code> root cause.
105     *
106     * @param msg  the error message.
107     * @param rootCause  the exception or error that caused this exception
108     *                   to be thrown.
109     */
110    public EmailException(String msg, Throwable rootCause)
111    {
112        super(msg);
113        this.rootCause = rootCause;
114    }
115
116    /**
117     * Gets the cause of this throwable.
118     *
119     * @return  the cause of this throwable, or <code>null</code>
120     */
121    public Throwable getCause()
122    {
123        return rootCause;
124    }
125
126    /**
127     * Prints the stack trace of this exception to the standard error stream.
128     */
129    public void printStackTrace()
130    {
131        printStackTrace(System.err);
132    }
133
134    /**
135     * Prints the stack trace of this exception to the specified stream.
136     *
137     * @param out  the <code>PrintStream</code> to use for output
138     */
139    public void printStackTrace(PrintStream out)
140    {
141        synchronized (out)
142        {
143            PrintWriter pw = new PrintWriter(out, false);
144            printStackTrace(pw);
145
146            // Flush the PrintWriter before it's GC'ed.
147            pw.flush();
148        }
149    }
150
151    /**
152     * Prints the stack trace of this exception to the specified writer.
153     *
154     * @param out  the <code>PrintWriter</code> to use for output
155     */
156    public void printStackTrace(PrintWriter out)
157    {
158        synchronized (out)
159        {
160            super.printStackTrace(out);
161
162            if (!JDK_SUPPORTS_NESTED && (rootCause != null))
163            {
164                out.print("Caused by: ");
165                rootCause.printStackTrace(out);
166            }
167        }
168    }
169}