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]