001 /** 002 * www.jcoverage.com 003 * Copyright (C)2003 jcoverage ltd. 004 * 005 * This file is part of jcoverage. 006 * 007 * jcoverage is free software; you can redistribute it and/or modify 008 * it under the terms of the GNU General Public License as published 009 * by the Free Software Foundation; either version 2 of the License, 010 * or (at your option) any later version. 011 * 012 * jcoverage is distributed in the hope that it will be useful, but 013 * WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * General Public License for more details. 016 * 017 * You should have received a copy of the GNU General Public License 018 * along with jcoverage; if not, write to the Free Software 019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 020 * USA 021 * 022 */ 023 package com.jcoverage.util; 024 025 import java.lang.reflect.InvocationTargetException; 026 027 import java.io.PrintStream; 028 import java.io.PrintWriter; 029 030 031 /** 032 * J2SE 1.4 introduced a common API to record the fact that one 033 * exception caused another, to access causative exceptions, and to 034 * access the entire "causal chain" as part of the standard stack 035 * backtrace. 036 * 037 * <p> This class provides support for such "causal chains" under 038 *earlier JDKs 039 * @see <a href="http://developer.java.sun.com/developer/bugParade/bugs/4209652.html">Chained Exception</a> 040 */ 041 public class NestedRuntimeException extends RuntimeException { 042 /** 043 * @serial detail include 044 */ 045 Throwable detail; 046 static final String CONTAINED_EXCEPTION="nested exception:"; 047 048 public NestedRuntimeException() { 049 } 050 051 public NestedRuntimeException(String s) { 052 super(s); 053 } 054 055 public NestedRuntimeException(String s,Throwable t) { 056 super(s); 057 try { 058 getClass().getMethod("initCause",new Class[] {Throwable.class}).invoke(this,new Object[] {t}); 059 } catch(NoSuchMethodException ex) { 060 this.detail=t; 061 } catch(IllegalAccessException ex) { 062 ex.printStackTrace(); 063 } catch(InvocationTargetException ex) { 064 ex.printStackTrace(); 065 } 066 } 067 068 public NestedRuntimeException(Throwable t) { 069 try { 070 getClass().getMethod("initCause",new Class[] {Throwable.class}).invoke(this,new Object[] {t}); 071 } catch(NoSuchMethodException ex) { 072 this.detail=t; 073 } catch(IllegalAccessException ex) { 074 ex.printStackTrace(); 075 } catch(InvocationTargetException ex) { 076 ex.printStackTrace(); 077 } 078 } 079 080 boolean supportChainedException() { 081 try { 082 getClass().getMethod("initCause",new Class[] {Throwable.class}); 083 return true; 084 } catch(NoSuchMethodException ex) { 085 return false; 086 } 087 } 088 089 public void printStackTrace(PrintStream out) { 090 super.printStackTrace(out); 091 if((!supportChainedException())&&(detail!=null)) { 092 out.println(CONTAINED_EXCEPTION); 093 detail.printStackTrace(out); 094 } 095 } 096 097 public void printStackTrace(PrintWriter out) { 098 super.printStackTrace(out); 099 if((!supportChainedException())&&(detail!=null)) { 100 out.println(CONTAINED_EXCEPTION); 101 detail.printStackTrace(out); 102 } 103 } 104 105 public void printStackTrace() { 106 printStackTrace(System.err); 107 } 108 109 public String toString() { 110 if(supportChainedException()) { 111 return super.toString(); 112 } else { 113 StringBuffer sb=new StringBuffer(); 114 sb.append(super.toString()); 115 if(detail!=null) { 116 sb.append(' ').append(CONTAINED_EXCEPTION).append(' ').append(detail); 117 } 118 return sb.toString(); 119 } 120 } 121 }