package org.hyperic.util;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class MultiRuntimeException extends RuntimeException {
private static final long serialVersionUID = -7173670617853595611L;
private static final String NESTED_EXCEPTION_MSG_PREFIX = "--- Next Exception ---" ;
private static final String CONTEXT_PREFIX = "[Context]: " ;
private final List<ExceptionWrapper> nestedExceptions;
public MultiRuntimeException() {
super() ;
this.nestedExceptions = new ArrayList<ExceptionWrapper>();
}//EOM
public MultiRuntimeException(final Throwable t) {
this() ;
this.addThrowable(t) ;
}//EOM
public MultiRuntimeException(final String message, final Throwable t) {
super(message);
this.nestedExceptions = new ArrayList<ExceptionWrapper>();
this.addThrowable(t) ;
}//EOM
public final MultiRuntimeException addThrowable(Throwable t) {
return this.addThrowable(t, null) ;
}//EOM
public final MultiRuntimeException addThrowable(Throwable t, final String message) {
this.nestedExceptions.add(new ExceptionWrapper(t, message));
return this;
}//EOM
public final boolean isEmpty() {
return (this.nestedExceptions == null || nestedExceptions.isEmpty()) ;
}//EOM
public final int size() { return (this.isEmpty() ? 0 : this.nestedExceptions.size()) ; }//EOM
public String getMessage() {
final String msg = super.getMessage() ;
final String origMsg = (msg == null ? "" : msg) + "\n";
final StringBuilder builder = new StringBuilder(origMsg).append(this.nestedExceptions.size()).append(" Exception(s) have occured:\n");
return builder.toString() ;
}//EOM
public String getCompleteMessage(final MessageType enumMessageType) {
final StringBuilder builder = new StringBuilder() ;
enumMessageType.appendMessage(this, builder) ;
final int iLength = this.nestedExceptions.size() ;
for(int i=0; i < iLength; i++) {
this.getMessage(enumMessageType, this.nestedExceptions.get(i), builder);
if(i < iLength-1) builder.append("\n--- Next Exception ---\n") ;
}//EO while there are more exceptions
return builder.toString();
}//EOM
public String toCompleteString() {
return this.getCompleteMessage(ToString) ;
}//EOM
private final StringBuilder getMessage(final MessageType enumMessageType, final ExceptionWrapper wrapper, final StringBuilder builder) {
final Throwable exception = wrapper.t ;
if(wrapper.message != null) builder.append(CONTEXT_PREFIX).append(wrapper.message).append("\n") ;
if ((exception instanceof SQLException)) {
SQLException sqle = (SQLException)exception;
Throwable t = null;
do {
t = sqle;
enumMessageType.appendMessage(t, builder) ;
if(((sqle = sqle.getNextException()) != null) && (sqle != t)) builder.append("\n---Next SQL Exception---\n") ;
else break ;
}while (true);
}else {
enumMessageType.appendMessage(exception, builder) ;
}//EO else if new SQLException
return builder ;
}//EOM
public final void printStackTrace(final PrintStream ps) {
this.printStackTrace(ps, StreamHandlerInterface.printStreamStrategy) ;
}//EOM
public final void printSelfStacktrace(final PrintStream ps) { super.printStackTrace(ps) ; }//EOM
public final void printSelfStacktrace(final PrintWriter pw) { super.printStackTrace(pw) ; }//EOM
private final <T> void printStackTrace(final T visitor, StreamHandlerInterface<T> strategy) {
synchronized (visitor) {
strategy.printParentStackTrace(visitor, this) ;
Throwable exception = null ;
for (ExceptionWrapper wrapper : this.nestedExceptions) {
strategy.println(visitor, NESTED_EXCEPTION_MSG_PREFIX) ;
if(wrapper.message != null) strategy.println(visitor, CONTEXT_PREFIX + wrapper.message) ;
exception = wrapper.t ;
if ((exception instanceof SQLException)){
SQLException sqle = (SQLException)exception;
Throwable t = null;
do {
t = sqle;
strategy.printStackTrace(visitor, t) ;
}while (((sqle = sqle.getNextException()) != null) && (sqle != t));
} else {
strategy.printStackTrace(visitor, exception) ;
}//EO else if not sqlexception
}//EO while there are more nested exceptions
}//EO sync block
}//EOM
public final void printStackTrace(final PrintWriter pw) {
this.printStackTrace(pw, StreamHandlerInterface.printWriterStrategy) ;
}//EOM
public static final MultiRuntimeException newMultiRuntimeException(MultiRuntimeException multiException, final Throwable t) {
return newMultiRuntimeException(multiException, t, null/*message*/) ;
}//EOM
public static final MultiRuntimeException newMultiRuntimeException(MultiRuntimeException multiException, final Throwable t, final String nestedExcpetionMessage) {
if (multiException == null) {
if ((t instanceof MultiRuntimeException)) multiException = (MultiRuntimeException)t; else
multiException = new MultiRuntimeException(t);
}else multiException.addThrowable(t, nestedExcpetionMessage);
return multiException;
}//EOM
private static interface StreamHandlerInterface<T> {
StreamHandlerInterface<PrintStream> printStreamStrategy = new PrintStreamHandler() ;
StreamHandlerInterface<PrintWriter> printWriterStrategy = new PrintWriterHandler() ;
void printParentStackTrace(final T visitor, final MultiRuntimeException mre) ;
void println(final T visitor, final String line) ;
void print(final T visitor, final String line) ;
void printStackTrace(final T visitor, final Throwable throwable) ;
}//EOI StreamHandlerInterface
private static final class PrintStreamHandler implements StreamHandlerInterface<PrintStream> {
public final void println(final PrintStream visitor, final String line) {
visitor.println(line) ;
}//EOM
public final void print(final PrintStream visitor, final String line) {
visitor.print(line) ;
}//EOM
public final void printStackTrace(final PrintStream visitor, final Throwable throwable) {
throwable.printStackTrace(visitor) ;
}//EOM
public final void printParentStackTrace(final PrintStream visitor, final MultiRuntimeException mre) {
mre.printSelfStacktrace(visitor) ;
}//EOM
}//EO inner class
private static final class PrintWriterHandler implements StreamHandlerInterface<PrintWriter> {
public final void println(final PrintWriter visitor, final String line) {
visitor.println(line) ;
}//EOM
public final void print(final PrintWriter visitor, final String line) {
visitor.print(line) ;
}//EOM
public final void printStackTrace(final PrintWriter visitor, final Throwable throwable) {
throwable.printStackTrace(visitor) ;
}//EOM
public final void printParentStackTrace(final PrintWriter visitor, final MultiRuntimeException mre) {
mre.printSelfStacktrace(visitor) ;
}//EOM
}//EO inner class PrintWriterHandler
private interface MessageType {
StringBuilder appendMessage(final Throwable t, final StringBuilder messageBuilder) ;
}//EO inner interface MessageType
final MessageType ToString = new MessageType(){
public final StringBuilder appendMessage(final Throwable t, final StringBuilder messageBuilder) {
return messageBuilder.append((t instanceof MultiRuntimeException ?
MultiRuntimeException.super.toString() :
t.toString())) ;
}//EOM
};//EO inner class ToString
static final MessageType getMessage = new MessageType(){
public final StringBuilder appendMessage(final Throwable t, final StringBuilder messageBuilder) {
return messageBuilder.append(t.getMessage()) ;
}//EOM
};//EO inner class getMessage
private static final class ExceptionWrapper {
private Throwable t;
private String message ;
public ExceptionWrapper(final Throwable t, final String message) {
this.t = t ;
this.message = message ;
}//EOM
}//EO inner class ExceptionWrapper
/*public static void main(String[] args) throws Throwable {
final StringWriter sw = new StringWriter() ;
final PrintWriter writer = new PrintWriter(sw) ;
try{
test1() ;
}catch(Throwable t) {
System.out.println("--------------------------------------------------------------------");
System.out.println("toString");
System.out.println("--------------------------------------------------------------------");
System.out.println(((MultiRuntimeException)t).toString());
System.out.println("--------------------------------------------------------------------");
System.out.println("toCompleteString");
System.out.println("--------------------------------------------------------------------");
System.out.println(((MultiRuntimeException)t).toCompleteString());
System.out.println("--------------------------------------------------------------------");
System.out.println("getMessage");
System.out.println("--------------------------------------------------------------------");
System.out.println(((MultiRuntimeException)t).getCompleteMessage(getMessage));
System.out.println("--------------------------------------------------------------------");
System.out.println("printStackTrace");
System.out.println("--------------------------------------------------------------------");
t.printStackTrace(writer) ;
System.out.println(sw.toString());
Thread.currentThread().sleep(300) ;
t.printStackTrace() ;
}//EO catch block
}//EOM
static void test1() { test2() ; }//EOM
static void test2() { test3() ; }//EOM
static void test3() { test4() ; }//EOM
static void test4() {
final Exception exception = new Exception("this is the exception") ;
MultiRuntimeException mre = MultiRuntimeException.newMultiRuntimeException(null, exception) ;
final SQLException sqle = new SQLException("second") ;
sqle.setNextException(new SQLException("second-nested"));
mre.addThrowable(sqle) ;
mre.addThrowable(new IllegalStateException("third"), "this is the message 3") ;
mre.addThrowable(new EncryptionOperationNotPossibleException("fourth"), "this is the message 4") ;
throw mre ;
}//EOM
*/
}//EOC