001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Nuxeo - initial API and implementation 018 * 019 * $Id: JOOoConvertPluginImpl.java 18651 2007-05-13 20:28:53Z sfermigier $ 020 */ 021 022package org.nuxeo.common.utils; 023 024import java.io.InterruptedIOException; 025import java.lang.reflect.InvocationTargetException; 026 027/** 028 * Provides utility methods for manipulating and examining exceptions in a generic way. 029 * 030 * @author DM 031 */ 032public final class ExceptionUtils { 033 034 // This is an utility class. 035 private ExceptionUtils() { 036 } 037 038 /** 039 * Gets the root cause of the given <code>Throwable</code>. 040 * <p> 041 * This method walks through the exception chain up to the root of the exceptions tree using 042 * {@link Throwable#getCause()}, and returns the root exception. 043 * 044 * @param throwable the throwable to get the root cause for, may be null - this is to avoid throwing other 045 * un-interesting exception when handling a business-important exception 046 * @return the root cause of the <code>Throwable</code>, <code>null</code> if none found or null throwable input 047 */ 048 public static Throwable getRootCause(Throwable throwable) { 049 Throwable cause = throwable; 050 if (throwable != null) { 051 cause = throwable.getCause(); 052 while ((throwable = cause.getCause()) != null) { 053 cause = throwable; 054 } 055 } 056 057 return cause; 058 } 059 060 /** 061 * Throws a {@link RuntimeException} if the passed exception is an {@link InterruptedException} or 062 * {@link InterruptedIOException}, or if the current thread is marked interrupted. 063 * 064 * @param e the exception to check 065 * @throws RuntimeException if there was an interrupt 066 * @since 7.1 067 */ 068 public static void checkInterrupt(Exception e) { 069 if (e instanceof InterruptedException || e instanceof InterruptedIOException) { 070 // reset interrupted status 071 Thread.currentThread().interrupt(); 072 // continue interrupt 073 throw new RuntimeException(e); 074 } 075 if (Thread.currentThread().isInterrupted()) { 076 // if an InterruptedException occurred earlier but was wrapped, 077 // continue interrupt 078 if (e instanceof RuntimeException) { 079 throw (RuntimeException) e; 080 } else { 081 throw new RuntimeException(e); 082 } 083 } 084 } 085 086 /** 087 * Unwraps the exception if it's an {@link InvocationTargetException}. 088 * <p> 089 * Also deals with interrupts by immediately throwing an exception. 090 * 091 * @param e the exception to unwrap 092 * @return the unwrapped exception 093 * @throws RuntimeException if there was an interrupt 094 * @since 7.1 095 */ 096 public static Exception unwrapInvoke(Exception e) { 097 if (e instanceof InvocationTargetException) { 098 Throwable cause = e.getCause(); 099 if (cause instanceof Error) { 100 // Error, throw immediately 101 throw (Error) cause; 102 } else if (cause instanceof Exception) { 103 e = (Exception) cause; 104 } else { 105 // Throwable direct subclass?! 106 e = new RuntimeException(cause); 107 } 108 } 109 checkInterrupt(e); 110 return e; 111 } 112 113 /** 114 * Wraps the exception into a {@link RuntimeException}, if needed, for re-throw. 115 * <p> 116 * Deals with {@link InvocationTargetException}, {@link InterruptedException} and {@link InterruptedIOException}. 117 * 118 * @param e the exception to wrap 119 * @return a {@link RuntimeException} 120 * @throws RuntimeException if there was an interrupt 121 * @since 7.1 122 */ 123 public static RuntimeException runtimeException(Exception e) { 124 e = unwrapInvoke(e); 125 if (e instanceof RuntimeException) { 126 return (RuntimeException) e; 127 } else { 128 return new RuntimeException(e); 129 } 130 } 131 132}