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

at.spardat.enterprise.exc.StackTrace Maven / Gradle / Ivy

There is a newer version: 6.0.2
Show newest version
/*******************************************************************************
 * Copyright (c) 2003, 2007 s IT Solutions AT Spardat GmbH .
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     s IT Solutions AT Spardat GmbH - initial API and implementation
 *******************************************************************************/

// @(#) $Id: StackTrace.java 2093 2007-11-28 14:23:36Z s3460 $
package at.spardat.enterprise.exc;

import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.StringTokenizer;

/**
 * This class provides methods that print stack traces as JDK1.4 does, i.e.,
 * with a collapsed stack. 
 * 
 * @author YSD, 22.05.2003 22:19:08
 */
class StackTrace implements java.io.Serializable {
    
    /**
     * The frame lines of the stack trace. Is null, if the exception is not
     * understood.
     */
    private String []               lines_;
    
    /**
     * The first number of lines which does not comprise the stack frame information
     */
    private int                     numHeaderLines_;
    
    /**
     * Indicates if this stack allows collapsing
     */
    private boolean                 isWellFormed_;
    
    /**
     * Increase this if u make non compatible changes
     */
    private static final long       serialVersionUID = 1L;
    
    
    

    /**
     * Extracts the stacktrace from ex.
     */
    public StackTrace (Throwable ex) {
        this (getStackTraceLines(ex));
    }

    /**
     * Constructs and checks if the provided stack trace lines are well formed.
     * If this succeeds, {@link #isWellFormed} will return true and other
     * methods may be called.
     */
    public StackTrace (String [] lines) {
        lines_ = new String[lines.length];
        System.arraycopy(lines, 0, lines_, 0, lines.length);
        analyze();
    }
    
    
    /**
     * Prints the stacktrace of Throwable toPrint in a way as JDK1.4 does, i.e.,
     * omitting outer frames that are in common with an enclosing exception. 
     */
    public void printStackTrace (PrintWriter s, StackTrace enclosing) {
        if (enclosing != null) {
            if (isWellFormed() && enclosing.isWellFormed()) {
                // both are well formed so that we can do the smart print
                String [] lines = getDifferentLines (enclosing);
                for (int i=0; itoPrint in a way as JDK1.4 does, i.e.,
     * omitting outer frames that are in common with an enclosing exception. 
     */
    public void printStackTrace (PrintStream s, StackTrace enclosing) {
        if (enclosing != null) {
            if (isWellFormed() && enclosing.isWellFormed()) {
                // both are well formed so that we can do the smart print
                String [] lines = getDifferentLines (enclosing);
                for (int i=0; iwellFormed(). Returns the stack frames
     * that should be printed with respect to the provided enclosing exception
     * so that no stack frames are in common. 
     * 
     * @param enclosing StackFrames of the enclosing exception.
     */
    private String [] getDifferentLines (StackTrace enclosing) {
        if (!isWellFormed()) throw new IllegalStateException();
        
        /**
         * enclosing is not well formed, so return all lines of this
         */
        if (enclosing == null || !enclosing.isWellFormed()) return lines_;
        
        /**
         * enclosing is well formed; return the lines of this but
         * strip the tailing lines this has in common with enclosing. 
         */
        int         inCommon = 0;
        for (int i=lines_.length-1, j=enclosing.lines_.length-1; i >= 0 && j >= 0; i--, j--) {
            if (lines_[i].equals(enclosing.lines_[j])) inCommon++;
            else break;
        }
        if (inCommon == 0) return lines_;
        else {
            int         different = lines_.length-inCommon;
            String [] lines = new String[different+1];
            System.arraycopy(lines_, 0, lines, 0, different);
            lines[different] = "\t... " + inCommon + " more";
            return lines;
        }
    }
    
    /**
     * Analyzes the lines and sets wellFormed to be true if the stack consists
     * of at a block of consecutive header lines followed by a block of
     * consecutive stack frame lines. Both blocks must consist of at least
     * one line.
     */
    private void analyze () {
        boolean         inStackFrameLineSection = true;
        isWellFormed_ = true;
        numHeaderLines_ = 0;
        for (int i=lines_.length-1; i>=0; i--) {
            String line = lines_[i];
            if (inStackFrameLineSection) {
                if (!isStackFrameLine(line)) {
                    // the first line bottom up which is not a frame line
                    inStackFrameLineSection = false;
                    numHeaderLines_ = i+1;
                }
            } else {
                if (isStackFrameLine(line)) {
                    isWellFormed_ = false; break;
                }
            }
        }
        if (isWellFormed_) {
            if (numHeaderLines_ <= 0 || numHeaderLines_ >= lines_.length) {
                isWellFormed_ = false;
            }
        }
    }
    
    /**
     * Returns true if the stack trace of the provided exception is
     * well formed so that stack frames may be collapsed.
     */
    public boolean isWellFormed () {
        return isWellFormed_;
    }
    
    /**
     * Returns the header lines. Must only be called if isWellFormed.
     */
    public String [] getHeaderLines () {
        if (!isWellFormed_) throw new IllegalStateException();
        String [] result = new String[numHeaderLines_];
        System.arraycopy(lines_, 0, result, 0, numHeaderLines_);
        return result;
    }
    
    /**
     * Replaces the header lines with new ones. Must only be called if isWellFormed. 

* * This method may result in this being not well formed after this call if * the new header lines are badly formed. * * @param newHeader the new header lines. Array of minimum length 1. */ public void replaceHeaderLines (String [] newHeader) { if (!isWellFormed_) throw new IllegalStateException(); if (newHeader.length == 0) throw new IllegalArgumentException(); String [] newLines = new String[lines_.length - numHeaderLines_ + newHeader.length]; System.arraycopy(newHeader, 0, newLines, 0, newHeader.length); System.arraycopy(lines_, numHeaderLines_, newLines, newHeader.length, lines_.length-numHeaderLines_); lines_ = newLines; analyze(); } /** * Calls printStackTrace on ex and returns the result * as String. */ public static String getStackTraceAsString (Throwable ex) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); ex.printStackTrace(pw); pw.close(); return sw.toString(); } /** * Expects a string, splits the lines * and returns an String[] with one entry per line. */ public static String [] splitLines (String stackTraceString) { /** * parse the string */ StringTokenizer tokizer = new StringTokenizer (stackTraceString, System.getProperty("line.separator")); int lineCount = 0; ArrayList lines = new ArrayList(); while (tokizer.hasMoreTokens()) { String line = tokizer.nextToken(); lines.add(line); lineCount++; } String [] linesArray = new String[lines.size()]; lines.toArray(linesArray); return linesArray; } /** * Calls printStackTrace on ex, splits the lines * and returns them. */ public static String [] getStackTraceLines (Throwable ex) { return splitLines(getStackTraceAsString(ex)); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy