View Javadoc
1   /*
2    * This file is part of dependency-check-core.
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   * Copyright (c) 2016 Jeremy Long. All Rights Reserved.
17   */
18  package org.owasp.dependencycheck.exception;
19  
20  import java.io.PrintStream;
21  import java.io.PrintWriter;
22  import java.util.ArrayList;
23  import java.util.List;
24  import javax.annotation.concurrent.NotThreadSafe;
25  
26  /**
27   * A collection of several exceptions.
28   *
29   * @author Jeremy Long
30   */
31  @NotThreadSafe
32  public class ExceptionCollection extends Exception {
33  
34      /**
35       * The serial version UID for serialization.
36       */
37      private static final long serialVersionUID = -3032674811026089923L;
38  
39      /**
40       * The default exception message.
41       */
42      private static final String MSG = "One or more exceptions occurred during analysis:";
43      /**
44       * A collection of exceptions.
45       */
46      private final List<Throwable> exceptions;
47      /**
48       * Flag indicating if a fatal exception occurred that would prevent the
49       * attempt at completing the analysis even if exceptions occurred.
50       */
51      private boolean fatal = false;
52  
53      /**
54       * Instantiates a new exception collection.
55       *
56       * @param exceptions a list of exceptions
57       */
58      public ExceptionCollection(List<Throwable> exceptions) {
59          super(MSG);
60          this.exceptions = exceptions;
61      }
62  
63      /**
64       * Instantiates a new exception collection.
65       *
66       * @param exceptions a list of exceptions
67       * @param fatal indicates if any of the exceptions that occurred is fatal -
68       * meaning that no analysis was performed.
69       */
70      public ExceptionCollection(List<Throwable> exceptions, boolean fatal) {
71          super(MSG);
72          this.exceptions = exceptions;
73          this.fatal = fatal;
74      }
75  
76      /**
77       * Instantiates a new exception collection.
78       *
79       * @param exception a list of exceptions
80       * @param fatal indicates if the exception that occurred is fatal - meaning
81       * that no analysis was performed.
82       */
83      public ExceptionCollection(Throwable exception, boolean fatal) {
84          super(MSG);
85          if (exception instanceof ExceptionCollection) {
86              final ExceptionCollection other = ((ExceptionCollection) exception);
87              this.exceptions = other.getExceptions();
88              this.fatal = other.isFatal();
89          } else {
90              this.exceptions = new ArrayList<>();
91              this.exceptions.add(exception);
92              this.fatal = fatal;
93          }
94      }
95  
96      /**
97       * Instantiates a new exception collection.
98       *
99       * @param exception a list of exceptions
100      */
101     public ExceptionCollection(Throwable exception) {
102         super(MSG);
103         if (exception instanceof ExceptionCollection) {
104             final ExceptionCollection other = ((ExceptionCollection) exception);
105             this.exceptions = other.getExceptions();
106             this.fatal = other.isFatal();
107         } else {
108             this.exceptions = new ArrayList<>();
109             this.exceptions.add(exception);
110             this.fatal = false;
111         }
112     }
113 
114     /**
115      * Instantiates a new exception collection.
116      */
117     public ExceptionCollection() {
118         super(MSG);
119         this.exceptions = new ArrayList<>();
120     }
121 
122     /**
123      * Get the value of exceptions.
124      *
125      * @return the value of exceptions
126      */
127     public List<Throwable> getExceptions() {
128         return exceptions;
129     }
130 
131     /**
132      * Adds an exception to the collection.
133      *
134      * @param ex the exception to add
135      */
136     public void addException(Throwable ex) {
137         if (ex instanceof ExceptionCollection) {
138             this.exceptions.addAll(((ExceptionCollection) ex).getExceptions());
139         }
140         this.exceptions.add(ex);
141     }
142 
143     /**
144      * Adds an exception to the collection.
145      *
146      * @param ex the exception to add
147      * @param fatal flag indicating if this is a fatal error
148      */
149     public void addException(Throwable ex, boolean fatal) {
150         addException(ex);
151         this.fatal = fatal;
152     }
153 
154     /**
155      * Get the value of fatal.
156      *
157      * @return the value of fatal
158      */
159     public boolean isFatal() {
160         return fatal;
161     }
162 
163     /**
164      * Set the value of fatal.
165      *
166      * @param fatal new value of fatal
167      */
168     public void setFatal(boolean fatal) {
169         this.fatal = fatal;
170     }
171 
172     /**
173      * Prints the stack trace.
174      *
175      * @param s the writer to print to
176      */
177     @Override
178     public void printStackTrace(PrintWriter s) {
179         s.println(MSG);
180         super.printStackTrace(s);
181         this.exceptions.forEach((t) -> {
182             s.println("Next Exception:");
183             t.printStackTrace(s);
184         });
185     }
186 
187     /**
188      * Prints the stack trace.
189      *
190      * @param s the stream to write the stack trace to
191      */
192     @Override
193     public void printStackTrace(PrintStream s) {
194         s.println(MSG);
195         super.printStackTrace(s);
196         this.exceptions.forEach((t) -> {
197             s.println("Next Exception:");
198             t.printStackTrace(s);
199         });
200     }
201 
202     /**
203      * Returns the error message, including the message from all contained
204      * exceptions.
205      *
206      * @return the error message
207      */
208     @Override
209     public String getMessage() {
210         final StringBuilder sb = new StringBuilder(MSG);
211 
212         this.exceptions.forEach((t) -> sb.append("\n\t")
213                 .append(t.getClass().getSimpleName())
214                 .append(": ")
215                 .append(ExceptionCollection.nestedCauseList(t)));
216         return sb.toString();
217     }
218 
219     private static StringBuilder nestedCauseList(Throwable t) {
220         final StringBuilder sb = new StringBuilder().append(t.getMessage());
221         Throwable nestedCause = t.getCause();
222         while (nestedCause != null) {
223             sb.append("\n\t\tcaused by ").append(nestedCause.getClass().getSimpleName()).append(": ").append(nestedCause.getMessage());
224             nestedCause = nestedCause.getCause();
225         }
226         return sb;
227     }
228 }