HHH-3918: Use standard JDK exception nesting
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@16604 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
97a0919521
commit
6eb4caf053
|
@ -23,6 +23,8 @@
|
|||
*/
|
||||
package org.hibernate.test.cache.jbc2.functional;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
@ -42,7 +44,6 @@ import org.hibernate.cache.RegionFactory;
|
|||
import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
|
||||
import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.exception.ExceptionUtils;
|
||||
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||
import org.hibernate.stat.SecondLevelCacheStatistics;
|
||||
import org.hibernate.test.cache.jbc2.functional.util.DualNodeConnectionProviderImpl;
|
||||
|
@ -579,13 +580,21 @@ public class MVCCConcurrentWriteTest extends CacheTestCaseBase {
|
|||
"[customerId=" + getCustomerId() +
|
||||
" iterationsCompleted=" + getCompletedIterations() +
|
||||
" completedAll=" + isSuccess() +
|
||||
" causeOfFailure=" + (this.causeOfFailure != null ? ExceptionUtils.getStackTrace(causeOfFailure) : "") + "] ";
|
||||
" causeOfFailure=" + (this.causeOfFailure != null ? getStackTrace(causeOfFailure) : "") + "] ";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String getStackTrace(Throwable throwable) {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter( sw, true );
|
||||
throwable.printStackTrace( pw );
|
||||
return sw.getBuffer().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* sleep between 0 and THINK_TIME_MILLIS.
|
||||
* @throws RuntimeException if sleep is interruped or TERMINATE_ALL_USERS flag was set to true i
|
||||
* @throws RuntimeException if sleep is interrupted or TERMINATE_ALL_USERS flag was set to true i
|
||||
n the meantime
|
||||
*/
|
||||
private void thinkRandomTime() {
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
*/
|
||||
package org.hibernate;
|
||||
|
||||
import org.hibernate.exception.NestableRuntimeException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -34,7 +32,7 @@ import org.slf4j.LoggerFactory;
|
|||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class AssertionFailure extends NestableRuntimeException {
|
||||
public class AssertionFailure extends RuntimeException {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger( AssertionFailure.class );
|
||||
|
||||
|
|
|
@ -24,18 +24,17 @@
|
|||
*/
|
||||
package org.hibernate;
|
||||
|
||||
import org.hibernate.exception.NestableRuntimeException;
|
||||
|
||||
/**
|
||||
* Any exception that occurs inside the persistence layer
|
||||
* or JDBC driver. <tt>SQLException</tt>s are always wrapped
|
||||
* by instances of <tt>JDBCException</tt>.
|
||||
*
|
||||
* The base {@link Throwable} type for Hibernate.
|
||||
* <p/>
|
||||
* Note that all {@link java.sql.SQLException SQLExceptions} will be wrapped in some form of
|
||||
* {@link JDBCException}.
|
||||
*
|
||||
* @see JDBCException
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
|
||||
public class HibernateException extends NestableRuntimeException {
|
||||
public class HibernateException extends RuntimeException {
|
||||
|
||||
public HibernateException(Throwable root) {
|
||||
super(root);
|
||||
|
|
|
@ -1,705 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.exception;
|
||||
|
||||
import org.hibernate.util.ArrayHelper;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* <p>Provides utilities for manipulating and examining
|
||||
* <code>Throwable</code> objects.</p>
|
||||
*
|
||||
* @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
|
||||
* @author Dmitri Plotnikov
|
||||
* @author Stephen Colebourne
|
||||
* @author <a href="mailto:ggregory@seagullsw.com">Gary Gregory</a>
|
||||
* @author Pete Gieser
|
||||
* @version $Id: ExceptionUtils.java 4782 2004-11-21 00:11:27Z pgmjsd $
|
||||
* @since 1.0
|
||||
*/
|
||||
public final class ExceptionUtils {
|
||||
|
||||
private static final String LINE_SEPARATOR = System.getProperty( "line.separator" );
|
||||
|
||||
/**
|
||||
* <p>Used when printing stack frames to denote the start of a
|
||||
* wrapped exception.</p>
|
||||
* <p/>
|
||||
* <p>Package private for accessibility by test suite.</p>
|
||||
*/
|
||||
static final String WRAPPED_MARKER = " [wrapped] ";
|
||||
|
||||
/**
|
||||
* <p>The names of methods commonly used to access a wrapped exception.</p>
|
||||
*/
|
||||
private static final String[] CAUSE_METHOD_NAMES = {
|
||||
"getCause",
|
||||
"getNextException",
|
||||
"getTargetException",
|
||||
"getException",
|
||||
"getSourceException",
|
||||
"getRootCause",
|
||||
"getCausedByException",
|
||||
"getNested"
|
||||
};
|
||||
|
||||
/**
|
||||
* <p>The Method object for JDK1.4 getCause.</p>
|
||||
*/
|
||||
private static final Method THROWABLE_CAUSE_METHOD;
|
||||
|
||||
static {
|
||||
Method getCauseMethod;
|
||||
try {
|
||||
getCauseMethod = Throwable.class.getMethod( "getCause", null );
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
getCauseMethod = null;
|
||||
}
|
||||
THROWABLE_CAUSE_METHOD = getCauseMethod;
|
||||
}
|
||||
|
||||
private ExceptionUtils() {
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Adds to the list of method names used in the search for <code>Throwable</code>
|
||||
* objects.</p>
|
||||
*
|
||||
* @param methodName the methodName to add to the list, <code>null</code>
|
||||
* and empty strings are ignored
|
||||
* @since 2.0
|
||||
*/
|
||||
/*public static void addCauseMethodName(String methodName) {
|
||||
if ( StringHelper.isNotEmpty(methodName) ) {
|
||||
List list = new ArrayList( Arrays.asList(CAUSE_METHOD_NAMES );
|
||||
list.add(methodName);
|
||||
CAUSE_METHOD_NAMES = (String[]) list.toArray(new String[list.size()]);
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* <p>Introspects the <code>Throwable</code> to obtain the cause.</p>
|
||||
* <p/>
|
||||
* <p>The method searches for methods with specific names that return a
|
||||
* <code>Throwable</code> object. This will pick up most wrapping exceptions,
|
||||
* including those from JDK 1.4, and
|
||||
* {@link org.apache.commons.lang.exception.NestableException NestableException}.
|
||||
* The method names can be added to using {@link #addCauseMethodName(String)}.</p>
|
||||
* <p/>
|
||||
* <p>The default list searched for are:</p>
|
||||
* <ul>
|
||||
* <li><code>getCause()</code></li>
|
||||
* <li><code>getNextException()</code></li>
|
||||
* <li><code>getTargetException()</code></li>
|
||||
* <li><code>getException()</code></li>
|
||||
* <li><code>getSourceException()</code></li>
|
||||
* <li><code>getRootCause()</code></li>
|
||||
* <li><code>getCausedByException()</code></li>
|
||||
* <li><code>getNested()</code></li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* <p>In the absence of any such method, the object is inspected for a
|
||||
* <code>detail</code> field assignable to a <code>Throwable</code>.</p>
|
||||
* <p/>
|
||||
* <p>If none of the above is found, returns <code>null</code>.</p>
|
||||
*
|
||||
* @param throwable the throwable to introspect for a cause, may be null
|
||||
* @return the cause of the <code>Throwable</code>,
|
||||
* <code>null</code> if none found or null throwable input
|
||||
*/
|
||||
public static Throwable getCause(Throwable throwable) {
|
||||
return getCause( throwable, CAUSE_METHOD_NAMES );
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Introspects the <code>Throwable</code> to obtain the cause.</p>
|
||||
* <p/>
|
||||
* <ol>
|
||||
* <li>Try known exception types.</li>
|
||||
* <li>Try the supplied array of method names.</li>
|
||||
* <li>Try the field 'detail'.</li>
|
||||
* </ol>
|
||||
* <p/>
|
||||
* <p>A <code>null</code> set of method names means use the default set.
|
||||
* A <code>null</code> in the set of method names will be ignored.</p>
|
||||
*
|
||||
* @param throwable the throwable to introspect for a cause, may be null
|
||||
* @param methodNames the method names, null treated as default set
|
||||
* @return the cause of the <code>Throwable</code>,
|
||||
* <code>null</code> if none found or null throwable input
|
||||
*/
|
||||
public static Throwable getCause(Throwable throwable, String[] methodNames) {
|
||||
if ( throwable == null ) {
|
||||
return null;
|
||||
}
|
||||
Throwable cause = getCauseUsingWellKnownTypes( throwable );
|
||||
if ( cause == null ) {
|
||||
if ( methodNames == null ) {
|
||||
methodNames = CAUSE_METHOD_NAMES;
|
||||
}
|
||||
for ( int i = 0; i < methodNames.length; i++ ) {
|
||||
String methodName = methodNames[i];
|
||||
if ( methodName != null ) {
|
||||
cause = getCauseUsingMethodName( throwable, methodName );
|
||||
if ( cause != null ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( cause == null ) {
|
||||
cause = getCauseUsingFieldName( throwable, "detail" );
|
||||
}
|
||||
}
|
||||
return cause;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Introspects the <code>Throwable</code> to obtain the root cause.</p>
|
||||
* <p/>
|
||||
* <p>This method walks through the exception chain to the last element,
|
||||
* "root" of the tree, using {@link #getCause(Throwable)}, and
|
||||
* returns that exception.</p>
|
||||
*
|
||||
* @param throwable the throwable to get the root cause for, may be null
|
||||
* @return the root cause of the <code>Throwable</code>,
|
||||
* <code>null</code> if none found or null throwable input
|
||||
*/
|
||||
public static Throwable getRootCause(Throwable throwable) {
|
||||
Throwable cause = getCause( throwable );
|
||||
if ( cause != null ) {
|
||||
throwable = cause;
|
||||
while ( ( throwable = getCause( throwable ) ) != null ) {
|
||||
cause = throwable;
|
||||
}
|
||||
}
|
||||
return cause;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Finds a <code>Throwable</code> for known types.</p>
|
||||
* <p/>
|
||||
* <p>Uses <code>instanceof</code> checks to examine the exception,
|
||||
* looking for well known types which could contain chained or
|
||||
* wrapped exceptions.</p>
|
||||
*
|
||||
* @param throwable the exception to examine
|
||||
* @return the wrapped exception, or <code>null</code> if not found
|
||||
*/
|
||||
private static Throwable getCauseUsingWellKnownTypes(Throwable throwable) {
|
||||
if ( throwable instanceof Nestable ) {
|
||||
return ( ( Nestable ) throwable ).getCause();
|
||||
}
|
||||
else if ( throwable instanceof SQLException ) {
|
||||
return ( ( SQLException ) throwable ).getNextException();
|
||||
}
|
||||
else if ( throwable instanceof InvocationTargetException ) {
|
||||
return ( ( InvocationTargetException ) throwable ).getTargetException();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Finds a <code>Throwable</code> by method name.</p>
|
||||
*
|
||||
* @param throwable the exception to examine
|
||||
* @param methodName the name of the method to find and invoke
|
||||
* @return the wrapped exception, or <code>null</code> if not found
|
||||
*/
|
||||
private static Throwable getCauseUsingMethodName(Throwable throwable, String methodName) {
|
||||
Method method = null;
|
||||
try {
|
||||
method = throwable.getClass().getMethod( methodName, null );
|
||||
}
|
||||
catch ( NoSuchMethodException ignored ) {
|
||||
}
|
||||
catch ( SecurityException ignored ) {
|
||||
}
|
||||
|
||||
if ( method != null && Throwable.class.isAssignableFrom( method.getReturnType() ) ) {
|
||||
try {
|
||||
return ( Throwable ) method.invoke( throwable, ArrayHelper.EMPTY_OBJECT_ARRAY );
|
||||
}
|
||||
catch ( IllegalAccessException ignored ) {
|
||||
}
|
||||
catch ( IllegalArgumentException ignored ) {
|
||||
}
|
||||
catch ( InvocationTargetException ignored ) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Finds a <code>Throwable</code> by field name.</p>
|
||||
*
|
||||
* @param throwable the exception to examine
|
||||
* @param fieldName the name of the attribute to examine
|
||||
* @return the wrapped exception, or <code>null</code> if not found
|
||||
*/
|
||||
private static Throwable getCauseUsingFieldName(Throwable throwable, String fieldName) {
|
||||
Field field = null;
|
||||
try {
|
||||
field = throwable.getClass().getField( fieldName );
|
||||
}
|
||||
catch ( NoSuchFieldException ignored ) {
|
||||
}
|
||||
catch ( SecurityException ignored ) {
|
||||
}
|
||||
|
||||
if ( field != null && Throwable.class.isAssignableFrom( field.getType() ) ) {
|
||||
try {
|
||||
return ( Throwable ) field.get( throwable );
|
||||
}
|
||||
catch ( IllegalAccessException ignored ) {
|
||||
}
|
||||
catch ( IllegalArgumentException ignored ) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Checks if the Throwable class has a <code>getCause</code> method.</p>
|
||||
* <p/>
|
||||
* <p>This is true for JDK 1.4 and above.</p>
|
||||
*
|
||||
* @return true if Throwable is nestable
|
||||
* @since 2.0
|
||||
*/
|
||||
public static boolean isThrowableNested() {
|
||||
return ( THROWABLE_CAUSE_METHOD != null );
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Checks whether this <code>Throwable</code> class can store a cause.</p>
|
||||
* <p/>
|
||||
* <p>This method does <b>not</b> check whether it actually does store a cause.<p>
|
||||
*
|
||||
* @param throwable the <code>Throwable</code> to examine, may be null
|
||||
* @return boolean <code>true</code> if nested otherwise <code>false</code>
|
||||
* @since 2.0
|
||||
*/
|
||||
public static boolean isNestedThrowable(Throwable throwable) {
|
||||
if ( throwable == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( throwable instanceof Nestable ) {
|
||||
return true;
|
||||
}
|
||||
else if ( throwable instanceof SQLException ) {
|
||||
return true;
|
||||
}
|
||||
else if ( throwable instanceof InvocationTargetException ) {
|
||||
return true;
|
||||
}
|
||||
else if ( isThrowableNested() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Class cls = throwable.getClass();
|
||||
for ( int i = 0, isize = CAUSE_METHOD_NAMES.length; i < isize; i++ ) {
|
||||
try {
|
||||
Method method = cls.getMethod( CAUSE_METHOD_NAMES[i], null );
|
||||
if ( method != null && Throwable.class.isAssignableFrom( method.getReturnType() ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch ( NoSuchMethodException ignored ) {
|
||||
}
|
||||
catch ( SecurityException ignored ) {
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Field field = cls.getField( "detail" );
|
||||
if ( field != null ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch ( NoSuchFieldException ignored ) {
|
||||
}
|
||||
catch ( SecurityException ignored ) {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Counts the number of <code>Throwable</code> objects in the
|
||||
* exception chain.</p>
|
||||
* <p/>
|
||||
* <p>A throwable without cause will return <code>1</code>.
|
||||
* A throwable with one cause will return <code>2</code> and so on.
|
||||
* A <code>null</code> throwable will return <code>0</code>.</p>
|
||||
*
|
||||
* @param throwable the throwable to inspect, may be null
|
||||
* @return the count of throwables, zero if null input
|
||||
*/
|
||||
public static int getThrowableCount(Throwable throwable) {
|
||||
int count = 0;
|
||||
while ( throwable != null ) {
|
||||
count++;
|
||||
throwable = ExceptionUtils.getCause( throwable );
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the list of <code>Throwable</code> objects in the
|
||||
* exception chain.</p>
|
||||
* <p/>
|
||||
* <p>A throwable without cause will return an array containing
|
||||
* one element - the input throwable.
|
||||
* A throwable with one cause will return an array containing
|
||||
* two elements. - the input throwable and the cause throwable.
|
||||
* A <code>null</code> throwable will return an array size zero.</p>
|
||||
*
|
||||
* @param throwable the throwable to inspect, may be null
|
||||
* @return the array of throwables, never null
|
||||
*/
|
||||
public static Throwable[] getThrowables(Throwable throwable) {
|
||||
List list = new ArrayList();
|
||||
while ( throwable != null ) {
|
||||
list.add( throwable );
|
||||
throwable = ExceptionUtils.getCause( throwable );
|
||||
}
|
||||
return ( Throwable[] ) list.toArray( new Throwable[list.size()] );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Returns the (zero based) index of the first <code>Throwable</code>
|
||||
* that matches the specified type in the exception chain.</p>
|
||||
* <p/>
|
||||
* <p>A <code>null</code> throwable returns <code>-1</code>.
|
||||
* A <code>null</code> type returns <code>-1</code>.
|
||||
* No match in the chain returns <code>-1</code>.</p>
|
||||
*
|
||||
* @param throwable the throwable to inspect, may be null
|
||||
* @param type the type to search for
|
||||
* @return the index into the throwable chain, -1 if no match or null input
|
||||
*/
|
||||
public static int indexOfThrowable(Throwable throwable, Class type) {
|
||||
return indexOfThrowable( throwable, type, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the (zero based) index of the first <code>Throwable</code>
|
||||
* that matches the specified type in the exception chain from
|
||||
* a specified index.</p>
|
||||
* <p/>
|
||||
* <p>A <code>null</code> throwable returns <code>-1</code>.
|
||||
* A <code>null</code> type returns <code>-1</code>.
|
||||
* No match in the chain returns <code>-1</code>.
|
||||
* A negative start index is treated as zero.
|
||||
* A start index greater than the number of throwables returns <code>-1</code>.</p>
|
||||
*
|
||||
* @param throwable the throwable to inspect, may be null
|
||||
* @param type the type to search for
|
||||
* @param fromIndex the (zero based) index of the starting position,
|
||||
* negative treated as zero, larger than chain size returns -1
|
||||
* @return the index into the throwable chain, -1 if no match or null input
|
||||
*/
|
||||
public static int indexOfThrowable(Throwable throwable, Class type, int fromIndex) {
|
||||
if ( throwable == null ) {
|
||||
return -1;
|
||||
}
|
||||
if ( fromIndex < 0 ) {
|
||||
fromIndex = 0;
|
||||
}
|
||||
Throwable[] throwables = ExceptionUtils.getThrowables( throwable );
|
||||
if ( fromIndex >= throwables.length ) {
|
||||
return -1;
|
||||
}
|
||||
for ( int i = fromIndex; i < throwables.length; i++ ) {
|
||||
if ( throwables[i].getClass().equals( type ) ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Prints a compact stack trace for the root cause of a throwable
|
||||
* to <code>System.err</code>.</p>
|
||||
* <p/>
|
||||
* <p>The compact stack trace starts with the root cause and prints
|
||||
* stack frames up to the place where it was caught and wrapped.
|
||||
* Then it prints the wrapped exception and continues with stack frames
|
||||
* until the wrapper exception is caught and wrapped again, etc.</p>
|
||||
* <p/>
|
||||
* <p>The method is equivalent to <code>printStackTrace</code> for throwables
|
||||
* that don't have nested causes.</p>
|
||||
*
|
||||
* @param throwable the throwable to output
|
||||
* @since 2.0
|
||||
*/
|
||||
public static void printRootCauseStackTrace(Throwable throwable) {
|
||||
printRootCauseStackTrace( throwable, System.err );
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Prints a compact stack trace for the root cause of a throwable.</p>
|
||||
* <p/>
|
||||
* <p>The compact stack trace starts with the root cause and prints
|
||||
* stack frames up to the place where it was caught and wrapped.
|
||||
* Then it prints the wrapped exception and continues with stack frames
|
||||
* until the wrapper exception is caught and wrapped again, etc.</p>
|
||||
* <p/>
|
||||
* <p>The method is equivalent to <code>printStackTrace</code> for throwables
|
||||
* that don't have nested causes.</p>
|
||||
*
|
||||
* @param throwable the throwable to output, may be null
|
||||
* @param stream the stream to output to, may not be null
|
||||
* @throws IllegalArgumentException if the stream is <code>null</code>
|
||||
* @since 2.0
|
||||
*/
|
||||
public static void printRootCauseStackTrace(Throwable throwable, PrintStream stream) {
|
||||
if ( throwable == null ) {
|
||||
return;
|
||||
}
|
||||
if ( stream == null ) {
|
||||
throw new IllegalArgumentException( "The PrintStream must not be null" );
|
||||
}
|
||||
String trace[] = getRootCauseStackTrace( throwable );
|
||||
for ( int i = 0; i < trace.length; i++ ) {
|
||||
stream.println( trace[i] );
|
||||
}
|
||||
stream.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Prints a compact stack trace for the root cause of a throwable.</p>
|
||||
* <p/>
|
||||
* <p>The compact stack trace starts with the root cause and prints
|
||||
* stack frames up to the place where it was caught and wrapped.
|
||||
* Then it prints the wrapped exception and continues with stack frames
|
||||
* until the wrapper exception is caught and wrapped again, etc.</p>
|
||||
* <p/>
|
||||
* <p>The method is equivalent to <code>printStackTrace</code> for throwables
|
||||
* that don't have nested causes.</p>
|
||||
*
|
||||
* @param throwable the throwable to output, may be null
|
||||
* @param writer the writer to output to, may not be null
|
||||
* @throws IllegalArgumentException if the writer is <code>null</code>
|
||||
* @since 2.0
|
||||
*/
|
||||
public static void printRootCauseStackTrace(Throwable throwable, PrintWriter writer) {
|
||||
if ( throwable == null ) {
|
||||
return;
|
||||
}
|
||||
if ( writer == null ) {
|
||||
throw new IllegalArgumentException( "The PrintWriter must not be null" );
|
||||
}
|
||||
String trace[] = getRootCauseStackTrace( throwable );
|
||||
for ( int i = 0; i < trace.length; i++ ) {
|
||||
writer.println( trace[i] );
|
||||
}
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Creates a compact stack trace for the root cause of the supplied
|
||||
* <code>Throwable</code>.</p>
|
||||
*
|
||||
* @param throwable the throwable to examine, may be null
|
||||
* @return an array of stack trace frames, never null
|
||||
* @since 2.0
|
||||
*/
|
||||
public static String[] getRootCauseStackTrace(Throwable throwable) {
|
||||
if ( throwable == null ) {
|
||||
return ArrayHelper.EMPTY_STRING_ARRAY;
|
||||
}
|
||||
Throwable throwables[] = getThrowables( throwable );
|
||||
int count = throwables.length;
|
||||
ArrayList frames = new ArrayList();
|
||||
List nextTrace = getStackFrameList( throwables[count - 1] );
|
||||
for ( int i = count; --i >= 0; ) {
|
||||
List trace = nextTrace;
|
||||
if ( i != 0 ) {
|
||||
nextTrace = getStackFrameList( throwables[i - 1] );
|
||||
removeCommonFrames( trace, nextTrace );
|
||||
}
|
||||
if ( i == count - 1 ) {
|
||||
frames.add( throwables[i].toString() );
|
||||
}
|
||||
else {
|
||||
frames.add( WRAPPED_MARKER + throwables[i].toString() );
|
||||
}
|
||||
for ( int j = 0; j < trace.size(); j++ ) {
|
||||
frames.add( trace.get( j ) );
|
||||
}
|
||||
}
|
||||
return ( String[] ) frames.toArray( new String[0] );
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Removes common frames from the cause trace given the two stack traces.</p>
|
||||
*
|
||||
* @param causeFrames stack trace of a cause throwable
|
||||
* @param wrapperFrames stack trace of a wrapper throwable
|
||||
* @throws IllegalArgumentException if either argument is null
|
||||
* @since 2.0
|
||||
*/
|
||||
public static void removeCommonFrames(List causeFrames, List wrapperFrames) {
|
||||
if ( causeFrames == null || wrapperFrames == null ) {
|
||||
throw new IllegalArgumentException( "The List must not be null" );
|
||||
}
|
||||
int causeFrameIndex = causeFrames.size() - 1;
|
||||
int wrapperFrameIndex = wrapperFrames.size() - 1;
|
||||
while ( causeFrameIndex >= 0 && wrapperFrameIndex >= 0 ) {
|
||||
// Remove the frame from the cause trace if it is the same
|
||||
// as in the wrapper trace
|
||||
String causeFrame = ( String ) causeFrames.get( causeFrameIndex );
|
||||
String wrapperFrame = ( String ) wrapperFrames.get( wrapperFrameIndex );
|
||||
if ( causeFrame.equals( wrapperFrame ) ) {
|
||||
causeFrames.remove( causeFrameIndex );
|
||||
}
|
||||
causeFrameIndex--;
|
||||
wrapperFrameIndex--;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Gets the stack trace from a Throwable as a String.</p>
|
||||
*
|
||||
* @param throwable the <code>Throwable</code> to be examined
|
||||
* @return the stack trace as generated by the exception's
|
||||
* <code>printStackTrace(PrintWriter)</code> method
|
||||
*/
|
||||
public static String getStackTrace(Throwable throwable) {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter( sw, true );
|
||||
throwable.printStackTrace( pw );
|
||||
return sw.getBuffer().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>A way to get the entire nested stack-trace of an throwable.</p>
|
||||
*
|
||||
* @param throwable the <code>Throwable</code> to be examined
|
||||
* @return the nested stack trace, with the root cause first
|
||||
* @since 2.0
|
||||
*/
|
||||
public static String getFullStackTrace(Throwable throwable) {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter( sw, true );
|
||||
Throwable[] ts = getThrowables( throwable );
|
||||
for ( int i = 0; i < ts.length; i++ ) {
|
||||
ts[i].printStackTrace( pw );
|
||||
if ( isNestedThrowable( ts[i] ) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sw.getBuffer().toString();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Captures the stack trace associated with the specified
|
||||
* <code>Throwable</code> object, decomposing it into a list of
|
||||
* stack frames.</p>
|
||||
*
|
||||
* @param throwable the <code>Throwable</code> to exaamine, may be null
|
||||
* @return an array of strings describing each stack frame, never null
|
||||
*/
|
||||
public static String[] getStackFrames(Throwable throwable) {
|
||||
if ( throwable == null ) {
|
||||
return ArrayHelper.EMPTY_STRING_ARRAY;
|
||||
}
|
||||
return getStackFrames( getStackTrace( throwable ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Functionality shared between the
|
||||
* <code>getStackFrames(Throwable)</code> methods of this and the
|
||||
* {@link org.apache.commons.lang.exception.NestableDelegate}
|
||||
* classes.</p>
|
||||
*/
|
||||
static String[] getStackFrames(String stackTrace) {
|
||||
String linebreak = LINE_SEPARATOR;
|
||||
StringTokenizer frames = new StringTokenizer( stackTrace, linebreak );
|
||||
List list = new LinkedList();
|
||||
while ( frames.hasMoreTokens() ) {
|
||||
list.add( frames.nextToken() );
|
||||
}
|
||||
return ( String[] ) list.toArray( new String[list.size()] );
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Produces a <code>List</code> of stack frames - the message
|
||||
* is not included.</p>
|
||||
* <p/>
|
||||
* <p>This works in most cases - it will only fail if the exception
|
||||
* message contains a line that starts with:
|
||||
* <code>" at".</code></p>
|
||||
*
|
||||
* @param t is any throwable
|
||||
* @return List of stack frames
|
||||
*/
|
||||
static List getStackFrameList(Throwable t) {
|
||||
String stackTrace = getStackTrace( t );
|
||||
String linebreak = LINE_SEPARATOR;
|
||||
StringTokenizer frames = new StringTokenizer( stackTrace, linebreak );
|
||||
List list = new LinkedList();
|
||||
boolean traceStarted = false;
|
||||
while ( frames.hasMoreTokens() ) {
|
||||
String token = frames.nextToken();
|
||||
// Determine if the line starts with <whitespace>at
|
||||
int at = token.indexOf( "at" );
|
||||
if ( at != -1 && token.substring( 0, at ).trim().length() == 0 ) {
|
||||
traceStarted = true;
|
||||
list.add( token );
|
||||
}
|
||||
else if ( traceStarted ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,174 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.exception;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* An interface to be implemented by {@link java.lang.Throwable}
|
||||
* extensions which would like to be able to nest root exceptions
|
||||
* inside themselves.
|
||||
*
|
||||
* @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
|
||||
* @author <a href="mailto:knielsen@apache.org">Kasper Nielsen</a>
|
||||
* @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
|
||||
* @author Pete Gieser
|
||||
* @version $Id: Nestable.java 4782 2004-11-21 00:11:27Z pgmjsd $
|
||||
* @since 1.0
|
||||
*/
|
||||
public interface Nestable {
|
||||
|
||||
/**
|
||||
* Returns the reference to the exception or error that caused the
|
||||
* exception implementing the <code>Nestable</code> to be thrown.
|
||||
*
|
||||
* @return throwable that caused the original exception
|
||||
*/
|
||||
public Throwable getCause();
|
||||
|
||||
/**
|
||||
* Returns the error message of this and any nested
|
||||
* <code>Throwable</code>.
|
||||
*
|
||||
* @return the error message
|
||||
*/
|
||||
public String getMessage();
|
||||
|
||||
/**
|
||||
* Returns the error message of the <code>Throwable</code> in the chain
|
||||
* of <code>Throwable</code>s at the specified index, numbererd from 0.
|
||||
*
|
||||
* @param index the index of the <code>Throwable</code> in the chain of
|
||||
* <code>Throwable</code>s
|
||||
* @return the error message, or null if the <code>Throwable</code> at the
|
||||
* specified index in the chain does not contain a message
|
||||
* @throws IndexOutOfBoundsException if the <code>index</code> argument is
|
||||
* negative or not less than the count of <code>Throwable</code>s in the
|
||||
* chain
|
||||
*/
|
||||
public String getMessage(int index);
|
||||
|
||||
/**
|
||||
* Returns the error message of this and any nested <code>Throwable</code>s
|
||||
* in an array of Strings, one element for each message. Any
|
||||
* <code>Throwable</code> not containing a message is represented in the
|
||||
* array by a null. This has the effect of cause the length of the returned
|
||||
* array to be equal to the result of the {@link #getThrowableCount()}
|
||||
* operation.
|
||||
*
|
||||
* @return the error messages
|
||||
*/
|
||||
public String[] getMessages();
|
||||
|
||||
/**
|
||||
* Returns the <code>Throwable</code> in the chain of
|
||||
* <code>Throwable</code>s at the specified index, numbererd from 0.
|
||||
*
|
||||
* @param index the index, numbered from 0, of the <code>Throwable</code> in
|
||||
* the chain of <code>Throwable</code>s
|
||||
* @return the <code>Throwable</code>
|
||||
* @throws IndexOutOfBoundsException if the <code>index</code> argument is
|
||||
* negative or not less than the count of <code>Throwable</code>s in the
|
||||
* chain
|
||||
*/
|
||||
public Throwable getThrowable(int index);
|
||||
|
||||
/**
|
||||
* Returns the number of nested <code>Throwable</code>s represented by
|
||||
* this <code>Nestable</code>, including this <code>Nestable</code>.
|
||||
*
|
||||
* @return the throwable count
|
||||
*/
|
||||
public int getThrowableCount();
|
||||
|
||||
/**
|
||||
* Returns this <code>Nestable</code> and any nested <code>Throwable</code>s
|
||||
* in an array of <code>Throwable</code>s, one element for each
|
||||
* <code>Throwable</code>.
|
||||
*
|
||||
* @return the <code>Throwable</code>s
|
||||
*/
|
||||
public Throwable[] getThrowables();
|
||||
|
||||
/**
|
||||
* Returns the index, numbered from 0, of the first occurrence of the
|
||||
* specified type in the chain of <code>Throwable</code>s, or -1 if the
|
||||
* specified type is not found in the chain.
|
||||
*
|
||||
* @param type <code>Class</code> to be found
|
||||
* @return index of the first occurrence of the type in the chain, or -1 if
|
||||
* the type is not found
|
||||
*/
|
||||
public int indexOfThrowable(Class type);
|
||||
|
||||
/**
|
||||
* Returns the index, numbered from 0, of the first <code>Throwable</code>
|
||||
* that matches the specified type in the chain of <code>Throwable</code>s
|
||||
* with an index greater than or equal to the specified index, or -1 if
|
||||
* the type is not found.
|
||||
*
|
||||
* @param type <code>Class</code> to be found
|
||||
* @param fromIndex the index, numbered from 0, of the starting position in
|
||||
* the chain to be searched
|
||||
* @return index of the first occurrence of the type in the chain, or -1 if
|
||||
* the type is not found
|
||||
* @throws IndexOutOfBoundsException if the <code>fromIndex</code> argument
|
||||
* is negative or not less than the count of <code>Throwable</code>s in the
|
||||
* chain
|
||||
*/
|
||||
public int indexOfThrowable(Class type, int fromIndex);
|
||||
|
||||
/**
|
||||
* Prints the stack trace of this exception to the specified print
|
||||
* writer. Includes information from the exception, if any,
|
||||
* which caused this exception.
|
||||
*
|
||||
* @param out <code>PrintWriter</code> to use for output.
|
||||
*/
|
||||
public void printStackTrace(PrintWriter out);
|
||||
|
||||
/**
|
||||
* Prints the stack trace of this exception to the specified print
|
||||
* stream. Includes inforamation from the exception, if any,
|
||||
* which caused this exception.
|
||||
*
|
||||
* @param out <code>PrintStream</code> to use for output.
|
||||
*/
|
||||
public void printStackTrace(PrintStream out);
|
||||
|
||||
/**
|
||||
* Prints the stack trace for this exception only--root cause not
|
||||
* included--using the provided writer. Used by {@link
|
||||
* org.apache.commons.lang.exception.NestableDelegate} to write
|
||||
* individual stack traces to a buffer. The implementation of
|
||||
* this method should call
|
||||
* <code>super.printStackTrace(out);</code> in most cases.
|
||||
*
|
||||
* @param out The writer to use.
|
||||
*/
|
||||
public void printPartialStackTrace(PrintWriter out);
|
||||
|
||||
}
|
|
@ -1,383 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.exception;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Serializable;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>A shared implementation of the nestable exception functionality.</p>
|
||||
* <p/>
|
||||
* The code is shared between
|
||||
* {@link org.apache.commons.lang.exception.NestableError NestableError},
|
||||
* {@link org.apache.commons.lang.exception.NestableException NestableException} and
|
||||
* {@link org.apache.commons.lang.exception.NestableRuntimeException NestableRuntimeException}.
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
|
||||
* @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
|
||||
* @author <a href="mailto:knielsen@apache.org">Kasper Nielsen</a>
|
||||
* @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
|
||||
* @author Sean C. Sullivan
|
||||
* @author Stephen Colebourne
|
||||
* @version $Id: NestableDelegate.java 4782 2004-11-21 00:11:27Z pgmjsd $
|
||||
* @since 1.0
|
||||
*/
|
||||
public class NestableDelegate implements Serializable {
|
||||
|
||||
/**
|
||||
* Constructor error message.
|
||||
*/
|
||||
private static final String MUST_BE_THROWABLE =
|
||||
"The Nestable implementation passed to the NestableDelegate(Nestable) "
|
||||
+ "constructor must extend java.lang.Throwable";
|
||||
|
||||
/**
|
||||
* Holds the reference to the exception or error that we're
|
||||
* wrapping (which must be a {@link
|
||||
* org.apache.commons.lang.exception.Nestable} implementation).
|
||||
*/
|
||||
private Throwable nestable = null;
|
||||
|
||||
/**
|
||||
* Whether to print the stack trace top-down.
|
||||
* This public flag may be set by calling code, typically in initialisation.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
private static boolean topDown = true;
|
||||
|
||||
/**
|
||||
* Whether to trim the repeated stack trace.
|
||||
* This public flag may be set by calling code, typically in initialisation.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
private static boolean trimStackFrames = true;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>NestableDelegate</code> instance to manage the
|
||||
* specified <code>Nestable</code>.
|
||||
*
|
||||
* @param nestable the Nestable implementation (<i>must</i> extend
|
||||
* {@link java.lang.Throwable})
|
||||
* @since 2.0
|
||||
*/
|
||||
public NestableDelegate(Nestable nestable) {
|
||||
if ( nestable instanceof Throwable ) {
|
||||
this.nestable = ( Throwable ) nestable;
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException( MUST_BE_THROWABLE );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error message of the <code>Throwable</code> in the chain
|
||||
* of <code>Throwable</code>s at the specified index, numbererd from 0.
|
||||
*
|
||||
* @param index the index of the <code>Throwable</code> in the chain of
|
||||
* <code>Throwable</code>s
|
||||
* @return the error message, or null if the <code>Throwable</code> at the
|
||||
* specified index in the chain does not contain a message
|
||||
* @throws IndexOutOfBoundsException if the <code>index</code> argument is
|
||||
* negative or not less than the count of <code>Throwable</code>s in the
|
||||
* chain
|
||||
* @since 2.0
|
||||
*/
|
||||
public String getMessage(int index) {
|
||||
Throwable t = this.getThrowable( index );
|
||||
if ( Nestable.class.isInstance( t ) ) {
|
||||
return ( ( Nestable ) t ).getMessage( 0 );
|
||||
}
|
||||
else {
|
||||
return t.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full message contained by the <code>Nestable</code>
|
||||
* and any nested <code>Throwable</code>s.
|
||||
*
|
||||
* @param baseMsg the base message to use when creating the full
|
||||
* message. Should be generally be called via
|
||||
* <code>nestableHelper.getMessage( super.getMessage() )</code>,
|
||||
* where <code>super</code> is an instance of {@link
|
||||
* java.lang.Throwable}.
|
||||
* @return The concatenated message for this and all nested
|
||||
* <code>Throwable</code>s
|
||||
* @since 2.0
|
||||
*/
|
||||
public String getMessage(String baseMsg) {
|
||||
StringBuffer msg = new StringBuffer();
|
||||
if ( baseMsg != null ) {
|
||||
msg.append( baseMsg );
|
||||
}
|
||||
|
||||
Throwable nestedCause = ExceptionUtils.getCause( this.nestable );
|
||||
if ( nestedCause != null ) {
|
||||
String causeMsg = nestedCause.getMessage();
|
||||
if ( causeMsg != null ) {
|
||||
if ( baseMsg != null ) {
|
||||
msg.append( ": " );
|
||||
}
|
||||
msg.append( causeMsg );
|
||||
}
|
||||
|
||||
}
|
||||
return ( msg.length() > 0 ? msg.toString() : null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error message of this and any nested <code>Throwable</code>s
|
||||
* in an array of Strings, one element for each message. Any
|
||||
* <code>Throwable</code> not containing a message is represented in the
|
||||
* array by a null. This has the effect of cause the length of the returned
|
||||
* array to be equal to the result of the {@link #getThrowableCount()}
|
||||
* operation.
|
||||
*
|
||||
* @return the error messages
|
||||
* @since 2.0
|
||||
*/
|
||||
public String[] getMessages() {
|
||||
Throwable[] throwables = this.getThrowables();
|
||||
String[] msgs = new String[throwables.length];
|
||||
for ( int i = 0; i < throwables.length; i++ ) {
|
||||
msgs[i] = Nestable.class.isInstance( throwables[i] ) ?
|
||||
( ( Nestable ) throwables[i] ).getMessage( 0 ) :
|
||||
throwables[i].getMessage();
|
||||
}
|
||||
return msgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>Throwable</code> in the chain of
|
||||
* <code>Throwable</code>s at the specified index, numbererd from 0.
|
||||
*
|
||||
* @param index the index, numbered from 0, of the <code>Throwable</code> in
|
||||
* the chain of <code>Throwable</code>s
|
||||
* @return the <code>Throwable</code>
|
||||
* @throws IndexOutOfBoundsException if the <code>index</code> argument is
|
||||
* negative or not less than the count of <code>Throwable</code>s in the
|
||||
* chain
|
||||
* @since 2.0
|
||||
*/
|
||||
public Throwable getThrowable(int index) {
|
||||
if ( index == 0 ) {
|
||||
return this.nestable;
|
||||
}
|
||||
Throwable[] throwables = this.getThrowables();
|
||||
return throwables[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of <code>Throwable</code>s contained in the
|
||||
* <code>Nestable</code> contained by this delegate.
|
||||
*
|
||||
* @return the throwable count
|
||||
* @since 2.0
|
||||
*/
|
||||
public int getThrowableCount() {
|
||||
return ExceptionUtils.getThrowableCount( this.nestable );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this delegate's <code>Nestable</code> and any nested
|
||||
* <code>Throwable</code>s in an array of <code>Throwable</code>s, one
|
||||
* element for each <code>Throwable</code>.
|
||||
*
|
||||
* @return the <code>Throwable</code>s
|
||||
* @since 2.0
|
||||
*/
|
||||
public Throwable[] getThrowables() {
|
||||
return ExceptionUtils.getThrowables( this.nestable );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index, numbered from 0, of the first <code>Throwable</code>
|
||||
* that matches the specified type in the chain of <code>Throwable</code>s
|
||||
* held in this delegate's <code>Nestable</code> with an index greater than
|
||||
* or equal to the specified index, or -1 if the type is not found.
|
||||
*
|
||||
* @param type <code>Class</code> to be found
|
||||
* @param fromIndex the index, numbered from 0, of the starting position in
|
||||
* the chain to be searched
|
||||
* @return index of the first occurrence of the type in the chain, or -1 if
|
||||
* the type is not found
|
||||
* @throws IndexOutOfBoundsException if the <code>fromIndex</code> argument
|
||||
* is negative or not less than the count of <code>Throwable</code>s in the
|
||||
* chain
|
||||
* @since 2.0
|
||||
*/
|
||||
public int indexOfThrowable(Class type, int fromIndex) {
|
||||
if ( fromIndex < 0 ) {
|
||||
throw new IndexOutOfBoundsException( "The start index was out of bounds: " + fromIndex );
|
||||
}
|
||||
Throwable[] throwables = ExceptionUtils.getThrowables( this.nestable );
|
||||
if ( fromIndex >= throwables.length ) {
|
||||
throw new IndexOutOfBoundsException( "The start index was out of bounds: "
|
||||
+ fromIndex + " >= " + throwables.length );
|
||||
}
|
||||
for ( int i = fromIndex; i < throwables.length; i++ ) {
|
||||
if ( throwables[i].getClass().equals( type ) ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the stack trace of this exception the the standar error
|
||||
* stream.
|
||||
*/
|
||||
public void printStackTrace() {
|
||||
printStackTrace( System.err );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the stack trace of this exception to the specified
|
||||
* stream.
|
||||
*
|
||||
* @param out <code>PrintStream</code> to use for output.
|
||||
* @see #printStackTrace(PrintWriter)
|
||||
*/
|
||||
public void printStackTrace(PrintStream out) {
|
||||
synchronized ( out ) {
|
||||
PrintWriter pw = new PrintWriter( out, false );
|
||||
printStackTrace( pw );
|
||||
// Flush the PrintWriter before it's GC'ed.
|
||||
pw.flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the stack trace of this exception to the specified
|
||||
* writer. If the Throwable class has a <code>getCause</code>
|
||||
* method (i.e. running on jre1.4 or higher), this method just
|
||||
* uses Throwable's printStackTrace() method. Otherwise, generates
|
||||
* the stack-trace, by taking into account the 'topDown' and
|
||||
* 'trimStackFrames' parameters. The topDown and trimStackFrames
|
||||
* are set to 'true' by default (produces jre1.4-like stack trace).
|
||||
*
|
||||
* @param out <code>PrintWriter</code> to use for output.
|
||||
*/
|
||||
public void printStackTrace(PrintWriter out) {
|
||||
Throwable throwable = this.nestable;
|
||||
// if running on jre1.4 or higher, use default printStackTrace
|
||||
if ( ExceptionUtils.isThrowableNested() ) {
|
||||
if ( throwable instanceof Nestable ) {
|
||||
( ( Nestable ) throwable ).printPartialStackTrace( out );
|
||||
}
|
||||
else {
|
||||
throwable.printStackTrace( out );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// generating the nested stack trace
|
||||
List stacks = new ArrayList();
|
||||
while ( throwable != null ) {
|
||||
String[] st = getStackFrames( throwable );
|
||||
stacks.add( st );
|
||||
throwable = ExceptionUtils.getCause( throwable );
|
||||
}
|
||||
|
||||
// If NOT topDown, reverse the stack
|
||||
String separatorLine = "Caused by: ";
|
||||
if ( !topDown ) {
|
||||
separatorLine = "Rethrown as: ";
|
||||
Collections.reverse( stacks );
|
||||
}
|
||||
|
||||
// Remove the repeated lines in the stack
|
||||
if ( trimStackFrames ) trimStackFrames( stacks );
|
||||
|
||||
synchronized ( out ) {
|
||||
for ( Iterator iter = stacks.iterator(); iter.hasNext(); ) {
|
||||
String[] st = ( String[] ) iter.next();
|
||||
for ( int i = 0, len = st.length; i < len; i++ ) {
|
||||
out.println( st[i] );
|
||||
}
|
||||
if ( iter.hasNext() ) out.print( separatorLine );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures the stack trace associated with the specified
|
||||
* <code>Throwable</code> object, decomposing it into a list of
|
||||
* stack frames.
|
||||
*
|
||||
* @param t The <code>Throwable</code>.
|
||||
* @return An array of strings describing each stack frame.
|
||||
* @since 2.0
|
||||
*/
|
||||
protected String[] getStackFrames(Throwable t) {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter( sw, true );
|
||||
|
||||
// Avoid infinite loop between decompose() and printStackTrace().
|
||||
if ( t instanceof Nestable ) {
|
||||
( ( Nestable ) t ).printPartialStackTrace( pw );
|
||||
}
|
||||
else {
|
||||
t.printStackTrace( pw );
|
||||
}
|
||||
return ExceptionUtils.getStackFrames( sw.getBuffer().toString() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims the stack frames. The first set is left untouched. The rest
|
||||
* of the frames are truncated from the bottom by comparing with
|
||||
* one just on top.
|
||||
*
|
||||
* @param stacks The list containing String[] elements
|
||||
* @since 2.0
|
||||
*/
|
||||
protected void trimStackFrames(List stacks) {
|
||||
for ( int size = stacks.size(), i = size - 1; i > 0; i-- ) {
|
||||
String[] curr = ( String[] ) stacks.get( i );
|
||||
String[] next = ( String[] ) stacks.get( i - 1 );
|
||||
|
||||
List currList = new ArrayList( Arrays.asList( curr ) );
|
||||
List nextList = new ArrayList( Arrays.asList( next ) );
|
||||
ExceptionUtils.removeCommonFrames( currList, nextList );
|
||||
|
||||
int trimmed = curr.length - currList.size();
|
||||
if ( trimmed > 0 ) {
|
||||
currList.add( "\t... " + trimmed + " more" );
|
||||
stacks.set( i,
|
||||
currList.toArray( new String[currList.size()] ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,225 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.exception;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* The base class of all exceptions which can contain other exceptions.
|
||||
* <p/>
|
||||
* It is intended to ease the debugging by carrying on the information
|
||||
* about the exception which was caught and provoked throwing the
|
||||
* current exception. Catching and rethrowing may occur multiple
|
||||
* times, and provided that all exceptions except the first one
|
||||
* are descendands of <code>NestedException</code>, when the
|
||||
* exception is finally printed out using any of the <code>
|
||||
* printStackTrace()</code> methods, the stacktrace will contain
|
||||
* the information about all exceptions thrown and caught on
|
||||
* the way.
|
||||
* <p> Running the following program
|
||||
* <p><blockquote><pre>
|
||||
* 1 import org.apache.commons.lang.exception.NestableException;
|
||||
* 2
|
||||
* 3 public class Test {
|
||||
* 4 public static void main( String[] args ) {
|
||||
* 5 try {
|
||||
* 6 a();
|
||||
* 7 } catch(Exception e) {
|
||||
* 8 e.printStackTrace();
|
||||
* 9 }
|
||||
* 10 }
|
||||
* 11
|
||||
* 12 public static void a() throws Exception {
|
||||
* 13 try {
|
||||
* 14 b();
|
||||
* 15 } catch(Exception e) {
|
||||
* 16 throw new NestableException("foo", e);
|
||||
* 17 }
|
||||
* 18 }
|
||||
* 19
|
||||
* 20 public static void b() throws Exception {
|
||||
* 21 try {
|
||||
* 22 c();
|
||||
* 23 } catch(Exception e) {
|
||||
* 24 throw new NestableException("bar", e);
|
||||
* 25 }
|
||||
* 26 }
|
||||
* 27
|
||||
* 28 public static void c() throws Exception {
|
||||
* 29 throw new Exception("baz");
|
||||
* 30 }
|
||||
* 31 }
|
||||
* </pre></blockquote>
|
||||
* <p>Yields the following stacktrace:
|
||||
* <p><blockquote><pre>
|
||||
* org.apache.commons.lang.exception.NestableException: foo
|
||||
* at Test.a(Test.java:16)
|
||||
* at Test.main(Test.java:6)
|
||||
* Caused by: org.apache.commons.lang.exception.NestableException: bar
|
||||
* at Test.b(Test.java:24)
|
||||
* at Test.a(Test.java:14)
|
||||
* ... 1 more
|
||||
* Caused by: java.lang.Exception: baz
|
||||
* at Test.c(Test.java:29)
|
||||
* at Test.b(Test.java:22)
|
||||
* ... 2 more
|
||||
* </pre></blockquote><br>
|
||||
*
|
||||
* @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
|
||||
* @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
|
||||
* @author <a href="mailto:knielsen@apache.org">Kasper Nielsen</a>
|
||||
* @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
|
||||
* @version $Id: NestableException.java 4782 2004-11-21 00:11:27Z pgmjsd $
|
||||
* @since 1.0
|
||||
*/
|
||||
public class NestableException extends Exception implements Nestable {
|
||||
|
||||
/**
|
||||
* The helper instance which contains much of the code which we
|
||||
* delegate to.
|
||||
*/
|
||||
protected NestableDelegate delegate = new NestableDelegate( this );
|
||||
|
||||
/**
|
||||
* Holds the reference to the exception or error that caused
|
||||
* this exception to be thrown.
|
||||
*/
|
||||
private Throwable cause = null;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>NestableException</code> without specified
|
||||
* detail message.
|
||||
*/
|
||||
public NestableException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>NestableException</code> with specified
|
||||
* detail message.
|
||||
*
|
||||
* @param msg The error message.
|
||||
*/
|
||||
public NestableException(String msg) {
|
||||
super( msg );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>NestableException</code> with specified
|
||||
* nested <code>Throwable</code>.
|
||||
*
|
||||
* @param cause the exception or error that caused this exception to be
|
||||
* thrown
|
||||
*/
|
||||
public NestableException(Throwable cause) {
|
||||
super();
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>NestableException</code> with specified
|
||||
* detail message and nested <code>Throwable</code>.
|
||||
*
|
||||
* @param msg the error message
|
||||
* @param cause the exception or error that caused this exception to be
|
||||
* thrown
|
||||
*/
|
||||
public NestableException(String msg, Throwable cause) {
|
||||
super( msg );
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
public Throwable getCause() {
|
||||
return cause;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the detail message string of this throwable. If it was
|
||||
* created with a null message, returns the following:
|
||||
* ( cause==null ? null : cause.toString() ).
|
||||
*/
|
||||
public String getMessage() {
|
||||
if ( super.getMessage() != null ) {
|
||||
return super.getMessage();
|
||||
}
|
||||
else if ( cause != null ) {
|
||||
return cause.toString();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getMessage(int index) {
|
||||
if ( index == 0 ) {
|
||||
return super.getMessage();
|
||||
}
|
||||
else {
|
||||
return delegate.getMessage( index );
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getMessages() {
|
||||
return delegate.getMessages();
|
||||
}
|
||||
|
||||
public Throwable getThrowable(int index) {
|
||||
return delegate.getThrowable( index );
|
||||
}
|
||||
|
||||
public int getThrowableCount() {
|
||||
return delegate.getThrowableCount();
|
||||
}
|
||||
|
||||
public Throwable[] getThrowables() {
|
||||
return delegate.getThrowables();
|
||||
}
|
||||
|
||||
public int indexOfThrowable(Class type) {
|
||||
return delegate.indexOfThrowable( type, 0 );
|
||||
}
|
||||
|
||||
public int indexOfThrowable(Class type, int fromIndex) {
|
||||
return delegate.indexOfThrowable( type, fromIndex );
|
||||
}
|
||||
|
||||
public void printStackTrace() {
|
||||
delegate.printStackTrace();
|
||||
}
|
||||
|
||||
public void printStackTrace(PrintStream out) {
|
||||
delegate.printStackTrace( out );
|
||||
}
|
||||
|
||||
public void printStackTrace(PrintWriter out) {
|
||||
delegate.printStackTrace( out );
|
||||
}
|
||||
|
||||
public final void printPartialStackTrace(PrintWriter out) {
|
||||
super.printStackTrace( out );
|
||||
}
|
||||
|
||||
}
|
|
@ -1,185 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.exception;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import antlr.RecognitionException;
|
||||
|
||||
/**
|
||||
* The base class of all runtime exceptions which can contain other
|
||||
* exceptions.
|
||||
*
|
||||
* @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
|
||||
* @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
|
||||
* @author <a href="mailto:knielsen@apache.org">Kasper Nielsen</a>
|
||||
* @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
|
||||
* @version $Id: NestableRuntimeException.java 8137 2005-09-09 15:21:10Z epbernard $
|
||||
* @see org.apache.commons.lang.exception.NestableException
|
||||
* @since 1.0
|
||||
*/
|
||||
public class NestableRuntimeException extends RuntimeException implements Nestable {
|
||||
|
||||
/**
|
||||
* The helper instance which contains much of the code which we
|
||||
* delegate to.
|
||||
*/
|
||||
protected NestableDelegate delegate = new NestableDelegate( this );
|
||||
|
||||
/**
|
||||
* Holds the reference to the exception or error that caused
|
||||
* this exception to be thrown.
|
||||
*/
|
||||
private Throwable cause = null;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>NestableRuntimeException</code> without specified
|
||||
* detail message.
|
||||
*/
|
||||
public NestableRuntimeException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>NestableRuntimeException</code> with specified
|
||||
* detail message.
|
||||
*
|
||||
* @param msg the error message
|
||||
*/
|
||||
public NestableRuntimeException(String msg) {
|
||||
super( msg );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>NestableRuntimeException</code> with specified
|
||||
* nested <code>Throwable</code>.
|
||||
*
|
||||
* @param cause the exception or error that caused this exception to be
|
||||
* thrown
|
||||
*/
|
||||
public NestableRuntimeException(Throwable cause) {
|
||||
super();
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>NestableRuntimeException</code> with specified
|
||||
* detail message and nested <code>Throwable</code>.
|
||||
*
|
||||
* @param msg the error message
|
||||
* @param cause the exception or error that caused this exception to be
|
||||
* thrown
|
||||
*/
|
||||
public NestableRuntimeException(String msg, Throwable cause) {
|
||||
super( msg );
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
public Throwable getCause() {
|
||||
return cause;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the detail message string of this throwable. If it was
|
||||
* created with a null message, returns the following:
|
||||
* ( cause==null ? null : cause.toString( ).
|
||||
*/
|
||||
public String getMessage() {
|
||||
if ( super.getMessage() != null ) {
|
||||
return super.getMessage();
|
||||
}
|
||||
else if ( cause != null ) {
|
||||
return cause.toString();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getMessage(int index) {
|
||||
if ( index == 0 ) {
|
||||
return super.getMessage();
|
||||
}
|
||||
else {
|
||||
return delegate.getMessage( index );
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getMessages() {
|
||||
return delegate.getMessages();
|
||||
}
|
||||
|
||||
public Throwable getThrowable(int index) {
|
||||
return delegate.getThrowable( index );
|
||||
}
|
||||
|
||||
public int getThrowableCount() {
|
||||
return delegate.getThrowableCount();
|
||||
}
|
||||
|
||||
public Throwable[] getThrowables() {
|
||||
return delegate.getThrowables();
|
||||
}
|
||||
|
||||
public int indexOfThrowable(Class type) {
|
||||
return delegate.indexOfThrowable( type, 0 );
|
||||
}
|
||||
|
||||
public int indexOfThrowable(Class type, int fromIndex) {
|
||||
return delegate.indexOfThrowable( type, fromIndex );
|
||||
}
|
||||
|
||||
public void printStackTrace() {
|
||||
delegate.printStackTrace();
|
||||
}
|
||||
|
||||
public void printStackTrace(PrintStream out) {
|
||||
delegate.printStackTrace( out );
|
||||
}
|
||||
|
||||
public void printStackTrace(PrintWriter out) {
|
||||
delegate.printStackTrace( out );
|
||||
}
|
||||
|
||||
public final void printPartialStackTrace(PrintWriter out) {
|
||||
super.printStackTrace( out );
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void writeObject(ObjectOutputStream oos) throws IOException {
|
||||
Throwable tempCause = cause;
|
||||
//don't propagate RecognitionException, might be not serializable
|
||||
if ( cause instanceof RecognitionException ) {
|
||||
cause = null;
|
||||
}
|
||||
oos.defaultWriteObject();
|
||||
cause = tempCause;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue