View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.apache.log4j;
18  
19  import java.util.Enumeration;
20  import java.util.Map;
21  import java.util.ResourceBundle;
22  import java.util.WeakHashMap;
23  import java.util.concurrent.ConcurrentHashMap;
24  import java.util.concurrent.ConcurrentMap;
25  
26  import org.apache.log4j.helpers.NullEnumeration;
27  import org.apache.log4j.spi.LoggerFactory;
28  import org.apache.log4j.spi.LoggingEvent;
29  import org.apache.logging.log4j.core.LoggerContext;
30  import org.apache.logging.log4j.core.helpers.NameUtil;
31  import org.apache.logging.log4j.message.LocalizedMessage;
32  import org.apache.logging.log4j.message.Message;
33  import org.apache.logging.log4j.message.ObjectMessage;
34  
35  
36  /**
37   * Implementation of the Category class for compatibility, despite it having been deprecated a long, long time ago.
38   */
39  public class Category {
40  
41      private static LoggerFactory loggerFactory = new PrivateFactory();
42  
43      private static final Map<LoggerContext, ConcurrentMap<String, Logger>> CONTEXT_MAP =
44          new WeakHashMap<LoggerContext, ConcurrentMap<String, Logger>>();
45  
46      private static final String FQCN = Category.class.getName();
47  
48      /**
49       * Resource bundle for localized messages.
50       */
51      protected ResourceBundle bundle = null;
52  
53      private final org.apache.logging.log4j.core.Logger logger;
54  
55      /**
56       * Constructor used by Logger to specify a LoggerContext.
57       * @param context The LoggerContext.
58       * @param name The name of the Logger.
59       */
60      protected Category(final LoggerContext context, final String name) {
61          this.logger = context.getLogger(name);
62      }
63  
64      /**
65       * Constructor exposed by Log4j 1.2.
66       * @param name The name of the Logger.
67       */
68      protected Category(final String name) {
69          this((LoggerContext) PrivateManager.getContext(), name);
70      }
71  
72      private Category(final org.apache.logging.log4j.core.Logger logger) {
73          this.logger = logger;
74      }
75  
76      public static Category getInstance(final String name) {
77          return getInstance((LoggerContext) PrivateManager.getContext(), name, loggerFactory);
78      }
79  
80      static Category getInstance(final LoggerContext context, final String name) {
81          return getInstance(context, name, loggerFactory);
82      }
83  
84      static Category getInstance(final LoggerContext context, final String name, final LoggerFactory factory) {
85          final ConcurrentMap<String, Logger> loggers = getLoggersMap(context);
86          Logger logger = loggers.get(name);
87          if (logger != null) {
88              return logger;
89          }
90          logger = factory.makeNewLoggerInstance(context, name);
91          final Logger prev = loggers.putIfAbsent(name, logger);
92          return prev == null ? logger : prev;
93      }
94  
95      public static Category getInstance(@SuppressWarnings("rawtypes") final Class clazz) {
96          return getInstance(clazz.getName());
97      }
98  
99      static Category getInstance(final LoggerContext context, @SuppressWarnings("rawtypes") final Class clazz) {
100         return getInstance(context, clazz.getName());
101     }
102 
103     public final String getName() {
104         return logger.getName();
105     }
106 
107     org.apache.logging.log4j.core.Logger getLogger() {
108         return logger;
109     }
110 
111     public final Category getParent() {
112         final org.apache.logging.log4j.core.Logger parent = logger.getParent();
113         if (parent == null) {
114             return null;
115         }
116         final ConcurrentMap<String, Logger> loggers = getLoggersMap(logger.getContext());
117         final Logger l = loggers.get(parent.getName());
118         return l == null ? new Category(parent) : l;
119     }
120 
121     public static Category getRoot() {
122         return getInstance("");
123     }
124 
125 
126     static Category getRoot(final LoggerContext context) {
127         return getInstance(context, "");
128     }
129 
130     private static ConcurrentMap<String, Logger> getLoggersMap(final LoggerContext context) {
131         synchronized (CONTEXT_MAP) {
132             ConcurrentMap<String, Logger> map = CONTEXT_MAP.get(context);
133             if (map == null) {
134                 map = new ConcurrentHashMap<String, Logger>();
135                 CONTEXT_MAP.put(context, map);
136             }
137             return map;
138         }
139     }
140 
141     /**
142      Returns all the currently defined categories in the default
143      hierarchy as an {@link java.util.Enumeration Enumeration}.
144 
145      <p>The root category is <em>not</em> included in the returned
146      {@link Enumeration}.
147      @return and Enumeration of the Categories.
148 
149      @deprecated Please use {@link LogManager#getCurrentLoggers()} instead.
150      */
151     @SuppressWarnings("rawtypes")
152     @Deprecated
153     public static Enumeration getCurrentCategories() {
154         return LogManager.getCurrentLoggers();
155     }
156 
157     public final Level getEffectiveLevel() {
158         final org.apache.logging.log4j.Level level = logger.getLevel();
159 
160         switch (level) {
161             case TRACE:
162                 return Level.TRACE;
163             case DEBUG:
164                 return Level.DEBUG;
165             case INFO:
166                 return Level.INFO;
167             case WARN:
168                 return Level.WARN;
169             default:
170                 return Level.ERROR;
171         }
172     }
173 
174     public final Priority getChainedPriority() {
175         return getEffectiveLevel();
176     }
177 
178     public final Level getLevel() {
179         return getEffectiveLevel();
180     }
181 
182     public void setLevel(final Level level) {
183         logger.setLevel(org.apache.logging.log4j.Level.toLevel(level.levelStr));
184     }
185 
186     public final Level getPriority() {
187         return getEffectiveLevel();
188     }
189 
190     public void setPriority(final Priority priority) {
191         logger.setLevel(org.apache.logging.log4j.Level.toLevel(priority.levelStr));
192     }
193 
194     public void debug(final Object message) {
195         maybeLog(FQCN, org.apache.logging.log4j.Level.DEBUG, message, null);
196     }
197 
198     public void debug(final Object message, final Throwable t) {
199         maybeLog(FQCN, org.apache.logging.log4j.Level.DEBUG, message, t);
200     }
201 
202     public boolean isDebugEnabled() {
203         return logger.isDebugEnabled();
204     }
205 
206     public void error(final Object message) {
207         maybeLog(FQCN, org.apache.logging.log4j.Level.ERROR, message, null);
208     }
209 
210     public void error(final Object message, final Throwable t) {
211         maybeLog(FQCN, org.apache.logging.log4j.Level.ERROR, message, t);
212     }
213 
214     public boolean isErrorEnabled() {
215         return logger.isErrorEnabled();
216     }
217 
218     public void warn(final Object message) {
219         maybeLog(FQCN, org.apache.logging.log4j.Level.WARN, message, null);
220     }
221 
222     public void warn(final Object message, final Throwable t) {
223         maybeLog(FQCN, org.apache.logging.log4j.Level.WARN, message, t);
224     }
225 
226     public boolean isWarnEnabled() {
227         return logger.isWarnEnabled();
228     }
229 
230     public void fatal(final Object message) {
231         maybeLog(FQCN, org.apache.logging.log4j.Level.FATAL, message, null);
232     }
233 
234     public void fatal(final Object message, final Throwable t) {
235         maybeLog(FQCN, org.apache.logging.log4j.Level.FATAL, message, t);
236     }
237 
238     public boolean isFatalEnabled() {
239         return logger.isFatalEnabled();
240     }
241 
242     public void info(final Object message) {
243         maybeLog(FQCN, org.apache.logging.log4j.Level.INFO, message, null);
244     }
245 
246     public void info(final Object message, final Throwable t) {
247         maybeLog(FQCN, org.apache.logging.log4j.Level.INFO, message, t);
248     }
249 
250     public boolean isInfoEnabled() {
251         return logger.isInfoEnabled();
252     }
253 
254     public void trace(final Object message) {
255         maybeLog(FQCN, org.apache.logging.log4j.Level.TRACE, message, null);
256     }
257 
258     public void trace(final Object message, final Throwable t) {
259         maybeLog(FQCN, org.apache.logging.log4j.Level.TRACE, message, t);
260     }
261 
262     public boolean isTraceEnabled() {
263         return logger.isTraceEnabled();
264     }
265 
266     public boolean isEnabledFor(final Priority level) {
267         final org.apache.logging.log4j.Level lvl = org.apache.logging.log4j.Level.toLevel(level.toString());
268         return isEnabledFor(lvl);
269     }
270 
271     /**
272      * No-op implementation.
273      * @param appender The Appender to add.
274      */
275     public void addAppender(final Appender appender) {
276     }
277 
278     /**
279      * No-op implementation.
280      * @param event The logging event.
281      */
282     public void callAppenders(final LoggingEvent event) {
283     }
284 
285     @SuppressWarnings("rawtypes")
286     public Enumeration getAllAppenders() {
287         return NullEnumeration.getInstance();
288     }
289 
290     /**
291      * No-op implementation.
292      * @param name The name of the Appender.
293      * @return null.
294      */
295     public Appender getAppender(final String name) {
296         return null;
297     }
298 
299     /**
300      Is the appender passed as parameter attached to this category?
301      * @param appender The Appender to add.
302      * @return true if the appender is attached.
303      */
304     public boolean isAttached(final Appender appender) {
305         return false;
306     }
307 
308     /**
309      * No-op implementation.
310      */
311     public void removeAllAppenders() {
312     }
313 
314     /**
315      * No-op implementation.
316      * @param appender The Appender to remove.
317      */
318     public void removeAppender(final Appender appender) {
319     }
320 
321     /**
322      * No-op implementation.
323      * @param name The Appender to remove.
324      */
325     public void removeAppender(final String name) {
326     }
327 
328     /**
329      * No-op implementation.
330      */
331     public static void shutdown() {
332     }
333 
334 
335     public void forcedLog(final String fqcn, final Priority level, final Object message, final Throwable t) {
336         final org.apache.logging.log4j.Level lvl = org.apache.logging.log4j.Level.toLevel(level.toString());
337         final Message msg = message instanceof Message ? (Message) message : new ObjectMessage(message);
338         logger.log(null, fqcn, lvl, msg, t);
339     }
340 
341     public boolean exists(final String name) {
342         return PrivateManager.getContext().hasLogger(name);
343     }
344 
345     public boolean getAdditivity() {
346         return logger.isAdditive();
347     }
348 
349     public void setAdditivity(final boolean additivity) {
350         logger.setAdditive(additivity);
351     }
352 
353     public void setResourceBundle(final ResourceBundle bundle) {
354         this.bundle = bundle;
355     }
356 
357     public ResourceBundle getResourceBundle() {
358         if (bundle != null) {
359             return bundle;
360         }
361         String name = logger.getName();
362         final ConcurrentMap<String, Logger> loggers = getLoggersMap(logger.getContext());
363         while ((name = NameUtil.getSubName(name)) != null) {
364             if (loggers.containsKey(name)) {
365                 final ResourceBundle rb = loggers.get(name).bundle;
366                 if (rb != null) {
367                     return rb;
368                 }
369             }
370         }
371         return null;
372     }
373 
374     /**
375      If <code>assertion</code> parameter is {@code false}, then
376      logs <code>msg</code> as an {@link #error(Object) error} statement.
377 
378      <p>The <code>assert</code> method has been renamed to
379      <code>assertLog</code> because <code>assert</code> is a language
380      reserved word in JDK 1.4.
381 
382      @param assertion The assertion.
383      @param msg The message to print if <code>assertion</code> is
384      false.
385 
386      @since 1.2
387      */
388     public void assertLog(final boolean assertion, final String msg) {
389         if (!assertion) {
390             this.error(msg);
391         }
392     }
393 
394     public void l7dlog(final Priority priority, final String key, final Throwable t) {
395         if (isEnabledFor(priority)) {
396             final Message msg = new LocalizedMessage(bundle, key, null);
397             forcedLog(FQCN, priority, msg, t);
398         }
399     }
400 
401     public void l7dlog(final Priority priority, final String key, final Object[] params, final Throwable t) {
402         if (isEnabledFor(priority)) {
403             final Message msg = new LocalizedMessage(bundle, key, params);
404             forcedLog(FQCN, priority, msg, t);
405         }
406     }
407 
408     public void log(final Priority priority, final Object message, final Throwable t) {
409         if (isEnabledFor(priority)) {
410             final Message msg = new ObjectMessage(message);
411             forcedLog(FQCN, priority, msg, t);
412         }
413     }
414 
415     public void log(final Priority priority, final Object message) {
416         if (isEnabledFor(priority)) {
417             final Message msg = new ObjectMessage(message);
418             forcedLog(FQCN, priority, msg, null);
419         }
420     }
421 
422     public void log(final String fqcn, final Priority priority, final Object message, final Throwable t) {
423         if (isEnabledFor(priority)) {
424             final Message msg = new ObjectMessage(message);
425             forcedLog(fqcn, priority, msg, t);
426         }
427     }
428 
429     private void maybeLog(final String fqcn, final org.apache.logging.log4j.Level level,
430             final Object message, final Throwable throwable) {
431         if (logger.isEnabled(level, null, message, throwable)) {
432             logger.log(null, FQCN, level, new ObjectMessage(message), throwable);
433         }
434     }
435 
436     /**
437      * Private logger factory.
438      */
439     private static class PrivateFactory implements LoggerFactory {
440 
441         @Override
442         public Logger makeNewLoggerInstance(final LoggerContext context, final String name) {
443             return new Logger(context, name);
444         }
445     }
446 
447     /**
448      * Private LogManager.
449      */
450     private static class PrivateManager extends org.apache.logging.log4j.LogManager {
451         private static final String FQCN = Category.class.getName();
452 
453         public static org.apache.logging.log4j.spi.LoggerContext getContext() {
454             return getContext(FQCN, false);
455         }
456 
457         public static org.apache.logging.log4j.Logger getLogger(final String name) {
458             return getLogger(FQCN, name);
459         }
460     }
461 
462     private boolean isEnabledFor(final org.apache.logging.log4j.Level level) {
463         return logger.isEnabled(level, null, null);
464     }
465 
466 }