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.OutputStreamWriter;
021import java.io.PrintStream;
022import java.io.PrintWriter;
023import java.nio.charset.Charset;
024import java.util.Collection;
025import java.util.concurrent.Callable;
026import java.util.function.Supplier;
027
028/**
029 * Exception thrown when a checked error occurs in commons-email.
030 * <p>
031 * Adapted from FunctorException in Commons Collections.
032 * </p>
033 * <p>
034 * Emulation support for nested exceptions has been removed in {@code Email 1.3}, supported by JDK 1.4 and above.
035 * </p>
036 *
037 * @since 1.0
038 */
039public class EmailException extends Exception {
040
041    /** Serializable version identifier. */
042    private static final long serialVersionUID = 5550674499282474616L;
043
044    static <V> V call(final Callable<V> callable) throws EmailException {
045        try {
046            return callable.call();
047        } catch (final Exception e) {
048            throw new EmailException(e);
049        }
050    }
051
052    static <T> T check(final Supplier<Boolean> test, final T subject, final Supplier<String> message) throws EmailException {
053        if (test.get()) {
054            throw new EmailException(message.get());
055        }
056        return subject;
057    }
058
059    static <T> Collection<T> checkNonEmpty(final Collection<T> value, final Supplier<String> message) throws EmailException {
060        return check(() -> EmailUtils.isEmpty(value), value, message);
061    }
062
063    static String checkNonEmpty(final String value, final Supplier<String> message) throws EmailException {
064        return check(() -> EmailUtils.isEmpty(value), value, message);
065    }
066
067    static <T> T[] checkNonEmpty(final T[] value, final Supplier<String> message) throws EmailException {
068        return check(() -> EmailUtils.isEmpty(value), value, message);
069    }
070
071    static <T> T checkNonNull(final T test, final Supplier<String> message) throws EmailException {
072        if (test == null) {
073            throw new EmailException(message.get());
074        }
075        return test;
076    }
077
078    /**
079     * Constructs a new {@code EmailException} with no detail message.
080     */
081    public EmailException() {
082    }
083
084    /**
085     * Constructs a new {@code EmailException} with specified detail message.
086     *
087     * @param msg the error message.
088     */
089    public EmailException(final String msg) {
090        super(msg);
091    }
092
093    /**
094     * Constructs a new {@code EmailException} with specified detail message and nested {@code Throwable} root cause.
095     *
096     * @param msg       the error message.
097     * @param rootCause the exception or error that caused this exception to be thrown.
098     */
099    public EmailException(final String msg, final Throwable rootCause) {
100        super(msg, rootCause);
101    }
102
103    /**
104     * Constructs a new {@code EmailException} with specified nested {@code Throwable} root cause.
105     *
106     * @param rootCause the exception or error that caused this exception to be thrown.
107     */
108    public EmailException(final Throwable rootCause) {
109        super(rootCause);
110    }
111
112    /**
113     * Prints the stack trace of this exception to the standard error stream.
114     */
115    @Override
116    public void printStackTrace() {
117        printStackTrace(System.err);
118    }
119
120    /**
121     * Prints the stack trace of this exception to the specified stream.
122     *
123     * @param out the {@code PrintStream} to use for output
124     */
125    @Override
126    public void printStackTrace(final PrintStream out) {
127        synchronized (out) {
128            final PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, Charset.defaultCharset()), false);
129            printStackTrace(pw);
130            // Flush the PrintWriter before it's GC'ed.
131            pw.flush();
132        }
133    }
134
135    /**
136     * Prints the stack trace of this exception to the specified writer.
137     *
138     * @param out the {@code PrintWriter} to use for output
139     */
140    @Override
141    public void printStackTrace(final PrintWriter out) {
142        synchronized (out) {
143            super.printStackTrace(out);
144        }
145    }
146}