Repository: logging-log4j2
Updated Branches:
  refs/heads/master d71541572 -> 4ccf5cc41


LOG4J2-920: Fix import-package omission causing CNFE in OSGi


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/4ccf5cc4
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/4ccf5cc4
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/4ccf5cc4

Branch: refs/heads/master
Commit: 4ccf5cc41e479ef370ef5e21e99bc0adf1ebd79e
Parents: d715415
Author: Matt Sicker <[email protected]>
Authored: Mon Feb 8 20:27:09 2016 -0600
Committer: Matt Sicker <[email protected]>
Committed: Mon Feb 8 20:27:09 2016 -0600

----------------------------------------------------------------------
 log4j-api/pom.xml                               |  13 +-
 .../log4j/osgi/AbstractLoadBundleTest.java      | 140 ++++++++++++++++++-
 .../logging/log4j/osgi/BundleTestInfo.java      |   2 +-
 .../logging/log4j/core/osgi/Activator.java      |   3 +-
 src/changes/changes.xml                         |   3 +
 5 files changed, 148 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/4ccf5cc4/log4j-api/pom.xml
----------------------------------------------------------------------
diff --git a/log4j-api/pom.xml b/log4j-api/pom.xml
index 0291d96..e4df6f5 100644
--- a/log4j-api/pom.xml
+++ b/log4j-api/pom.xml
@@ -33,6 +33,12 @@
     <projectDir>/api</projectDir>
   </properties>
   <dependencies>
+    <!-- Place Felix before Equinox because Felix is signed. / also place it 
before org.osgi.core so that its versions of the OSGi classes are used -->
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.framework</artifactId>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.osgi</groupId>
       <artifactId>org.osgi.core</artifactId>
@@ -43,12 +49,6 @@
       <artifactId>junit</artifactId>
       <scope>test</scope>
     </dependency>
-    <!-- Place Felix before Equinox because Felix is signed. -->
-    <dependency>
-      <groupId>org.apache.felix</groupId>
-      <artifactId>org.apache.felix.framework</artifactId>
-      <scope>test</scope>
-    </dependency>
     <dependency>
       <groupId>org.eclipse.osgi</groupId>
       <artifactId>org.eclipse.osgi</artifactId>
@@ -121,6 +121,7 @@
             <Export-Package>org.apache.logging.log4j.*</Export-Package>
             <Import-Package>
               sun.reflect;resolution:=optional,
+              org.apache.logging.log4j.core.osgi;resolution:=optional,
               *
             </Import-Package>
             
<Bundle-Activator>org.apache.logging.log4j.util.Activator</Bundle-Activator>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/4ccf5cc4/log4j-api/src/test/java/org/apache/logging/log4j/osgi/AbstractLoadBundleTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-api/src/test/java/org/apache/logging/log4j/osgi/AbstractLoadBundleTest.java
 
b/log4j-api/src/test/java/org/apache/logging/log4j/osgi/AbstractLoadBundleTest.java
index 9c6acab..15f0f5b 100644
--- 
a/log4j-api/src/test/java/org/apache/logging/log4j/osgi/AbstractLoadBundleTest.java
+++ 
b/log4j-api/src/test/java/org/apache/logging/log4j/osgi/AbstractLoadBundleTest.java
@@ -16,7 +16,11 @@
  */
 package org.apache.logging.log4j.osgi;
 
+import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.PrintStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
 
 import org.junit.Assert;
 import org.junit.Assume;
@@ -29,7 +33,7 @@ import org.osgi.framework.BundleException;
 import org.osgi.framework.launch.FrameworkFactory;
 
 /**
- * Tests loading a bundle into an OSGi container.
+ * Tests loading a bundle into an OSGi container. Also test a basic Log4J 
'setup' in an OSGi container.
  * <p>
  * Requires that "mvn package" has been previously run, otherwise test fails 
its JUnit {@link Assume}.
  * </p>
@@ -62,8 +66,9 @@ public abstract class AbstractLoadBundleTest {
         final String bundlePath = getBundlePath();
         Assume.assumeNotNull(bundlePath);
         final File file = new File(bundlePath);
-        Assume.assumeTrue("File does not exist: " + file.getAbsolutePath() + 
". Run 'mvn package' before 'mvn test'",
-                file.exists());
+        Assume.assumeTrue(
+            "File does not exist: " + file.getAbsolutePath() + ". Run 'mvn 
package -DskipTests' before 'mvn test'",
+            file.exists());
     }
 
     protected String getBundlePath() {
@@ -76,7 +81,7 @@ public abstract class AbstractLoadBundleTest {
      * @return the expected bundle symbolic name.
      */
     public String getExpectedBundleSymbolicName() {
-        return "org.apache.logging." + bundleTestInfo.getArtifactId();
+        return "org.apache.logging." + 
bundleTestInfo.getArtifactId().replace('-', '.');
     }
 
     /**
@@ -90,7 +95,7 @@ public abstract class AbstractLoadBundleTest {
         final Bundle bundle = bundleContext.installBundle("file:" + 
getBundlePath());
         Assert.assertNotNull("Error loading bundle: null returned", bundle);
         Assert.assertEquals("Error loading bundle: symbolic name mismatch", 
getExpectedBundleSymbolicName(),
-                bundle.getSymbolicName());
+            bundle.getSymbolicName());
         Assert.assertEquals("Bundle is not in INSTALLED state", 
Bundle.INSTALLED, bundle.getState());
 
         // sanity check: start and stop bundle
@@ -102,6 +107,131 @@ public abstract class AbstractLoadBundleTest {
         Assert.assertEquals("Bundle is not in ACTIVE state", Bundle.ACTIVE, 
bundle.getState());
         bundle.stop();
         Assert.assertEquals("Bundle is not in RESOLVED state", 
Bundle.RESOLVED, bundle.getState());
+        bundle.uninstall();
+        Assert.assertEquals("Bundle is not in UNINSTALLED state", 
Bundle.UNINSTALLED, bundle.getState());
+    }
+
+    /**
+     * Tests the log of a simple message in an OSGi container
+     */
+    @Test
+    public void testSimpleLogInAnOsgiContext() throws BundleException, 
ReflectiveOperationException {
+
+        final BundleContext bundleContext = 
osgi.getFramework().getBundleContext();
+
+        final Bundle api = bundleContext.installBundle("file:" + 
getBundlePath());
+        final Bundle core = bundleContext.installBundle(
+            "file:../log4j-core/target/log4j-core-" + 
bundleTestInfo.getVersion() + ".jar");
+        final Bundle dummy = bundleContext.installBundle(
+            
"file:../log4j-samples/configuration/target/log4j-samples-configuration-" + 
bundleTestInfo.getVersion() + ".jar");
+
+        api.start();
+        core.start();
+        dummy.start();
+
+        final PrintStream bakStream = System.out;
+        try {
+            final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            final PrintStream logStream = new PrintStream(baos);
+            System.setOut(logStream);
+
+            log(dummy);
+
+            final String result = baos.toString().substring(
+                12).trim(); // remove the instant then the spaces at start and 
end, that are non constant
+            Assert.assertEquals("[main] ERROR 
org.apache.logging.log4j.configuration.CustomConfiguration - Test OK",
+                result);
+        } finally {
+            System.setOut(bakStream);
+        }
+
+        dummy.stop();
+        core.stop();
+        api.stop();
+
+        dummy.uninstall();
+        core.uninstall();
+        api.uninstall();
+    }
+
+    /**
+     * Tests LOG4J2-920.
+     */
+    @Test
+    public void testMissingImportOfCoreOsgiPackage() throws BundleException, 
ReflectiveOperationException {
+
+        final BundleContext bundleContext = 
osgi.getFramework().getBundleContext();
+
+        final Bundle api = bundleContext.installBundle("file:" + 
getBundlePath());
+        final Bundle core = bundleContext.installBundle(
+            "file:../log4j-core/target/log4j-core-" + 
bundleTestInfo.getVersion() + ".jar");
+        final Bundle dummy = bundleContext.installBundle(
+            
"file:../log4j-samples/configuration/target/log4j-samples-configuration-" + 
bundleTestInfo.getVersion() + ".jar");
+
+        api.start();
+        core.start();
+        dummy.start();
+
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        final PrintStream logStream = new PrintStream(baos);
+
+        final PrintStream bakStream = setupStream(api, logStream);
+
+        log(dummy);
+
+        setupStream(api, bakStream);
+
+        final boolean result = baos.toString().contains(
+            "ERROR StatusLogger Unable to create context 
org.apache.logging.log4j.core.osgi.BundleContextSelector");
+        Assert.assertFalse(
+            "org.apache.logging.log4j.core.osgi;resolution:=optional is 
missing in Import-Package in the POM", result);
+
+        dummy.stop();
+        core.stop();
+        api.stop();
+
+        dummy.uninstall();
+        core.uninstall();
+        api.uninstall();
+    }
+
+    private void log(final Bundle dummy) throws ReflectiveOperationException {
+        // use reflection to log in the context of the dummy bundle
+
+        final Class<?> logManagerClass = 
dummy.loadClass("org.apache.logging.log4j.LogManager");
+        final Method getLoggerMethod = logManagerClass.getMethod("getLogger", 
Class.class);
+
+        final Class<?> loggerClass = 
dummy.loadClass("org.apache.logging.log4j.configuration.CustomConfiguration");
+
+        final Object logger = getLoggerMethod.invoke(null, loggerClass);
+        final Method infoMethod = logger.getClass().getMethod("error", 
Object.class);
+
+        infoMethod.invoke(logger, "Test OK");
+    }
+
+    private PrintStream setupStream(final Bundle api, final PrintStream 
newStream) throws ReflectiveOperationException {
+        // use reflection to access the classes internals and in the context 
of the api bundle
+
+        final Class<?> statusLoggerClass = 
api.loadClass("org.apache.logging.log4j.status.StatusLogger");
+
+        final Field statusLoggerField = 
statusLoggerClass.getDeclaredField("STATUS_LOGGER");
+        statusLoggerField.setAccessible(true);
+        final Object statusLoggerFieldValue = statusLoggerField.get(null);
+
+        final Field loggerField = statusLoggerClass.getDeclaredField("logger");
+        loggerField.setAccessible(true);
+        final Object loggerFieldValue = 
loggerField.get(statusLoggerFieldValue);
+
+        final Class<?> simpleLoggerClass = 
api.loadClass("org.apache.logging.log4j.simple.SimpleLogger");
+
+        final Field streamField = simpleLoggerClass.getDeclaredField("stream");
+        streamField.setAccessible(true);
+
+        final PrintStream oldStream = (PrintStream) 
streamField.get(loggerFieldValue);
+
+        streamField.set(loggerFieldValue, newStream);
+
+        return oldStream;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/4ccf5cc4/log4j-api/src/test/java/org/apache/logging/log4j/osgi/BundleTestInfo.java
----------------------------------------------------------------------
diff --git 
a/log4j-api/src/test/java/org/apache/logging/log4j/osgi/BundleTestInfo.java 
b/log4j-api/src/test/java/org/apache/logging/log4j/osgi/BundleTestInfo.java
index 64c4a0b..cd53f63 100644
--- a/log4j-api/src/test/java/org/apache/logging/log4j/osgi/BundleTestInfo.java
+++ b/log4j-api/src/test/java/org/apache/logging/log4j/osgi/BundleTestInfo.java
@@ -78,7 +78,7 @@ public class BundleTestInfo {
      * @return the Maven version String.
      */
     public String getVersion() {
-        return project.getProperties().getProperty("project.version.osgi");
+        return project.getVersion();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/4ccf5cc4/log4j-core/src/main/java/org/apache/logging/log4j/core/osgi/Activator.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/osgi/Activator.java 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/osgi/Activator.java
index 2cf6f47..d926d2e 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/osgi/Activator.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/osgi/Activator.java
@@ -56,7 +56,8 @@ public final class Activator implements BundleActivator, 
SynchronousBundleListen
     private static void scanInstalledBundlesForPlugins(final BundleContext 
context) {
         final Bundle[] bundles = context.getBundles();
         for (final Bundle bundle : bundles) {
-            if (bundle.getState() == Bundle.ACTIVE) {
+            // LOG4J2-920: don't scan system bundle for plugins
+            if (bundle.getState() == Bundle.ACTIVE && bundle.getBundleId() != 
0) {
                 // TODO: bundle state can change during this
                 scanBundleForPlugins(bundle);
             }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/4ccf5cc4/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index a302ce3..80fc4b7 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -105,6 +105,9 @@
       <action issue="LOG4J2-1254" dev="rpopma" type="fix" due-to="Josh Trow">
         Fix typo in Flow Tracing documentation.
       </action>
+      <action issue="LOG4J2-920" dev="mattsicker" type="fix" due-to="Ludovic 
Hochet">
+        ClassNotFoundException for BundleContextSelector when initialising in 
an OSGi environment.
+      </action>
     </release>
     <release version="2.5" date="2015-12-06" description="GA Release 2.5">
       <action issue="LOG4J2-324" dev="rpopma" type="fix">

Reply via email to