/******************************************************************************* * Copyright (c) 2007, 2010 The original authors/Contributors listed below. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bruce Eckel - initial code * Bruno Medeiros - modifications *******************************************************************************/ package melnorme.utilbox.core; import static melnorme.utilbox.core.Assert.AssertNamespace.assertFail; import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; import java.io.IOException; /** * Exception adapter to make checked exceptions less annoying. * Based on Bruce Eckel's article: * http://www.mindview.net/Etc/Discussions/CheckedExceptions */ @SuppressWarnings("serial") public class ExceptionAdapter extends RuntimeException { // Number of frames that originalException traveled while checked protected int checkedLength; protected ExceptionAdapter(Exception e) { super(e); assertNotNull(e); // Determine checkedLength based on the difference to this stack trace StackTraceElement[] est = e.getStackTrace(); checkedLength = est.length - getStackTrace().length; StackTraceElement ste = getStackTrace()[0]; String firstMethod = ste.getClassName() +"."+ ste.getMethodName(); // Adjust checkedLength if EA was created in method unchecked if(firstMethod.endsWith("ExceptionAdapter.unchecked")) { checkedLength++; } } protected void printStackTraceAppendable(Appendable pr) { synchronized(pr) { try { pr.append(this.toString()); StackTraceElement[] trace = getCause().getStackTrace(); for (int i=0; i < trace.length; i++) { pr.append("\tat " + trace[i]); if(i == checkedLength) { pr.append(" [UNCHECKED]"); } pr.append("\n"); } } catch (IOException e) { assertFail(); } } } @Override public void printStackTrace(java.io.PrintStream ps) { printStackTraceAppendable(ps); } @Override public void printStackTrace(java.io.PrintWriter pw) { printStackTraceAppendable(pw); } @Override public Exception getCause() { return (Exception) super.getCause(); } public void rethrow() throws Exception { throw getCause(); } @Override public String toString() { String className = getClass().getSimpleName(); return "["+className+"] " + getLocalizedMessage() + "\n"; } /** Creates an unchecked Throwable, if not unchecked already. */ public static final RuntimeException unchecked(Throwable e) { if(e instanceof RuntimeException) { throw (RuntimeException) e; } else if(e instanceof Exception) { throw new ExceptionAdapter((Exception) e); } else if(e instanceof Error) { throw (Error) e; } else { assertFail("uncheck: Unsupported Throwable: " + e); return null; } } /** Same as {@link #unchecked(Throwable)} but used during development for temporary code only. * Uses the Deprecated annotation to cause a warning in IDEs, to warn that code should be reviewed. */ @Deprecated public static RuntimeException uncheckedTODO(Throwable e) { return unchecked(e); } }