| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache license, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the license for the specific language governing permissions and |
| * limitations under the license. |
| */ |
| package org.apache.log4j; |
| |
| import java.util.Enumeration; |
| import java.util.Map; |
| import java.util.ResourceBundle; |
| import java.util.WeakHashMap; |
| import java.util.concurrent.ConcurrentHashMap; |
| import java.util.concurrent.ConcurrentMap; |
| |
| import org.apache.log4j.helpers.NullEnumeration; |
| import org.apache.log4j.legacy.core.CategoryUtil; |
| import org.apache.log4j.or.ObjectRenderer; |
| import org.apache.log4j.or.RendererSupport; |
| import org.apache.log4j.spi.LoggerFactory; |
| import org.apache.log4j.spi.LoggingEvent; |
| import org.apache.logging.log4j.message.MapMessage; |
| import org.apache.logging.log4j.message.SimpleMessage; |
| import org.apache.logging.log4j.spi.ExtendedLogger; |
| import org.apache.logging.log4j.spi.LoggerContext; |
| import org.apache.logging.log4j.message.LocalizedMessage; |
| import org.apache.logging.log4j.message.Message; |
| import org.apache.logging.log4j.message.ObjectMessage; |
| import org.apache.logging.log4j.spi.AbstractLoggerAdapter; |
| import org.apache.logging.log4j.util.Strings; |
| |
| |
| /** |
| * Implementation of the Category class for compatibility, despite it having been deprecated a long, long time ago. |
| */ |
| public class Category { |
| |
| private static final PrivateAdapter adapter = new PrivateAdapter(); |
| |
| private static final Map<LoggerContext, ConcurrentMap<String, Logger>> CONTEXT_MAP = |
| new WeakHashMap<>(); |
| |
| private static final String FQCN = Category.class.getName(); |
| |
| private static final boolean isCoreAvailable; |
| |
| private final Map<Class<?>, ObjectRenderer> rendererMap; |
| |
| static { |
| boolean available; |
| |
| try { |
| available = Class.forName("org.apache.logging.log4j.core.Logger") != null; |
| } catch (Exception ex) { |
| available = false; |
| } |
| isCoreAvailable = available; |
| } |
| |
| /** |
| * Resource bundle for localized messages. |
| */ |
| protected ResourceBundle bundle = null; |
| |
| private final org.apache.logging.log4j.Logger logger; |
| |
| /** |
| * Constructor used by Logger to specify a LoggerContext. |
| * @param context The LoggerContext. |
| * @param name The name of the Logger. |
| */ |
| protected Category(final LoggerContext context, final String name) { |
| this.logger = context.getLogger(name); |
| rendererMap = ((RendererSupport) LogManager.getLoggerRepository()).getRendererMap(); |
| } |
| |
| /** |
| * Constructor exposed by Log4j 1.2. |
| * @param name The name of the Logger. |
| */ |
| protected Category(final String name) { |
| this(PrivateManager.getContext(), name); |
| } |
| |
| private Category(final org.apache.logging.log4j.Logger logger) { |
| this.logger = logger; |
| rendererMap = ((RendererSupport) LogManager.getLoggerRepository()).getRendererMap(); |
| } |
| |
| public static Category getInstance(final String name) { |
| return getInstance(PrivateManager.getContext(), name, adapter); |
| } |
| |
| static Logger getInstance(final LoggerContext context, final String name) { |
| return getInstance(context, name, adapter); |
| } |
| |
| static Logger getInstance(final LoggerContext context, final String name, final LoggerFactory factory) { |
| final ConcurrentMap<String, Logger> loggers = getLoggersMap(context); |
| Logger logger = loggers.get(name); |
| if (logger != null) { |
| return logger; |
| } |
| logger = factory.makeNewLoggerInstance(name); |
| final Logger prev = loggers.putIfAbsent(name, logger); |
| return prev == null ? logger : prev; |
| } |
| |
| static Logger getInstance(final LoggerContext context, final String name, final PrivateAdapter factory) { |
| final ConcurrentMap<String, Logger> loggers = getLoggersMap(context); |
| Logger logger = loggers.get(name); |
| if (logger != null) { |
| return logger; |
| } |
| logger = factory.newLogger(name, context); |
| final Logger prev = loggers.putIfAbsent(name, logger); |
| return prev == null ? logger : prev; |
| } |
| |
| public static Category getInstance(@SuppressWarnings("rawtypes") final Class clazz) { |
| return getInstance(clazz.getName()); |
| } |
| |
| static Logger getInstance(final LoggerContext context, @SuppressWarnings("rawtypes") final Class clazz) { |
| return getInstance(context, clazz.getName()); |
| } |
| |
| public final String getName() { |
| return logger.getName(); |
| } |
| |
| org.apache.logging.log4j.Logger getLogger() { |
| return logger; |
| } |
| |
| public final Category getParent() { |
| if (!isCoreAvailable) { |
| return null; |
| } |
| org.apache.logging.log4j.Logger parent = CategoryUtil.getParent(logger); |
| LoggerContext loggerContext = CategoryUtil.getLoggerContext(logger); |
| if (parent == null || loggerContext == null) { |
| return null; |
| } |
| final ConcurrentMap<String, Logger> loggers = getLoggersMap(loggerContext); |
| final Logger l = loggers.get(parent.getName()); |
| return l == null ? new Category(parent) : l; |
| } |
| |
| public static Category getRoot() { |
| return getInstance(Strings.EMPTY); |
| } |
| |
| static Logger getRoot(final LoggerContext context) { |
| return getInstance(context, Strings.EMPTY); |
| } |
| |
| private static ConcurrentMap<String, Logger> getLoggersMap(final LoggerContext context) { |
| synchronized (CONTEXT_MAP) { |
| ConcurrentMap<String, Logger> map = CONTEXT_MAP.get(context); |
| if (map == null) { |
| map = new ConcurrentHashMap<>(); |
| CONTEXT_MAP.put(context, map); |
| } |
| return map; |
| } |
| } |
| |
| /** |
| Returns all the currently defined categories in the default |
| hierarchy as an {@link java.util.Enumeration Enumeration}. |
| |
| <p>The root category is <em>not</em> included in the returned |
| {@link Enumeration}. |
| @return and Enumeration of the Categories. |
| |
| @deprecated Please use {@link LogManager#getCurrentLoggers()} instead. |
| */ |
| @SuppressWarnings("rawtypes") |
| @Deprecated |
| public static Enumeration getCurrentCategories() { |
| return LogManager.getCurrentLoggers(); |
| } |
| |
| public final Level getEffectiveLevel() { |
| switch (logger.getLevel().getStandardLevel()) { |
| case ALL: |
| return Level.ALL; |
| case TRACE: |
| return Level.TRACE; |
| case DEBUG: |
| return Level.DEBUG; |
| case INFO: |
| return Level.INFO; |
| case WARN: |
| return Level.WARN; |
| case ERROR: |
| return Level.ERROR; |
| case FATAL: |
| return Level.FATAL; |
| default: |
| // TODO Should this be an IllegalStateException? |
| return Level.OFF; |
| } |
| } |
| |
| public final Priority getChainedPriority() { |
| return getEffectiveLevel(); |
| } |
| |
| public final Level getLevel() { |
| return getEffectiveLevel(); |
| } |
| |
| private String getLevelStr(final Priority priority) { |
| return priority == null ? null : priority.levelStr; |
| } |
| |
| public void setLevel(final Level level) { |
| setLevel(getLevelStr(level)); |
| } |
| |
| public final Level getPriority() { |
| return getEffectiveLevel(); |
| } |
| |
| public void setPriority(final Priority priority) { |
| setLevel(getLevelStr(priority)); |
| } |
| |
| private void setLevel(final String levelStr) { |
| if (isCoreAvailable) { |
| CategoryUtil.setLevel(logger, org.apache.logging.log4j.Level.toLevel(levelStr)); |
| } |
| } |
| |
| public void debug(final Object message) { |
| maybeLog(FQCN, org.apache.logging.log4j.Level.DEBUG, message, null); |
| } |
| |
| public void debug(final Object message, final Throwable t) { |
| maybeLog(FQCN, org.apache.logging.log4j.Level.DEBUG, message, t); |
| } |
| |
| public boolean isDebugEnabled() { |
| return logger.isDebugEnabled(); |
| } |
| |
| public void error(final Object message) { |
| maybeLog(FQCN, org.apache.logging.log4j.Level.ERROR, message, null); |
| } |
| |
| public void error(final Object message, final Throwable t) { |
| maybeLog(FQCN, org.apache.logging.log4j.Level.ERROR, message, t); |
| } |
| |
| public boolean isErrorEnabled() { |
| return logger.isErrorEnabled(); |
| } |
| |
| public void warn(final Object message) { |
| maybeLog(FQCN, org.apache.logging.log4j.Level.WARN, message, null); |
| } |
| |
| public void warn(final Object message, final Throwable t) { |
| maybeLog(FQCN, org.apache.logging.log4j.Level.WARN, message, t); |
| } |
| |
| public boolean isWarnEnabled() { |
| return logger.isWarnEnabled(); |
| } |
| |
| public void fatal(final Object message) { |
| maybeLog(FQCN, org.apache.logging.log4j.Level.FATAL, message, null); |
| } |
| |
| public void fatal(final Object message, final Throwable t) { |
| maybeLog(FQCN, org.apache.logging.log4j.Level.FATAL, message, t); |
| } |
| |
| public boolean isFatalEnabled() { |
| return logger.isFatalEnabled(); |
| } |
| |
| public void info(final Object message) { |
| maybeLog(FQCN, org.apache.logging.log4j.Level.INFO, message, null); |
| } |
| |
| public void info(final Object message, final Throwable t) { |
| maybeLog(FQCN, org.apache.logging.log4j.Level.INFO, message, t); |
| } |
| |
| public boolean isInfoEnabled() { |
| return logger.isInfoEnabled(); |
| } |
| |
| public void trace(final Object message) { |
| maybeLog(FQCN, org.apache.logging.log4j.Level.TRACE, message, null); |
| } |
| |
| public void trace(final Object message, final Throwable t) { |
| maybeLog(FQCN, org.apache.logging.log4j.Level.TRACE, message, t); |
| } |
| |
| public boolean isTraceEnabled() { |
| return logger.isTraceEnabled(); |
| } |
| |
| public boolean isEnabledFor(final Priority level) { |
| final org.apache.logging.log4j.Level lvl = org.apache.logging.log4j.Level.toLevel(level.toString()); |
| return isEnabledFor(lvl); |
| } |
| |
| /** |
| * No-op implementation. |
| * @param appender The Appender to add. |
| */ |
| public void addAppender(final Appender appender) { |
| } |
| |
| /** |
| * No-op implementation. |
| * @param event The logging event. |
| */ |
| public void callAppenders(final LoggingEvent event) { |
| } |
| |
| @SuppressWarnings("rawtypes") |
| public Enumeration getAllAppenders() { |
| return NullEnumeration.getInstance(); |
| } |
| |
| /** |
| * No-op implementation. |
| * @param name The name of the Appender. |
| * @return null. |
| */ |
| public Appender getAppender(final String name) { |
| return null; |
| } |
| |
| /** |
| Is the appender passed as parameter attached to this category? |
| * @param appender The Appender to add. |
| * @return true if the appender is attached. |
| */ |
| public boolean isAttached(final Appender appender) { |
| return false; |
| } |
| |
| /** |
| * No-op implementation. |
| */ |
| public void removeAllAppenders() { |
| } |
| |
| /** |
| * No-op implementation. |
| * @param appender The Appender to remove. |
| */ |
| public void removeAppender(final Appender appender) { |
| } |
| |
| /** |
| * No-op implementation. |
| * @param name The Appender to remove. |
| */ |
| public void removeAppender(final String name) { |
| } |
| |
| /** |
| * No-op implementation. |
| */ |
| public static void shutdown() { |
| } |
| |
| public void forcedLog(final String fqcn, final Priority level, final Object message, final Throwable t) { |
| final org.apache.logging.log4j.Level lvl = org.apache.logging.log4j.Level.toLevel(level.toString()); |
| if (logger instanceof ExtendedLogger) { |
| @SuppressWarnings("unchecked") |
| Message msg = message instanceof Message ? (Message) message : message instanceof Map ? |
| new MapMessage((Map) message) : new ObjectMessage(message); |
| ((ExtendedLogger) logger).logMessage(fqcn, lvl, null, msg, t); |
| } else { |
| ObjectRenderer renderer = get(message.getClass()); |
| final Message msg = message instanceof Message ? (Message) message : renderer != null ? |
| new RenderedMessage(renderer, message) : new ObjectMessage(message); |
| logger.log(lvl, msg, t); |
| } |
| } |
| |
| public boolean exists(final String name) { |
| return PrivateManager.getContext().hasLogger(name); |
| } |
| |
| public boolean getAdditivity() { |
| return isCoreAvailable ? CategoryUtil.isAdditive(logger) : false; |
| } |
| |
| public void setAdditivity(final boolean additivity) { |
| if (isCoreAvailable) { |
| CategoryUtil.setAdditivity(logger, additivity); |
| } |
| } |
| |
| public void setResourceBundle(final ResourceBundle bundle) { |
| this.bundle = bundle; |
| } |
| |
| public ResourceBundle getResourceBundle() { |
| if (bundle != null) { |
| return bundle; |
| } |
| String name = logger.getName(); |
| if (isCoreAvailable) { |
| LoggerContext ctx = CategoryUtil.getLoggerContext(logger); |
| if (ctx != null) { |
| final ConcurrentMap<String, Logger> loggers = getLoggersMap(ctx); |
| while ((name = getSubName(name)) != null) { |
| final Logger subLogger = loggers.get(name); |
| if (subLogger != null) { |
| final ResourceBundle rb = subLogger.bundle; |
| if (rb != null) { |
| return rb; |
| } |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| private static String getSubName(final String name) { |
| if (Strings.isEmpty(name)) { |
| return null; |
| } |
| final int i = name.lastIndexOf('.'); |
| return i > 0 ? name.substring(0, i) : Strings.EMPTY; |
| } |
| |
| /** |
| If <code>assertion</code> parameter is {@code false}, then |
| logs <code>msg</code> as an {@link #error(Object) error} statement. |
| |
| <p>The <code>assert</code> method has been renamed to |
| <code>assertLog</code> because <code>assert</code> is a language |
| reserved word in JDK 1.4. |
| |
| @param assertion The assertion. |
| @param msg The message to print if <code>assertion</code> is |
| false. |
| |
| @since 1.2 |
| */ |
| public void assertLog(final boolean assertion, final String msg) { |
| if (!assertion) { |
| this.error(msg); |
| } |
| } |
| |
| public void l7dlog(final Priority priority, final String key, final Throwable t) { |
| if (isEnabledFor(priority)) { |
| final Message msg = new LocalizedMessage(bundle, key, null); |
| forcedLog(FQCN, priority, msg, t); |
| } |
| } |
| |
| public void l7dlog(final Priority priority, final String key, final Object[] params, final Throwable t) { |
| if (isEnabledFor(priority)) { |
| final Message msg = new LocalizedMessage(bundle, key, params); |
| forcedLog(FQCN, priority, msg, t); |
| } |
| } |
| |
| public void log(final Priority priority, final Object message, final Throwable t) { |
| if (isEnabledFor(priority)) { |
| @SuppressWarnings("unchecked") |
| final Message msg = message instanceof Map ? new MapMessage((Map) message) : new ObjectMessage(message); |
| forcedLog(FQCN, priority, msg, t); |
| } |
| } |
| |
| public void log(final Priority priority, final Object message) { |
| if (isEnabledFor(priority)) { |
| @SuppressWarnings("unchecked") |
| final Message msg = message instanceof Map ? new MapMessage((Map) message) : new ObjectMessage(message); |
| forcedLog(FQCN, priority, msg, null); |
| } |
| } |
| |
| public void log(final String fqcn, final Priority priority, final Object message, final Throwable t) { |
| if (isEnabledFor(priority)) { |
| final Message msg = new ObjectMessage(message); |
| forcedLog(fqcn, priority, msg, t); |
| } |
| } |
| |
| private void maybeLog( |
| final String fqcn, |
| final org.apache.logging.log4j.Level level, |
| final Object message, |
| final Throwable throwable) { |
| if (logger.isEnabled(level)) { |
| final Message msg; |
| if (message instanceof String) { |
| msg = new SimpleMessage((String) message); |
| } |
| // SimpleMessage treats String and CharSequence differently, hence |
| // this else-if block. |
| else if (message instanceof CharSequence) { |
| msg = new SimpleMessage((CharSequence) message); |
| } else if (message instanceof Map) { |
| @SuppressWarnings("unchecked") |
| final Map<String, ?> map = (Map<String, ?>) message; |
| msg = new MapMessage<>(map); |
| } else { |
| msg = new ObjectMessage(message); |
| } |
| if (logger instanceof ExtendedLogger) { |
| ((ExtendedLogger) logger).logMessage(fqcn, level, null, msg, throwable); |
| } else { |
| logger.log(level, msg, throwable); |
| } |
| } |
| } |
| |
| private static class PrivateAdapter extends AbstractLoggerAdapter<Logger> { |
| |
| @Override |
| protected Logger newLogger(final String name, final org.apache.logging.log4j.spi.LoggerContext context) { |
| return new Logger(context, name); |
| } |
| |
| @Override |
| protected org.apache.logging.log4j.spi.LoggerContext getContext() { |
| return PrivateManager.getContext(); |
| } |
| } |
| |
| /** |
| * Private LogManager. |
| */ |
| private static class PrivateManager extends org.apache.logging.log4j.LogManager { |
| private static final String FQCN = Category.class.getName(); |
| |
| public static LoggerContext getContext() { |
| return getContext(FQCN, false); |
| } |
| |
| public static org.apache.logging.log4j.Logger getLogger(final String name) { |
| return getLogger(FQCN, name); |
| } |
| } |
| |
| private boolean isEnabledFor(final org.apache.logging.log4j.Level level) { |
| return logger.isEnabled(level); |
| } |
| |
| private ObjectRenderer get(Class clazz) { |
| ObjectRenderer renderer = null; |
| for(Class c = clazz; c != null; c = c.getSuperclass()) { |
| renderer = rendererMap.get(c); |
| if (renderer != null) { |
| return renderer; |
| } |
| renderer = searchInterfaces(c); |
| if (renderer != null) { |
| return renderer; |
| } |
| } |
| return null; |
| } |
| |
| ObjectRenderer searchInterfaces(Class c) { |
| ObjectRenderer renderer = rendererMap.get(c); |
| if(renderer != null) { |
| return renderer; |
| } else { |
| Class[] ia = c.getInterfaces(); |
| for (Class clazz : ia) { |
| renderer = searchInterfaces(clazz); |
| if (renderer != null) { |
| return renderer; |
| } |
| } |
| } |
| return null; |
| } |
| |
| } |