    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    }