1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /* 18 * As per the Apache license requirements, this file has been modified 19 * from its original state. 20 * 21 * Such modifications are Copyright (C) 2010 Ben Gruver, and are released 22 * under the original license 23 */ 24 25 package org.jf.util; 26 27 import java.io.PrintStream; 28 import java.io.PrintWriter; 29 30 /** 31 * Exception which carries around structured context. 32 */ 33 public class ExceptionWithContext 34 extends RuntimeException { 35 /** non-null; human-oriented context of the exception */ 36 private StringBuffer context; 37 38 /** 39 * Augments the given exception with the given context, and return the 40 * result. The result is either the given exception if it was an 41 * {@link ExceptionWithContext}, or a newly-constructed exception if it 42 * was not. 43 * 44 * @param ex non-null; the exception to augment 45 * @param str non-null; context to add 46 * @return non-null; an appropriate instance 47 */ withContext(Throwable ex, String str, Object... formatArgs)48 public static ExceptionWithContext withContext(Throwable ex, String str, Object... formatArgs) { 49 ExceptionWithContext ewc; 50 51 if (ex instanceof ExceptionWithContext) { 52 ewc = (ExceptionWithContext) ex; 53 } else { 54 ewc = new ExceptionWithContext(ex); 55 } 56 57 ewc.addContext(String.format(str, formatArgs)); 58 return ewc; 59 } 60 61 /** 62 * Constructs an instance. 63 * 64 * @param message human-oriented message 65 */ ExceptionWithContext(String message, Object... formatArgs)66 public ExceptionWithContext(String message, Object... formatArgs) { 67 this(null, message, formatArgs); 68 } 69 70 /** 71 * Constructs an instance. 72 * 73 * @param cause null-ok; exception that caused this one 74 */ ExceptionWithContext(Throwable cause)75 public ExceptionWithContext(Throwable cause) { 76 this(cause, null); 77 } 78 79 /** 80 * Constructs an instance. 81 * 82 * @param message human-oriented message 83 * @param cause null-ok; exception that caused this one 84 */ ExceptionWithContext(Throwable cause, String message, Object... formatArgs)85 public ExceptionWithContext(Throwable cause, String message, Object... formatArgs) { 86 super((message != null) ? formatMessage(message, formatArgs) : 87 (cause != null) ? cause.getMessage() : null, 88 cause); 89 90 if (cause instanceof ExceptionWithContext) { 91 String ctx = ((ExceptionWithContext) cause).context.toString(); 92 context = new StringBuffer(ctx.length() + 200); 93 context.append(ctx); 94 } else { 95 context = new StringBuffer(200); 96 } 97 } 98 formatMessage(String message, Object... formatArgs)99 private static String formatMessage(String message, Object... formatArgs) { 100 if (message == null) { 101 return null; 102 } 103 return String.format(message, formatArgs); 104 } 105 106 /** {@inheritDoc} */ 107 @Override printStackTrace(PrintStream out)108 public void printStackTrace(PrintStream out) { 109 super.printStackTrace(out); 110 out.println(context); 111 } 112 113 /** {@inheritDoc} */ 114 @Override printStackTrace(PrintWriter out)115 public void printStackTrace(PrintWriter out) { 116 super.printStackTrace(out); 117 out.println(context); 118 } 119 120 /** 121 * Adds a line of context to this instance. 122 * 123 * @param str non-null; new context 124 */ addContext(String str)125 public void addContext(String str) { 126 if (str == null) { 127 throw new NullPointerException("str == null"); 128 } 129 130 context.append(str); 131 if (!str.endsWith("\n")) { 132 context.append('\n'); 133 } 134 } 135 136 /** 137 * Gets the context. 138 * 139 * @return non-null; the context 140 */ getContext()141 public String getContext() { 142 return context.toString(); 143 } 144 145 /** 146 * Prints the message and context. 147 * 148 * @param out non-null; where to print to 149 */ printContext(PrintStream out)150 public void printContext(PrintStream out) { 151 out.println(getMessage()); 152 out.print(context); 153 } 154 155 /** 156 * Prints the message and context. 157 * 158 * @param out non-null; where to print to 159 */ printContext(PrintWriter out)160 public void printContext(PrintWriter out) { 161 out.println(getMessage()); 162 out.print(context); 163 } 164 }