001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *  
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *  
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License. 
018 *  
019 */
020package org.apache.directory.api.util.exception;
021
022
023import java.io.PrintStream;
024import java.io.PrintWriter;
025
026import java.util.ArrayList;
027import java.util.Collection;
028import java.util.Iterator;
029
030
031/**
032 * This exception is thrown when Base class for nested exceptions.
033 * 
034 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
035 */
036public class MultiException extends Exception
037{
038    /** The serialVersionUID. */
039    static final long serialVersionUID = 2889747406899775761L;
040
041    /** Collection of nested exceptions. */
042    private final Collection<Throwable> nestedExceptions = new ArrayList<>();
043
044
045    /**
046     * Constructs an Exception without a message.
047     */
048    public MultiException()
049    {
050        super();
051    }
052
053
054    /**
055     * Constructs an Exception with a detailed message.
056     * 
057     * @param message The message associated with the exception.
058     */
059    public MultiException( String message )
060    {
061        super( message );
062    }
063
064
065    /**
066     * Lists the nested exceptions that this Exception encapsulates.
067     * 
068     * @return an Iterator over the nested exceptions.
069     */
070    public Iterator<Throwable> listNestedExceptions()
071    {
072        return nestedExceptions.iterator();
073    }
074
075
076    /**
077     * Gets the size of this nested exception which equals the number of
078     * exception nested within.
079     * 
080     * @return the size of this nested exception.
081     */
082    public int size()
083    {
084        return nestedExceptions.size();
085    }
086
087
088    /**
089     * Tests to see if there are any nested exceptions within this
090     * MultiException.
091     * 
092     * @return true if no exceptions are nested, false otherwise.
093     */
094    public boolean isEmpty()
095    {
096        return nestedExceptions.isEmpty();
097    }
098
099
100    /**
101     * Add an exception to this multiexception.
102     * 
103     * @param nested exception to add to this MultiException.
104     */
105    public void addThrowable( Throwable nested )
106    {
107        nestedExceptions.add( nested );
108    }
109
110
111    // ///////////////////////////////////////////
112    // Overriden Throwable Stack Trace Methods //
113    // ///////////////////////////////////////////
114
115    /**
116     * Beside printing out the standard stack trace this method prints out the
117     * stack traces of all the nested exceptions.
118     * 
119     * @param out PrintWriter to write the nested stack trace to.
120     */
121    @Override
122    public void printStackTrace( PrintWriter out )
123    {
124        super.printStackTrace( out );
125
126        out.println( "Nested exceptions to follow:\n" );
127        boolean isFirst = true;
128
129        for ( Throwable throwable : nestedExceptions )
130        {
131            if ( isFirst )
132            {
133                isFirst = false;
134            }
135            else
136            {
137                out.println( "\n\t<<========= Next Nested Exception" + " ========>>\n" );
138            }
139
140            throwable.printStackTrace( out );
141        }
142
143        out.println( "\n\t<<========= Last Nested Exception" + " ========>>\n" );
144    }
145
146
147    /**
148     * Beside printing out the standard stack trace this method prints out the
149     * stack traces of all the nested exceptions.
150     * 
151     * @param out PrintStream to write the nested stack trace to.
152     */
153    @Override
154    public void printStackTrace( PrintStream out )
155    {
156        super.printStackTrace( out );
157
158        out.println( "Nested exceptions to follow:\n" );
159        boolean isFirst = true;
160
161        for ( Throwable throwable : nestedExceptions )
162        {
163            if ( isFirst )
164            {
165                isFirst = false;
166            }
167            else
168            {
169                out.println( "\n\t<<========= Next Nested Exception" + " ========>>\n" );
170            }
171
172            throwable.printStackTrace( out );
173        }
174
175        out.println( "\n\t<<========= Last Nested Exception" + " ========>>\n" );
176    }
177
178
179    /**
180     * Beside printing out the standard stack trace this method prints out the
181     * stack traces of all the nested exceptions using standard error.
182     */
183    @Override
184    public void printStackTrace()
185    {
186        this.printStackTrace( System.err );
187    }
188}