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