001package com.hfg.util;
002
003
004
005import com.hfg.util.collection.CollectionUtil;
006
007import java.util.List;
008
009//------------------------------------------------------------------------------
010/**
011 Utility functions for manipulating StackTrace information.
012 
013 * @author J. Alex Taylor, hairyfatguy.com
014 */
015//------------------------------------------------------------------------------
016// com.hfg XML/HTML Coding Library
017//
018// This library is free software; you can redistribute it and/or
019// modify it under the terms of the GNU Lesser General Public
020// License as published by the Free Software Foundation; either
021// version 2.1 of the License, or (at your option) any later version.
022//
023// This library is distributed in the hope that it will be useful,
024// but WITHOUT ANY WARRANTY; without even the implied warranty of
025// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
026// Lesser General Public License for more details.
027//
028// You should have received a copy of the GNU Lesser General Public
029// License along with this library; if not, write to the Free Software
030// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
031//
032// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
033// jataylor@hairyfatguy.com
034//------------------------------------------------------------------------------
035
036public class StackTraceUtil
037{
038   //##########################################################################
039   // PUBLIC FUNCTIONS
040   //##########################################################################
041
042   //--------------------------------------------------------------------------
043   public static String getCurrentMethodName()
044   {
045      StackTraceElement e[] = Thread.currentThread().getStackTrace();
046      return e[2].getMethodName();
047   }
048
049   //--------------------------------------------------------------------------
050   public static String getCallingMethodName()
051   {
052      StackTraceElement e[] = Thread.currentThread().getStackTrace();
053      return e[3].getMethodName();
054   }
055
056   //--------------------------------------------------------------------------
057   public static String getCurrentClassName()
058   {
059      StackTraceElement e[] = Thread.currentThread().getStackTrace();
060      return e[2].getClassName();
061   }
062
063   //--------------------------------------------------------------------------
064   public static String getCallingClassName()
065   {
066      StackTraceElement e[] = Thread.currentThread().getStackTrace();
067      return e[3].getClassName();
068   }
069
070   //--------------------------------------------------------------------------
071   public static int getCurrentLineNumber()
072   {
073      StackTraceElement e[] = Thread.currentThread().getStackTrace();
074      return e[2].getLineNumber();
075   }
076
077   //--------------------------------------------------------------------------
078   public static StackTraceElement getCallingStackTraceElement(List<StackTraceElementFilter> inExclusions)
079   {
080      StackTraceElement caller = null;
081
082      StackTraceElement e[] = Thread.currentThread().getStackTrace();
083      // TODO: Is using Throwable faster?
084//      StackTraceElement e[] = new Throwable().getStackTrace();
085      if (CollectionUtil.hasValues(inExclusions))
086      {
087         for (int i = 3; i < e.length; i++)
088         {
089            StackTraceElement element = e[i];
090
091            boolean skip = false;
092            for (StackTraceElementFilter exclusionFilter : inExclusions)
093            {
094               if (exclusionFilter.accept(element))
095               {
096                  skip = true;
097                  break;
098               }
099            }
100
101            if (! skip)
102            {
103               caller = element;
104               break;
105            }
106         }
107      }
108      else
109      {
110         caller = e[3];
111//         caller = e[2];  // for Throwable version
112      }
113
114      return caller;
115   }
116
117   //--------------------------------------------------------------------------
118   /**
119    Returns the root exception from an exception.
120    * @param inException the exception from which to find the root exception
121    * @return Throwable the root exception
122    */
123   public static Throwable getRootException(Throwable inException)
124   {
125      Throwable rootException = inException;
126      while (rootException.getCause() != null)
127      {
128         rootException = rootException.getCause();
129      }
130
131      return rootException;
132   }
133
134   //--------------------------------------------------------------------------
135   /**
136    Returns a stack trace formatted similarly to the one produced by e.printStackTrace().
137    * @param inException the exception from which to get the stack trace
138    * @return String version of the stack trace
139    */
140   public static String getExceptionStackTrace(Throwable inException)
141   {
142
143      StringBuilderPlus buffer = new StringBuilderPlus().setDelimiter(System.getProperty("line.separator"));
144
145
146      Throwable e = inException;
147      while (e != null)
148      {
149         StackTraceElement[] stackTrace = e.getStackTrace();
150
151         if (e != inException)
152         {
153            buffer.delimitedAppend("Caused by: ");
154         }
155
156         buffer.append(e.getClass().getName() + ": ");
157
158         if (e.getMessage() != null)
159         {
160            buffer.append(e.getMessage());
161         }
162
163         for (StackTraceElement element : stackTrace)
164         {
165            buffer.delimitedAppend("\tat ");
166            buffer.append(element.toString());
167         }
168
169         e = e.getCause();
170      }
171
172      return buffer.toString();
173   }
174}