View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.apache.logging.log4j.core.util;
18  
19  import java.io.IOException;
20  import java.io.InterruptedIOException;
21  import java.io.LineNumberReader;
22  import java.io.PrintWriter;
23  import java.io.StringReader;
24  import java.io.StringWriter;
25  import java.lang.reflect.InvocationTargetException;
26  import java.lang.reflect.Method;
27  import java.util.ArrayList;
28  import java.util.List;
29  
30  import org.apache.logging.log4j.status.StatusLogger;
31  
32  /**
33   * Helps with Throwable objects.
34   */
35  public final class Throwables {
36  
37      private static final Method ADD_SUPPRESSED;
38  
39      private static final Method GET_SUPPRESSED;
40  
41      static {
42          Method getSuppressed = null, addSuppressed = null;
43          final Method[] methods = Throwable.class.getMethods();
44          for (final Method method : methods) {
45              if (method.getName().equals("getSuppressed")) {
46                  getSuppressed = method;
47              } else if (method.getName().equals("addSuppressed")) {
48                  addSuppressed = method;
49              }
50          }
51          GET_SUPPRESSED = getSuppressed;
52          ADD_SUPPRESSED = addSuppressed;
53      }
54  
55      /**
56       * Has no effect on Java 6 and below.
57       *
58       * @param throwable a Throwable
59       * @param suppressedThrowable a suppressed Throwable
60       * @see Throwable#addSuppressed(Throwable)
61       * @deprecated If compiling on Java 7 and above use {@link Throwable#addSuppressed(Throwable)}. Marked as deprecated because Java 6 is
62       *             deprecated.
63       */
64      @Deprecated
65      public static void addSuppressed(final Throwable throwable, final Throwable suppressedThrowable) {
66          if (ADD_SUPPRESSED != null) {
67              try {
68                  ADD_SUPPRESSED.invoke(throwable, suppressedThrowable);
69              } catch (final IllegalAccessException e) {
70                  // Only happens on Java >= 7 if this class has a bug.
71                  StatusLogger.getLogger().error(e);
72              } catch (final IllegalArgumentException e) {
73                  // Only happens on Java >= 7 if this class has a bug.
74                  StatusLogger.getLogger().error(e);
75              } catch (final InvocationTargetException e) {
76                  // Only happens on Java >= 7 if this class has a bug.
77                  StatusLogger.getLogger().error(e);
78              }
79          }
80  
81      }
82  
83      /**
84       * Has no effect on Java 6 and below.
85       *
86       * @param throwable a Throwable
87       * @return see Java 7's {@link Throwable#getSuppressed()}
88       * @see Throwable#getSuppressed()
89       * @deprecated If compiling on Java 7 and above use {@link Throwable#getSuppressed()}. Marked as deprecated because Java 6 is
90       *             deprecated.
91       */
92      @Deprecated
93      public static Throwable[] getSuppressed(final Throwable throwable) {
94          if (GET_SUPPRESSED != null) {
95              try {
96                  return (Throwable[]) GET_SUPPRESSED.invoke(throwable);
97              } catch (final Exception e) {
98                  // Only happens on Java >= 7 if this class has a bug.
99                  StatusLogger.getLogger().error(e);
100                 return null;
101             }
102         }
103         return null;
104     }
105 
106     /**
107      * Returns true if the getSuppressed method is available.
108      * 
109      * @return True if getSuppressed is available.
110      */
111     public static boolean isGetSuppressedAvailable() {
112         return GET_SUPPRESSED != null;
113     }
114 
115     /**
116      * Converts a Throwable stack trace into a List of Strings
117      *
118      * @param throwable the Throwable
119      * @return a List of Strings
120      */
121     public static List<String> toStringList(final Throwable throwable) {
122         final StringWriter sw = new StringWriter();
123         final PrintWriter pw = new PrintWriter(sw);
124         try {
125             throwable.printStackTrace(pw);
126         } catch (final RuntimeException ex) {
127             // Ignore any exceptions.
128         }
129         pw.flush();
130         final List<String> lines = new ArrayList<String>();
131         final LineNumberReader reader = new LineNumberReader(new StringReader(sw.toString()));
132         try {
133             String line = reader.readLine();
134             while (line != null) {
135                 lines.add(line);
136                 line = reader.readLine();
137             }
138         } catch (final IOException ex) {
139             if (ex instanceof InterruptedIOException) {
140                 Thread.currentThread().interrupt();
141             }
142             lines.add(ex.toString());
143         } finally {
144             Closer.closeSilently(reader);
145         }
146         return lines;
147     }
148 
149     private Throwables() {
150     }
151 
152 }