1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* ident "%Z%%M% %I% %E% SMI" */ 28 29 package com.sun.solaris.service.exception; 30 31 import java.io.*; 32 33 /** 34 * Formats a stack trace in a single line. The format is meant to 35 * convey the stack trace as a sequence of class names and line numbers, 36 * with the topmost frame first, suitable for logging. Beware, the 37 * format may evolve. 38 */ 39 public class SuccinctStackTraceFormatter { 40 /** 41 * Formats a Throwable and adds an optional description string. 42 * The string should be suitable to precede the top stack 43 * element, and include any punctuation that should 44 * differentiate it from the element. 45 */ formatWithDescription(Throwable t, String description)46 public static String formatWithDescription(Throwable t, 47 String description) 48 { 49 StringBuffer s = new StringBuffer(); 50 51 s.append("("); 52 53 if (description != null) 54 s.append(description); 55 56 s.append(t.getClass().getName()); 57 s.append(", "); 58 StackTraceElement[] trace = t.getStackTrace(); 59 for (int i = 0; i < trace.length; i++) { 60 appendStackTraceElement(i > 0 ? trace[i - 1] : null, 61 trace[i], s); 62 if (i != trace.length - 1) 63 s.append(", "); 64 } 65 s.append(")"); 66 67 if (t.getCause() != null) { 68 s.append(" caused by "); 69 s.append(format(t.getCause())); 70 } 71 72 return (s.toString()); 73 } 74 75 /** 76 * Formats a Throwable's stack trace. The format is meant to be 77 * a single line of output, conveying the stack trace as a 78 * sequence of class names and line numbers, with the topmost 79 * frame first, suitable for logging. If two adjacent stack 80 * trace elements share some portion of a class name, the 81 * bottommost element may have the common part replaced with an 82 * ampersand. 83 */ format(Throwable t)84 public static String format(Throwable t) 85 { 86 return (formatWithDescription(t, null)); 87 } 88 89 /** 90 * Formats a stack trace element as per <code>format()</code>. 91 */ appendStackTraceElement(StackTraceElement last, StackTraceElement e, StringBuffer s)92 private static void appendStackTraceElement(StackTraceElement last, 93 StackTraceElement e, StringBuffer s) 94 { 95 /* 96 * This could grab more of a common class name. (See 97 * SuccinctStackTraceFormatter.format()) 98 */ 99 if (last == null || !last.getClassName().equals( 100 e.getClassName())) { 101 s.append(e.getClassName()); 102 s.append("."); 103 } else 104 s.append("&."); 105 106 s.append(e.getMethodName()); 107 if (e.getLineNumber() > 0) { 108 s.append(":"); 109 s.append(e.getLineNumber()); 110 } 111 if (e.isNativeMethod()) { 112 s.append(":"); 113 s.append("native"); 114 } 115 } 116 printStackTrace(Throwable t)117 public static void printStackTrace(Throwable t) 118 { 119 printStackTrace(t, System.err); 120 } 121 printStackTrace(Throwable t, PrintStream out)122 public static void printStackTrace(Throwable t, PrintStream out) 123 { 124 out.print(t); 125 out.print(" at "); 126 out.print(format(t)); 127 } 128 main(String args[])129 public static final void main(String args[]) 130 { 131 SuccinctStackTraceFormatter.printStackTrace(big()); 132 } 133 big()134 public static final Throwable big() { 135 return new Throwable().initCause(little()); 136 } 137 little()138 public static final Throwable little() { 139 return new Throwable(); 140 } 141 142 } 143