001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017 package org.apache.log4j;
018
019 import java.util.Enumeration;
020 import java.util.Map;
021 import java.util.ResourceBundle;
022 import java.util.WeakHashMap;
023 import java.util.concurrent.ConcurrentHashMap;
024 import java.util.concurrent.ConcurrentMap;
025
026 import org.apache.log4j.helpers.NullEnumeration;
027 import org.apache.log4j.spi.LoggerFactory;
028 import org.apache.log4j.spi.LoggingEvent;
029 import org.apache.logging.log4j.core.LoggerContext;
030 import org.apache.logging.log4j.core.util.NameUtil;
031 import org.apache.logging.log4j.message.LocalizedMessage;
032 import org.apache.logging.log4j.message.Message;
033 import org.apache.logging.log4j.message.ObjectMessage;
034 import org.apache.logging.log4j.util.Strings;
035
036
037 /**
038 * Implementation of the Category class for compatibility, despite it having been deprecated a long, long time ago.
039 */
040 public class Category {
041
042 private static LoggerFactory loggerFactory = new PrivateFactory();
043
044 private static final Map<LoggerContext, ConcurrentMap<String, Logger>> CONTEXT_MAP =
045 new WeakHashMap<LoggerContext, ConcurrentMap<String, Logger>>();
046
047 private static final String FQCN = Category.class.getName();
048
049 /**
050 * Resource bundle for localized messages.
051 */
052 protected ResourceBundle bundle = null;
053
054 private final org.apache.logging.log4j.core.Logger logger;
055
056 /**
057 * Constructor used by Logger to specify a LoggerContext.
058 * @param context The LoggerContext.
059 * @param name The name of the Logger.
060 */
061 protected Category(final LoggerContext context, final String name) {
062 this.logger = context.getLogger(name);
063 }
064
065 /**
066 * Constructor exposed by Log4j 1.2.
067 * @param name The name of the Logger.
068 */
069 protected Category(final String name) {
070 this((LoggerContext) PrivateManager.getContext(), name);
071 }
072
073 private Category(final org.apache.logging.log4j.core.Logger logger) {
074 this.logger = logger;
075 }
076
077 public static Category getInstance(final String name) {
078 return getInstance((LoggerContext) PrivateManager.getContext(), name, loggerFactory);
079 }
080
081 static Category getInstance(final LoggerContext context, final String name) {
082 return getInstance(context, name, loggerFactory);
083 }
084
085 static Category getInstance(final LoggerContext context, final String name, final LoggerFactory factory) {
086 final ConcurrentMap<String, Logger> loggers = getLoggersMap(context);
087 Logger logger = loggers.get(name);
088 if (logger != null) {
089 return logger;
090 }
091 logger = factory.makeNewLoggerInstance(context, name);
092 final Logger prev = loggers.putIfAbsent(name, logger);
093 return prev == null ? logger : prev;
094 }
095
096 public static Category getInstance(@SuppressWarnings("rawtypes") final Class clazz) {
097 return getInstance(clazz.getName());
098 }
099
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 }