diff --git a/pax-logging-log4j2-maven-plugin/pom.xml b/pax-logging-log4j2-maven-plugin/pom.xml
new file mode 100644
index 000000000..f6b00b367
--- /dev/null
+++ b/pax-logging-log4j2-maven-plugin/pom.xml
@@ -0,0 +1,104 @@
+
+
+
+
+ 4.0.0
+
+
+ org.ops4j.pax
+ logging
+ 2.2.8-SNAPSHOT
+ ../pom.xml
+
+
+ org.ops4j.pax.logging
+ pax-logging-log4j2-maven-plugin
+ maven-plugin
+
+ OPS4J Pax Logging - Maven plugin
+
+
+ This plugin is used to generate additional /META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat
+ files available from additional entries on Bundle-ClassPath.
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-plugin-plugin
+
+
+ org.codehaus.plexus
+ plexus-component-metadata
+
+
+
+ generate-metadata
+
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.logging.log4j
+ log4j-api
+ provided
+
+
+ org.apache.logging.log4j
+ log4j-core
+
+
+ org.apache.logging.log4j
+ log4j-layout-template-json
+ provided
+
+
+
+
+
+ org.apache.maven
+ maven-core
+ provided
+
+
+ org.apache.maven
+ maven-plugin-api
+ provided
+
+
+ org.apache.maven.plugin-tools
+ maven-plugin-annotations
+ provided
+ true
+
+
+
+
+
diff --git a/pax-logging-log4j2-maven-plugin/src/main/java/org/ops4j/pax/logging/log4j/maven/Generate.java b/pax-logging-log4j2-maven-plugin/src/main/java/org/ops4j/pax/logging/log4j/maven/Generate.java
new file mode 100644
index 000000000..944ae9b3b
--- /dev/null
+++ b/pax-logging-log4j2-maven-plugin/src/main/java/org/ops4j/pax/logging/log4j/maven/Generate.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2020 OPS4J.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.ops4j.pax.logging.log4j.maven;
+
+import java.io.BufferedOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.IdentityHashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import javax.inject.Inject;
+
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.util.PluginRegistry;
+import org.apache.logging.log4j.core.config.plugins.util.ResolverUtil;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.DefaultArtifact;
+import org.apache.maven.artifact.handler.ArtifactHandler;
+import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
+import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.repository.RepositorySystem;
+
+/**
+ * Log4j2 has deprecated {@code org.apache.logging.log4j.core.config.plugins.util.PluginManager#addPackage()} method,
+ * so we need to allow Log4j to discover another location of {@code Log4j2Plugins.dat} file.
+ * This plugin generates such file into a Jar which will be added to {@code Bundle-ClassPath} OSGi manifest header
+ * (because we can't override the file coming from log4j-core...).
+ */
+@Mojo(name = "generate-log4j-plugin-descriptor", defaultPhase = LifecyclePhase.VERIFY, threadSafe = true, aggregator = true)
+public class Generate extends AbstractMojo {
+
+ @Parameter(defaultValue = "${project}", readonly = true)
+ private MavenProject project;
+
+ @Parameter(defaultValue = "${session}", readonly = true)
+ private MavenSession session;
+
+ @Inject
+ private RepositorySystem system;
+
+ @Parameter
+ private String[] plugins;
+
+ @Override
+ public void execute() {
+ // prepare classpath
+ Set locations = new LinkedHashSet<>();
+ locations.add(project.getBuild().getOutputDirectory());
+ ArtifactHandler artifactHandler = project.getArtifact().getArtifactHandler();
+ for (Dependency d : project.getDependencies()) {
+ ArtifactResolutionRequest req = new ArtifactResolutionRequest();
+ DefaultArtifact artifact = new DefaultArtifact(d.getGroupId(), d.getArtifactId(), d.getVersion(), d.getScope(), d.getType(), d.getClassifier(), artifactHandler);
+ req.setArtifact(artifact);
+ ArtifactResolutionResult result = system.resolve(req);
+ if (!result.hasExceptions()) {
+ for (Artifact a : result.getArtifacts()) {
+ locations.add(a.getFile().getAbsolutePath());
+ }
+ }
+ }
+
+ List cp = new ArrayList<>();
+ for (String loc : locations) {
+ try {
+ cp.add(new File(loc).toURI().toURL());
+ } catch (MalformedURLException ignored) {
+ }
+ }
+
+ Set> classes = new LinkedHashSet<>();
+ List foundAnnotations = new LinkedList<>();
+ Map> a2c = new IdentityHashMap<>();
+ try (URLClassLoader cl = new URLClassLoader(cp.toArray(new URL[0]), Plugin.class.getClassLoader())) {
+ for (String plugin : plugins) {
+ try {
+ Class> pluginClass = cl.loadClass(plugin);
+ getLog().info("Analyzing package " + pluginClass.getPackage().getName());
+ collectPlugins(cl, pluginClass.getPackage(), foundAnnotations, a2c);
+ } catch (ClassNotFoundException e) {
+ getLog().warn("Can't load " + plugin + ":" + e.getMessage());
+ }
+ }
+ } catch (IOException ignored) {
+ }
+
+ // keyed by plugin category
+ final Map> pluginMap = new LinkedHashMap<>();
+ foundAnnotations.forEach(p -> pluginMap.computeIfAbsent(p.category(), k -> new ArrayList<>()).add(p));
+
+ // see org.apache.logging.log4j.core.config.plugins.processor.PluginCache.loadCacheFiles()
+ File log4jPluginDataJar = new File(project.getBuild().getOutputDirectory(), "META-INF/pax-logging-log4j-plugins/META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat");
+ log4jPluginDataJar.getParentFile().mkdirs();
+ try (final DataOutputStream out = new DataOutputStream(new BufferedOutputStream(Files.newOutputStream(log4jPluginDataJar.toPath())))) {
+ out.writeInt(pluginMap.size());
+ for (Map.Entry> entry : pluginMap.entrySet()) {
+ String category = entry.getKey();
+ List pluginsInCategory = entry.getValue();
+ out.writeUTF(category.toLowerCase(Locale.ROOT));
+ out.writeInt(pluginsInCategory.size());
+ for (Plugin plugin : pluginsInCategory) {
+ // Must always read all parts of the entry, even if not adding, so that the stream progresses
+ // see org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor.PluginElementVisitor.visitType()
+ out.writeUTF(plugin.name().toLowerCase(Locale.ROOT));
+ out.writeUTF(a2c.get(plugin).getName());
+ out.writeUTF(Plugin.EMPTY.equals(plugin.elementType()) ? plugin.name() : plugin.elementType());
+ out.writeBoolean(plugin.printObject());
+ out.writeBoolean(plugin.deferChildren());
+
+ }
+ }
+ } catch (IOException e) {
+ getLog().error("Can't write jar file with Pax Logging Lo4j2 annotation data", e);
+ }
+ }
+
+ private void collectPlugins(ClassLoader loader, Package pkg, List foundAnnotations, Map> a2c) {
+ final ResolverUtil resolver = new ResolverUtil();
+ resolver.setClassLoader(loader);
+ resolver.findInPackage(new PluginRegistry.PluginTest(), pkg.getName());
+
+ for (Class> cls : resolver.getClasses()) {
+ final Plugin annotation = cls.getAnnotation(Plugin.class);
+ if (annotation != null) {
+ getLog().info(" Found plugin " + cls.getName());
+ foundAnnotations.add(annotation);
+ a2c.put(annotation, cls);
+ }
+ }
+ }
+
+}
diff --git a/pax-logging-log4j2/osgi.bnd b/pax-logging-log4j2/osgi.bnd
index 5346a7038..d692b73e5 100644
--- a/pax-logging-log4j2/osgi.bnd
+++ b/pax-logging-log4j2/osgi.bnd
@@ -19,6 +19,8 @@
Bundle-Activator: org.ops4j.pax.logging.log4j2.internal.Activator
+Bundle-ClassPath: ., META-INF/pax-logging-log4j-plugins
+
Private-Package: \
org.apache.logging.log4j.core.*; -split-package:=merge-first, \
org.apache.logging.log4j.layout.*; -split-package:=merge-first, \
@@ -30,6 +32,7 @@ Private-Package: \
Include-Resource: \
{maven-resources}, \
META-INF/maven=target/classes/META-INF/maven, \
+ META-INF/pax-logging-log4j-plugins=target/classes/META-INF/pax-logging-log4j-plugins, \
META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat=target/classes/META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat, \
/=target/classes;filter:=*.json;recursive:=false, \
/=target/classes;filter:=*.xsd;recursive:=false, \
diff --git a/pax-logging-log4j2/pom.xml b/pax-logging-log4j2/pom.xml
index aefeea095..21f8de6bf 100644
--- a/pax-logging-log4j2/pom.xml
+++ b/pax-logging-log4j2/pom.xml
@@ -153,6 +153,28 @@
+
+ org.ops4j.pax.logging
+ pax-logging-log4j2-maven-plugin
+
+
+ generate-pax-logging-log4j2-plugin-descriptor
+ prepare-package
+
+ generate-log4j-plugin-descriptor
+
+
+
+
+ org.ops4j.pax.logging.log4j2.internal.bridges.PaxOsgiAppender
+ org.apache.logging.log4j.layout.template.json.JsonTemplateLayout
+ org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory
+ org.apache.logging.log4j.layout.template.json.util.RecyclerFactoryConverter
+
+
+
+
+
org.apache.maven.plugins
maven-jar-plugin
@@ -199,6 +221,12 @@
org.ops4j.pax.logging
pax-logging-api
+
+
+ org.ops4j.pax.logging
+ pax-logging-log4j2-maven-plugin
+ runtime
+
diff --git a/pax-logging-log4j2/src/main/java/org/ops4j/pax/logging/log4j2/internal/PaxLoggingServiceImpl.java b/pax-logging-log4j2/src/main/java/org/ops4j/pax/logging/log4j2/internal/PaxLoggingServiceImpl.java
index 7e483c0d0..40b010a74 100644
--- a/pax-logging-log4j2/src/main/java/org/ops4j/pax/logging/log4j2/internal/PaxLoggingServiceImpl.java
+++ b/pax-logging-log4j2/src/main/java/org/ops4j/pax/logging/log4j2/internal/PaxLoggingServiceImpl.java
@@ -76,10 +76,13 @@ public class PaxLoggingServiceImpl implements PaxLoggingService, ServiceFactory<
// We don't have to add "org.apache.logging.log4j.core", because this package will be handled
// using default cache file "/META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat"
// taken unchanged from "org.apache.logging.log4j:log4j-core".
- PluginManager.addPackage(PaxOsgiAppender.class.getPackage().getName());
- PluginManager.addPackage(JsonTemplateLayout.class.getPackage().getName());
- PluginManager.addPackage(LoggerResolverFactory.class.getPackage().getName());
- PluginManager.addPackage(RecyclerFactoryConverter.class.getPackage().getName());
+ // plugins are now added using org.ops4j.pax.logging:pax-logging-log4j2-maven-plugin
+ // and the descriptor it generates, because
+ // org.apache.logging.log4j.core.config.plugins.util.PluginManager.addPackage() is now deprecated
+// PluginManager.addPackage(PaxOsgiAppender.class.getPackage().getName());
+// PluginManager.addPackage(JsonTemplateLayout.class.getPackage().getName());
+// PluginManager.addPackage(LoggerResolverFactory.class.getPackage().getName());
+// PluginManager.addPackage(RecyclerFactoryConverter.class.getPackage().getName());
}
private final BundleContext m_bundleContext;
diff --git a/pom.xml b/pom.xml
index 47b7d6ea3..80736711a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -234,6 +234,8 @@
6.0.5
7.0.5
2.24.1
+ 3.9.9
+ 3.15.0
1_3
1.2.14
@@ -267,6 +269,7 @@
3.2.7
3.1.3
3.8.0
+ 3.15.0
3.4.2
3.10.0
3.1.1
@@ -280,6 +283,7 @@
+ 2.2.0
5.1.9
3.6.0
4.6
@@ -405,6 +409,11 @@
maven-invoker-plugin
${plugin.maven-invoker-plugin}
+
+ org.apache.maven.plugins
+ maven-plugin-plugin
+ ${version.plugin.maven-plugin-plugin}
+
org.apache.maven.plugins
maven-release-plugin
@@ -481,6 +490,17 @@
license-maven-plugin
${plugin.mycila.license-maven-plugin}
+
+ org.codehaus.plexus
+ plexus-component-metadata
+ ${plugin.codehaus.plexus-component-metadata}
+
+
+
+ org.ops4j.pax.logging
+ pax-logging-log4j2-maven-plugin
+ ${project.version}
+
@@ -586,6 +606,11 @@
pax-logging-log4j2
${project.version}
+
+ org.ops4j.pax.logging
+ pax-logging-log4j2-maven-plugin
+ ${project.version}
+
org.ops4j.pax.logging
@@ -948,6 +973,24 @@
+
+
+
+ org.apache.maven
+ maven-core
+ ${version.org.apache.maven}
+
+
+ org.apache.maven
+ maven-plugin-api
+ ${version.org.apache.maven}
+
+
+ org.apache.maven.plugin-tools
+ maven-plugin-annotations
+ ${version.org.apache.maven.plugin-tools}
+
+
@@ -1009,6 +1052,7 @@
pax-logging-api
pax-logging-api-test
+ pax-logging-log4j2-maven-plugin
pax-logging-log4j2
pax-logging-log4j2-extra
pax-logging-logback