Author: carnold
Date: Tue Aug 12 13:27:58 2008
New Revision: 685300

URL: http://svn.apache.org/viewvc?rev=685300&view=rev
Log:
Bug 45039: Use Throwable.getStackTrace for location on JDK 1.4 and later

Modified:
    logging/log4j/trunk/src/changes/changes.xml
    logging/log4j/trunk/src/main/java/org/apache/log4j/spi/LocationInfo.java

Modified: logging/log4j/trunk/src/changes/changes.xml
URL: 
http://svn.apache.org/viewvc/logging/log4j/trunk/src/changes/changes.xml?rev=685300&r1=685299&r2=685300&view=diff
==============================================================================
--- logging/log4j/trunk/src/changes/changes.xml (original)
+++ logging/log4j/trunk/src/changes/changes.xml Tue Aug 12 13:27:58 2008
@@ -48,6 +48,7 @@
        <action action="fix" issue="45335">NullPointerException in NDC.remove 
after unload by Tomcat.</action>
        <action action="fix" issue="36384">Configuring triggering/rolling 
policys should be supported through properties.</action>
        <action action="fix" issue="25747">More explanations when hitting WARN 
No appenders could be found for logger.</action>
+       <action action="fix" issue="45039">Use Throwable.getStackTrace to 
obtain location when running on JDK 1.4 or later.</action>
     </release>
   
     <release version="1.2.15" date="2007-08-24" description="SyslogAppender 
enhancements, NTEventLogAppender and Maven build.">

Modified: 
logging/log4j/trunk/src/main/java/org/apache/log4j/spi/LocationInfo.java
URL: 
http://svn.apache.org/viewvc/logging/log4j/trunk/src/main/java/org/apache/log4j/spi/LocationInfo.java?rev=685300&r1=685299&r2=685300&view=diff
==============================================================================
--- logging/log4j/trunk/src/main/java/org/apache/log4j/spi/LocationInfo.java 
(original)
+++ logging/log4j/trunk/src/main/java/org/apache/log4j/spi/LocationInfo.java 
Tue Aug 12 13:27:58 2008
@@ -19,10 +19,12 @@
 
 package org.apache.log4j.spi;
 
-import java.io.StringWriter;
-import java.io.PrintWriter;
-import org.apache.log4j.helpers.LogLog;
 import org.apache.log4j.Layout;
+import org.apache.log4j.helpers.LogLog;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Method;
 
 /**
    The internal representation of caller location information.
@@ -56,6 +58,13 @@
   private static StringWriter sw = new StringWriter();
   private static PrintWriter pw = new PrintWriter(sw);
 
+  private static Method getStackTraceMethod;
+  private static Method getClassNameMethod;
+  private static Method getMethodNameMethod;
+  private static Method getFileNameMethod;
+  private static Method getLineNumberMethod;
+
+
   /**
      When location information is not available the constant
      <code>NA</code> is returned. Current value of this string
@@ -82,6 +91,17 @@
     } catch(Throwable e) {
       // nothing to do
     }
+      try {
+          Class[] noArgs = null;
+          getStackTraceMethod = Throwable.class.getMethod("getStackTrace", 
noArgs);
+          Class stackTraceElementClass = 
Class.forName("java.lang.StackTraceElement");
+          getClassNameMethod = 
stackTraceElementClass.getMethod("getClassName", noArgs);
+          getMethodNameMethod = 
stackTraceElementClass.getMethod("getMethodName", noArgs);
+          getFileNameMethod = stackTraceElementClass.getMethod("getFileName", 
noArgs);
+          getLineNumberMethod = 
stackTraceElementClass.getMethod("getLineNumber", noArgs);
+      } catch(Exception ex) {
+          LogLog.debug("LocationInfo will use pre-JDK 1.4 methods to determine 
location.");
+      }
   }
 
   /**
@@ -101,11 +121,48 @@
 
        <p>However, we can also deal with JIT compilers that "lose" the
        location information, especially between the parentheses.
+        @param t throwable used to determine location, may be null.
+        @param fqnOfCallingClass class name of first class considered part of
+           the logging framework.  Location will be site that calls a method 
on this class.
 
     */
     public LocationInfo(Throwable t, String fqnOfCallingClass) {
       if(t == null || fqnOfCallingClass == null)
        return;
+      if (getLineNumberMethod != null) {
+          try {
+              boolean hitCaller = false;
+              Object[] noArgs = null;
+              Object[] elements =  (Object[]) getStackTraceMethod.invoke(t, 
noArgs);
+              for(int i = 0; i < elements.length; i++) {
+                  String thisClass = 
String.valueOf(getClassNameMethod.invoke(elements[i], noArgs));
+                  boolean isCaller = thisClass.equals(fqnOfCallingClass);
+                  if (hitCaller) {
+                      if(!isCaller) {
+                          className = thisClass;
+                          methodName = (String) 
getMethodNameMethod.invoke(elements[i], noArgs);
+                          fileName = (String) 
getFileNameMethod.invoke(elements[i], noArgs);
+                          if (fileName == null) {
+                              fileName = NA;
+                          }
+                          int line = ((Integer) 
getLineNumberMethod.invoke(elements[i], noArgs)).intValue();
+                          if (line < 0) {
+                              lineNumber = NA;
+                          } else {
+                              lineNumber = String.valueOf(line);
+                          }
+                          fullInfo = elements[i].toString();
+                          return;
+                      }
+                  } else {
+                      hitCaller = isCaller;
+                  }
+              }
+
+          } catch(Exception ex) {
+              LogLog.debug("LocationInfo failed using JDK 1.4 methods", ex);
+          }
+      }
 
       String s;
       // Protect against multiple access to sw.



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to