Return-Path: X-Original-To: apmail-sling-commits-archive@www.apache.org Delivered-To: apmail-sling-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id BAB3A103DF for ; Wed, 13 Nov 2013 11:17:32 +0000 (UTC) Received: (qmail 38359 invoked by uid 500); 13 Nov 2013 11:17:32 -0000 Delivered-To: apmail-sling-commits-archive@sling.apache.org Received: (qmail 38289 invoked by uid 500); 13 Nov 2013 11:17:32 -0000 Mailing-List: contact commits-help@sling.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@sling.apache.org Delivered-To: mailing list commits@sling.apache.org Received: (qmail 38282 invoked by uid 99); 13 Nov 2013 11:17:32 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 13 Nov 2013 11:17:32 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 13 Nov 2013 11:17:27 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id D99AD238896F; Wed, 13 Nov 2013 11:17:05 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1541471 - in /sling/trunk/bundles/commons/log: ./ src/main/java/ch/qos/logback/classic/spi/ src/test/java/org/apache/sling/commons/log/logback/integration/ Date: Wed, 13 Nov 2013 11:17:05 -0000 To: commits@sling.apache.org From: chetanm@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20131113111705.D99AD238896F@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: chetanm Date: Wed Nov 13 11:17:05 2013 New Revision: 1541471 URL: http://svn.apache.org/r1541471 Log: SLING-3049 - Make Logback Stacktrace Packaging data support OSGi aware Adding OSGi aware PackagingDataCalculator Also disabled animal-sniffer-maven-plugin as it is causing issue. See bug notes for details Added: sling/trunk/bundles/commons/log/src/main/java/ch/qos/logback/classic/spi/ sling/trunk/bundles/commons/log/src/main/java/ch/qos/logback/classic/spi/PackagingDataCalculator.java (with props) Modified: sling/trunk/bundles/commons/log/pom.xml sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITAppenderServices.java sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITConfigFragments.java Modified: sling/trunk/bundles/commons/log/pom.xml URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/log/pom.xml?rev=1541471&r1=1541470&r2=1541471&view=diff ============================================================================== --- sling/trunk/bundles/commons/log/pom.xml (original) +++ sling/trunk/bundles/commons/log/pom.xml Wed Nov 13 11:17:05 2013 @@ -59,6 +59,36 @@ + + + + + org.codehaus.mojo + animal-sniffer-maven-plugin + 1.8 + + true + + ch.qos.logback.classic.spi* + + + org.codehaus.mojo.signature + java1${sling.java.version} + 1.0 + + + + + + org.apache.felix @@ -209,6 +239,8 @@ + + @@ -259,12 +291,14 @@ org.osgi org.osgi.core - 4.0.0 + 4.2.0 + provided org.osgi org.osgi.compendium - 4.0.0 + 4.2.0 + provided Added: sling/trunk/bundles/commons/log/src/main/java/ch/qos/logback/classic/spi/PackagingDataCalculator.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/log/src/main/java/ch/qos/logback/classic/spi/PackagingDataCalculator.java?rev=1541471&view=auto ============================================================================== --- sling/trunk/bundles/commons/log/src/main/java/ch/qos/logback/classic/spi/PackagingDataCalculator.java (added) +++ sling/trunk/bundles/commons/log/src/main/java/ch/qos/logback/classic/spi/PackagingDataCalculator.java Wed Nov 13 11:17:05 2013 @@ -0,0 +1,264 @@ +/** + * Logback: the reliable, generic, fast and flexible logging framework. + * Copyright (C) 1999-2013, QOS.ch. All rights reserved. + * + * This program and the accompanying materials are dual-licensed under + * either the terms of the Eclipse Public License v1.0 as published by + * the Eclipse Foundation + * + * or (per the licensee's choosing) + * + * under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation. + */ +package ch.qos.logback.classic.spi; + +import java.net.URL; +import java.security.CodeSource; +import java.util.HashMap; + +import org.osgi.framework.Bundle; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.Version; +import sun.reflect.Reflection; +// import java.security.AccessControlException; import java.security.AccessController;import java.security.PrivilegedAction; +/** + * Given a classname locate associated PackageInfo (jar name, version name). + * + * @author James Strachan + * @Ceki Gülcü + */ +public class PackagingDataCalculator { + + final static StackTraceElementProxy[] STEP_ARRAY_TEMPLATE = new StackTraceElementProxy[0]; + + HashMap cache = new HashMap(); + + private static boolean GET_CALLER_CLASS_METHOD_AVAILABLE = false; //private static boolean HAS_GET_CLASS_LOADER_PERMISSION = false; + + static { + // if either the Reflection class or the getCallerClass method + // are unavailable, then we won't invoke Reflection.getCallerClass() + // This approach ensures that this class will *run* on JDK's lacking + // sun.reflect.Reflection class. However, this class will *not compile* + // on JDKs lacking sun.reflect.Reflection. + try { + Reflection.getCallerClass(2); + GET_CALLER_CLASS_METHOD_AVAILABLE = true; + } catch (NoClassDefFoundError e) { + } catch (NoSuchMethodError e) { + } catch (Throwable e) { + System.err.println("Unexpected exception"); + e.printStackTrace(); + } + } + + + public void calculate(IThrowableProxy tp) { + while (tp != null) { + populateFrames(tp.getStackTraceElementProxyArray()); + IThrowableProxy[] suppressed = tp.getSuppressed(); + if(suppressed != null) { + for(IThrowableProxy current:suppressed) { + populateFrames(current.getStackTraceElementProxyArray()); + } + } + tp = tp.getCause(); + } + } + + void populateFrames(StackTraceElementProxy[] stepArray) { + // in the initial part of this method we populate package information for + // common stack frames + final Throwable t = new Throwable("local stack reference"); + final StackTraceElement[] localteSTEArray = t.getStackTrace(); + final int commonFrames = STEUtil.findNumberOfCommonFrames(localteSTEArray, + stepArray); + final int localFirstCommon = localteSTEArray.length - commonFrames; + final int stepFirstCommon = stepArray.length - commonFrames; + + ClassLoader lastExactClassLoader = null; + ClassLoader firsExactClassLoader = null; + + int missfireCount = 0; + for (int i = 0; i < commonFrames; i++) { + Class callerClass = null; + if (GET_CALLER_CLASS_METHOD_AVAILABLE) { + callerClass = Reflection.getCallerClass(localFirstCommon + i + - missfireCount + 1); + } + StackTraceElementProxy step = stepArray[stepFirstCommon + i]; + String stepClassname = step.ste.getClassName(); + + if (callerClass != null && stepClassname.equals(callerClass.getName())) { + // see also LBCLASSIC-263 + lastExactClassLoader = callerClass.getClassLoader(); + if (firsExactClassLoader == null) { + firsExactClassLoader = lastExactClassLoader; + } + ClassPackagingData pi = calculateByExactType(callerClass); + step.setClassPackagingData(pi); + } else { + missfireCount++; + ClassPackagingData pi = computeBySTEP(step, lastExactClassLoader); + step.setClassPackagingData(pi); + } + } + populateUncommonFrames(commonFrames, stepArray, firsExactClassLoader); + } + + void populateUncommonFrames(int commonFrames, + StackTraceElementProxy[] stepArray, ClassLoader firstExactClassLoader) { + int uncommonFrames = stepArray.length - commonFrames; + for (int i = 0; i < uncommonFrames; i++) { + StackTraceElementProxy step = stepArray[i]; + ClassPackagingData pi = computeBySTEP(step, firstExactClassLoader); + step.setClassPackagingData(pi); + } + } + + private ClassPackagingData calculateByExactType(Class type) { + String className = type.getName(); + ClassPackagingData cpd = cache.get(className); + if (cpd != null) { + return cpd; + } + String version = getImplementationVersion(type); + String codeLocation = getCodeLocation(type); + cpd = new ClassPackagingData(codeLocation, version); + cache.put(className, cpd); + return cpd; + } + + private ClassPackagingData computeBySTEP(StackTraceElementProxy step, + ClassLoader lastExactClassLoader) { + String className = step.ste.getClassName(); + ClassPackagingData cpd = cache.get(className); + if (cpd != null) { + return cpd; + } + Class type = bestEffortLoadClass(lastExactClassLoader, className); + String version = getImplementationVersion(type); + String codeLocation = getCodeLocation(type); + cpd = new ClassPackagingData(codeLocation, version, false); + cache.put(className, cpd); + return cpd; + } + + String getImplementationVersion(Class type) { + if (type == null) { + return "na"; + } + + Bundle b = FrameworkUtil.getBundle(type); + if(b != null){ + final Version version = b.getVersion(); + return version == org.osgi.framework.Version.emptyVersion ? "na" : version.toString(); + } + + Package aPackage = type.getPackage(); + if (aPackage != null) { + String v = aPackage.getImplementationVersion(); + if (v == null) { + return "na"; + } else { + return v; + } + } + return "na"; + + } + + String getCodeLocation(Class type) { + try { + if (type != null) { + + Bundle b = FrameworkUtil.getBundle(type); + if(b != null){ + return b.getSymbolicName(); + } + // file:/C:/java/maven-2.0.8/repo/com/icegreen/greenmail/1.3/greenmail-1.3.jar + CodeSource codeSource = type.getProtectionDomain().getCodeSource(); + if (codeSource != null) { + URL resource = codeSource.getLocation(); + if (resource != null) { + String locationStr = resource.toString(); + // now lets remove all but the file name + String result = getCodeLocation(locationStr, '/'); + if (result != null) { + return result; + } + return getCodeLocation(locationStr, '\\'); + } + } + } + } catch (Exception e) { + // ignore + } + return "na"; + } + + private String getCodeLocation(String locationStr, char separator) { + int idx = locationStr.lastIndexOf(separator); + if (isFolder(idx, locationStr)) { + idx = locationStr.lastIndexOf(separator, idx - 1); + return locationStr.substring(idx + 1); + } else if (idx > 0) { + return locationStr.substring(idx + 1); + } + return null; + } + + private boolean isFolder(int idx, String text) { + return (idx != -1 && idx + 1 == text.length()); + } + + private Class loadClass(ClassLoader cl, String className) { + if (cl == null) { + return null; + } + try { + return cl.loadClass(className); + } catch (ClassNotFoundException e1) { + return null; + } catch (NoClassDefFoundError e1) { + return null; + } catch (Exception e) { + e.printStackTrace(); // this is unexpected + return null; + } + + } + + /** + * @param lastGuaranteedClassLoader may be null + * @param className + * @return + */ + private Class bestEffortLoadClass(ClassLoader lastGuaranteedClassLoader, + String className) { + Class result = loadClass(lastGuaranteedClassLoader, className); + if (result != null) { + return result; + } + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + if (tccl != lastGuaranteedClassLoader) { + result = loadClass(tccl, className); + } + if (result != null) { + return result; + } + + try { + return Class.forName(className); + } catch (ClassNotFoundException e1) { + return null; + } catch (NoClassDefFoundError e1) { + return null; + } catch (Exception e) { + e.printStackTrace(); // this is unexpected + return null; + } + } + +} Propchange: sling/trunk/bundles/commons/log/src/main/java/ch/qos/logback/classic/spi/PackagingDataCalculator.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITAppenderServices.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITAppenderServices.java?rev=1541471&r1=1541470&r2=1541471&view=diff ============================================================================== --- sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITAppenderServices.java (original) +++ sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITAppenderServices.java Wed Nov 13 11:17:05 2013 @@ -28,7 +28,9 @@ import javax.inject.Inject; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ClassPackagingData; import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.StackTraceElementProxy; import ch.qos.logback.core.Appender; import ch.qos.logback.core.AppenderBase; import org.junit.After; @@ -44,7 +46,9 @@ import org.osgi.service.cm.Configuration import org.osgi.service.cm.ConfigurationAdmin; import org.slf4j.LoggerFactory; +import static org.hamcrest.CoreMatchers.startsWith; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.ops4j.pax.exam.CoreOptions.composite; import static org.ops4j.pax.exam.CoreOptions.mavenBundle; @@ -119,6 +123,26 @@ public class ITAppenderServices extends assertEquals(2, ta.events.size()); } + @Test + public void testPackagingData() throws Exception { + TestAppender ta = registerAppender("foo.bar.packaging"); + delay(); + + Logger foo = (Logger)LoggerFactory.getLogger("foo.bar.packaging"); + foo.warn("This is a test", new Exception()); + + // One event should be logged. + assertEquals(1, ta.events.size()); + ILoggingEvent e = ta.events.get(0); + StackTraceElementProxy[] stProxies = e.getThrowableProxy().getStackTraceElementProxyArray(); + + ClassPackagingData cpd1 = stProxies[0].getClassPackagingData(); + + //For pax exam the bundle is created with name starting with PAXEXAM-PROBE + //As codeLocation is OSGi env is bundle symbolic name we check for that + assertThat(cpd1.getCodeLocation(), startsWith("PAXEXAM-PROBE")); + } + @After public void unregisterAppender(){ sr.unregister(); Modified: sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITConfigFragments.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITConfigFragments.java?rev=1541471&r1=1541470&r2=1541471&view=diff ============================================================================== --- sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITConfigFragments.java (original) +++ sling/trunk/bundles/commons/log/src/test/java/org/apache/sling/commons/log/logback/integration/ITConfigFragments.java Wed Nov 13 11:17:05 2013 @@ -19,12 +19,12 @@ package org.apache.sling.commons.log.logback.integration; +import java.util.Dictionary; import java.util.Properties; import javax.inject.Inject; import org.apache.sling.commons.log.logback.ConfigProvider; -import org.apache.sling.commons.log.logback.integration.LogTestBase; import org.junit.Test; import org.junit.runner.RunWith; import org.ops4j.pax.exam.Option; @@ -109,7 +109,7 @@ public class ITConfigFragments extends L fcp.fileName = "test-reset-config-2.xml"; - eventAdmin.sendEvent(new Event(RESET_EVENT_TOPIC, new Properties())); + eventAdmin.sendEvent(new Event(RESET_EVENT_TOPIC, (Dictionary)null)); delay();