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<LoggerContext, ConcurrentMap<String, Logger>>();
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((LoggerContext) 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((LoggerContext) PrivateManager.getContext(), name, loggerFactory);
79      }
80  
81      static Category getInstance(final LoggerContext context, final String name) {
82          return getInstance(context, name, loggerFactory);
83      }
84  
85      static Category 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 Category 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 
127     static Category getRoot(final LoggerContext context) {
128         return getInstance(context, Strings.EMPTY);
129     }
130 
131     private static ConcurrentMap<String, Logger> getLoggersMap(final LoggerContext context) {
132         synchronized (CONTEXT_MAP) {
133             ConcurrentMap<String, Logger> map = CONTEXT_MAP.get(context);
134             if (map == null) {
135                 map = new ConcurrentHashMap<String, Logger>();
136                 CONTEXT_MAP.put(context, map);
137             }
138             return map;
139         }
140     }
141 
142     /**
143      Returns all the currently defined categories in the default
144      hierarchy as an {@link java.util.Enumeration Enumeration}.
145 
146      <p>The root category is <em>not</em> included in the returned
147      {@link Enumeration}.
148      @return and Enumeration of the Categories.
149 
150      @deprecated Please use {@link LogManager#getCurrentLoggers()} instead.
151      */
152     @SuppressWarnings("rawtypes")
153     @Deprecated
154     public static Enumeration getCurrentCategories() {
155         return LogManager.getCurrentLoggers();
156     }
157 
158     public final Level getEffectiveLevel() {
159         switch (logger.getLevel().getStandardLevel()) {
160         case ALL:
161             return Level.ALL;
162         case TRACE:
163             return Level.TRACE;
164         case DEBUG:
165             return Level.DEBUG;
166         case INFO:
167             return Level.INFO;
168         case WARN:
169             return Level.WARN;
170         case ERROR:
171             return Level.ERROR;
172         case FATAL:
173             return Level.FATAL;
174         case OFF:
175             return Level.OFF;
176         default:
177             // TODO Should this be an IllegalStateException?
178             return Level.OFF;
179         }
180     }
181 
182     public final Priority getChainedPriority() {
183         return getEffectiveLevel();
184     }
185 
186     public final Level getLevel() {
187         return getEffectiveLevel();
188     }
189 
190     public void setLevel(final Level level) {
191         logger.setLevel(org.apache.logging.log4j.Level.toLevel(level.levelStr));
192     }
193 
194     public final Level getPriority() {
195         return getEffectiveLevel();
196     }
197 
198     public void setPriority(final Priority priority) {
199         logger.setLevel(org.apache.logging.log4j.Level.toLevel(priority.levelStr));
200     }
201 
202     public void debug(final Object message) {
203         maybeLog(FQCN, org.apache.logging.log4j.Level.DEBUG, message, null);
204     }
205 
206     public void debug(final Object message, final Throwable t) {
207         maybeLog(FQCN, org.apache.logging.log4j.Level.DEBUG, message, t);
208     }
209 
210     public boolean isDebugEnabled() {
211         return logger.isDebugEnabled();
212     }
213 
214     public void error(final Object message) {
215         maybeLog(FQCN, org.apache.logging.log4j.Level.ERROR, message, null);
216     }
217 
218     public void error(final Object message, final Throwable t) {
219         maybeLog(FQCN, org.apache.logging.log4j.Level.ERROR, message, t);
220     }
221 
222     public boolean isErrorEnabled() {
223         return logger.isErrorEnabled();
224     }
225 
226     public void warn(final Object message) {
227         maybeLog(FQCN, org.apache.logging.log4j.Level.WARN, message, null);
228     }
229 
230     public void warn(final Object message, final Throwable t) {
231         maybeLog(FQCN, org.apache.logging.log4j.Level.WARN, message, t);
232     }
233 
234     public boolean isWarnEnabled() {
235         return logger.isWarnEnabled();
236     }
237 
238     public void fatal(final Object message) {
239         maybeLog(FQCN, org.apache.logging.log4j.Level.FATAL, message, null);
240     }
241 
242     public void fatal(final Object message, final Throwable t) {
243         maybeLog(FQCN, org.apache.logging.log4j.Level.FATAL, message, t);
244     }
245 
246     public boolean isFatalEnabled() {
247         return logger.isFatalEnabled();
248     }
249 
250     public void info(final Object message) {
251         maybeLog(FQCN, org.apache.logging.log4j.Level.INFO, message, null);
252     }
253 
254     public void info(final Object message, final Throwable t) {
255         maybeLog(FQCN, org.apache.logging.log4j.Level.INFO, message, t);
256     }
257 
258     public boolean isInfoEnabled() {
259         return logger.isInfoEnabled();
260     }
261 
262     public void trace(final Object message) {
263         maybeLog(FQCN, org.apache.logging.log4j.Level.TRACE, message, null);
264     }
265 
266     public void trace(final Object message, final Throwable t) {
267         maybeLog(FQCN, org.apache.logging.log4j.Level.TRACE, message, t);
268     }
269 
270     public boolean isTraceEnabled() {
271         return logger.isTraceEnabled();
272     }
273 
274     public boolean isEnabledFor(final Priority level) {
275         final org.apache.logging.log4j.Level lvl = org.apache.logging.log4j.Level.toLevel(level.toString());
276         return isEnabledFor(lvl);
277     }
278 
279     /**
280      * No-op implementation.
281      * @param appender The Appender to add.
282      */
283     public void addAppender(final Appender appender) {
284     }
285 
286     /**
287      * No-op implementation.
288      * @param event The logging event.
289      */
290     public void callAppenders(final LoggingEvent event) {
291     }
292 
293     @SuppressWarnings("rawtypes")
294     public Enumeration getAllAppenders() {
295         return NullEnumeration.getInstance();
296     }
297 
298     /**
299      * No-op implementation.
300      * @param name The name of the Appender.
301      * @return null.
302      */
303     public Appender getAppender(final String name) {
304         return null;
305     }
306 
307     /**
308      Is the appender passed as parameter attached to this category?
309      * @param appender The Appender to add.
310      * @return true if the appender is attached.
311      */
312     public boolean isAttached(final Appender appender) {
313         return false;
314     }
315 
316     /**
317      * No-op implementation.
318      */
319     public void removeAllAppenders() {
320     }
321 
322     /**
323      * No-op implementation.
324      * @param appender The Appender to remove.
325      */
326     public void removeAppender(final Appender appender) {
327     }
328 
329     /**
330      * No-op implementation.
331      * @param name The Appender to remove.
332      */
333     public void removeAppender(final String name) {
334     }
335 
336     /**
337      * No-op implementation.
338      */
339     public static void shutdown() {
340     }
341 
342 
343     public void forcedLog(final String fqcn, final Priority level, final Object message, final Throwable t) {
344         final org.apache.logging.log4j.Level lvl = org.apache.logging.log4j.Level.toLevel(level.toString());
345         final Message msg = message instanceof Message ? (Message) message : new ObjectMessage(message);
346         logger.logMessage(fqcn, lvl, null, msg, t);
347     }
348 
349     public boolean exists(final String name) {
350         return PrivateManager.getContext().hasLogger(name);
351     }
352 
353     public boolean getAdditivity() {
354         return logger.isAdditive();
355     }
356 
357     public void setAdditivity(final boolean additivity) {
358         logger.setAdditive(additivity);
359     }
360 
361     public void setResourceBundle(final ResourceBundle bundle) {
362         this.bundle = bundle;
363     }
364 
365     public ResourceBundle getResourceBundle() {
366         if (bundle != null) {
367             return bundle;
368         }
369         String name = logger.getName();
370         final ConcurrentMap<String, Logger> loggers = getLoggersMap(logger.getContext());
371         while ((name = NameUtil.getSubName(name)) != null) {
372             if (loggers.containsKey(name)) {
373                 final ResourceBundle rb = loggers.get(name).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 org.apache.logging.log4j.spi.LoggerContext getContext() {
462             return 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 }