All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.enhydra.error.ChainedThrowableSupport Maven / Gradle / Ivy

The newest version!
/*
 * Enhydra Java Application Server Project
 *
 * The contents of this file are subject to the Enhydra Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License on
 * the Enhydra web site ( http://www.enhydra.org/ ).
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific terms governing rights and limitations
 * under the License.
 *
 * The Initial Developer of the Enhydra Application Server is Lutris
 * Technologies, Inc. The Enhydra Application Server and portions created
 * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
 * All Rights Reserved.
 *
 * Contributor(s):
 *
 * $Id: ChainedThrowableSupport.java,v 1.2 2005/01/26 08:29:24 jkjome Exp $
 */

package org.enhydra.error;

import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Static methods used to implement the Chained* throwables.
 */
public final class ChainedThrowableSupport {
    /** Name of SAXException class. */
    private static final String SAX_EXCEPTION_CLASS = "org.xml.sax.SAXException";

    /**
     * Can't makes instances of this class.
     */
    private ChainedThrowableSupport() {
    }

    /**
     * Generate the message to set for the exception message when an explict
     * message is not available.  The message is derived from the causing
     * exception.  Used to support constructor that take only a cause
     * {@link Throwable Throwable} as an argument.  This method is used to
     * generate the message to has to the super constructor.
     *
     * @param cause The causing exception, which maybe null.
     */
    public static String makeMessage(Throwable cause) {
        if (cause == null) {
            return null;
        } else {
            String causeMsg = cause.getMessage();
            if (causeMsg == null) {
                return cause.getClass().getName();
            } else {
                return causeMsg;
            }
        }
    }

    /**
     * Get the message associated with this exception.
     * @param except The chained throwable generating the
     *  message.
     * @param superMsg The result of super.getMessage(), so
     *  that the contained messages is available.  Maybe null.
     */
    public static String getMessage(ChainedThrowable except,
                                    String superMsg) {
        if (superMsg != null) {
            return superMsg;
        }
        Thread thread = Thread.currentThread();
        String threadMsg = " " + thread + " (" + thread.getThreadGroup().getName() + ", " + thread.getName() + ")";
        Throwable cause = except.getCause();
        if (cause == null) {
            return except.getClass().getName() + threadMsg;
        } else {
            String causeMsg = cause.getMessage();
            if ((causeMsg == null) || (causeMsg.length() == 0)) {
                causeMsg = cause.getClass().getName();
            }
            return causeMsg + threadMsg;
        }
    }

    /**
     * Get the localhist message associated with this exception.
     * @param except The chained throwable generating the message.
     * @param superMsg The result of super.getLocalizedMessage(), so
     *  that the contained messages is available.  Maybe null.
     */
    public static String getLocalizedMessage(ChainedThrowable except,
                                             String superMsg) {
        if (superMsg != null) {
            return superMsg;
        }
        Throwable cause = except.getCause();
        if (cause == null) {
            return except.getClass().getName();
        } else {
            String causeMsg = cause.getLocalizedMessage();
            if ((causeMsg == null) || (causeMsg.length() == 0)) {
                causeMsg = cause.getClass().getName();
            }
            return causeMsg;
        }
    }

    /**
     * Check if this is one of the many java.* classes that contained
     * a chained throwable.
     */
    private static Throwable getJavaChain(Throwable cause) {
        if (cause instanceof java.io.WriteAbortedException) {
            return ((java.io.WriteAbortedException)cause).detail;
        } else if (cause instanceof java.lang.ClassNotFoundException) {
            return ((java.lang.ClassNotFoundException)cause).getException();
        } else if (cause instanceof java.lang.ExceptionInInitializerError) {
            return ((java.lang.ExceptionInInitializerError)cause).getException();
        } else if (cause instanceof java.lang.reflect.InvocationTargetException) {
            return ((java.lang.reflect.InvocationTargetException)cause).getTargetException();
        } else if (cause instanceof java.rmi.RemoteException) {
            return ((java.rmi.RemoteException)cause).detail;
        } else if (cause instanceof java.rmi.activation.ActivationException) {
            return ((java.rmi.activation.ActivationException)cause).detail;
        } else if (cause instanceof java.rmi.server.ServerCloneException) {
            return ((java.rmi.server.ServerCloneException)cause).detail;
        } else if (cause instanceof java.security.PrivilegedActionException) {
            return ((java.security.PrivilegedActionException)cause).getException();
        } else if (cause instanceof java.sql.SQLException) {
            return ((java.sql.SQLException)cause).getNextException();
        } else {
            return null;
        }
    }

    /**
     * Obtain a chain cause via an parameterless method accessed through
     * reflection.
     */
    private static Throwable getChainWithAccessor(Throwable cause,
                                                  String accessorName)
            throws NoSuchMethodException, IllegalAccessException,
                   InvocationTargetException {
        Method accessor = cause.getClass().getMethod(accessorName, (Class[])null);
        return (Throwable)accessor.invoke(cause, (Object[])null);
    }

    /**
     * Check for AWT exception with a chain.  These are treated as optional,
     * despite being a java.* class, since a server-only JVM might not
     * include them.
     */
    private static Throwable getAWTChain(Throwable cause)
            throws NoSuchMethodException, IllegalAccessException,
                   InvocationTargetException {
        if (cause.getClass().getName().equals("java.awt.print.PrinterIOException")) {
            return getChainWithAccessor(cause, "getIOException");
        } else {
            return null;
        }
    }

    /**
     * Check if an exception is a SAXException without actually referencing
     * the class.
     */
    private static boolean isSAXException(Throwable except) {
        return except.getClass().getName().equals(SAX_EXCEPTION_CLASS);
    }

    /**
     * Check SAXException chain.
     */
    private static Throwable getSAXExceptionChain(Throwable cause)
            throws NoSuchMethodException, IllegalAccessException,
                   InvocationTargetException {
        if (isSAXException(cause)) {
            return getChainWithAccessor(cause, "getException");
        } else {
            return null;
        }
    }

    /**
     * Do work of printing the causes of a chained exception.  This is
     * recursive. This attempts to following causing exceptions that are
     * chained in other types of exception objects.  If only Sun would
     * standardize a mechanism in throwable.  For classes that are
     * not part of the standard runtime we access them by reflection,
     * as this class if often lower down in the class loader hierarchy.
     */
    private static void printChainedCauses(Throwable cause,
                                           PrintWriter out) {
        if (cause != null) {
            out.println("*** Caused by:");  //FIXME: I18N

            if (isSAXException(cause)) {
                // SAXException `hides' itself when printing the stack by
                // overriding toString() to print the contained exception,
                // we print something extra to keep this from being confusing
                out.print(SAX_EXCEPTION_CLASS);
                out.print(": ");
            }

            cause.printStackTrace(out);
            try {
                // If cause was is a ChainedThrowable, its chain has already
                // been followed, otherwise, see what we can do.
                if (!(cause instanceof ChainedThrowable)) {
                    Throwable nextCause = getJavaChain(cause);
                    if (nextCause == null) {
                        nextCause = getAWTChain(cause);
                    }
                    if (nextCause == null) {
                        nextCause = getSAXExceptionChain(cause);
                    }
                    if (nextCause != null) {
                        printChainedCauses(nextCause, out);
                    }
                }
            } catch (Throwable except) {
                // Can't find one of the chained exceptions
                out.println("WARNING: can't print rest of exception chain: "
                            + except);
            }
        }
    }

    /**
     * Prints stacktrace and cause stacktrace.
     */
    public static void printCauseTrace(ChainedThrowable except) {
        PrintWriter pw = new PrintWriter(System.err);
        printChainedCauses(except.getCause(), pw);
        pw.flush();
    }

    /**
     * Prints stacktrace and cause stacktrace.
     */
    public static void printCauseTrace(ChainedThrowable except,
                                       PrintStream s) {
        PrintWriter pw = new PrintWriter(s);
        printChainedCauses(except.getCause(), pw);
        pw.flush();
    }

    /**
     * Prints stacktrace and cause stacktrace.
     */
    public static void printCauseTrace(ChainedThrowable except,
                                       PrintWriter out) {
        printChainedCauses(except.getCause(), out);
        out.flush();
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy