[logback-dev] svn commit: r1794 - in logback/trunk: logback-classic/src/main/java/ch/qos/logback/classic logback-classic/src/main/java/ch/qos/logback/classic/db logback-classic/src/main/java/ch/qos/logback/classic/helpers logback-classic/src/main/java/ch/qos/logback/classic/html logback-classic/src/main/java/ch/qos/logback/classic/joran logback-classic/src/main/java/ch/qos/logback/classic/net logback-classic/src/main/java/ch/qos/logback/classic/pattern logback-classic/src/main/java/ch/qos/logback/classic/spi logback-classic/src/test/java/ch/qos/logback/classic logback-classic/src/test/java/ch/qos/logback/classic/html logback-classic/src/test/java/ch/qos/logback/classic/pattern logback-classic/src/test/java/ch/qos/logback/classic/spi logback-core/src/main/java/ch/qos/logback/core/helpers logback-core/src/main/java/ch/qos/logback/core/util logback-core/src/test/java/ch/qos/logback/core logback-core/src/test/java/ch/qos/logback/core/helpers

noreply.ceki at qos.ch noreply.ceki at qos.ch
Fri Sep 5 19:14:47 CEST 2008


Author: ceki
Date: Fri Sep  5 19:14:47 2008
New Revision: 1794

Added:
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ExtendedThrowableProxyConverter.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableProxyConverter.java
      - copied, changed from r1793, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableInformationConverter.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/PackageInfo.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/PackageInfoCalculator.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/PlatformInfo.java
      - copied, changed from r1772, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/helpers/PlatformInfo.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/STEUtil.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/StackTraceElementProxy.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableDataPoint.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableToDataPointArray.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ExtendedThrowableProxyConverterTest.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ThrowableProxyConverterTest.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/spi/PackageInfoTest.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/spi/PackageVersionCalculatorTest.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/spi/ThrowableToDataPointTest.java
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/helpers/PackageTest.java
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/helpers/ThrowableToStringArrayTest.java
Removed:
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/helpers/PlatformInfo.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableInformationConverter.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/pattern/UtilTest.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/PackageInfo.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/StackTraceElementProxy.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/ThrowableDataPoint.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/ThrowableToDataPointArray.java
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/helpers/ThrowableToDataPointTest.java
Modified:
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DBAppender.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DBHelper.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultThrowableRenderer.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/net/SyslogAppender.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/EnsureExceptionHandling.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/Util.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableProxy.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ConverterTest.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/pattern/LRUCacheTest.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/spi/PackageTest.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/ThrowableToStringArray.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/StatusPrinter.java
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java

Log:
 	 LBGENERAL-23
 	 
 	 Working on the reliability of the extracted package information which is actually quite a difficult problem.

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java	Fri Sep  5 19:14:47 2008
@@ -28,7 +28,7 @@
 import ch.qos.logback.classic.pattern.NopThrowableInformationConverter;
 import ch.qos.logback.classic.pattern.RelativeTimeConverter;
 import ch.qos.logback.classic.pattern.ThreadConverter;
-import ch.qos.logback.classic.pattern.ThrowableInformationConverter;
+import ch.qos.logback.classic.pattern.ThrowableProxyConverter;
 import ch.qos.logback.classic.spi.LoggingEvent;
 import ch.qos.logback.core.CoreGlobal;
 import ch.qos.logback.core.pattern.PatternLayoutBase;
@@ -90,10 +90,10 @@
     defaultConverterMap.put("mdc", MDCConverter.class.getName());
 
     defaultConverterMap
-        .put("ex", ThrowableInformationConverter.class.getName());
-    defaultConverterMap.put("exception", ThrowableInformationConverter.class
+        .put("ex", ThrowableProxyConverter.class.getName());
+    defaultConverterMap.put("exception", ThrowableProxyConverter.class
         .getName());
-    defaultConverterMap.put("throwable", ThrowableInformationConverter.class
+    defaultConverterMap.put("throwable", ThrowableProxyConverter.class
         .getName());
     
     defaultConverterMap.put("nopex", NopThrowableInformationConverter.class

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DBAppender.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DBAppender.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DBAppender.java	Fri Sep  5 19:14:47 2008
@@ -21,8 +21,8 @@
 
 import ch.qos.logback.classic.spi.CallerData;
 import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.classic.spi.ThrowableDataPoint;
 import ch.qos.logback.core.db.DBAppenderBase;
-import ch.qos.logback.core.helpers.ThrowableDataPoint;
 
 /**
  * The DBAppender inserts logging events into three database tables in a format

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DBHelper.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DBHelper.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/db/DBHelper.java	Fri Sep  5 19:14:47 2008
@@ -11,7 +11,7 @@
 package ch.qos.logback.classic.db;
 
 import ch.qos.logback.classic.spi.LoggingEvent;
-import ch.qos.logback.core.helpers.ThrowableDataPoint;
+import ch.qos.logback.classic.spi.ThrowableDataPoint;
 
 /**
  * @author Ceki Gülcü

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultThrowableRenderer.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultThrowableRenderer.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/html/DefaultThrowableRenderer.java	Fri Sep  5 19:14:47 2008
@@ -3,8 +3,8 @@
 import static ch.qos.logback.core.Layout.LINE_SEP;
 import ch.qos.logback.classic.helpers.Transform;
 import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.classic.spi.ThrowableDataPoint;
 import ch.qos.logback.classic.spi.ThrowableProxy;
-import ch.qos.logback.core.helpers.ThrowableDataPoint;
 import ch.qos.logback.core.html.IThrowableRenderer;
 
 public class DefaultThrowableRenderer implements IThrowableRenderer {

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java	Fri Sep  5 19:14:47 2008
@@ -10,7 +10,6 @@
 
 package ch.qos.logback.classic.joran;
 
-import ch.qos.logback.classic.helpers.PlatformInfo;
 import ch.qos.logback.classic.joran.action.ConfigurationAction;
 import ch.qos.logback.classic.joran.action.ConsolePluginAction;
 import ch.qos.logback.classic.joran.action.EvaluatorAction;
@@ -19,6 +18,7 @@
 import ch.qos.logback.classic.joran.action.LevelAction;
 import ch.qos.logback.classic.joran.action.LoggerAction;
 import ch.qos.logback.classic.joran.action.RootLoggerAction;
+import ch.qos.logback.classic.spi.PlatformInfo;
 import ch.qos.logback.core.joran.JoranConfiguratorBase;
 import ch.qos.logback.core.joran.action.AppenderRefAction;
 import ch.qos.logback.core.joran.action.IncludeAction;

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/net/SyslogAppender.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/net/SyslogAppender.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/net/SyslogAppender.java	Fri Sep  5 19:14:47 2008
@@ -14,9 +14,9 @@
 import ch.qos.logback.classic.PatternLayout;
 import ch.qos.logback.classic.pattern.SyslogStartConverter;
 import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.classic.spi.ThrowableDataPoint;
 import ch.qos.logback.classic.util.LevelToSyslogSeverity;
 import ch.qos.logback.core.Layout;
-import ch.qos.logback.core.helpers.ThrowableDataPoint;
 import ch.qos.logback.core.net.SyslogAppenderBase;
 import ch.qos.logback.core.net.SyslogWriter;
 

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/EnsureExceptionHandling.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/EnsureExceptionHandling.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/EnsureExceptionHandling.java	Fri Sep  5 19:14:47 2008
@@ -30,7 +30,7 @@
   public void process(Converter<LoggingEvent> head) {
     if (!chainHandlesThrowable(head)) {
       Converter<LoggingEvent> tail = ConverterUtil.findTail(head);
-      Converter<LoggingEvent> exConverter = new ThrowableInformationConverter();
+      Converter<LoggingEvent> exConverter = new ThrowableProxyConverter();
       if (tail == null) {
         head = exConverter;
       } else {

Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ExtendedThrowableProxyConverter.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ExtendedThrowableProxyConverter.java	Fri Sep  5 19:14:47 2008
@@ -0,0 +1,29 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ * 
+ * Copyright (C) 2000-2008, QOS.ch
+ * 
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.classic.pattern;
+
+import ch.qos.logback.classic.spi.PackageInfo;
+import ch.qos.logback.classic.spi.StackTraceElementProxy;
+import ch.qos.logback.classic.spi.ThrowableDataPoint;
+
+
+public class ExtendedThrowableProxyConverter extends ThrowableProxyConverter {
+
+  @Override
+  protected void extraData(StringBuilder builder, ThrowableDataPoint tdp) {
+    StackTraceElementProxy step = tdp.getStackTraceElementProxy();
+    if(step != null) {
+      PackageInfo pi = step.getPackageInfo();
+      if(pi != null) {
+        builder.append(" [").append(pi.getJarName()).append(':').append(pi.getVersion()).append(']');
+      }
+    }
+  }
+}

Copied: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableProxyConverter.java (from r1793, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableInformationConverter.java)
==============================================================================
--- /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableInformationConverter.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ThrowableProxyConverter.java	Fri Sep  5 19:14:47 2008
@@ -14,20 +14,20 @@
 import java.util.Map;
 
 import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.classic.spi.ThrowableDataPoint;
 import ch.qos.logback.classic.spi.ThrowableProxy;
 import ch.qos.logback.core.Context;
 import ch.qos.logback.core.CoreGlobal;
 import ch.qos.logback.core.boolex.EvaluationException;
 import ch.qos.logback.core.boolex.EventEvaluator;
-import ch.qos.logback.core.helpers.ThrowableDataPoint;
 import ch.qos.logback.core.status.ErrorStatus;
 
 /**
- * Add a stack trace i case the event contains a Throwable.
+ * Add a stack trace in case the event contains a Throwable.
  * 
  * @author Ceki G&uuml;lc&uuml;
  */
-public class ThrowableInformationConverter extends ThrowableHandlingConverter {
+public class ThrowableProxyConverter extends ThrowableHandlingConverter {
 
   int lengthOption;
   List<EventEvaluator> evaluatorList = null;
@@ -85,8 +85,12 @@
     super.stop();
   }
 
+  protected void extraData(StringBuilder builder, ThrowableDataPoint tdp) {
+    // nop
+  }
+  
   public String convert(LoggingEvent event) {
-    StringBuffer buf = new StringBuffer(32);
+    StringBuilder buf = new StringBuilder(32);
 
     ThrowableProxy information = event.getThrowableProxy();
 
@@ -133,15 +137,9 @@
     buf.append(tdpArray[0]).append(CoreGlobal.LINE_SEPARATOR);
     for (int i = 1; i < length; i++) {
       String string = tdpArray[i].toString();
-
-      if (string.startsWith(CoreGlobal.CAUSED_BY)) {
-        // nothing
-      } else if (Character.isDigit(string.charAt(0))) {
-        buf.append("\t... ");
-      } else {
-        buf.append("\tat ");
-      }
-      buf.append(string).append(CoreGlobal.LINE_SEPARATOR);
+      buf.append(string);
+      extraData(buf, tdpArray[i]); // allow other data to be appended
+      buf.append(CoreGlobal.LINE_SEPARATOR);
     }
 
     return buf.toString();

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/Util.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/Util.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/pattern/Util.java	Fri Sep  5 19:14:47 2008
@@ -9,17 +9,15 @@
  */
 package ch.qos.logback.classic.pattern;
 
-import java.net.URL;
 import java.util.HashMap;
 import java.util.Map;
 
 import org.slf4j.Marker;
 
-import ch.qos.logback.core.helpers.PackageInfo;
+import ch.qos.logback.classic.spi.PackageInfo;
 
 /**
  * 
- * @author James Strachan
  * @author Ceki Gulcu
  */
 public class Util {
@@ -44,123 +42,5 @@
     return false;
   }
 
-  static String getVersion(String className) {
-    String packageName = getPackageName(className);
-    Package aPackage = Package.getPackage(packageName);
-    if (aPackage != null) {
-      String v = aPackage.getImplementationVersion();
-      if (v == null) {
-        return "na";
-      } else {
-        return v;
-      }
-    }
-    return "na";
-  }
-
-  static public PackageInfo getPackageInfo(String className) {
-    PackageInfo pi = cache.get(className);
-    if(pi != null) {
-      return pi;
-    }
-    String version = getVersion(className);
-    String jarname = getJarNameOfClass(className);
-    pi = new PackageInfo(jarname, version);
-    //cache.put(className, pi);
-    return pi;
-  }
-
-  static String getPackageName(String className) {
-    int j = className.lastIndexOf('.');
-    return className.substring(0, j);
-  }
-
-  /**
-   * Uses the context class path or the current global class loader to deduce
-   * the file that the given class name comes from
-   */
-  static String getJarNameOfClass0(String className) {
-    try {
-      Class type = findClass(className);
-      if (type != null) {
-        URL resource = type.getClassLoader().getResource(
-            type.getName().replace('.', '/') + ".class");
-         
-         
-        // "jar:file:/C:/java/../repo/groupId/artifact/1.3/artifact-1.3.jar!/com/some/package/Some.class
-        if (resource != null) {
-          String text = resource.toString();
-          int idx = text.lastIndexOf('!');
-          if (idx > 0) {
-            text = text.substring(0, idx);
-            // now lets remove all but the file name
-            idx = text.lastIndexOf('/');
-            if (idx > 0) {
-              text = text.substring(idx + 1);
-            }
-            idx = text.lastIndexOf('\\');
-            if (idx > 0) {
-              text = text.substring(idx + 1);
-            }
-            return text;
-          }
-        }
-      }
-    } catch (Exception e) {
-      // ignore
-    }
-    return "na";
-  }
-  
-  static String getJarNameOfClass1(String className) {
-    try {
-      Class type = findClass(className);
-      if (type != null) {
-        
-        
-        // file:/C:/java/maven-2.0.8/repo/com/icegreen/greenmail/1.3/greenmail-1.3.jar
-        URL resource = type.getProtectionDomain().getCodeSource().getLocation();
-        if (resource != null) {
-          String text = resource.toString();
-            // now lets remove all but the file name
-          int  idx = text.lastIndexOf('/');
-          if (idx > 0) {
-            text = text.substring(idx + 1);
-          }
-          idx = text.lastIndexOf('\\');
-          if (idx > 0) {
-            text = text.substring(idx + 1);
-          }
-           return text;
-        }
-      }
-    } catch (Exception e) {
-      // ignore
-    }
-    return "na";
-  }
-  
-  
-  
-  static String getJarNameOfClass(String className) {
-    return getJarNameOfClass1(className);
-  }
-  
-  static private Class findClass(String className) {
-    try {
-      return Thread.currentThread().getContextClassLoader()
-          .loadClass(className);
-    } catch (ClassNotFoundException e) {
-      try {
-        return Class.forName(className);
-      } catch (ClassNotFoundException e1) {
-        try {
-          return Util.class.getClassLoader().loadClass(className);
-        } catch (ClassNotFoundException e2) {
-          return null;
-        }
-      }
-    }
-  }
-
+ 
 }

Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/PackageInfo.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/PackageInfo.java	Fri Sep  5 19:14:47 2008
@@ -0,0 +1,34 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ * 
+ * Copyright (C) 2000-2008, QOS.ch
+ * 
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.classic.spi;
+
+import java.io.Serializable;
+
+public class PackageInfo implements Serializable {
+
+  private static final long serialVersionUID = 637783570208674312L;
+
+  String jarName;
+  String version;
+  
+  public PackageInfo(String jarName, String version) {
+    this.jarName = jarName;
+    this.version = version;
+  }
+
+  public String getJarName() {
+    return jarName;
+  }
+
+  public String getVersion() {
+    return version;
+  }
+  
+}

Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/PackageInfoCalculator.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/PackageInfoCalculator.java	Fri Sep  5 19:14:47 2008
@@ -0,0 +1,197 @@
+package ch.qos.logback.classic.spi;
+
+import java.net.URL;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+import sun.reflect.Reflection;
+
+import ch.qos.logback.classic.spi.ThrowableDataPoint.ThrowableDataPointType;
+
+
+
+/**
+ * 
+ * Given a classname locate associated PackageInfo (jar name, version name).
+ * 
+ * @author James Strachan
+ * @Ceki G&uuml;lc&uuml;
+ */
+public class PackageInfoCalculator {
+
+  final static StackTraceElementProxy[] STEP_ARRAY_TEMPLATE = new StackTraceElementProxy[0];
+  
+  HashMap<String, PackageInfo> cache = new HashMap<String, PackageInfo>();
+
+ 
+  PackageInfoCalculator() {
+    
+  }
+  
+  public void computePackageInfo(ThrowableDataPoint[] tdpArray) {
+  
+    int steStart= findSTEStartIndex(tdpArray, 0);
+    StackTraceElementProxy[] stepArray = getSTEPArray(tdpArray, steStart);
+    populateWithPackageInfo(stepArray);
+    
+  }
+  
+  void populateWithPackageInfo(StackTraceElementProxy[] stepArray) {
+    Throwable t = new Throwable("local");
+    //t.printStackTrace();
+    StackTraceElement[] localteSTEArray = t.getStackTrace();
+    int commonFrames = STEUtil.findNumberOfCommonFrames(localteSTEArray, stepArray);
+  
+    int  localFirstCommon = localteSTEArray.length-commonFrames;
+    int  stepFirstCommon = stepArray.length-commonFrames;
+    
+    //System.out.println("commonFr4ames="+commonFrames);
+    
+    int missfireCount = 0;
+    for(int i = 0; i < commonFrames; i++) {
+      Class callerClass = Reflection.getCallerClass(localFirstCommon+i-missfireCount+1);
+      StackTraceElementProxy step =  stepArray[stepFirstCommon+i];
+      String stepClassname = step.ste.getClassName();
+      //System.out.println("step.class = "+stepClassname);
+      
+      if(!stepClassname.equals(callerClass.getName())) {
+        missfireCount++;
+        PackageInfo pi = compute(step);
+        step.setPackageInfo(pi);
+      } else {
+        PackageInfo pi = computeByType(callerClass);
+        step.setPackageInfo(pi);
+      }  
+    }
+    
+    populateX(commonFrames, stepArray); 
+    
+  }
+  
+  int findSTEStartIndex(ThrowableDataPoint[] tdpArray, int from) {
+    int len = tdpArray.length;
+    if(from < 0 || from >= len) {
+      return -1;
+    }
+    for(int i = from; i < len; i++) {
+      if(tdpArray[i].type == ThrowableDataPointType.STEP) {
+        return i;
+      }
+    }
+    return -1;
+  }
+  
+  void populateX(int commonFrames, StackTraceElementProxy[] stepArray) {
+    for(int i = 0; i < commonFrames; i++) {
+      StackTraceElementProxy step = stepArray[i];
+      PackageInfo pi = compute(step);
+      step.setPackageInfo(pi);
+    }
+  }
+  
+  StackTraceElementProxy[] getSTEPArray(ThrowableDataPoint[] tdpArray, int from) {
+    List<StackTraceElementProxy> stepList = new LinkedList<StackTraceElementProxy>();
+    int len = tdpArray.length;
+    if(from < 0 || from >= len) {
+      return stepList.toArray(STEP_ARRAY_TEMPLATE);
+    }
+    for(int i = from; i < len; i++) {
+      final ThrowableDataPoint tdp = tdpArray[i];
+      
+      if(tdp.type == ThrowableDataPointType.STEP) {
+        stepList.add(tdp.getStackTraceElementProxy());
+      } else {
+        break;
+      }
+    }
+    return stepList.toArray(STEP_ARRAY_TEMPLATE);
+  }
+
+  private PackageInfo computeByType(Class type) {
+    String className = type.getName();
+    PackageInfo pi = cache.get(className);
+    if (pi != null) {
+      return pi;
+    }
+    String version = getVersion(className);
+    String jarname = getJarNameOfClass(type);
+    pi = new PackageInfo(jarname, version);
+    cache.put(className, pi);
+    return pi;
+  }
+  
+  private PackageInfo compute(StackTraceElementProxy step) {
+    String className = step.ste.getClassName();
+    PackageInfo pi = cache.get(className);
+    if (pi != null) {
+      return pi;
+    }
+    String version = getVersion(className);
+    Class type = bestEffortFindClass(className);
+    String jarname = getJarNameOfClass(type);
+    pi = new PackageInfo(jarname, version);
+    cache.put(className, pi);
+    return pi;
+  }
+
+  String getVersion(String className) {
+    String packageName = getPackageName(className);
+    Package aPackage = Package.getPackage(packageName);
+    if (aPackage != null) {
+      String v = aPackage.getImplementationVersion();
+      if (v == null) {
+        return "na";
+      } else {
+        return v;
+      }
+    }
+    return "na";
+  }
+
+  static String getPackageName(String className) {
+    int j = className.lastIndexOf('.');
+    return className.substring(0, j);
+  }
+
+  String getJarNameOfClass(Class type) {
+    try {
+      if (type != null) {
+
+        // file:/C:/java/maven-2.0.8/repo/com/icegreen/greenmail/1.3/greenmail-1.3.jar
+        URL resource = type.getProtectionDomain().getCodeSource().getLocation();
+        if (resource != null) {
+          String text = resource.toString();
+          // now lets remove all but the file name
+          int idx = text.lastIndexOf('/');
+          if (idx > 0) {
+            text = text.substring(idx + 1);
+          }
+          idx = text.lastIndexOf('\\');
+          if (idx > 0) {
+            text = text.substring(idx + 1);
+          }
+          return text;
+        }
+      }
+    } catch (Exception e) {
+      // ignore
+    }
+    return "na";
+  }
+
+  
+  private Class bestEffortFindClass(String className) {
+    try {
+      return Thread.currentThread().getContextClassLoader()
+          .loadClass(className);
+    } catch (ClassNotFoundException e) {
+      try {
+        return Class.forName(className);
+      } catch (ClassNotFoundException e1) {
+        return null;
+      }
+    }
+  }
+
+}

Copied: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/PlatformInfo.java (from r1772, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/helpers/PlatformInfo.java)
==============================================================================
--- /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/helpers/PlatformInfo.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/PlatformInfo.java	Fri Sep  5 19:14:47 2008
@@ -1,4 +1,4 @@
-package ch.qos.logback.classic.helpers;
+package ch.qos.logback.classic.spi;
 
 /**
  * This class provides information about the runtime platform.

Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/STEUtil.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/STEUtil.java	Fri Sep  5 19:14:47 2008
@@ -0,0 +1,48 @@
+package ch.qos.logback.classic.spi;
+
+public class STEUtil {
+
+  
+  static int findNumberOfCommonFrames(StackTraceElement[] steArray,
+      StackTraceElement[] otherSTEArray) {
+    if (otherSTEArray == null) {
+      return 0;
+    }
+
+    int steIndex = steArray.length - 1;
+    int parentIndex = otherSTEArray.length - 1;
+    int count = 0;
+    while (steIndex >= 0 && parentIndex >= 0) {
+      if (steArray[steIndex].equals(otherSTEArray[parentIndex])) {
+        count++;
+      } else {
+        break;
+      }
+      steIndex--;
+      parentIndex--;
+    }
+    return count;
+  }
+  
+  
+  static int findNumberOfCommonFrames(StackTraceElement[] steArray,
+      StackTraceElementProxy[] otherSTEPArray) {
+    if (otherSTEPArray == null) {
+      return 0;
+    }
+
+    int steIndex = steArray.length - 1;
+    int parentIndex = otherSTEPArray.length - 1;
+    int count = 0;
+    while (steIndex >= 0 && parentIndex >= 0) {
+      if (steArray[steIndex].equals(otherSTEPArray[parentIndex].ste)) {
+        count++;
+      } else {
+        break;
+      }
+      steIndex--;
+      parentIndex--;
+    }
+    return count;
+  }
+}

Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/StackTraceElementProxy.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/StackTraceElementProxy.java	Fri Sep  5 19:14:47 2008
@@ -0,0 +1,59 @@
+package ch.qos.logback.classic.spi;
+
+import java.io.Serializable;
+
+
+
+public class StackTraceElementProxy implements Serializable {
+
+  private static final long serialVersionUID = -4832130320500439038L;
+
+  final StackTraceElement ste;
+  private String steAsString;
+  private PackageInfo pi;
+  
+  StackTraceElementProxy(StackTraceElement ste) {
+    if(ste == null) {
+      throw new IllegalArgumentException("ste cannot be null");
+    }
+    this.ste = ste;
+  }
+  
+  public String getSTEAsString() {
+    if(steAsString == null) {
+      steAsString = "\tat "+ste.toString();
+    }
+    return steAsString;
+  }
+  
+  void setPackageInfo(PackageInfo pi) {
+    this.pi = pi;
+  }
+  
+  public PackageInfo getPackageInfo() {
+    return pi;
+  }
+
+  @Override
+  public int hashCode() {
+    return ste.hashCode();
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj)
+      return true;
+    if (obj == null)
+      return false;
+    if (getClass() != obj.getClass())
+      return false;
+    final StackTraceElementProxy other = (StackTraceElementProxy) obj;
+    return ste.equals(other.ste);
+  }
+  
+  @Override
+  public String toString() {
+    return getSTEAsString();
+  }
+  
+}

Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableDataPoint.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableDataPoint.java	Fri Sep  5 19:14:47 2008
@@ -0,0 +1,100 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ * 
+ * Copyright (C) 2000-2008, QOS.ch
+ * 
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.classic.spi;
+
+import java.io.Serializable;
+
+
+
+/**
+ * A container for either raw strings or StackTraceElementProxy instances.
+ * 
+ * @author Ceki G&uuml;lc&uuml;
+ * 
+ */
+public class ThrowableDataPoint implements Serializable {
+
+  private static final long serialVersionUID = -2891376879381358469L;
+
+  public enum ThrowableDataPointType {
+    RAW, STEP;
+  }
+
+  String rawString;
+  StackTraceElementProxy step;
+  final ThrowableDataPointType type;
+
+  public ThrowableDataPoint(String rawString) {
+    this.rawString = rawString;
+    this.type = ThrowableDataPointType.RAW;
+  }
+
+  public ThrowableDataPoint(StackTraceElement ste) {
+    this.step = new StackTraceElementProxy(ste);
+    this.type = ThrowableDataPointType.STEP;
+  }
+
+  public ThrowableDataPointType getType() {
+    return type;
+  }
+
+  public StackTraceElementProxy getStackTraceElementProxy() {
+    return step;
+  }
+  
+  @Override
+  public String toString() {
+    switch (type) {
+    case RAW:
+      return rawString;
+    case STEP:
+      return step.getSTEAsString();
+    }
+    throw new IllegalStateException("Unreachable code");
+  }
+
+  @Override
+  public int hashCode() {
+    switch (type) {
+    case RAW:
+      return rawString.hashCode();
+    case STEP:
+      return step.hashCode();
+    }
+    throw new IllegalStateException("Unreachable code");
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj)
+      return true;
+    if (obj == null)
+      return false;
+    if (getClass() != obj.getClass())
+      return false;
+    final ThrowableDataPoint other = (ThrowableDataPoint) obj;
+
+    switch (type) {
+    case RAW:
+      if (rawString == null) {
+        if (other.rawString != null)
+          return false;
+        else
+          return true;
+      } else {
+        return rawString.equals(other.rawString);
+      }
+    case STEP:
+      return step.equals(other.step);
+    }
+    throw new IllegalStateException("Unreachable code");
+  }
+
+}

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableProxy.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableProxy.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableProxy.java	Fri Sep  5 19:14:47 2008
@@ -11,25 +11,34 @@
 
 import java.util.Arrays;
 
-import ch.qos.logback.core.Layout;
-import ch.qos.logback.core.helpers.ThrowableDataPoint;
-import ch.qos.logback.core.helpers.ThrowableToDataPointArray;
 
 public class ThrowableProxy implements java.io.Serializable {
 
   private static final long serialVersionUID = 6307784764626694851L;
   private ThrowableDataPoint[] tdpArray;
   private transient final Throwable throwable;
+  private transient PackageInfoCalculator packageInfoCalculator;
 
   public ThrowableProxy(Throwable throwable) {
     this.throwable = throwable;
-    tdpArray = ThrowableToDataPointArray.convert(throwable);
+    this.tdpArray =  ThrowableToDataPointArray.convert(throwable);
   }
 
   public Throwable getThrowable() {
     return throwable;
   }
   
+  
+  public PackageInfoCalculator getPackageInfoCalculator() {
+    // if original instance (non-deserialized), and packageInfoCalculator
+    // is not already initialized, then create an instance
+    // here we assume that (throwable == null) for deserialized instances 
+    if(throwable != null && packageInfoCalculator == null) {
+      packageInfoCalculator = new PackageInfoCalculator();
+    }
+    return packageInfoCalculator;
+  }
+
   /**
    * The data point representation of the throwable proxy.
    */

Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableToDataPointArray.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/ThrowableToDataPointArray.java	Fri Sep  5 19:14:47 2008
@@ -0,0 +1,72 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ * 
+ * Copyright (C) 2000-2008, QOS.ch
+ * 
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+
+package ch.qos.logback.classic.spi;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import ch.qos.logback.core.CoreGlobal;
+
+/**
+ * Convert a throwable into an array of ThrowableDataPoint objects.
+ * 
+ *  
+ * @author Ceki G&uuml;lc&uuml;
+ */
+public class ThrowableToDataPointArray {
+
+  static final ThrowableDataPoint[] TEMPLATE_ARRAY = new ThrowableDataPoint[0];
+
+  
+  static public ThrowableDataPoint[] convert(Throwable t) {
+    List<ThrowableDataPoint> tdpList = new LinkedList<ThrowableDataPoint>();
+    extract(tdpList, t, null);
+    return tdpList.toArray(TEMPLATE_ARRAY);
+  }
+
+  static private void extract(List<ThrowableDataPoint> tdpList, Throwable t,
+      StackTraceElement[] parentSTE) {
+    StackTraceElement[] ste = t.getStackTrace();
+    final int numberOfcommonFrames = STEUtil.findNumberOfCommonFrames(ste, parentSTE);
+
+    tdpList.add(firstLineToDataPoint(t, parentSTE));
+    for (int i = 0; i < (ste.length - numberOfcommonFrames); i++) {
+      tdpList.add(new ThrowableDataPoint(ste[i]));
+    }
+    
+    if (numberOfcommonFrames != 0) {
+      tdpList.add(new ThrowableDataPoint("\t... "+numberOfcommonFrames
+          + " common frames omitted"));
+    }
+
+    Throwable cause = t.getCause();
+    if (cause != null) {
+      extract(tdpList, cause, ste);
+    }
+  }
+
+  private static ThrowableDataPoint firstLineToDataPoint(Throwable t,
+      StackTraceElement[] parentSTE) {
+    String prefix = "";
+    if (parentSTE != null) {
+      prefix = CoreGlobal.CAUSED_BY;
+    }
+
+    String result = prefix + t.getClass().getName();
+    if (t.getMessage() != null) {
+      result += ": " + t.getMessage();
+    }
+    return new ThrowableDataPoint(result);
+  }
+
+ 
+
+}

Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java	(original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/AllClassicTest.java	Fri Sep  5 19:14:47 2008
@@ -20,7 +20,6 @@
  
     suite.addTest(ch.qos.logback.classic.PackageTest.suite());
     suite.addTest(ch.qos.logback.classic.control.PackageTest.suite());
-    
     suite.addTest(ch.qos.logback.classic.joran.PackageTest.suite());
     suite.addTest(ch.qos.logback.classic.boolex.PackageTest.suite());
     suite.addTest(ch.qos.logback.classic.selector.PackageTest.suite()); 

Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java	(original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java	Fri Sep  5 19:14:47 2008
@@ -20,9 +20,9 @@
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.classic.spi.ThrowableDataPoint;
 import ch.qos.logback.classic.spi.ThrowableProxy;
 import ch.qos.logback.core.CoreGlobal;
-import ch.qos.logback.core.helpers.ThrowableDataPoint;
 import ch.qos.logback.core.read.ListAppender;
 
 public class HTMLLayoutTest {

Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ConverterTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ConverterTest.java	(original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ConverterTest.java	Fri Sep  5 19:14:47 2008
@@ -116,14 +116,14 @@
 
   public void testException() {
     {
-      DynamicConverter<LoggingEvent> converter = new ThrowableInformationConverter();
+      DynamicConverter<LoggingEvent> converter = new ThrowableProxyConverter();
       StringBuffer buf = new StringBuffer();
       converter.write(buf, le);
       // System.out.println(buf);
     }
 
     {
-      DynamicConverter<LoggingEvent> converter = new ThrowableInformationConverter();
+      DynamicConverter<LoggingEvent> converter = new ThrowableProxyConverter();
       this.optionList.add("3");
       converter.setOptionList(this.optionList);
       StringBuffer buf = new StringBuffer();

Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ExtendedThrowableProxyConverterTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ExtendedThrowableProxyConverterTest.java	Fri Sep  5 19:14:47 2008
@@ -0,0 +1,71 @@
+package ch.qos.logback.classic.pattern;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.spi.LoggingEvent;
+
+public class ExtendedThrowableProxyConverterTest {
+
+  LoggerContext lc = new LoggerContext();
+  ExtendedThrowableProxyConverter etpc = new ExtendedThrowableProxyConverter();
+  StringWriter sw = new StringWriter();
+  PrintWriter pw = new PrintWriter(sw);
+
+  @Before
+  public void setUp() throws Exception {
+    etpc.setContext(lc);
+    etpc.start();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+  }
+
+  private LoggingEvent createLoggingEvent(Throwable t) {
+    LoggingEvent le = new LoggingEvent(this.getClass().getName(), lc
+        .getLogger(LoggerContext.ROOT_NAME), Level.DEBUG, "test message", t,
+        null);
+    return le;
+  }
+
+  @Test
+  public void smoke() {
+    Exception t = new Exception("smoke");
+    verify(t);
+  }
+
+  @Test
+  @Ignore
+  public void nested() {
+    Throwable t = makeNestedException(1);
+    verify(t);
+  }
+
+  void verify(Throwable t) {
+    t.printStackTrace(pw);
+
+    LoggingEvent le = createLoggingEvent(t);
+    String result = etpc.convert(le);
+    result = result.replace("common frames omitted", "more");
+    result = result.replaceAll(" \\[.*\\]", "");
+    assertEquals(sw.toString(), result);
+  }
+
+  Throwable makeNestedException(int level) {
+    if (level == 0) {
+      return new Exception("nesting level=" + level);
+    }
+    Throwable cause = makeNestedException(level - 1);
+    return new Exception("nesting level =" + level, cause);
+  }
+}

Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/pattern/LRUCacheTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/pattern/LRUCacheTest.java	(original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/pattern/LRUCacheTest.java	Fri Sep  5 19:14:47 2008
@@ -11,6 +11,7 @@
 import ch.qos.logback.classic.pattern.lru.Event;
 import ch.qos.logback.classic.pattern.lru.T_LRUCache;
 
+ at Ignore
 public class LRUCacheTest {
 
   @Test

Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ThrowableProxyConverterTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ThrowableProxyConverterTest.java	Fri Sep  5 19:14:47 2008
@@ -0,0 +1,69 @@
+package ch.qos.logback.classic.pattern;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.spi.LoggingEvent;
+
+public class ThrowableProxyConverterTest {
+
+  LoggerContext lc = new LoggerContext();
+  ThrowableProxyConverter tpc = new ThrowableProxyConverter();
+  StringWriter sw = new StringWriter();
+  PrintWriter pw = new PrintWriter(sw);
+
+  @Before
+  public void setUp() throws Exception {
+    tpc.setContext(lc);
+    tpc.start();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+  }
+
+  private LoggingEvent createLoggingEvent(Throwable t) {
+    LoggingEvent le = new LoggingEvent(this.getClass().getName(), lc
+        .getLogger(LoggerContext.ROOT_NAME), Level.DEBUG, "test message", t,
+        null);
+    return le;
+  }
+
+  @Test
+  public void smoke() {
+    Exception t = new Exception("smoke");
+    verify(t);
+  }
+
+  @Test
+  public void nested() {
+    Throwable t = makeNestedException(1);
+    verify(t);
+  }
+
+  void verify(Throwable t) {
+    t.printStackTrace(pw);
+
+    LoggingEvent le = createLoggingEvent(t);
+    String result = tpc.convert(le);
+    System.out.println(result);
+    result = result.replace("common frames omitted", "more");
+    assertEquals(sw.toString(), result);
+  }
+
+  Throwable makeNestedException(int level) {
+    if (level == 0) {
+      return new Exception("nesting level=" + level);
+    }
+    Throwable cause = makeNestedException(level - 1);
+    return new Exception("nesting level =" + level, cause);
+  }
+}

Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/spi/PackageInfoTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/spi/PackageInfoTest.java	Fri Sep  5 19:14:47 2008
@@ -0,0 +1,85 @@
+package ch.qos.logback.classic.spi;
+
+import java.util.Random;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.icegreen.greenmail.util.GreenMail;
+import com.icegreen.greenmail.util.ServerSetup;
+
+public class PackageInfoTest {
+
+  int diff = 1024 + new Random().nextInt(10000);
+ 
+  @Before
+  public void setUp() throws Exception {
+  }
+
+  @After
+  public void tearDown() throws Exception {
+  }
+
+  @Test
+  public void withGreenMail() {
+    try {
+      ServerSetup serverSetup = new ServerSetup(-1, "localhost",
+          ServerSetup.PROTOCOL_SMTP);
+      GreenMail greenMail = new GreenMail((ServerSetup) null);
+      // greenMail.start();
+    } catch (Throwable e) {
+      // e.printStackTrace();
+      StackTraceElement[] stea = e.getStackTrace();
+      PackageInfoCalculator pic = new PackageInfoCalculator();
+      
+      ThrowableDataPoint[] tdpa = ThrowableToDataPointArray.convert(e);
+      pic.computePackageInfo(tdpa);
+      
+      
+      //for (ThrowableDataPoint ste : stea) {
+///
+   //   }
+    }
+  }
+
+  public void doPerf(boolean withPI) {
+    try {
+      ServerSetup serverSetup = new ServerSetup(-1, "localhost",
+          ServerSetup.PROTOCOL_SMTP);
+      GreenMail greenMail = new GreenMail((ServerSetup) null);
+      // greenMail.start();
+    } catch (Throwable e) {
+      StackTraceElement[] stea = e.getStackTrace();
+      
+      if (withPI) {
+        PackageInfoCalculator pic = new PackageInfoCalculator();
+        for (StackTraceElement ste : stea) {
+          String className = ste.getClassName();
+          //PackageInfo pi = pic.compute(className);
+        }
+      }
+    }
+  }
+
+  double loop(int len, boolean withPI) {
+    long start = System.nanoTime();
+    for (int i = 0; i < len; i++) {
+      doPerf(withPI);
+    }
+    return (1.0*System.nanoTime() - start)/len/1000;
+  }
+
+  @Test
+  public void perfTest() {
+    int len = 10000;
+    loop(len, false);
+    loop(len, true);
+    
+    double d0 = loop(len, false);
+    System.out.println("without package info " + d0+" microseconds");
+
+    double d1 = loop(len, true);
+    System.out.println("with    package info " + d1 +" microseconds");
+  }
+}

Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/spi/PackageTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/spi/PackageTest.java	(original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/spi/PackageTest.java	Fri Sep  5 19:14:47 2008
@@ -23,6 +23,7 @@
     suite.addTestSuite(CallerDataTest.class); 
     suite.addTest(new JUnit4TestAdapter (LoggerComparatorTest.class));
     suite.addTest(new JUnit4TestAdapter (LoggingEventSerializationTest.class));
+    suite.addTest(new JUnit4TestAdapter(ch.qos.logback.classic.spi.ThrowableToDataPointTest.class));
     return suite;
   }
 }
\ No newline at end of file

Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/spi/PackageVersionCalculatorTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/spi/PackageVersionCalculatorTest.java	Fri Sep  5 19:14:47 2008
@@ -0,0 +1,47 @@
+package ch.qos.logback.classic.spi;
+
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import ch.qos.logback.core.CoreGlobal;
+
+public class PackageVersionCalculatorTest {
+
+  @Before
+  public void setUp() throws Exception {
+  }
+
+  @After
+  public void tearDown() throws Exception {
+  }
+
+  @Test
+  public void test() throws Exception {
+    Throwable t = new Throwable("x");
+    //t.printStackTrace();
+    ThrowableProxy tp = new ThrowableProxy(t);
+    PackageInfoCalculator pic = new PackageInfoCalculator();
+    pic.computePackageInfo(tp.getThrowableDataPointArray());
+    StringBuilder builder = new StringBuilder();
+    for(ThrowableDataPoint tdp: tp.getThrowableDataPointArray()) {
+      String string = tdp.toString();
+      builder.append(string);
+      extraData(builder, tdp);
+      builder.append(CoreGlobal.LINE_SEPARATOR);
+    }
+    System.out.println(builder.toString());
+  }
+  
+  protected void extraData(StringBuilder builder, ThrowableDataPoint tdp) {
+    StackTraceElementProxy step = tdp.getStackTraceElementProxy();
+    if(step != null) {
+      PackageInfo pi = step.getPackageInfo();
+      if(pi != null) {
+        builder.append(" [").append(pi.getJarName()).append(':').append(pi.getVersion()).append(']');
+      }
+    }
+  }
+  
+}

Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/spi/ThrowableToDataPointTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/spi/ThrowableToDataPointTest.java	Fri Sep  5 19:14:47 2008
@@ -0,0 +1,83 @@
+package ch.qos.logback.classic.spi;
+
+import static org.junit.Assert.*;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import ch.qos.logback.classic.spi.ThrowableDataPoint;
+import ch.qos.logback.classic.spi.ThrowableToDataPointArray;
+import ch.qos.logback.core.Layout;
+
+public class ThrowableToDataPointTest {
+
+  StringWriter sw = new StringWriter();
+  PrintWriter pw = new PrintWriter(sw);
+
+  @Before
+  public void setUp() throws Exception {
+  }
+
+  @After
+  public void tearDown() throws Exception {
+  }
+
+  public void verify(Throwable t) {
+    t.printStackTrace(pw);
+    
+    ThrowableDataPoint[] tdpArray = ThrowableToDataPointArray.convert(t);
+    StringBuilder sb = new StringBuilder();
+    for (ThrowableDataPoint tdp : tdpArray) {
+      sb.append(tdp.toString());
+      sb.append(Layout.LINE_SEP);
+    }
+    String expected = sw.toString();
+    String result = sb.toString().replace("common frames omitted", "more");
+    
+    assertEquals(expected, result);
+  }
+  
+  @Test
+  public void smoke() {
+    Exception e = new Exception("smoke");
+    verify(e);
+  }
+
+  @Test
+  public void nested() {
+    Exception w = null;
+    try {
+      someMethod();
+    } catch (Exception e) {
+      w = new Exception("wrapping", e);
+    }
+    verify(w);
+  }
+
+  @Test
+  public void multiNested() {
+    Exception w = null;
+    try {
+      someOtherMethod();
+    } catch (Exception e) {
+      w = new Exception("wrapping", e);
+    }
+    verify(w);
+  }
+  
+  void someMethod() throws Exception {
+    throw new Exception("someMethod");
+  }
+
+  void someOtherMethod() throws Exception {
+    try {
+      someMethod();
+    } catch (Exception e) {
+      throw new Exception("someOtherMethod", e);
+    }
+  }
+}

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/ThrowableToStringArray.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/ThrowableToStringArray.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/ThrowableToStringArray.java	Fri Sep  5 19:14:47 2008
@@ -9,49 +9,43 @@
  */
 package ch.qos.logback.core.helpers;
 
-import ch.qos.logback.core.CoreGlobal;
+import java.util.LinkedList;
+import java.util.List;
 
+import ch.qos.logback.core.CoreGlobal;
 
 public class ThrowableToStringArray {
 
-  public static String[] extractStringRep(Throwable t, StackTraceElement[] parentSTE) {
-    String[] result;
+  public static String[] convert(Throwable t) {
+    List<String> strList = new LinkedList<String>();
+    extract(strList, t, null);
+    return strList.toArray(new String[0]);
+
+  }
+
+  private static void extract(List<String> strList, Throwable t,
+      StackTraceElement[] parentSTE) {
 
     StackTraceElement[] ste = t.getStackTrace();
     final int numberOfcommonFrames = findNumberOfCommonFrames(ste, parentSTE);
 
-    final String[] firstArray;
-    if (numberOfcommonFrames == 0) {
-      firstArray = new String[ste.length + 1];
-    } else {
-      firstArray = new String[ste.length - numberOfcommonFrames + 2];
-    }
-
-    firstArray[0] = formatFirstLine(t, parentSTE);
+    strList.add(formatFirstLine(t, parentSTE));
     for (int i = 0; i < (ste.length - numberOfcommonFrames); i++) {
-      firstArray[i + 1] = ste[i].toString();
+      strList.add("\tat "+ste[i].toString());
     }
 
     if (numberOfcommonFrames != 0) {
-      firstArray[firstArray.length - 1] = numberOfcommonFrames
-          + " common frames omitted";
+      strList.add("\t... "+numberOfcommonFrames + " common frames omitted");
     }
 
     Throwable cause = t.getCause();
     if (cause != null) {
-      final String[] causeArray = ThrowableToStringArray.extractStringRep(cause, ste);
-      String[] tmp = new String[firstArray.length + causeArray.length];
-      System.arraycopy(firstArray, 0, tmp, 0, firstArray.length);
-      System
-          .arraycopy(causeArray, 0, tmp, firstArray.length, causeArray.length);
-      result = tmp;
-    } else {
-      result = firstArray;
+      ThrowableToStringArray.extract(strList, cause, ste);
     }
-    return result;
   }
-  
-  private static String formatFirstLine(Throwable t, StackTraceElement[] parentSTE) {
+
+  private static String formatFirstLine(Throwable t,
+      StackTraceElement[] parentSTE) {
     String prefix = "";
     if (parentSTE != null) {
       prefix = CoreGlobal.CAUSED_BY;
@@ -63,7 +57,7 @@
     }
     return result;
   }
-  
+
   private static int findNumberOfCommonFrames(StackTraceElement[] ste,
       StackTraceElement[] parentSTE) {
     if (parentSTE == null) {

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/StatusPrinter.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/StatusPrinter.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/StatusPrinter.java	Fri Sep  5 19:14:47 2008
@@ -91,7 +91,7 @@
   }
 
   private static void appendThrowable(StringBuilder sb, Throwable t) {
-    String[] stringRep = ThrowableToStringArray.extractStringRep(t, null);
+    String[] stringRep = ThrowableToStringArray.convert(t);
 
     for (String s : stringRep) {
       if (s.startsWith(CoreGlobal.CAUSED_BY)) {

Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java	(original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java	Fri Sep  5 19:14:47 2008
@@ -18,6 +18,7 @@
   public static Test suite() {
     TestSuite suite = new TestSuite();
     suite.addTest(ch.qos.logback.core.util.PackageTest.suite());
+    suite.addTest(ch.qos.logback.core.helpers.PackageTest.suite());
     suite.addTest(ch.qos.logback.core.pattern.PackageTest.suite());
     suite.addTest(ch.qos.logback.core.joran.PackageTest.suite());
     suite.addTest(ch.qos.logback.core.appender.PackageTest.suite());

Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/helpers/PackageTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/helpers/PackageTest.java	Fri Sep  5 19:14:47 2008
@@ -0,0 +1,15 @@
+package ch.qos.logback.core.helpers;
+
+import junit.framework.JUnit4TestAdapter;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class PackageTest extends TestCase {
+
+  public static Test suite() {
+    TestSuite suite = new TestSuite();
+    suite.addTest(new JUnit4TestAdapter(ch.qos.logback.core.helpers.ThrowableToStringArrayTest.class));
+    return suite;
+  }
+}

Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/helpers/ThrowableToStringArrayTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/helpers/ThrowableToStringArrayTest.java	Fri Sep  5 19:14:47 2008
@@ -0,0 +1,80 @@
+package ch.qos.logback.core.helpers;
+
+import static org.junit.Assert.*;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import ch.qos.logback.core.Layout;
+
+public class ThrowableToStringArrayTest {
+
+  StringWriter sw = new StringWriter();
+  PrintWriter pw = new PrintWriter(sw);
+
+  @Before
+  public void setUp() throws Exception {
+  }
+
+  @After
+  public void tearDown() throws Exception {
+  }
+
+  public void verify(Throwable t) {
+    t.printStackTrace(pw);
+    
+    String[] sa = ThrowableToStringArray.convert(t);
+    StringBuilder sb = new StringBuilder();
+    for (String tdp : sa) {
+      sb.append(tdp.toString());
+      sb.append(Layout.LINE_SEP);
+    }
+    String expected = sw.toString();
+    String result = sb.toString().replace("common frames omitted", "more");
+    assertEquals(expected, result);
+  }
+  
+  @Test
+  public void smoke() {
+    Exception e = new Exception("smoke");
+    verify(e);
+  }
+
+  @Test
+  public void nested() {
+    Exception w = null;
+    try {
+      someMethod();
+    } catch (Exception e) {
+      w = new Exception("wrapping", e);
+    }
+    verify(w);
+  }
+
+  @Test
+  public void multiNested() {
+    Exception w = null;
+    try {
+      someOtherMethod();
+    } catch (Exception e) {
+      w = new Exception("wrapping", e);
+    }
+    verify(w);
+  }
+  
+  void someMethod() throws Exception {
+    throw new Exception("someMethod");
+  }
+
+  void someOtherMethod() throws Exception {
+    try {
+      someMethod();
+    } catch (Exception e) {
+      throw new Exception("someOtherMethod", e);
+    }
+  }
+}


More information about the logback-dev mailing list