KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > log4j > spi > LocationInfo


1 /*
2  * Copyright 1999-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 // Contributors: Mathias Rupprecht <mmathias.rupprecht@fja.com>
18

19 package org.apache.log4j.spi;
20
21 import java.io.StringWriter JavaDoc;
22 import java.io.PrintWriter JavaDoc;
23 import org.apache.log4j.helpers.LogLog;
24 import org.apache.log4j.Layout;
25
26 /**
27    The internal representation of caller location information.
28
29    @since 0.8.3
30 */

31 public class LocationInfo implements java.io.Serializable JavaDoc {
32
33   /**
34      Caller's line number.
35   */

36   transient String JavaDoc lineNumber;
37   /**
38      Caller's file name.
39   */

40   transient String JavaDoc fileName;
41   /**
42      Caller's fully qualified class name.
43   */

44   transient String JavaDoc className;
45   /**
46      Caller's method name.
47   */

48   transient String JavaDoc methodName;
49   /**
50      All available caller information, in the format
51      <code>fully.qualified.classname.of.caller.methodName(Filename.java:line)</code>
52     */

53   public String JavaDoc fullInfo;
54
55   private static StringWriter JavaDoc sw = new StringWriter JavaDoc();
56   private static PrintWriter JavaDoc pw = new PrintWriter JavaDoc(sw);
57
58   /**
59      When location information is not available the constant
60      <code>NA</code> is returned. Current value of this string
61      constant is <b>?</b>. */

62   public final static String JavaDoc NA = "?";
63
64   static final long serialVersionUID = -1325822038990805636L;
65
66
67   // Check if we are running in IBM's visual age.
68
static boolean inVisualAge = false;
69   static {
70     try {
71       Class JavaDoc dummy = Class.forName("com.ibm.uvm.tools.DebugSupport");
72       inVisualAge = true;
73       LogLog.debug("Detected IBM VisualAge environment.");
74     } catch(Throwable JavaDoc e) {
75       // nothing to do
76
}
77   }
78
79   /**
80      Instantiate location information based on a Throwable. We
81      expect the Throwable <code>t</code>, to be in the format
82
83        <pre>
84         java.lang.Throwable
85         ...
86           at org.apache.log4j.PatternLayout.format(PatternLayout.java:413)
87           at org.apache.log4j.FileAppender.doAppend(FileAppender.java:183)
88         at org.apache.log4j.Category.callAppenders(Category.java:131)
89         at org.apache.log4j.Category.log(Category.java:512)
90         at callers.fully.qualified.className.methodName(FileName.java:74)
91     ...
92        </pre>
93
94        <p>However, we can also deal with JIT compilers that "lose" the
95        location information, especially between the parentheses.
96
97     */

98     public LocationInfo(Throwable JavaDoc t, String JavaDoc fqnOfCallingClass) {
99       if(t == null)
100     return;
101
102       String JavaDoc s;
103       // Protect against multiple access to sw.
104
synchronized(sw) {
105     t.printStackTrace(pw);
106     s = sw.toString();
107     sw.getBuffer().setLength(0);
108       }
109       //System.out.println("s is ["+s+"].");
110
int ibegin, iend;
111
112       // Given the current structure of the package, the line
113
// containing "org.apache.log4j.Category." should be printed just
114
// before the caller.
115

116       // This method of searching may not be fastest but it's safer
117
// than counting the stack depth which is not guaranteed to be
118
// constant across JVM implementations.
119
ibegin = s.lastIndexOf(fqnOfCallingClass);
120       if(ibegin == -1)
121     return;
122
123
124       ibegin = s.indexOf(Layout.LINE_SEP, ibegin);
125       if(ibegin == -1)
126     return;
127       ibegin+= Layout.LINE_SEP_LEN;
128
129       // determine end of line
130
iend = s.indexOf(Layout.LINE_SEP, ibegin);
131       if(iend == -1)
132     return;
133
134       // VA has a different stack trace format which doesn't
135
// need to skip the inital 'at'
136
if(!inVisualAge) {
137     // back up to first blank character
138
ibegin = s.lastIndexOf("at ", iend);
139     if(ibegin == -1)
140       return;
141     // Add 3 to skip "at ";
142
ibegin += 3;
143       }
144       // everything between is the requested stack item
145
this.fullInfo = s.substring(ibegin, iend);
146     }
147
148     /**
149        Return the fully qualified class name of the caller making the
150        logging request.
151     */

152     public
153     String JavaDoc getClassName() {
154       if(fullInfo == null) return NA;
155       if(className == null) {
156     // Starting the search from '(' is safer because there is
157
// potentially a dot between the parentheses.
158
int iend = fullInfo.lastIndexOf('(');
159     if(iend == -1)
160       className = NA;
161     else {
162       iend =fullInfo.lastIndexOf('.', iend);
163
164       // This is because a stack trace in VisualAge looks like:
165

166           //java.lang.RuntimeException
167
// java.lang.Throwable()
168
// java.lang.Exception()
169
// java.lang.RuntimeException()
170
// void test.test.B.print()
171
// void test.test.A.printIndirect()
172
// void test.test.Run.main(java.lang.String [])
173
int ibegin = 0;
174       if (inVisualAge) {
175         ibegin = fullInfo.lastIndexOf(' ', iend)+1;
176           }
177
178       if(iend == -1)
179         className = NA;
180       else
181         className = this.fullInfo.substring(ibegin, iend);
182     }
183       }
184       return className;
185     }
186
187     /**
188        Return the file name of the caller.
189
190        <p>This information is not always available.
191     */

192     public
193     String JavaDoc getFileName() {
194       if(fullInfo == null) return NA;
195
196       if(fileName == null) {
197     int iend = fullInfo.lastIndexOf(':');
198     if(iend == -1)
199       fileName = NA;
200     else {
201       int ibegin = fullInfo.lastIndexOf('(', iend - 1);
202       fileName = this.fullInfo.substring(ibegin + 1, iend);
203     }
204       }
205       return fileName;
206     }
207
208     /**
209        Returns the line number of the caller.
210
211        <p>This information is not always available.
212     */

213     public
214     String JavaDoc getLineNumber() {
215       if(fullInfo == null) return NA;
216
217       if(lineNumber == null) {
218     int iend = fullInfo.lastIndexOf(')');
219     int ibegin = fullInfo.lastIndexOf(':', iend -1);
220     if(ibegin == -1)
221       lineNumber = NA;
222     else
223       lineNumber = this.fullInfo.substring(ibegin + 1, iend);
224       }
225       return lineNumber;
226     }
227
228     /**
229        Returns the method name of the caller.
230     */

231     public
232     String JavaDoc getMethodName() {
233       if(fullInfo == null) return NA;
234       if(methodName == null) {
235     int iend = fullInfo.lastIndexOf('(');
236     int ibegin = fullInfo.lastIndexOf('.', iend);
237     if(ibegin == -1)
238       methodName = NA;
239     else
240       methodName = this.fullInfo.substring(ibegin + 1, iend);
241       }
242       return methodName;
243     }
244 }
245
Popular Tags