You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ch...@apache.org on 2013/11/13 12:17:05 UTC
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/
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 @@
</properties>
<build>
+ <pluginManagement>
+ <plugins>
+ <!--
+ Unfortunately the <ignores> sections do not seem to
+ properly work, so the sniffer is disabled by default.
+
+ Note: 1.9 contains a call to a Java 7 specific method
+ (java.nio.CharBuffer.subSequence(II)Ljava/nio/CharBuffer;)
+ that is triggered when an undefined reference is found. This breaks error
+ reporting on Java 5/6.
+ -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>animal-sniffer-maven-plugin</artifactId>
+ <version>1.8</version>
+ <configuration>
+ <skip>true</skip>
+ <ignores>
+ <ignore>ch.qos.logback.classic.spi*</ignore>
+ </ignores>
+ <signature>
+ <groupId>org.codehaus.mojo.signature</groupId>
+ <artifactId>java1${sling.java.version}</artifactId>
+ <version>1.0</version>
+ </signature>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
@@ -209,6 +239,8 @@
</plugins>
</build>
+
+
<reporting>
<plugins>
<plugin>
@@ -259,12 +291,14 @@
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
- <version>4.0.0</version>
+ <version>4.2.0</version>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
- <version>4.0.0</version>
+ <version>4.2.0</version>
+ <scope>provided</scope>
</dependency>
<!-- servlet API for the web console plugin -->
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<String, ClassPackagingData> cache = new HashMap<String, ClassPackagingData>();
+
+ 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();