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    }