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