ExceptionWithContext.java revision e8665c7a91f2af56de3124bd351b75dcc81fcf85
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 2007 The Android Open Source Project
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License");
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * you may not use this file except in compliance with the License.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * You may obtain a copy of the License at
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *      http://www.apache.org/licenses/LICENSE-2.0
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Unless required by applicable law or agreed to in writing, software
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * distributed under the License is distributed on an "AS IS" BASIS,
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * See the License for the specific language governing permissions and
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * limitations under the License.
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/*
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * As per the Apache license requirements, this file has been modified
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * from its original state.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Such modifications are Copyright (C) 2010 Ben Gruver, and are released
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * under the original license
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)package org.jf.util;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import java.io.PrintStream;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.io.PrintWriter;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Exception which carries around structured context.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public class ExceptionWithContext
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extends RuntimeException {
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /** non-null; human-oriented context of the exception */
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private StringBuffer context;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Augments the given exception with the given context, and return the
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * result. The result is either the given exception if it was an
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * {@link ExceptionWithContext}, or a newly-constructed exception if it
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * was not.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * @param ex non-null; the exception to augment
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param str non-null; context to add
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @return non-null; an appropriate instance
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public static ExceptionWithContext withContext(Throwable ex, String str, Object... formatArgs) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ExceptionWithContext ewc;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (ex instanceof ExceptionWithContext) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ewc = (ExceptionWithContext) ex;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            ewc = new ExceptionWithContext(ex);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ewc.addContext(String.format(str, formatArgs));
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ewc;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Constructs an instance.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param message human-oriented message
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public ExceptionWithContext(String message, Object... formatArgs) {
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        this(null, message, formatArgs);
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Constructs an instance.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * @param cause null-ok; exception that caused this one
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public ExceptionWithContext(Throwable cause) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this(cause, null);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Constructs an instance.
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param message human-oriented message
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param cause null-ok; exception that caused this one
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public ExceptionWithContext(Throwable cause, String message, Object... formatArgs) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        super((message != null) ? formatMessage(message, formatArgs) :
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (cause != null) ? cause.getMessage() : null,
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              cause);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (cause instanceof ExceptionWithContext) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            String ctx = ((ExceptionWithContext) cause).context.toString();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            context = new StringBuffer(ctx.length() + 200);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            context.append(ctx);
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        } else {
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            context = new StringBuffer(200);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private static String formatMessage(String message, Object... formatArgs) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (message == null) {
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return null;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return String.format(message, formatArgs);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** {@inheritDoc} */
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @Override
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void printStackTrace(PrintStream out) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        super.printStackTrace(out);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        out.println(context);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** {@inheritDoc} */
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @Override
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void printStackTrace(PrintWriter out) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        super.printStackTrace(out);
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        out.println(context);
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Adds a line of context to this instance.
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param str non-null; new context
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public void addContext(String str) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (str == null) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            throw new NullPointerException("str == null");
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        context.append(str);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!str.endsWith("\n")) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            context.append('\n');
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Gets the context.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @return non-null; the context
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public String getContext() {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return context.toString();
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Prints the message and context.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param out non-null; where to print to
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void printContext(PrintStream out) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        out.println(getMessage());
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        out.print(context);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Prints the message and context.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * @param out non-null; where to print to
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void printContext(PrintWriter out) {
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        out.println(getMessage());
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        out.print(context);
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}