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 17package com.android.dexgen.util; 18 19import java.io.PrintStream; 20import java.io.PrintWriter; 21 22/** 23 * Exception which carries around structured context. 24 */ 25public class ExceptionWithContext 26 extends RuntimeException { 27 /** {@code non-null;} human-oriented context of the exception */ 28 private StringBuffer context; 29 30 /** 31 * Augments the given exception with the given context, and return the 32 * result. The result is either the given exception if it was an 33 * {@link ExceptionWithContext}, or a newly-constructed exception if it 34 * was not. 35 * 36 * @param ex {@code non-null;} the exception to augment 37 * @param str {@code non-null;} context to add 38 * @return {@code non-null;} an appropriate instance 39 */ 40 public static ExceptionWithContext withContext(Throwable ex, String str) { 41 ExceptionWithContext ewc; 42 43 if (ex instanceof ExceptionWithContext) { 44 ewc = (ExceptionWithContext) ex; 45 } else { 46 ewc = new ExceptionWithContext(ex); 47 } 48 49 ewc.addContext(str); 50 return ewc; 51 } 52 53 /** 54 * Constructs an instance. 55 * 56 * @param message human-oriented message 57 */ 58 public ExceptionWithContext(String message) { 59 this(message, null); 60 } 61 62 /** 63 * Constructs an instance. 64 * 65 * @param cause {@code null-ok;} exception that caused this one 66 */ 67 public ExceptionWithContext(Throwable cause) { 68 this(null, cause); 69 } 70 71 /** 72 * Constructs an instance. 73 * 74 * @param message human-oriented message 75 * @param cause {@code null-ok;} exception that caused this one 76 */ 77 public ExceptionWithContext(String message, Throwable cause) { 78 super((message != null) ? message : 79 (cause != null) ? cause.getMessage() : null, 80 cause); 81 82 if (cause instanceof ExceptionWithContext) { 83 String ctx = ((ExceptionWithContext) cause).context.toString(); 84 context = new StringBuffer(ctx.length() + 200); 85 context.append(ctx); 86 } else { 87 context = new StringBuffer(200); 88 } 89 } 90 91 /** {@inheritDoc} */ 92 @Override 93 public void printStackTrace(PrintStream out) { 94 super.printStackTrace(out); 95 out.println(context); 96 } 97 98 /** {@inheritDoc} */ 99 @Override 100 public void printStackTrace(PrintWriter out) { 101 super.printStackTrace(out); 102 out.println(context); 103 } 104 105 /** 106 * Adds a line of context to this instance. 107 * 108 * @param str {@code non-null;} new context 109 */ 110 public void addContext(String str) { 111 if (str == null) { 112 throw new NullPointerException("str == null"); 113 } 114 115 context.append(str); 116 if (!str.endsWith("\n")) { 117 context.append('\n'); 118 } 119 } 120 121 /** 122 * Gets the context. 123 * 124 * @return {@code non-null;} the context 125 */ 126 public String getContext() { 127 return context.toString(); 128 } 129 130 /** 131 * Prints the message and context. 132 * 133 * @param out {@code non-null;} where to print to 134 */ 135 public void printContext(PrintStream out) { 136 out.println(getMessage()); 137 out.print(context); 138 } 139 140 /** 141 * Prints the message and context. 142 * 143 * @param out {@code non-null;} where to print to 144 */ 145 public void printContext(PrintWriter out) { 146 out.println(getMessage()); 147 out.print(context); 148 } 149} 150