KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jivesoftware > util > log > util > StackIntrospector


1 /*
2  * Copyright (C) The Apache Software Foundation. All rights reserved.
3  *
4  * This software is published under the terms of the Apache Software License
5  * version 1.1, a copy of which has been included with this distribution in
6  * the LICENSE file.
7  */

8 package org.jivesoftware.util.log.util;
9
10 import java.io.PrintWriter JavaDoc;
11 import java.io.StringWriter JavaDoc;
12
13 /**
14  * A set of utilities to inspect current stack frame.
15  *
16  * @author <a HREF="mailto:sylvain@apache.org">Sylvain Wallez</a>
17  * @author <a HREF="mailto:stuart.roebuck@adolos.com">Stuart Roebuck</a>
18  */

19 public final class StackIntrospector {
20     /**
21      * Hack to get the call stack as an array of classes. The
22      * SecurityManager class provides it as a protected method, so
23      * change it to public through a new method !
24      */

25     private final static class CallStack
26             extends SecurityManager JavaDoc {
27         /**
28          * Returns the current execution stack as an array of classes.
29          * The length of the array is the number of methods on the execution
30          * stack. The element at index 0 is the class of the currently executing
31          * method, the element at index 1 is the class of that method's caller,
32          * and so on.
33          */

34         public Class JavaDoc[] get() {
35             return getClassContext();
36         }
37     }
38
39     ///Method to cache CallStack hack as needed
40
private static CallStack c_callStack;
41
42     /**
43      * Private constructor to block instantiation.
44      */

45     private StackIntrospector() {
46     }
47
48     /**
49      * Create Hack SecurityManager to get CallStack.
50      *
51      * @return the CallStack object
52      * @throws SecurityException if an existing SecurityManager disallows construction
53      * of another SecurityManager
54      */

55     private synchronized static CallStack getCallStack()
56             throws SecurityException JavaDoc {
57         if (null == c_callStack) {
58             //Lazily create CallStack accessor as appropriate
59
c_callStack = new CallStack();
60         }
61
62         return c_callStack;
63     }
64
65     /**
66      * Find the caller of the passed in Class.
67      * May return null if caller not found on execution stack
68      *
69      * @param clazz the Class to search for on stack to find caller of
70      * @return the Class of object that called parrameter class
71      * @throws SecurityException if an existing SecurityManager disallows construction
72      * of another SecurityManager and thus blocks method results
73      */

74     public final static Class JavaDoc getCallerClass(final Class JavaDoc clazz)
75             throws SecurityException JavaDoc {
76         final Class JavaDoc[] stack = getCallStack().get();
77
78         // Traverse the call stack in reverse order until we find clazz
79
for (int i = stack.length - 1; i >= 0; i--) {
80             if (clazz.isAssignableFrom(stack[i])) {
81                 // Found : the caller is the previous stack element
82
return stack[i + 1];
83             }
84         }
85
86         //Unable to locate class in call stack
87
return null;
88     }
89
90     /**
91      * Get the method path name for the method from which the LogEvent was
92      * created, this includes the path name and the source filename and line
93      * number if the source was compiled with debugging on.
94      *
95      * @return The method path name in the form "the.package.path.Method"
96      */

97     public final static String JavaDoc getCallerMethod(final Class JavaDoc clazz) {
98         final String JavaDoc className = clazz.getName();
99
100         //Extract stack into a StringBuffer
101
final StringWriter JavaDoc sw = new StringWriter JavaDoc();
102         final Throwable JavaDoc throwable = new Throwable JavaDoc();
103         throwable.printStackTrace(new PrintWriter JavaDoc(sw, true));
104         final StringBuffer JavaDoc buffer = sw.getBuffer();
105
106         //Cache vars used in loop
107
final StringBuffer JavaDoc line = new StringBuffer JavaDoc();
108         final int length = buffer.length();
109
110         //setup state
111
boolean found = false;
112         int state = 0;
113
114         //parse line
115
for (int i = 0; i < length; i++) {
116             final char ch = buffer.charAt(i);
117
118             switch (state) {
119                 case 0:
120                     //Strip the first line from input
121
if ('\n' == ch) state = 1;
122                     break;
123
124                 case 1:
125                     //strip 't' from 'at'
126
if ('t' == ch) state = 2;
127                     break;
128
129                 case 2:
130                     //Strip space after 'at'
131
line.setLength(0);
132                     state = 3;
133                     break;
134
135                 case 3:
136                     //accumulate all characters to end of line
137
if ('\n' != ch)
138                         line.append(ch);
139                     else {
140                         //At this stage you have the line that looks like
141
//com.biz.SomeClass.someMethod(SomeClass.java:22)
142
final String JavaDoc method = line.toString();
143
144                         ///Determine if line is a match for class
145
final boolean match = method.startsWith(className);
146                         if (!found && match) {
147                             //If this is the first time we cound class then
148
//set found to true and look for caller into class
149
found = true;
150                         }
151                         else if (found && !match) {
152                             //We have now located caller of Clazz
153
return method;
154                         }
155
156                         //start parsing from start of line again
157
state = 1;
158                     }
159             }
160         }
161
162         return "";
163     }
164
165     /**
166      * Return the current call stack as a String, starting with the first call
167      * in the stack after a reference to the <code>clazz</code> class, and then
168      * display <code>entries</code> entries.
169      * <p/>
170      * <p>This can be useful for debugging code to determine where calls to a
171      * method are coming from.</p>
172      *
173      * @param clazz the last class on the stack you are <i>not</i> interested in!
174      * @param entries the number of stack lines to return.
175      * @return The method path name in the form "the.package.path.Method"
176      */

177     public final static String JavaDoc getRecentStack(final Class JavaDoc clazz, int entries) {
178         final String JavaDoc className = clazz.getName();
179
180         //Extract stack into a StringBuffer
181
final StringWriter JavaDoc sw = new StringWriter JavaDoc();
182         final Throwable JavaDoc throwable = new Throwable JavaDoc();
183         throwable.printStackTrace(new PrintWriter JavaDoc(sw, true));
184         final StringBuffer JavaDoc buffer = sw.getBuffer();
185
186         //Cache vars used in loop
187
final StringBuffer JavaDoc line = new StringBuffer JavaDoc();
188         final StringBuffer JavaDoc stack = new StringBuffer JavaDoc();
189         final int length = buffer.length();
190
191         //setup state
192
boolean found = false;
193         int state = 0;
194
195         //parse line
196
for (int i = 0; i < length; i++) {
197             final char ch = buffer.charAt(i);
198
199             switch (state) {
200                 case 0:
201                     //Strip the first line from input
202
if ('\n' == ch) state = 1;
203                     break;
204
205                 case 1:
206                     //strip 't' from 'at'
207
if ('t' == ch) state = 2;
208                     break;
209
210                 case 2:
211                     //Strip space after 'at'
212
line.setLength(0);
213                     state = 3;
214                     break;
215
216                 case 3:
217                     //accumulate all characters to end of line
218
if ('\n' != ch)
219                         line.append(ch);
220                     else {
221                         //At this stage you have the line that looks like
222
//com.biz.SomeClass.someMethod(SomeClass.java:22)
223
final String JavaDoc method = line.toString();
224
225                         ///Determine if line is a match for class
226
final boolean match = method.startsWith(className);
227                         if (!found && match) {
228                             //If this is the first time we cound class then
229
//set found to true and look for caller into class
230
found = true;
231                         }
232                         else if (found && !match) {
233                             //We are looking at the callers of Clazz
234
stack.append(method);
235                             entries--;
236                             if (entries == 0) return stack.toString();
237                             stack.append("\n");
238                         }
239
240                         //start parsing from start of line again
241
state = 1;
242                     }
243             }
244         }
245
246         return "";
247     }
248 }
249
250
Popular Tags