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 package com.android.dexgen.util;
18 
19 import java.io.PrintStream;
20 import java.io.PrintWriter;
21 
22 /**
23  * Exception which carries around structured context.
24  */
25 public 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      */
withContext(Throwable ex, String str)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      */
ExceptionWithContext(String message)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      */
ExceptionWithContext(Throwable cause)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      */
ExceptionWithContext(String message, Throwable cause)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
printStackTrace(PrintStream out)93     public void printStackTrace(PrintStream out) {
94         super.printStackTrace(out);
95         out.println(context);
96     }
97 
98     /** {@inheritDoc} */
99     @Override
printStackTrace(PrintWriter out)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      */
addContext(String str)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      */
getContext()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      */
printContext(PrintStream out)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      */
printContext(PrintWriter out)145     public void printContext(PrintWriter out) {
146         out.println(getMessage());
147         out.print(context);
148     }
149 }
150