1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 package org.slf4j;
26
27 import java.io.IOException;
28 import java.net.URL;
29 import java.util.*;
30
31 import org.slf4j.helpers.NOPLoggerFactory;
32 import org.slf4j.helpers.SubstituteLogger;
33 import org.slf4j.helpers.SubstituteLoggerFactory;
34 import org.slf4j.helpers.Util;
35 import org.slf4j.impl.StaticLoggerBinder;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 public final class LoggerFactory {
55
56 static final String CODES_PREFIX = "http://www.slf4j.org/codes.html";
57
58 static final String NO_STATICLOGGERBINDER_URL = CODES_PREFIX + "#StaticLoggerBinder";
59 static final String MULTIPLE_BINDINGS_URL = CODES_PREFIX + "#multiple_bindings";
60 static final String NULL_LF_URL = CODES_PREFIX + "#null_LF";
61 static final String VERSION_MISMATCH = CODES_PREFIX + "#version_mismatch";
62 static final String SUBSTITUTE_LOGGER_URL = CODES_PREFIX + "#substituteLogger";
63
64 static final String UNSUCCESSFUL_INIT_URL = CODES_PREFIX + "#unsuccessfulInit";
65 static final String UNSUCCESSFUL_INIT_MSG = "org.slf4j.LoggerFactory could not be successfully initialized. See also "
66 + UNSUCCESSFUL_INIT_URL;
67
68 static final int UNINITIALIZED = 0;
69 static final int ONGOING_INITIALIZATION = 1;
70 static final int FAILED_INITIALIZATION = 2;
71 static final int SUCCESSFUL_INITIALIZATION = 3;
72 static final int NOP_FALLBACK_INITIALIZATION = 4;
73
74 static int INITIALIZATION_STATE = UNINITIALIZED;
75 static SubstituteLoggerFactory TEMP_FACTORY = new SubstituteLoggerFactory();
76 static NOPLoggerFactory NOP_FALLBACK_FACTORY = new NOPLoggerFactory();
77
78
79
80
81
82
83
84
85 static private final String[] API_COMPATIBILITY_LIST = new String[]{"1.6", "1.7"};
86
87
88 private LoggerFactory() {
89 }
90
91
92
93
94
95
96
97
98
99
100
101
102 static void reset() {
103 INITIALIZATION_STATE = UNINITIALIZED;
104 TEMP_FACTORY = new SubstituteLoggerFactory();
105 }
106
107 private final static void performInitialization() {
108 bind();
109 if (INITIALIZATION_STATE == SUCCESSFUL_INITIALIZATION) {
110 versionSanityCheck();
111 }
112 }
113
114 private static boolean messageContainsOrgSlf4jImplStaticLoggerBinder(String msg) {
115 if (msg == null)
116 return false;
117 if (msg.indexOf("org/slf4j/impl/StaticLoggerBinder") != -1)
118 return true;
119 if (msg.indexOf("org.slf4j.impl.StaticLoggerBinder") != -1)
120 return true;
121 return false;
122 }
123
124 private final static void bind() {
125 try {
126 Set staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
127 reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);
128
129 StaticLoggerBinder.getSingleton();
130 INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
131 reportActualBinding(staticLoggerBinderPathSet);
132 fixSubstitutedLoggers();
133 } catch (NoClassDefFoundError ncde) {
134 String msg = ncde.getMessage();
135 if (messageContainsOrgSlf4jImplStaticLoggerBinder(msg)) {
136 INITIALIZATION_STATE = NOP_FALLBACK_INITIALIZATION;
137 Util.report("Failed to load class \"org.slf4j.impl.StaticLoggerBinder\".");
138 Util.report("Defaulting to no-operation (NOP) logger implementation");
139 Util.report("See " + NO_STATICLOGGERBINDER_URL
140 + " for further details.");
141 } else {
142 failedBinding(ncde);
143 throw ncde;
144 }
145 } catch (java.lang.NoSuchMethodError nsme) {
146 String msg = nsme.getMessage();
147 if (msg != null && msg.indexOf("org.slf4j.impl.StaticLoggerBinder.getSingleton()") != -1) {
148 INITIALIZATION_STATE = FAILED_INITIALIZATION;
149 Util.report("slf4j-api 1.6.x (or later) is incompatible with this binding.");
150 Util.report("Your binding is version 1.5.5 or earlier.");
151 Util.report("Upgrade your binding to version 1.6.x.");
152 }
153 throw nsme;
154 } catch (Exception e) {
155 failedBinding(e);
156 throw new IllegalStateException("Unexpected initialization failure", e);
157 }
158 }
159
160 static void failedBinding(Throwable t) {
161 INITIALIZATION_STATE = FAILED_INITIALIZATION;
162 Util.report("Failed to instantiate SLF4J LoggerFactory", t);
163 }
164
165 private final static void fixSubstitutedLoggers() {
166 List<SubstituteLogger> loggers = TEMP_FACTORY.getLoggers();
167
168 if(loggers.isEmpty()){
169 return;
170 }
171
172 Util.report("The following set of substitute loggers may have been accessed");
173 Util.report("during the initialization phase. Logging calls during this");
174 Util.report("phase were not honored. However, subsequent logging calls to these");
175 Util.report("loggers will work as normally expected.");
176 Util.report("See also " + SUBSTITUTE_LOGGER_URL);
177 for(SubstituteLogger subLogger : loggers){
178 subLogger.setDelegate(getLogger(subLogger.getName()));
179 Util.report(subLogger.getName());
180 }
181
182 TEMP_FACTORY.clear();
183 }
184
185 private final static void versionSanityCheck() {
186 try {
187 String requested = StaticLoggerBinder.REQUESTED_API_VERSION;
188
189 boolean match = false;
190 for (int i = 0; i < API_COMPATIBILITY_LIST.length; i++) {
191 if (requested.startsWith(API_COMPATIBILITY_LIST[i])) {
192 match = true;
193 }
194 }
195 if (!match) {
196 Util.report("The requested version " + requested
197 + " by your slf4j binding is not compatible with "
198 + Arrays.asList(API_COMPATIBILITY_LIST).toString());
199 Util.report("See " + VERSION_MISMATCH + " for further details.");
200 }
201 } catch (java.lang.NoSuchFieldError nsfe) {
202
203
204
205
206 } catch (Throwable e) {
207
208 Util.report("Unexpected problem occured during version sanity check", e);
209 }
210 }
211
212
213
214 private static String STATIC_LOGGER_BINDER_PATH = "org/slf4j/impl/StaticLoggerBinder.class";
215
216 private static Set findPossibleStaticLoggerBinderPathSet() {
217
218
219 Set staticLoggerBinderPathSet = new LinkedHashSet();
220 try {
221 ClassLoader loggerFactoryClassLoader = LoggerFactory.class
222 .getClassLoader();
223 Enumeration paths;
224 if (loggerFactoryClassLoader == null) {
225 paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH);
226 } else {
227 paths = loggerFactoryClassLoader
228 .getResources(STATIC_LOGGER_BINDER_PATH);
229 }
230 while (paths.hasMoreElements()) {
231 URL path = (URL) paths.nextElement();
232 staticLoggerBinderPathSet.add(path);
233 }
234 } catch (IOException ioe) {
235 Util.report("Error getting resources from path", ioe);
236 }
237 return staticLoggerBinderPathSet;
238 }
239
240 private static boolean isAmbiguousStaticLoggerBinderPathSet(Set staticLoggerBinderPathSet) {
241 return staticLoggerBinderPathSet.size() > 1;
242 }
243
244
245
246
247
248
249 private static void reportMultipleBindingAmbiguity(Set staticLoggerBinderPathSet) {
250 if (isAmbiguousStaticLoggerBinderPathSet(staticLoggerBinderPathSet)) {
251 Util.report("Class path contains multiple SLF4J bindings.");
252 Iterator iterator = staticLoggerBinderPathSet.iterator();
253 while (iterator.hasNext()) {
254 URL path = (URL) iterator.next();
255 Util.report("Found binding in [" + path + "]");
256 }
257 Util.report("See " + MULTIPLE_BINDINGS_URL + " for an explanation.");
258 }
259 }
260
261 private static void reportActualBinding(Set staticLoggerBinderPathSet) {
262 if (isAmbiguousStaticLoggerBinderPathSet(staticLoggerBinderPathSet)) {
263 Util.report("Actual binding is of type ["+StaticLoggerBinder.getSingleton().getLoggerFactoryClassStr()+"]");
264 }
265 }
266
267
268
269
270
271
272
273
274
275 public static Logger getLogger(String name) {
276 ILoggerFactory iLoggerFactory = getILoggerFactory();
277 return iLoggerFactory.getLogger(name);
278 }
279
280
281
282
283
284
285
286
287 public static Logger getLogger(Class clazz) {
288 return getLogger(clazz.getName());
289 }
290
291
292
293
294
295
296
297
298
299 public static ILoggerFactory getILoggerFactory() {
300 if (INITIALIZATION_STATE == UNINITIALIZED) {
301 INITIALIZATION_STATE = ONGOING_INITIALIZATION;
302 performInitialization();
303 }
304 switch (INITIALIZATION_STATE) {
305 case SUCCESSFUL_INITIALIZATION:
306 return StaticLoggerBinder.getSingleton().getLoggerFactory();
307 case NOP_FALLBACK_INITIALIZATION:
308 return NOP_FALLBACK_FACTORY;
309 case FAILED_INITIALIZATION:
310 throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
311 case ONGOING_INITIALIZATION:
312
313
314 return TEMP_FACTORY;
315 }
316 throw new IllegalStateException("Unreachable code");
317 }
318 }