1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.util;
18
19 import java.io.IOException;
20 import java.net.URL;
21 import java.util.Collection;
22 import java.util.Enumeration;
23 import java.util.HashSet;
24 import java.util.Properties;
25 import java.util.concurrent.locks.Lock;
26 import java.util.concurrent.locks.ReentrantLock;
27
28 import org.apache.logging.log4j.Logger;
29 import org.apache.logging.log4j.spi.Provider;
30 import org.apache.logging.log4j.status.StatusLogger;
31
32
33
34
35
36
37 public final class ProviderUtil {
38
39
40
41
42 protected static final String PROVIDER_RESOURCE = "META-INF/log4j-provider.properties";
43
44
45
46
47 protected static final Collection<Provider> PROVIDERS = new HashSet<>();
48
49
50
51
52
53
54 protected static final Lock STARTUP_LOCK = new ReentrantLock();
55
56 private static final String API_VERSION = "Log4jAPIVersion";
57 private static final String[] COMPATIBLE_API_VERSIONS = {"2.0.0", "2.1.0", "2.2.0", "2.3.0", "2.4.0", "2.5.0", "2.6.0"};
58 private static final Logger LOGGER = StatusLogger.getLogger();
59
60
61
62 private static volatile ProviderUtil instance;
63
64 private ProviderUtil() {
65 for (final LoaderUtil.UrlResource resource : LoaderUtil.findUrlResources(PROVIDER_RESOURCE)) {
66 loadProvider(resource.getUrl(), resource.getClassLoader());
67 }
68 }
69
70
71
72
73
74
75
76
77 protected static void loadProvider(final URL url, final ClassLoader cl) {
78 try {
79 final Properties props = PropertiesUtil.loadClose(url.openStream(), url);
80 if (validVersion(props.getProperty(API_VERSION))) {
81 final Provider provider = new Provider(props, url, cl);
82 PROVIDERS.add(provider);
83 LOGGER.debug("Loaded Provider {}", provider);
84 }
85 } catch (final IOException e) {
86 LOGGER.error("Unable to open {}", url, e);
87 }
88 }
89
90
91
92
93 @Deprecated
94 protected static void loadProviders(final Enumeration<URL> urls, final ClassLoader cl) {
95 if (urls != null) {
96 while (urls.hasMoreElements()) {
97 loadProvider(urls.nextElement(), cl);
98 }
99 }
100 }
101
102 public static Iterable<Provider> getProviders() {
103 lazyInit();
104 return PROVIDERS;
105 }
106
107 public static boolean hasProviders() {
108 lazyInit();
109 return !PROVIDERS.isEmpty();
110 }
111
112
113
114
115
116
117 protected static void lazyInit() {
118
119 if (instance == null) {
120 try {
121 STARTUP_LOCK.lockInterruptibly();
122 try {
123 if (instance == null) {
124 instance = new ProviderUtil();
125 }
126 } finally {
127 STARTUP_LOCK.unlock();
128 }
129 } catch (final InterruptedException e) {
130 LOGGER.fatal("Interrupted before Log4j Providers could be loaded.", e);
131 Thread.currentThread().interrupt();
132 }
133 }
134 }
135
136 public static ClassLoader findClassLoader() {
137 return LoaderUtil.getThreadContextClassLoader();
138 }
139
140 private static boolean validVersion(final String version) {
141 for (final String v : COMPATIBLE_API_VERSIONS) {
142 if (version.startsWith(v)) {
143 return true;
144 }
145 }
146 return false;
147 }
148 }