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 org.apache.log4j.helpers.NullEnumeration;
020    import org.apache.log4j.spi.LoggerFactory;
021    import org.apache.log4j.spi.LoggingEvent;
022    import org.apache.logging.log4j.core.LoggerContext;
023    import org.apache.logging.log4j.core.helpers.NameUtil;
024    import org.apache.logging.log4j.message.LocalizedMessage;
025    import org.apache.logging.log4j.message.Message;
026    import org.apache.logging.log4j.message.ObjectMessage;
027    
028    import java.util.Enumeration;
029    import java.util.Map;
030    import java.util.ResourceBundle;
031    import java.util.WeakHashMap;
032    import java.util.concurrent.ConcurrentHashMap;
033    import java.util.concurrent.ConcurrentMap;
034    
035    
036    /**
037     * Implementation of the Category class for compatibility, despite it having been deprecated a long, long time ago.
038     */
039    public class Category {
040    
041        private static LoggerFactory loggerFactory = new PrivateFactory();
042    
043        private static final Map<LoggerContext, ConcurrentMap<String, Logger>> CONTEXT_MAP =
044            new WeakHashMap<LoggerContext, ConcurrentMap<String, Logger>>();
045    
046        private static final String FQCN = Category.class.getName();
047    
048        /**
049         * Resource bundle for localized messages.
050         */
051        protected ResourceBundle bundle = null;
052    
053        private final org.apache.logging.log4j.core.Logger logger;
054    
055        /**
056         * Constructor used by Logger to specify a LoggerContext.
057         * @param context The LoggerContext.
058         * @param name The name of the Logger.
059         */
060        protected Category(final LoggerContext context, final String name) {
061            this.logger = context.getLogger(name);
062        }
063    
064        /**
065         * Constructor exposed by Log4j 1.2.
066         * @param name The name of the Logger.
067         */
068        protected Category(final String name) {
069            this((LoggerContext) PrivateManager.getContext(), name);
070        }
071    
072        private Category(final org.apache.logging.log4j.core.Logger logger) {
073            this.logger = logger;
074        }
075    
076        public static Category getInstance(final String name) {
077            return getInstance((LoggerContext) PrivateManager.getContext(), name, loggerFactory);
078        }
079    
080        static Category getInstance(final LoggerContext context, final String name) {
081            return getInstance(context, name, loggerFactory);
082        }
083    
084        static Category getInstance(final LoggerContext context, final String name, final LoggerFactory factory) {
085            final ConcurrentMap<String, Logger> loggers = getLoggersMap(context);
086            Logger logger = loggers.get(name);
087            if (logger != null) {
088                return logger;
089            }
090            logger = factory.makeNewLoggerInstance(context, name);
091            final Logger prev = loggers.putIfAbsent(name, logger);
092            return prev == null ? logger : prev;
093        }
094    
095        public static Category getInstance(final Class clazz) {
096            return getInstance(clazz.getName());
097        }
098    
099        static Category getInstance(final LoggerContext context, final Class clazz) {
100            return getInstance(context, clazz.getName());
101        }
102    
103        public final String getName() {
104            return logger.getName();
105        }
106    
107        org.apache.logging.log4j.core.Logger getLogger() {
108            return logger;
109        }
110    
111        public final Category getParent() {
112            final org.apache.logging.log4j.core.Logger parent = logger.getParent();
113            if (parent == null) {
114                return null;
115            }
116            final ConcurrentMap<String, Logger> loggers = getLoggersMap(logger.getContext());
117            final Logger l = loggers.get(parent.getName());
118            return l == null ? new Category(parent) : l;
119        }
120    
121        public static Category getRoot() {
122            return getInstance("");
123        }
124    
125    
126        static Category getRoot(final LoggerContext context) {
127            return getInstance(context, "");
128        }
129    
130        private static ConcurrentMap<String, Logger> getLoggersMap(final LoggerContext context) {
131            synchronized (CONTEXT_MAP) {
132                ConcurrentMap<String, Logger> map = CONTEXT_MAP.get(context);
133                if (map == null) {
134                    map = new ConcurrentHashMap<String, Logger>();
135                    CONTEXT_MAP.put(context, map);
136                }
137                return map;
138            }
139        }
140    
141        /**
142         Returns all the currently defined categories in the default
143         hierarchy as an {@link java.util.Enumeration Enumeration}.
144    
145         <p>The root category is <em>not</em> included in the returned
146         {@link Enumeration}.
147         @return and Enumeration of the Categories.
148    
149         @deprecated Please use {@link LogManager#getCurrentLoggers()} instead.
150         */
151        @Deprecated
152        public static Enumeration getCurrentCategories() {
153            return LogManager.getCurrentLoggers();
154        }
155    
156        public final Level getEffectiveLevel() {
157            final org.apache.logging.log4j.Level level = logger.getLevel();
158    
159            switch (level) {
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                default:
169                    return Level.ERROR;
170            }
171        }
172    
173        public final Priority getChainedPriority() {
174            return getEffectiveLevel();
175        }
176    
177        public final Level getLevel() {
178            return getEffectiveLevel();
179        }
180    
181        public void setLevel(final Level level) {
182            logger.setLevel(org.apache.logging.log4j.Level.toLevel(level.levelStr));
183        }
184    
185        public final Level getPriority() {
186            return getEffectiveLevel();
187        }
188    
189        public void setPriority(final Priority priority) {
190            logger.setLevel(org.apache.logging.log4j.Level.toLevel(priority.levelStr));
191        }
192    
193        public void debug(final Object message) {
194            maybeLog(FQCN, org.apache.logging.log4j.Level.DEBUG, message, null);
195        }
196    
197        public void debug(final Object message, final Throwable t) {
198            maybeLog(FQCN, org.apache.logging.log4j.Level.DEBUG, message, t);
199        }
200    
201        public boolean isDebugEnabled() {
202            return logger.isDebugEnabled();
203        }
204    
205        public void error(final Object message) {
206            maybeLog(FQCN, org.apache.logging.log4j.Level.ERROR, message, null);
207        }
208    
209        public void error(final Object message, final Throwable t) {
210            maybeLog(FQCN, org.apache.logging.log4j.Level.ERROR, message, t);
211        }
212    
213        public boolean isErrorEnabled() {
214            return logger.isErrorEnabled();
215        }
216    
217        public void warn(final Object message) {
218            maybeLog(FQCN, org.apache.logging.log4j.Level.WARN, message, null);
219        }
220    
221        public void warn(final Object message, final Throwable t) {
222            maybeLog(FQCN, org.apache.logging.log4j.Level.WARN, message, t);
223        }
224    
225        public boolean isWarnEnabled() {
226            return logger.isWarnEnabled();
227        }
228    
229        public void fatal(final Object message) {
230            maybeLog(FQCN, org.apache.logging.log4j.Level.FATAL, message, null);
231        }
232    
233        public void fatal(final Object message, final Throwable t) {
234            maybeLog(FQCN, org.apache.logging.log4j.Level.FATAL, message, t);
235        }
236    
237        public boolean isFatalEnabled() {
238            return logger.isFatalEnabled();
239        }
240    
241        public void info(final Object message) {
242            maybeLog(FQCN, org.apache.logging.log4j.Level.INFO, message, null);
243        }
244    
245        public void info(final Object message, final Throwable t) {
246            maybeLog(FQCN, org.apache.logging.log4j.Level.INFO, message, t);
247        }
248    
249        public boolean isInfoEnabled() {
250            return logger.isInfoEnabled();
251        }
252    
253        public void trace(final Object message) {
254            maybeLog(FQCN, org.apache.logging.log4j.Level.TRACE, message, null);
255        }
256    
257        public void trace(final Object message, final Throwable t) {
258            maybeLog(FQCN, org.apache.logging.log4j.Level.TRACE, message, t);
259        }
260    
261        public boolean isTraceEnabled() {
262            return logger.isTraceEnabled();
263        }
264    
265        public boolean isEnabledFor(final Priority level) {
266            final org.apache.logging.log4j.Level lvl = org.apache.logging.log4j.Level.toLevel(level.toString());
267            return isEnabledFor(lvl);
268        }
269    
270        /**
271         * No-op implementation.
272         * @param appender The Appender to add.
273         */
274        public void addAppender(final Appender appender) {
275        }
276    
277        /**
278         * No-op implementation.
279         * @param event The logging event.
280         */
281        public void callAppenders(final LoggingEvent event) {
282        }
283    
284        public Enumeration getAllAppenders() {
285            return NullEnumeration.getInstance();
286        }
287    
288        /**
289         * No-op implementation.
290         * @param name The name of the Appender.
291         * @return null.
292         */
293        public Appender getAppender(final String name) {
294            return null;
295        }
296    
297        /**
298         Is the appender passed as parameter attached to this category?
299         * @param appender The Appender to add.
300         * @return true if the appender is attached.
301         */
302        public boolean isAttached(final Appender appender) {
303            return false;
304        }
305    
306        /**
307         * No-op implementation.
308         */
309        public void removeAllAppenders() {
310        }
311    
312        /**
313         * No-op implementation.
314         * @param appender The Appender to remove.
315         */
316        public void removeAppender(final Appender appender) {
317        }
318    
319        /**
320         * No-op implementation.
321         * @param name The Appender to remove.
322         */
323        public void removeAppender(final String name) {
324        }
325    
326        /**
327         * No-op implementation.
328         */
329        public static void shutdown() {
330        }
331    
332    
333        public void forcedLog(final String fqcn, final Priority level, final Object message, final Throwable t) {
334            final org.apache.logging.log4j.Level lvl = org.apache.logging.log4j.Level.toLevel(level.toString());
335            final Message msg = message instanceof Message ? (Message) message : new ObjectMessage(message);
336            logger.log(null, fqcn, lvl, msg, t);
337        }
338    
339        public boolean exists(final String name) {
340            return PrivateManager.getContext().hasLogger(name);
341        }
342    
343        public boolean getAdditivity() {
344            return logger.isAdditive();
345        }
346    
347        public void setAdditivity(final boolean additivity) {
348            logger.setAdditive(additivity);
349        }
350    
351        public void setResourceBundle(final ResourceBundle bundle) {
352            this.bundle = bundle;
353        }
354    
355        public ResourceBundle getResourceBundle() {
356            if (bundle != null) {
357                return bundle;
358            }
359            String name = logger.getName();
360            final ConcurrentMap<String, Logger> loggers = getLoggersMap(logger.getContext());
361            while ((name = NameUtil.getSubName(name)) != null) {
362                if (loggers.containsKey(name)) {
363                    final ResourceBundle rb = loggers.get(name).bundle;
364                    if (rb != null) {
365                        return rb;
366                    }
367                }
368            }
369            return null;
370        }
371    
372        /**
373         If <code>assertion</code> parameter is {@code false}, then
374         logs <code>msg</code> as an {@link #error(Object) error} statement.
375    
376         <p>The <code>assert</code> method has been renamed to
377         <code>assertLog</code> because <code>assert</code> is a language
378         reserved word in JDK 1.4.
379    
380         @param assertion The assertion.
381         @param msg The message to print if <code>assertion</code> is
382         false.
383    
384         @since 1.2
385         */
386        public void assertLog(final boolean assertion, final String msg) {
387            if (!assertion) {
388                this.error(msg);
389            }
390        }
391    
392        public void l7dlog(final Priority priority, final String key, final Throwable t) {
393            if (isEnabledFor(priority)) {
394                final Message msg = new LocalizedMessage(bundle, key, null);
395                forcedLog(FQCN, priority, msg, t);
396            }
397        }
398    
399        public void l7dlog(final Priority priority, final String key, final Object[] params, final Throwable t) {
400            if (isEnabledFor(priority)) {
401                final Message msg = new LocalizedMessage(bundle, key, params);
402                forcedLog(FQCN, priority, msg, t);
403            }
404        }
405    
406        public void log(final Priority priority, final Object message, final Throwable t) {
407            if (isEnabledFor(priority)) {
408                final Message msg = new ObjectMessage(message);
409                forcedLog(FQCN, priority, msg, t);
410            }
411        }
412    
413        public void log(final Priority priority, final Object message) {
414            if (isEnabledFor(priority)) {
415                final Message msg = new ObjectMessage(message);
416                forcedLog(FQCN, priority, msg, null);
417            }
418        }
419    
420        public void log(final String fqcn, final Priority priority, final Object message, final Throwable t) {
421            if (isEnabledFor(priority)) {
422                final Message msg = new ObjectMessage(message);
423                forcedLog(fqcn, priority, msg, t);
424            }
425        }
426    
427        private void maybeLog(final String fqcn, final org.apache.logging.log4j.Level level,
428                final Object message, final Throwable throwable) {
429            if (logger.isEnabled(level, null, message, throwable)) {
430                logger.log(null, FQCN, level, new ObjectMessage(message), throwable);
431            }
432        }
433    
434        /**
435         * Private logger factory.
436         */
437        private static class PrivateFactory implements LoggerFactory {
438    
439            public Logger makeNewLoggerInstance(final LoggerContext context, final String name) {
440                return new Logger(context, name);
441            }
442        }
443    
444        /**
445         * Private LogManager.
446         */
447        private static class PrivateManager extends org.apache.logging.log4j.LogManager {
448            private static final String FQCN = Category.class.getName();
449    
450            public static org.apache.logging.log4j.spi.LoggerContext getContext() {
451                return getContext(FQCN, false);
452            }
453    
454            public static org.apache.logging.log4j.Logger getLogger(final String name) {
455                return getLogger(FQCN, name);
456            }
457        }
458    
459        private boolean isEnabledFor(final org.apache.logging.log4j.Level level) {
460            return logger.isEnabled(level, null, null);
461        }
462    
463    }