| /* |
| * Copyright (c) 2009, 2021 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // Jaro Kuruc - Initial API and implementation. |
| // Tomas Kraus - EclipseLink 2.7 integration. |
| package org.eclipse.persistence.logging.slf4j; |
| |
| import java.security.AccessController; |
| |
| import org.eclipse.persistence.config.PersistenceUnitProperties; |
| import org.eclipse.persistence.internal.security.PrivilegedAccessHelper; |
| import org.eclipse.persistence.internal.security.PrivilegedGetSystemProperty; |
| import org.eclipse.persistence.logging.AbstractSessionLog; |
| import org.eclipse.persistence.logging.LogCategory; |
| import org.eclipse.persistence.logging.LogLevel; |
| import org.eclipse.persistence.logging.SessionLogEntry; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * EclipseLink logger bridge over SLF4J. |
| */ |
| public class SLF4JLogger extends AbstractSessionLog { |
| |
| /** Logger callback interface. */ |
| private interface LoggerCall { |
| void log(final Logger logger, final String msg, final Throwable t); |
| void log(final Logger logger, final String message); |
| } |
| |
| /** {@code TRACE} level log. */ |
| private static final class LogTrace implements LoggerCall { |
| @Override |
| public void log(final Logger logger, final String msg, final Throwable t) { |
| logger.trace(msg, t); |
| } |
| @Override |
| public void log(final Logger logger, final String message) { |
| logger.trace(message); |
| } |
| } |
| |
| /** {@code DEBUG} level log. */ |
| private static final class LogDebug implements LoggerCall { |
| @Override |
| public void log(final Logger logger, final String msg, final Throwable t) { |
| logger.debug(msg, t); |
| } |
| @Override |
| public void log(final Logger logger, final String message) { |
| logger.debug(message); |
| } |
| } |
| |
| /** {@code INFO} level log. */ |
| private static final class LogInfo implements LoggerCall { |
| @Override |
| public void log(final Logger logger, final String msg, final Throwable t) { |
| logger.info(msg, t); |
| } |
| @Override |
| public void log(final Logger logger, final String message) { |
| logger.info(message); |
| } |
| } |
| |
| /** {@code WARN} level log. */ |
| private static final class LogWarn implements LoggerCall { |
| @Override |
| public void log(final Logger logger, final String msg, final Throwable t) { |
| logger.warn(msg, t); |
| } |
| @Override |
| public void log(final Logger logger, final String message) { |
| logger.warn(message); |
| } |
| } |
| |
| /** {@code ERROR} level log. */ |
| private static final class LogError implements LoggerCall { |
| @Override |
| public void log(final Logger logger, final String msg, final Throwable t) { |
| logger.error(msg, t); |
| } |
| @Override |
| public void log(final Logger logger, final String message) { |
| logger.error(message); |
| } |
| } |
| |
| /** Do not log anything. */ |
| private static final class LogNop implements LoggerCall { |
| @Override |
| public void log(final Logger logger, final String msg, final Throwable t) { |
| } |
| @Override |
| public void log(final Logger logger, final String message) { |
| } |
| } |
| |
| /** The default session name in case there is session name is missing. */ |
| public static final String ECLIPSELINK_NAMESPACE = "org.eclipse.persistence"; |
| |
| /** SLF4J logger calls mapping for EclipseLink logging levels. */ |
| private static final LoggerCall[] loggerCall = new LoggerCall[LogLevel.length]; |
| |
| /** Loggers lookup array. */ |
| private static final Logger[] categoryLoggers = new Logger[LogCategory.length]; |
| |
| static { |
| // Initialize loggers lookup array. |
| for (int i = 0; i < LogCategory.length; i++) { |
| categoryLoggers[i] = null; |
| } |
| // Initialize SLF4J logger calls mapping for EclipseLink logging levels. |
| loggerCall[LogLevel.ALL.getId()] = loggerCall[LogLevel.FINEST.getId()] = new LogTrace(); |
| loggerCall[LogLevel.FINER.getId()] = loggerCall[LogLevel.FINE.getId()] = new LogDebug(); |
| loggerCall[LogLevel.CONFIG.getId()] = loggerCall[LogLevel.INFO.getId()] = new LogInfo(); |
| loggerCall[LogLevel.WARNING.getId()] = new LogWarn(); |
| loggerCall[LogLevel.SEVERE.getId()] = new LogError(); |
| loggerCall[LogLevel.OFF.getId()] = new LogNop(); |
| } |
| |
| /** |
| * Retrieve Logger for the given category. |
| * @param category EclipseLink logging category |
| * @return Logger for the given logging category. |
| */ |
| private static Logger getLogger(final LogCategory category) { |
| final Logger logger = categoryLoggers[category.getId()]; |
| if (logger != null) { |
| return logger; |
| } |
| return categoryLoggers[category.getId()] = LoggerFactory.getLogger(category.getNameSpace()); |
| } |
| |
| /** Logging levels for individual logging categories. */ |
| private final LogLevel[] logLevels; |
| |
| /** |
| * Creates an instance of EclipseLink logger bridge over SLF4J |
| */ |
| public SLF4JLogger() { |
| super(); |
| // Set default logging levels for all logging categories. |
| final byte defaultLevel = LogLevel.toValue(level).getId(); |
| logLevels = new LogLevel[LogCategory.length]; |
| for (LogCategory category : LogCategory.values()) { |
| final int i = category.getId(); |
| switch(category) { |
| case ALL: |
| logLevels[i] = LogLevel.toValue(defaultLevel); |
| break; |
| default: |
| final String property = PersistenceUnitProperties.CATEGORY_LOGGING_LEVEL_ + category.getName(); |
| final String logLevelStr = PrivilegedAccessHelper.shouldUsePrivilegedAccess() |
| ? AccessController.doPrivileged(new PrivilegedGetSystemProperty(property)) |
| : System.getProperty(property); |
| logLevels[i] = LogLevel.toValue( |
| logLevelStr != null ? translateStringToLoggingLevel(logLevelStr) : defaultLevel); |
| } |
| } |
| } |
| |
| /** |
| * Get the logging level for the default logging category. |
| * @return level Current logging level for default the default logging category. |
| */ |
| @Override |
| public int getLevel() { |
| return logLevels[LogCategory.ALL.getId()].getId(); |
| } |
| |
| /** |
| * Get the logging level for the specified logging category. |
| * @param categoryName The {@link String} representation of an EclipseLink logging category. |
| * @return level Current logging level for default the default logging category. |
| */ |
| @Override |
| public int getLevel(final String categoryName) { |
| final LogCategory category = LogCategory.toValue(categoryName); |
| if (category == null) { |
| throw new IllegalArgumentException("Unknown logging category name."); |
| } |
| return logLevels[category.getId()].getId(); |
| } |
| |
| /** |
| * Set the logging level for the default logging category. |
| * @param level The logging level to be set. |
| */ |
| @Override |
| public void setLevel(final int level) { |
| super.setLevel(level); |
| logLevels[LogCategory.ALL.getId()] = LogLevel.toValue(level); |
| // TODO: Handle logging levels on SLF4J side too. |
| } |
| |
| /** |
| * Set the logging level for the specified logging category. |
| * @param level The logging level to be set. |
| * @param categoryName The {@link String} representation of an EclipseLink logging category. |
| */ |
| @Override |
| public void setLevel(final int level, final String categoryName) { |
| final LogCategory category = LogCategory.toValue(categoryName); |
| if (category == null) { |
| throw new IllegalArgumentException("Unknown logging category name."); |
| } |
| logLevels[category.getId()] = LogLevel.toValue(level); |
| // TODO: Handle logging levels on SLF4J side too. |
| } |
| |
| /** |
| * Check if a message of the given level would actually be logged under logging level for the default logging |
| * category. |
| * @param level Message logging level. |
| * @return Value of {@code true} if the given message logging level will be logged or {@code false} otherwise. |
| */ |
| @Override |
| public boolean shouldLog(final int level) { |
| return logLevels[LogCategory.ALL.getId()].shouldLog((byte)level); |
| } |
| |
| /** |
| * Check if a message of the given level would actually be logged under logging level for the specified logging |
| * category. |
| * @param level Message logging level. |
| * @param categoryName The {@link String} representation of an EclipseLink logging category. |
| * @return Value of {@code true} if the given message logging level will be logged or {@code false} otherwise. |
| */ |
| @Override |
| public boolean shouldLog(final int level, final String categoryName) { |
| final LogCategory category = LogCategory.toValue(categoryName); |
| if (category == null) { |
| throw new IllegalArgumentException("Unknown logging category name."); |
| } |
| return logLevels[category.getId()].shouldLog((byte)level); |
| } |
| |
| @Override |
| public void log(final SessionLogEntry logEntry) { |
| if (logEntry == null) { |
| return; |
| } |
| final LogCategory category = LogCategory.toValue(logEntry.getNameSpace()); |
| if (category == null) { |
| throw new IllegalArgumentException("Unknown logging category name."); |
| } |
| final byte levelId = (byte)logEntry.getLevel(); |
| if (logLevels[category.getId()].shouldLog(levelId)) { |
| final LogLevel level = LogLevel.toValue(levelId); |
| final Logger logger = getLogger(category); |
| if (logEntry.hasException()) { |
| if (shouldLogExceptionStackTrace()) { |
| // Message is rendered on EclipseLink side. SLF4J gets final String. Exception is passed too. |
| loggerCall[level.getId()].log(logger, formatMessage(logEntry), logEntry.getException()); |
| } else { |
| // Exception message is rendered on EclipseLink side. SLF4J gets final String. |
| loggerCall[level.getId()].log(logger, logEntry.getException().toString()); |
| } |
| } else { |
| // Message is rendered on EclipseLink side. SLF4J gets final String. |
| loggerCall[level.getId()].log(logger, formatMessage(logEntry)); |
| } |
| } |
| } |
| |
| } |