package dmg.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; /** * Contains static utility methods for exceptions. */ public class Exceptions { private static final Logger LOG = LoggerFactory.getLogger(Exceptions.class); private Exceptions() { } /** * Returns the message string of the Throwable and that of all its * causes. */ public static String getMessageWithCauses(Throwable t) { StringBuilder msg = new StringBuilder(t.getMessage()); t = t.getCause(); while (t != null) { msg.append("; caused by: ").append(t.getMessage()); t = t.getCause(); } return msg.toString(); } /** * Wrap the supplied Exception with an exception with message and * cause. This method attempts to wrap {@literal cause} with an exception of * the same type. If possible, the wrapped exception is created with * {@literal cause} as the cause, otherwise the single-String constructor is * used. If neither constructor is available then the method will attempt * to construct the wrapping exception from the super-class. * This continues until either a wrapping exception is constructed or the * enclosingType is reached. If enclosingType does not support wrapping * then {@literal cause} is returned and a warning is logged. * <p /> * Note that the wrapped exception will contain only a message and possibly * the {@literal cause} as the triggering exception; in particular, any * additional information from {@literal cause} is not copied into the * wrapped exception. */ public static <T extends Exception> T wrap(String message, T cause, Class<T> enclosingType) { ReflectiveOperationException lastException = null; Class type = cause.getClass(); while (enclosingType.isAssignableFrom(type)) { try { Constructor<? extends T> c = type.getConstructor(String.class, Throwable.class); return c.newInstance(message, cause); } catch (InvocationTargetException | IllegalAccessException | InstantiationException | NoSuchMethodException e) { lastException = e; } try { Constructor<? extends T> c = type.getConstructor(String.class); return c.newInstance(message); } catch (InvocationTargetException | IllegalAccessException | InstantiationException | NoSuchMethodException e) { lastException = e; } type = type.getSuperclass(); } if (lastException == null) { /* This should never happen */ LOG.error("Failed to wrap exception with message {}: " + "exception {} not subclass of {}", message, cause.getClass().getCanonicalName(), enclosingType.getCanonicalName()); } else { LOG.error("Failed to wrap exception with message {}: {}", message, lastException.getMessage()); } return cause; } }