001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache license, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the license for the specific language governing permissions and 015 * limitations under the license. 016 */ 017 package org.apache.logging.log4j.core.util; 018 019 import java.io.IOException; 020 import java.io.InterruptedIOException; 021 import java.io.LineNumberReader; 022 import java.io.PrintWriter; 023 import java.io.StringReader; 024 import java.io.StringWriter; 025 import java.lang.reflect.InvocationTargetException; 026 import java.lang.reflect.Method; 027 import java.util.ArrayList; 028 import java.util.List; 029 030 import org.apache.logging.log4j.status.StatusLogger; 031 032 /** 033 * Helps with Throwable objects. 034 */ 035 public final class Throwables { 036 037 private static final Method ADD_SUPPRESSED; 038 039 private static final Method GET_SUPPRESSED; 040 041 static { 042 Method getSuppressed = null, addSuppressed = null; 043 final Method[] methods = Throwable.class.getMethods(); 044 for (final Method method : methods) { 045 if (method.getName().equals("getSuppressed")) { 046 getSuppressed = method; 047 } else if (method.getName().equals("addSuppressed")) { 048 addSuppressed = method; 049 } 050 } 051 GET_SUPPRESSED = getSuppressed; 052 ADD_SUPPRESSED = addSuppressed; 053 } 054 055 /** 056 * Has no effect on Java 6 and below. 057 * 058 * @param throwable a Throwable 059 * @param suppressedThrowable a suppressed Throwable 060 * @see Throwable#addSuppressed(Throwable) 061 * @deprecated If compiling on Java 7 and above use {@link Throwable#addSuppressed(Throwable)}. Marked as deprecated because Java 6 is 062 * deprecated. 063 */ 064 @Deprecated 065 public static void addSuppressed(final Throwable throwable, final Throwable suppressedThrowable) { 066 if (ADD_SUPPRESSED != null) { 067 try { 068 ADD_SUPPRESSED.invoke(throwable, suppressedThrowable); 069 } catch (final IllegalAccessException e) { 070 // Only happens on Java >= 7 if this class has a bug. 071 StatusLogger.getLogger().error(e); 072 } catch (final IllegalArgumentException e) { 073 // Only happens on Java >= 7 if this class has a bug. 074 StatusLogger.getLogger().error(e); 075 } catch (final InvocationTargetException e) { 076 // Only happens on Java >= 7 if this class has a bug. 077 StatusLogger.getLogger().error(e); 078 } 079 } 080 081 } 082 083 /** 084 * Has no effect on Java 6 and below. 085 * 086 * @param throwable a Throwable 087 * @return see Java 7's {@link Throwable#getSuppressed()} 088 * @see Throwable#getSuppressed() 089 * @deprecated If compiling on Java 7 and above use {@link Throwable#getSuppressed()}. Marked as deprecated because Java 6 is 090 * deprecated. 091 */ 092 @Deprecated 093 public static Throwable[] getSuppressed(final Throwable throwable) { 094 if (GET_SUPPRESSED != null) { 095 try { 096 return (Throwable[]) GET_SUPPRESSED.invoke(throwable); 097 } catch (final Exception e) { 098 // Only happens on Java >= 7 if this class has a bug. 099 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 }