View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 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.util.ArrayList;
22  import java.util.Collections;
23  import java.util.List;
24  
25  /** 
26   * Wraps multiple exceptions.
27   *
28   * Allows multiple exceptions to be thrown as a single exception.
29   */
30  @SuppressWarnings("serial")
31  public class MultiException extends Exception
32  {
33      private List<Throwable> nested;
34  
35      /* ------------------------------------------------------------ */
36      public MultiException()
37      {
38          super("Multiple exceptions");
39      }
40  
41      /* ------------------------------------------------------------ */
42      public void add(Throwable e)
43      {
44          if (e==null)
45              throw new IllegalArgumentException();
46  
47          if(nested == null)
48          {
49              initCause(e);
50              nested = new ArrayList<>();
51          }
52          else
53              addSuppressed(e);
54          
55          if (e instanceof MultiException)
56          {
57              MultiException me = (MultiException)e;
58              nested.addAll(me.nested);
59          }
60          else
61              nested.add(e);
62      }
63  
64      /* ------------------------------------------------------------ */
65      public int size()
66      {
67          return (nested ==null)?0:nested.size();
68      }
69      
70      /* ------------------------------------------------------------ */
71      public List<Throwable> getThrowables()
72      {
73          if(nested == null)
74              return Collections.emptyList();
75          return nested;
76      }
77      
78      /* ------------------------------------------------------------ */
79      public Throwable getThrowable(int i)
80      {
81          return nested.get(i);
82      }
83  
84      /* ------------------------------------------------------------ */
85      /** Throw a multiexception.
86       * If this multi exception is empty then no action is taken. If it
87       * contains a single exception that is thrown, otherwise the this
88       * multi exception is thrown. 
89       * @exception Exception the Error or Exception if nested is 1, or the MultiException itself if nested is more than 1.
90       */
91      public void ifExceptionThrow()
92          throws Exception
93      {
94          if(nested == null)
95              return;
96          
97          switch (nested.size())
98          {
99            case 0:
100               break;
101           case 1:
102               Throwable th=nested.get(0);
103               if (th instanceof Error)
104                   throw (Error)th;
105               if (th instanceof Exception)
106                   throw (Exception)th;
107           default:
108               throw this;
109         }
110     }
111     
112     /* ------------------------------------------------------------ */
113     /** Throw a Runtime exception.
114      * If this multi exception is empty then no action is taken. If it
115      * contains a single error or runtime exception that is thrown, otherwise the this
116      * multi exception is thrown, wrapped in a runtime exception. 
117      * @exception Error If this exception contains exactly 1 {@link Error} 
118      * @exception RuntimeException If this exception contains 1 {@link Throwable} but it is not an error,
119      *                             or it contains more than 1 {@link Throwable} of any type.
120      */
121     public void ifExceptionThrowRuntime()
122         throws Error
123     {
124         if(nested == null)
125             return;
126         
127         switch (nested.size())
128         {
129           case 0:
130               break;
131           case 1:
132               Throwable th=nested.get(0);
133               if (th instanceof Error)
134                   throw (Error)th;
135               else if (th instanceof RuntimeException)
136                   throw (RuntimeException)th;
137               else
138                   throw new RuntimeException(th);
139           default:
140               throw new RuntimeException(this);
141         }
142     }
143     
144     /* ------------------------------------------------------------ */
145     /** Throw a multiexception.
146      * If this multi exception is empty then no action is taken. If it
147      * contains a any exceptions then this
148      * multi exception is thrown. 
149      * @throws MultiException the multiexception if there are nested exception
150      */
151     public void ifExceptionThrowMulti()
152         throws MultiException
153     {
154         if(nested == null)
155             return;
156         
157         if (nested.size()>0)
158             throw this;
159     }
160 
161     /* ------------------------------------------------------------ */
162     @Override
163     public String toString()
164     {
165         StringBuilder str = new StringBuilder();
166         str.append(MultiException.class.getSimpleName());
167         if((nested == null) || (nested.size()<=0)) {
168             str.append("[]");
169         } else {
170             str.append(nested);
171         }
172         return str.toString();
173     }
174 
175 }