1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.config.plugins.util;
18
19 import java.io.BufferedInputStream;
20 import java.io.DataInputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.net.URL;
24 import java.util.Enumeration;
25 import java.util.HashMap;
26 import java.util.Map;
27 import java.util.concurrent.ConcurrentMap;
28
29 import org.apache.logging.log4j.Logger;
30 import org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor;
31 import org.apache.logging.log4j.core.util.ClassLoaderResourceLoader;
32 import org.apache.logging.log4j.core.util.Closer;
33 import org.apache.logging.log4j.core.util.Loader;
34 import org.apache.logging.log4j.core.util.ResourceLoader;
35 import org.apache.logging.log4j.status.StatusLogger;
36
37
38
39
40 public class PluginManager {
41
42
43 private static final PluginRegistry<PluginType<?>> REGISTRY =
44 new PluginRegistry<PluginType<?>>();
45
46 private static final Logger LOGGER = StatusLogger.getLogger();
47
48 private Map<String, PluginType<?>> plugins = new HashMap<String, PluginType<?>>();
49 private final String category;
50
51
52
53
54
55 public PluginManager(final String category) {
56 this.category = category;
57 }
58
59
60
61
62
63
64
65
66 @Deprecated
67 public static void main(final String[] args) {
68 System.err.println("WARNING: this tool is superseded by the annotation processor included in log4j-core.");
69 System.exit(-1);
70 }
71
72
73
74
75
76 @Deprecated
77 public static void addPackage(final String p) {
78 }
79
80
81
82
83
84
85 public PluginType<?> getPluginType(final String name) {
86 return plugins.get(name.toLowerCase());
87 }
88
89
90
91
92
93 public Map<String, PluginType<?>> getPlugins() {
94 return plugins;
95 }
96
97
98
99
100 public void collectPlugins() {
101 collectPlugins(true);
102 }
103
104
105
106
107
108
109 public void collectPlugins(boolean preLoad) {
110 if (REGISTRY.hasCategory(category)) {
111 plugins = REGISTRY.getCategory(category);
112 preLoad = false;
113 }
114 if (preLoad) {
115 final ResourceLoader loader = new ClassLoaderResourceLoader(Loader.getClassLoader());
116 loadPlugins(loader);
117 }
118 plugins = REGISTRY.getCategory(category);
119 }
120
121 public static void loadPlugins(final ResourceLoader loader) {
122 final PluginRegistry<PluginType<?>> registry = decode(loader);
123 if (registry != null) {
124 for (final Map.Entry<String, ConcurrentMap<String, PluginType<?>>> entry : registry.getCategories()) {
125 REGISTRY.getCategory(entry.getKey()).putAll(entry.getValue());
126 }
127 } else {
128 LOGGER.info("Plugin preloads not available from class loader {}", loader);
129 }
130 }
131
132 private static PluginRegistry<PluginType<?>> decode(final ResourceLoader loader) {
133 final Enumeration<URL> resources;
134 try {
135 resources = loader.getResources(PluginProcessor.PLUGIN_CACHE_FILE);
136 if (resources == null) {
137 return null;
138 }
139 } catch (final IOException ioe) {
140 LOGGER.warn("Unable to preload plugins", ioe);
141 return null;
142 }
143 final PluginRegistry<PluginType<?>> map = new PluginRegistry<PluginType<?>>();
144 while (resources.hasMoreElements()) {
145 final URL url = resources.nextElement();
146 LOGGER.debug("Found Plugin Map at {}", url.toExternalForm());
147 final InputStream is;
148 try {
149 is = url.openStream();
150 } catch (final IOException e) {
151 LOGGER.warn("Unable to open {}", url.toExternalForm(), e);
152 continue;
153 }
154 final DataInputStream dis = new DataInputStream(new BufferedInputStream(is));
155 try {
156 final int count = dis.readInt();
157 for (int j = 0; j < count; ++j) {
158 final String category = dis.readUTF();
159 final int entries = dis.readInt();
160 final Map<String, PluginType<?>> types = map.getCategory(category);
161 for (int i = 0; i < entries; ++i) {
162 final String key = dis.readUTF();
163 final String className = dis.readUTF();
164 final String name = dis.readUTF();
165 final boolean printable = dis.readBoolean();
166 final boolean defer = dis.readBoolean();
167 try {
168 final Class<?> clazz = loader.loadClass(className);
169 @SuppressWarnings({"unchecked","rawtypes"})
170 final PluginType<?> pluginType = new PluginType(clazz, name, printable, defer);
171 types.put(key, pluginType);
172 } catch (final ClassNotFoundException e) {
173 LOGGER.info("Plugin [{}] could not be loaded due to missing classes.", className, e);
174 }
175 }
176 }
177 } catch (final IOException ex) {
178 LOGGER.warn("Unable to preload plugins", ex);
179 } finally {
180 Closer.closeSilent(dis);
181 }
182 }
183 return map.isEmpty() ? null : map;
184 }
185
186 }