• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.testing;
18 
19 import com.google.common.annotations.GwtCompatible;
20 
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 
25 /**
26  * An {@link ClusterException} is a data structure that allows for some code to
27  * "throw multiple exceptions", or something close to it. The prototypical code
28  * that calls for this class is presented below:
29  *
30  * <pre>
31  * void runManyThings(List&lt;ThingToRun&gt; thingsToRun) {
32  *   for (ThingToRun thingToRun : thingsToRun) {
33  *     thingToRun.run(); // <-- say this may throw an exception, but you want to
34  *                       // always run all thingsToRun
35  *   }
36  * }
37  * </pre>
38  *
39  * This is what the code would become:
40  *
41  * <pre>
42  * void runManyThings(List&lt;ThingToRun&gt; thingsToRun) {
43  *   List&lt;Exception&gt; exceptions = Lists.newArrayList();
44  *   for (ThingToRun thingToRun : thingsToRun) {
45  *     try {
46  *       thingToRun.run();
47  *     } catch (Exception e) {
48  *       exceptions.add(e);
49  *     }
50  *   }
51  *   if (exceptions.size() > 0) {
52  *     throw ClusterException.create(exceptions);
53  *   }
54  * }
55  * </pre>
56  *
57  * <p>See semantic details at {@link #create(Collection)}.
58  *
59  * @author Luiz-Otavio Zorzella
60  */
61 @GwtCompatible
62 final class ClusterException extends RuntimeException {
63 
64   public final Collection<? extends Throwable> exceptions;
65 
ClusterException(Collection<? extends Throwable> exceptions)66   private ClusterException(Collection<? extends Throwable> exceptions) {
67     super(
68         exceptions.size() + " exceptions were thrown. The first exception is listed as a cause.",
69         exceptions.iterator().next());
70     ArrayList<Throwable> temp = new ArrayList<Throwable>();
71     temp.addAll(exceptions);
72     this.exceptions = Collections.unmodifiableCollection(temp);
73   }
74 
75   /**
76    * @see #create(Collection)
77    */
create(Throwable... exceptions)78   public static RuntimeException create(Throwable... exceptions) {
79     ArrayList<Throwable> temp = new ArrayList<Throwable>();
80     for (Throwable exception : exceptions) {
81       temp.add(exception);
82     }
83     return create(temp);
84   }
85 
86   /**
87    * Given a collection of exceptions, returns a {@link RuntimeException}, with
88    * the following rules:
89    *
90    * <ul>
91    *  <li>If {@code exceptions} has a single exception and that exception is a
92    *    {@link RuntimeException}, return it
93    *  <li>If {@code exceptions} has a single exceptions and that exceptions is
94    *    <em>not</em> a {@link RuntimeException}, return a simple
95    *    {@code RuntimeException} that wraps it
96    *  <li>Otherwise, return an instance of {@link ClusterException} that wraps
97    *    the first exception in the {@code exceptions} collection.
98    * </ul>
99    *
100    * <p>Though this method takes any {@link Collection}, it often makes most
101    * sense to pass a {@link java.util.List} or some other collection that
102    * preserves the order in which the exceptions got added.
103    *
104    * @throws NullPointerException if {@code exceptions} is null
105    * @throws IllegalArgumentException if {@code exceptions} is empty
106    */
create(Collection<? extends Throwable> exceptions)107   public static RuntimeException create(Collection<? extends Throwable> exceptions) {
108     if (exceptions.size() == 0) {
109       throw new IllegalArgumentException(
110           "Can't create an ExceptionCollection with no exceptions");
111     }
112     if (exceptions.size() == 1) {
113       Throwable temp = exceptions.iterator().next();
114       if (temp instanceof RuntimeException) {
115         return (RuntimeException)temp;
116       } else {
117         return new RuntimeException(temp);
118       }
119     }
120     return new ClusterException(exceptions);
121   }
122 }
123