You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-dev@logging.apache.org by ce...@apache.org on 2004/09/07 20:58:42 UTC

cvs commit: logging-log4j/src/java/org/apache/log4j/spi/location StackTraceElementExtractor.java LocationInfo.java LegacyExtractor.java

ceki        2004/09/07 11:58:42

  Modified:    src/java/org/apache/log4j/spi/location LocationInfo.java
                        LegacyExtractor.java
  Added:       src/java/org/apache/log4j/spi/location
                        StackTraceElementExtractor.java
  Log:
  Added a new location info extraction mechanism based on Martin Shutlz' code.
  See http://marc.theaimsgroup.com/?t=108473346700001&r=1&w=2 for details.
  
  Revision  Changes    Path
  1.2       +19 -2     logging-log4j/src/java/org/apache/log4j/spi/location/LocationInfo.java
  
  Index: LocationInfo.java
  ===================================================================
  RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/spi/location/LocationInfo.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- LocationInfo.java	7 Sep 2004 17:16:02 -0000	1.1
  +++ LocationInfo.java	7 Sep 2004 18:58:42 -0000	1.2
  @@ -33,14 +33,26 @@
        <code>NA</code> is returned. Current value of this string
        constant is <b>?</b>.  */
     public static final String NA = "?";
  +  
     static final long serialVersionUID = -1325822038990805636L;
  -
  +  
  +  private static boolean haveStackTraceElement = false;
  +  
     /**
      * NA_LOCATION_INFO is used in conjunction with deserialized LoggingEvents 
      * without real location info available.
      * @since 1.3
      */
     public static LocationInfo NA_LOCATION_INFO = new LocationInfo(NA, NA, NA, NA);
  + 
  +  static {
  +    try {
  +      Class.forName("java.lang.StackTraceElement");
  +      haveStackTraceElement = true;
  +    } catch ( Throwable e) {
  +      // we are running on a JDK prior to 1.4
  +    } 
  +  }
     
     /**
        Caller's line number.
  @@ -100,7 +112,12 @@
       if (t == null) {
         return;
       }
  -    LegacyExtractor.extract(this, t, fqnOfCallingClass);  
  +    
  +    if(haveStackTraceElement) {
  +      StackTraceElementExtractor.extract(this, t, fqnOfCallingClass);
  +    } else {
  +      LegacyExtractor.extract(this, t, fqnOfCallingClass);  
  +    }
     }
   
     public boolean equals(Object o) {
  
  
  
  1.2       +3 -3      logging-log4j/src/java/org/apache/log4j/spi/location/LegacyExtractor.java
  
  Index: LegacyExtractor.java
  ===================================================================
  RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/spi/location/LegacyExtractor.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- LegacyExtractor.java	7 Sep 2004 17:16:02 -0000	1.1
  +++ LegacyExtractor.java	7 Sep 2004 18:58:42 -0000	1.2
  @@ -67,9 +67,9 @@
       //System.out.println("s is ["+s+"].");
       int iend;
   
  -    // Given the current structure of the package, the line
  -    // containing "org.apache.log4j.Category." should be printed just
  -    // before the caller.
  +    // Given the current structure of log4j, the line 
  +    // containing 'fqnOfCallingClass', usually "org.apache.log4j.Logger." 
  +    // should be printed just before the caller.
       // This method of searching may not be fastest but it's safer
       // than counting the stack depth which is not guaranteed to be
       // constant across JVM implementations.
  
  
  
  1.1                  logging-log4j/src/java/org/apache/log4j/spi/location/StackTraceElementExtractor.java
  
  Index: StackTraceElementExtractor.java
  ===================================================================
  /*
   * Copyright 1999,2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package org.apache.log4j.spi.location;
  
  import java.lang.reflect.Method;
  
  
  /**
   * A faster extractor based on StackTraceElements introduced in JDK 1.4.
   *
   * The present code uses reflection. Thus, it should compile on all platforms.
   *
   * @author Martin Schulz
   * @author Ceki G&uuml;lc&uuml;
   *
   */
  public class StackTraceElementExtractor {
    protected static boolean haveStackTraceElement = false;
    private static Method getStackTrace = null;
    private static Method getClassName = null;
    private static Method getFileName = null;
    private static Method getMethodName = null;
    private static Method getLineNumber = null;
    private static Object[] nullArgs = new Object[] {  };
  
    static {
      try {
        Class cStackTraceElement = Class.forName("java.lang.StackTraceElement");
        Class[] nullClassArray = new Class[] {  };
        getStackTrace =
          Throwable.class.getDeclaredMethod("getStackTrace", nullClassArray);
        getClassName =
          cStackTraceElement.getDeclaredMethod("getClassName", nullClassArray);
        getFileName =
          cStackTraceElement.getDeclaredMethod("getFileName", nullClassArray);
        getMethodName =
          cStackTraceElement.getDeclaredMethod("getMethodName", nullClassArray);
        getLineNumber =
          cStackTraceElement.getDeclaredMethod("getLineNumber", nullClassArray);
        haveStackTraceElement = true;
      } catch (Throwable e) {
        // we should never get here
      } 
    }
  
    static void extract(LocationInfo li, Throwable t, String fqnOfCallingClass) {
      if (t == null) {
        return;
      }
      
      Object location = null;
      try {
        Object[] stes = (Object[]) getStackTrace.invoke(t, nullArgs);
  
        boolean match = false;
        for (int i = 0; i < stes.length; i++) {
          if (((String) getClassName.invoke(stes[i], nullArgs)).equals(
                fqnOfCallingClass)) {
            match = true;
          } else if(match) {
            location = stes[i];
            break;
          }
        }
      } catch (Throwable e) {
        // some trouble worth announcing...
      }
      setClassName(li, location);
      setFileName(li, location);
      setMethodName(li, location);
      setLineNumber(li, location);
    }
  
    /**
       Return the fully qualified class name of the caller making the
       logging request.
    */
    static void setClassName(LocationInfo li, Object location) {
      try {
        li.className = (String) getClassName.invoke(location, nullArgs);
      } catch (Throwable e) {
      } // this should work, shouldn't it?
    }
  
    static void setFileName(LocationInfo li, Object location) {
      try {
        li.fileName = (String) getFileName.invoke(location, nullArgs);
      } catch (Throwable e) {
        li.fileName = LocationInfo.NA;
      }
    }
  
    static void setLineNumber(LocationInfo li, Object location) {
      Integer ln = null;
      try {
        ln = (Integer) getLineNumber.invoke(location, nullArgs);
        if (ln.intValue() >= 0) {
          li.lineNumber = ln.toString();
        }
      } catch (Throwable e) {
        li.lineNumber = LocationInfo.NA;
      }
    }
  
    static void setMethodName(LocationInfo li, Object location) {
      try {
        li.methodName = (String) getMethodName.invoke(location, nullArgs);
      } catch (Throwable e) {
        li.methodName = LocationInfo.NA;
      }
    }
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org