View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.util;
20  
21  import java.io.PrintStream;
22  import java.io.PrintWriter;
23  import java.util.ArrayList;
24  import java.util.Collections;
25  import java.util.List;
26  
27  /** 
28   * Wraps multiple exceptions.
29   *
30   * Allows multiple exceptions to be thrown as a single exception.
31   */
32  @SuppressWarnings("serial")
33  public class MultiException extends Exception
34  {
35      private List<Throwable> nested;
36  
37      /* ------------------------------------------------------------ */
38      public MultiException()
39      {
40          super("Multiple exceptions");
41      }
42  
43      /* ------------------------------------------------------------ */
44      public void add(Throwable e)
45      {
46          if (e==null)
47              throw new IllegalArgumentException();
48          
49          if(nested == null)
50              nested = new ArrayList<>();
51          
52          if (e instanceof MultiException)
53          {
54              MultiException me = (MultiException)e;
55              nested.addAll(me.nested);
56          }
57          else
58              nested.add(e);
59      }
60  
61      /* ------------------------------------------------------------ */
62      public int size()
63      {
64          return (nested ==null)?0:nested.size();
65      }
66      
67      /* ------------------------------------------------------------ */
68      public List<Throwable> getThrowables()
69      {
70          if(nested == null) {
71              return Collections.emptyList();
72          }
73          return nested;
74      }
75      
76      /* ------------------------------------------------------------ */
77      public Throwable getThrowable(int i)
78      {
79          return nested.get(i);
80      }
81  
82      /* ------------------------------------------------------------ */
83      /** Throw a multiexception.
84       * If this multi exception is empty then no action is taken. If it
85       * contains a single exception that is thrown, otherwise the this
86       * multi exception is thrown. 
87       * @exception Exception the Error or Exception if nested is 1, or the MultiException itself if nested is more than 1.
88       */
89      public void ifExceptionThrow()
90          throws Exception
91      {
92          if(nested == null)
93              return;
94          
95          switch (nested.size())
96          {
97            case 0:
98                break;
99            case 1:
100               Throwable th=nested.get(0);
101               if (th instanceof Error)
102                   throw (Error)th;
103               if (th instanceof Exception)
104                   throw (Exception)th;
105           default:
106               throw this;
107         }
108     }
109     
110     /* ------------------------------------------------------------ */
111     /** Throw a Runtime exception.
112      * If this multi exception is empty then no action is taken. If it
113      * contains a single error or runtime exception that is thrown, otherwise the this
114      * multi exception is thrown, wrapped in a runtime exception. 
115      * @exception Error If this exception contains exactly 1 {@link Error} 
116      * @exception RuntimeException If this exception contains 1 {@link Throwable} but it is not an error,
117      *                             or it contains more than 1 {@link Throwable} of any type.
118      */
119     public void ifExceptionThrowRuntime()
120         throws Error
121     {
122         if(nested == null)
123             return;
124         
125         switch (nested.size())
126         {
127           case 0:
128               break;
129           case 1:
130               Throwable th=nested.get(0);
131               if (th instanceof Error)
132                   throw (Error)th;
133               else if (th instanceof RuntimeException)
134                   throw (RuntimeException)th;
135               else
136                   throw new RuntimeException(th);
137           default:
138               throw new RuntimeException(this);
139         }
140     }
141     
142     /* ------------------------------------------------------------ */
143     /** Throw a multiexception.
144      * If this multi exception is empty then no action is taken. If it
145      * contains a any exceptions then this
146      * multi exception is thrown. 
147      * @throws MultiException the multiexception if there are nested exception
148      */
149     public void ifExceptionThrowMulti()
150         throws MultiException
151     {
152         if(nested == null)
153             return;
154         
155         if (nested.size()>0)
156             throw this;
157     }
158 
159     /* ------------------------------------------------------------ */
160     @Override
161     public String toString()
162     {
163         StringBuilder str = new StringBuilder();
164         str.append(MultiException.class.getSimpleName());
165         if((nested == null) || (nested.size()<=0)) {
166             str.append("[]");
167         } else {
168             str.append(nested);
169         }
170         return str.toString();
171     }
172 
173     /* ------------------------------------------------------------ */
174     @Override
175     public void printStackTrace()
176     {
177         super.printStackTrace();
178         if(nested != null) {
179             for(Throwable t: nested) {
180                 t.printStackTrace();
181             }
182         }
183     }
184    
185 
186     /* ------------------------------------------------------------------------------- */
187     /**
188      * @see java.lang.Throwable#printStackTrace(java.io.PrintStream)
189      */
190     @Override
191     public void printStackTrace(PrintStream out)
192     {
193         super.printStackTrace(out);
194         if(nested != null) {
195             for(Throwable t: nested) {
196                 t.printStackTrace(out);
197             }
198         }
199     }
200 
201     /* ------------------------------------------------------------------------------- */
202     /**
203      * @see java.lang.Throwable#printStackTrace(java.io.PrintWriter)
204      */
205     @Override
206     public void printStackTrace(PrintWriter out)
207     {
208         super.printStackTrace(out);
209         if(nested != null) {
210             for(Throwable t: nested) {
211                 t.printStackTrace(out);
212             }
213         }
214     }
215 
216 }