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 TRACE:
161                    return Level.TRACE;
162                case DEBUG:
163                    return Level.DEBUG;
164                case INFO:
165                    return Level.INFO;
166                case WARN:
167                    return Level.WARN;
168                case ERROR:
169                    return Level.ERROR;
170                case FATAL:
171                    return Level.FATAL;
172                default:
173                    return Level.OFF;
174            }
175        }
176    
177        public final Priority getChainedPriority() {
178            return getEffectiveLevel();
179        }
180    
181        public final Level getLevel() {
182            return getEffectiveLevel();
183        }
184    
185        public void setLevel(final Level level) {
186            logger.setLevel(org.apache.logging.log4j.Level.toLevel(level.levelStr));
187        }
188    
189        public final Level getPriority() {
190            return getEffectiveLevel();
191        }
192    
193        public void setPriority(final Priority priority) {
194            logger.setLevel(org.apache.logging.log4j.Level.toLevel(priority.levelStr));
195        }
196    
197        public void debug(final Object message) {
198            maybeLog(FQCN, org.apache.logging.log4j.Level.DEBUG, message, null);
199        }
200    
201        public void debug(final Object message, final Throwable t) {
202            maybeLog(FQCN, org.apache.logging.log4j.Level.DEBUG, message, t);
203        }
204    
205        public boolean isDebugEnabled() {
206            return logger.isDebugEnabled();
207        }
208    
209        public void error(final Object message) {
210            maybeLog(FQCN, org.apache.logging.log4j.Level.ERROR, message, null);
211        }
212    
213        public void error(final Object message, final Throwable t) {
214            maybeLog(FQCN, org.apache.logging.log4j.Level.ERROR, message, t);
215        }
216    
217        public boolean isErrorEnabled() {
218            return logger.isErrorEnabled();
219        }
220    
221        public void warn(final Object message) {
222            maybeLog(FQCN, org.apache.logging.log4j.Level.WARN, message, null);
223        }
224    
225        public void warn(final Object message, final Throwable t) {
226            maybeLog(FQCN, org.apache.logging.log4j.Level.WARN, message, t);
227        }
228    
229        public boolean isWarnEnabled() {
230            return logger.isWarnEnabled();
231        }
232    
233        public void fatal(final Object message) {
234            maybeLog(FQCN, org.apache.logging.log4j.Level.FATAL, message, null);
235        }
236    
237        public void fatal(final Object message, final Throwable t) {
238            maybeLog(FQCN, org.apache.logging.log4j.Level.FATAL, message, t);
239        }
240    
241        public boolean isFatalEnabled() {
242            return logger.isFatalEnabled();
243        }
244    
245        public void info(final Object message) {
246            maybeLog(FQCN, org.apache.logging.log4j.Level.INFO, message, null);
247        }
248    
249        public void info(final Object message, final Throwable t) {
250            maybeLog(FQCN, org.apache.logging.log4j.Level.INFO, message, t);
251        }
252    
253        public boolean isInfoEnabled() {
254            return logger.isInfoEnabled();
255        }
256    
257        public void trace(final Object message) {
258            maybeLog(FQCN, org.apache.logging.log4j.Level.TRACE, message, null);
259        }
260    
261        public void trace(final Object message, final Throwable t) {
262            maybeLog(FQCN, org.apache.logging.log4j.Level.TRACE, message, t);
263        }
264    
265        public boolean isTraceEnabled() {
266            return logger.isTraceEnabled();
267        }
268    
269        public boolean isEnabledFor(final Priority level) {
270            final org.apache.logging.log4j.Level lvl = org.apache.logging.log4j.Level.toLevel(level.toString());
271            return isEnabledFor(lvl);
272        }
273    
274        /**
275         * No-op implementation.
276         * @param appender The Appender to add.
277         */
278        public void addAppender(final Appender appender) {
279        }
280    
281        /**
282         * No-op implementation.
283         * @param event The logging event.
284         */
285        public void callAppenders(final LoggingEvent event) {
286        }
287    
288        @SuppressWarnings("rawtypes")
289        public Enumeration getAllAppenders() {
290            return NullEnumeration.getInstance();
291        }
292    
293        /**
294         * No-op implementation.
295         * @param name The name of the Appender.
296         * @return null.
297         */
298        public Appender getAppender(final String name) {
299            return null;
300        }
301    
302        /**
303         Is the appender passed as parameter attached to this category?
304         * @param appender The Appender to add.
305         * @return true if the appender is attached.
306         */
307        public boolean isAttached(final Appender appender) {
308            return false;
309        }
310    
311        /**
312         * No-op implementation.
313         */
314        public void removeAllAppenders() {
315        }
316    
317        /**
318         * No-op implementation.
319         * @param appender The Appender to remove.
320         */
321        public void removeAppender(final Appender appender) {
322        }
323    
324        /**
325         * No-op implementation.
326         * @param name The Appender to remove.
327         */
328        public void removeAppender(final String name) {
329        }
330    
331        /**
332         * No-op implementation.
333         */
334        public static void shutdown() {
335        }
336    
337    
338        public void forcedLog(final String fqcn, final Priority level, final Object message, final Throwable t) {
339            final org.apache.logging.log4j.Level lvl = org.apache.logging.log4j.Level.toLevel(level.toString());
340            final Message msg = message instanceof Message ? (Message) message : new ObjectMessage(message);
341            logger.logMessage(fqcn, lvl, null, msg, t);
342        }
343    
344        public boolean exists(final String name) {
345            return PrivateManager.getContext().hasLogger(name);
346        }
347    
348        public boolean getAdditivity() {
349            return logger.isAdditive();
350        }
351    
352        public void setAdditivity(final boolean additivity) {
353            logger.setAdditive(additivity);
354        }
355    
356        public void setResourceBundle(final ResourceBundle bundle) {
357            this.bundle = bundle;
358        }
359    
360        public ResourceBundle getResourceBundle() {
361            if (bundle != null) {
362                return bundle;
363            }
364            String name = logger.getName();
365            final ConcurrentMap<String, Logger> loggers = getLoggersMap(logger.getContext());
366            while ((name = NameUtil.getSubName(name)) != null) {
367                if (loggers.containsKey(name)) {
368                    final ResourceBundle rb = loggers.get(name).bundle;
369                    if (rb != null) {
370                        return rb;
371                    }
372                }
373            }
374            return null;
375        }
376    
377        /**
378         If <code>assertion</code> parameter is {@code false}, then
379         logs <code>msg</code> as an {@link #error(Object) error} statement.
380    
381         <p>The <code>assert</code> method has been renamed to
382         <code>assertLog</code> because <code>assert</code> is a language
383         reserved word in JDK 1.4.
384    
385         @param assertion The assertion.
386         @param msg The message to print if <code>assertion</code> is
387         false.
388    
389         @since 1.2
390         */
391        public void assertLog(final boolean assertion, final String msg) {
392            if (!assertion) {
393                this.error(msg);
394            }
395        }
396    
397        public void l7dlog(final Priority priority, final String key, final Throwable t) {
398            if (isEnabledFor(priority)) {
399                final Message msg = new LocalizedMessage(bundle, key, null);
400                forcedLog(FQCN, priority, msg, t);
401            }
402        }
403    
404        public void l7dlog(final Priority priority, final String key, final Object[] params, final Throwable t) {
405            if (isEnabledFor(priority)) {
406                final Message msg = new LocalizedMessage(bundle, key, params);
407                forcedLog(FQCN, priority, msg, t);
408            }
409        }
410    
411        public void log(final Priority priority, final Object message, final Throwable t) {
412            if (isEnabledFor(priority)) {
413                final Message msg = new ObjectMessage(message);
414                forcedLog(FQCN, priority, msg, t);
415            }
416        }
417    
418        public void log(final Priority priority, final Object message) {
419            if (isEnabledFor(priority)) {
420                final Message msg = new ObjectMessage(message);
421                forcedLog(FQCN, priority, msg, null);
422            }
423        }
424    
425        public void log(final String fqcn, final Priority priority, final Object message, final Throwable t) {
426            if (isEnabledFor(priority)) {
427                final Message msg = new ObjectMessage(message);
428                forcedLog(fqcn, priority, msg, t);
429            }
430        }
431    
432        private void maybeLog(final String fqcn, final org.apache.logging.log4j.Level level,
433                final Object message, final Throwable throwable) {
434            if (logger.isEnabled(level, null, message, throwable)) {
435                logger.logMessage(FQCN, level, null, new ObjectMessage(message), throwable);
436            }
437        }
438    
439        /**
440         * Private logger factory.
441         */
442        private static class PrivateFactory implements LoggerFactory {
443    
444            @Override
445            public Logger makeNewLoggerInstance(final LoggerContext context, final String name) {
446                return new Logger(context, name);
447            }
448        }
449    
450        /**
451         * Private LogManager.
452         */
453        private static class PrivateManager extends org.apache.logging.log4j.LogManager {
454            private static final String FQCN = Category.class.getName();
455    
456            public static org.apache.logging.log4j.spi.LoggerContext getContext() {
457                return getContext(FQCN, false);
458            }
459    
460            public static org.apache.logging.log4j.Logger getLogger(final String name) {
461                return getLogger(FQCN, name);
462            }
463        }
464    
465        private boolean isEnabledFor(final org.apache.logging.log4j.Level level) {
466            return logger.isEnabled(level, null, null);
467        }
468    
469    }