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