001 package org.shiftone.jrat.util; 002 003 004 import java.io.PrintStream; 005 import java.io.PrintWriter; 006 import java.lang.reflect.Method; 007 008 009 /** 010 * Ok.. before Java 1.4 - exceptions did not have a cause. 011 * 012 * @author jeff@shiftone.org (Jeff Drost) 013 */ 014 public class NestedRuntimeException extends RuntimeException { 015 016 private Throwable rootCause = null; 017 018 public NestedRuntimeException(String message) { 019 super(message); 020 } 021 022 023 public NestedRuntimeException(String message, Throwable rootCause) { 024 025 super(message); 026 027 initializeCause(rootCause); 028 } 029 030 031 private void initializeCause(Throwable rootCause) { 032 033 try { 034 035 // the idea here is to try to use the java 1.4 cause, but it that's 036 // not possible, 037 // fall back to the custom rootCause field 038 // --> public synchronized Throwable initCause(Throwable cause); 039 Method initCause = Throwable.class.getMethod("initCause", new Class[]{Throwable.class}); 040 041 initCause.invoke(this, new Object[]{rootCause}); 042 } 043 catch (Exception e) { 044 this.rootCause = rootCause; 045 } 046 } 047 048 049 public Throwable getRootCause() { 050 return rootCause; 051 } 052 053 054 public void printStackTrace() { 055 printStackTrace(System.out); 056 } 057 058 059 public void printStackTrace(PrintStream s) { 060 printStackTrace(new PrintWriter(s)); 061 } 062 063 064 public void printStackTrace(PrintWriter s) { 065 066 super.printStackTrace(s); 067 068 if (rootCause != null) { 069 s.println("** ROOT CAUSE"); 070 rootCause.printStackTrace(s); 071 } 072 } 073 }