Return to Snippet

Revision: 57442
at May 26, 2012 07:47 by dwijnand


Initial Code
/** Identifies throwables by creating a checksum (using a message digest, such as MD5 or SHA1) of its stack trace. */
public final class ThrowableIdentifier {
    private static final Logger LOGGER = Logger.getLogger(ThrowableIdentifier.class.getName());

    private ThrowableIdentifier() { /* Utility class */}

    /**
     * Returns the checksum of the specified throwable, using a specific message digest, which is reset at the end. The returned
     * byte array can be converted into a string by using {@link Strings#toHexString(byte[])}.
     */
    public static byte[] getChecksum(final Throwable throwable, final MessageDigest messageDigest) throws IOException {
        return getChecksum(newStackTraceBytesStream(throwable), messageDigest);
    }

    /**
     * Returns the checksum of the specified input stream, using a specific message digest, which is reset at the end. The
     * returned byte array can be converted into a string by using {@link Strings#toHexString(byte[])}.
     */
    public static byte[] getChecksum(final InputStream in, final MessageDigest messageDigest) throws IOException {
        try {
            final byte[] buffer = new byte[0x1000];
            for (int count = in.read(buffer); count != -1; count = in.read(buffer))
                messageDigest.update(buffer, 0, count);
            return messageDigest.digest();
        } finally {
            messageDigest.reset();
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    LOGGER.log(Level.WARNING, "IOException thrown while closing InputStream", e);
                }
            }
        }
    }

    /** Returns the hexadecimal string form of the specified byte array. */
    public static String toHexString(final byte... bytes) {
        final StringBuilder builder = new StringBuilder(2 * bytes.length);
        for (final byte b : bytes)
            builder.append(padStart(Integer.toHexString(0xff & b), 2, '0'));
        return builder.toString();
    }

    /** Returns the specified string, if necessary padded with the specified character until the desired length is reached. */
    public static String padStart(String s, final int length, final char c) {
        if (s.length() < length) {
            final StringBuilder sb = new StringBuilder(length);
            for (int i = s.length(); i < length; i++) {
                sb.append(c);
            }
            s = sb.append(s).toString();
        }
        return s;
    }

    /** Returns an input stream of the specified throwable's stack trace. */
    public static InputStream newStackTraceBytesStream(final Throwable throwable) {
        return new ByteArrayInputStream(getStackTrace(throwable).getBytes(Charset.forName("UTF-8")));
    }

    /** Returns the specified throwable's stack trace. */
    public static String getStackTrace(final Throwable throwable) {
        final StringWriter stringWriter = new StringWriter();
        final PrintWriter printWriter = new PrintWriter(stringWriter);
        try {
            throwable.printStackTrace(printWriter);
        } finally {
            printWriter.close();
        }
        return stringWriter.toString();
    }
}

Initial URL


Initial Description
A useful utility class to identify Throwables by creating a checksum (using a message digest, such as MD5 or SHA1) of its stack trace

Initial Title
Throwable Identifier

Initial Tags
java

Initial Language
Java