/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.logging.log4j.core.config.plugins.util;

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.Strings;

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;

Loads and manages all the plugins.
/** * Loads and manages all the plugins. */
public class PluginManager { private static final CopyOnWriteArrayList<String> PACKAGES = new CopyOnWriteArrayList<>(); private static final String LOG4J_PACKAGES = "org.apache.logging.log4j.core"; private static final Logger LOGGER = StatusLogger.getLogger(); private Map<String, PluginType<?>> plugins = new HashMap<>(); private final String category;
Constructs a PluginManager for the plugin category name given.
Params:
  • category – The plugin category name.
/** * Constructs a PluginManager for the plugin category name given. * * @param category The plugin category name. */
public PluginManager(final String category) { this.category = category; }
Process annotated plugins.
Deprecated:Use PluginProcessor instead. To do so, simply include log4j-core in your dependencies and make sure annotation processing is not disabled. By default, supported Java compilers will automatically use that plugin processor provided log4j-core is on the classpath.
/** * Process annotated plugins. * * @deprecated Use {@link org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor} instead. To do so, * simply include {@code log4j-core} in your dependencies and make sure annotation processing is not * disabled. By default, supported Java compilers will automatically use that plugin processor provided * {@code log4j-core} is on the classpath. */
@Deprecated // use PluginProcessor instead public static void main(final String[] args) { System.err.println("ERROR: this tool is superseded by the annotation processor included in log4j-core."); System.err.println("If the annotation processor does not work for you, please see the manual page:"); System.err.println("http://logging.apache.org/log4j/2.x/manual/configuration.html#ConfigurationSyntax"); System.exit(-1); }
Adds a package name to be scanned for plugins. Must be invoked prior to plugins being collected.
Params:
  • p – The package name. Ignored if null or empty.
/** * Adds a package name to be scanned for plugins. Must be invoked prior to plugins being collected. * * @param p The package name. Ignored if {@code null} or empty. */
public static void addPackage(final String p) { if (Strings.isBlank(p)) { return; } PACKAGES.addIfAbsent(p); }
Adds a list of package names to be scanned for plugins. Convenience method for addPackage(String).
Params:
  • packages – collection of package names to add. Empty and null package names are ignored.
/** * Adds a list of package names to be scanned for plugins. Convenience method for {@link #addPackage(String)}. * * @param packages collection of package names to add. Empty and null package names are ignored. */
public static void addPackages(final Collection<String> packages) { for (final String pkg : packages) { if (Strings.isNotBlank(pkg)) { PACKAGES.addIfAbsent(pkg); } } }
Returns the type of a specified plugin.
Params:
  • name – The name of the plugin.
Returns:The plugin's type.
/** * Returns the type of a specified plugin. * * @param name The name of the plugin. * @return The plugin's type. */
public PluginType<?> getPluginType(final String name) { return plugins.get(name.toLowerCase()); }
Returns all the matching plugins.
Returns:A Map containing the name of the plugin and its type.
/** * Returns all the matching plugins. * * @return A Map containing the name of the plugin and its type. */
public Map<String, PluginType<?>> getPlugins() { return plugins; }
Locates all the plugins.
/** * Locates all the plugins. */
public void collectPlugins() { collectPlugins(null); }
Locates all the plugins including search of specific packages. Warns about name collisions.
Params:
  • packages – the list of packages to scan for plugins
Since:2.1
/** * Locates all the plugins including search of specific packages. Warns about name collisions. * * @param packages the list of packages to scan for plugins * @since 2.1 */
public void collectPlugins(final List<String> packages) { final String categoryLowerCase = category.toLowerCase(); final Map<String, PluginType<?>> newPlugins = new LinkedHashMap<>(); // First, iterate the Log4j2Plugin.dat files found in the main CLASSPATH Map<String, List<PluginType<?>>> builtInPlugins = PluginRegistry.getInstance().loadFromMainClassLoader(); if (builtInPlugins.isEmpty()) { // If we didn't find any plugins above, someone must have messed with the log4j-core.jar. // Search the standard package in the hopes we can find our core plugins. builtInPlugins = PluginRegistry.getInstance().loadFromPackage(LOG4J_PACKAGES); } mergeByName(newPlugins, builtInPlugins.get(categoryLowerCase)); // Next, iterate any Log4j2Plugin.dat files from OSGi Bundles for (final Map<String, List<PluginType<?>>> pluginsByCategory : PluginRegistry.getInstance().getPluginsByCategoryByBundleId().values()) { mergeByName(newPlugins, pluginsByCategory.get(categoryLowerCase)); } // Next iterate any packages passed to the static addPackage method. for (final String pkg : PACKAGES) { mergeByName(newPlugins, PluginRegistry.getInstance().loadFromPackage(pkg).get(categoryLowerCase)); } // Finally iterate any packages provided in the configuration (note these can be changed at runtime). if (packages != null) { for (final String pkg : packages) { mergeByName(newPlugins, PluginRegistry.getInstance().loadFromPackage(pkg).get(categoryLowerCase)); } } LOGGER.debug("PluginManager '{}' found {} plugins", category, newPlugins.size()); plugins = newPlugins; } private static void mergeByName(final Map<String, PluginType<?>> newPlugins, final List<PluginType<?>> plugins) { if (plugins == null) { return; } for (final PluginType<?> pluginType : plugins) { final String key = pluginType.getKey(); final PluginType<?> existing = newPlugins.get(key); if (existing == null) { newPlugins.put(key, pluginType); } else if (!existing.getPluginClass().equals(pluginType.getPluginClass())) { LOGGER.warn("Plugin [{}] is already mapped to {}, ignoring {}", key, existing.getPluginClass(), pluginType.getPluginClass()); } } } }