org.snmp4j.log.LogFactory Maven / Gradle / Ivy
/*_############################################################################
_##
_## SNMP4J - LogFactory.java
_##
_## Copyright (C) 2003-2024 Frank Fock (SNMP4J.org)
_##
_## Licensed 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.snmp4j.log;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
/**
* The {@code LogFactory} singleton is used by SNMP4J to determine
* the logging framework used to process SNMP4J log messages. By default
* {@link NoLogger} instances are used.
*
* @author Frank Fock
* @version 3.4.1
* @since 1.2.1
*/
public class LogFactory {
public static final String SNMP4J_LOG_FACTORY_SYSTEM_PROPERTY = "snmp4j.LogFactory";
public static final String SNMP4J_LOG_FACTORY_LOGGER_DEFAULT_PREFIX = "snmp4j.log.logger.";
public static final String SNMP4J_LOG_FACTORY_LOG_HANDLER_DEFAULT_PREFIX = "snmp4j.log.handler.";
public static final String SNMP4J_LOG_ID = "id";
public static final String SNMP4J_LOG_LEVEL = "level";
public static final String SNMP4J_LOG_HANDLER = "handler";
public static final String SNMP4J_LOG_HANDLER_LIST = "handlers";
private static LogFactory snmp4jLogFactory = null;
private static boolean configChecked = false;
private String loggerConfigPrefix = SNMP4J_LOG_FACTORY_LOGGER_DEFAULT_PREFIX;
private String logHandlerConfigPrefix = SNMP4J_LOG_FACTORY_LOG_HANDLER_DEFAULT_PREFIX;
private final ReentrantLock configurationLock = new ReentrantLock();
protected LogFactory() {
}
/**
* Gets the logger for the supplied class.
*
* @param c
* the class for which a logger needs to be created.
* @return
* the {@code LogAdapter} instance.
*/
public static LogAdapter getLogger(Class> c) {
checkConfig();
if (snmp4jLogFactory == null) {
return NoLogger.instance;
}
else {
return snmp4jLogFactory.createLogger(c.getName());
}
}
private static void checkConfig() {
if (!configChecked) {
configChecked = true;
getFactoryFromSystemProperty();
}
}
@SuppressWarnings("unchecked")
private synchronized static void getFactoryFromSystemProperty() {
try {
String factory =
System.getProperty(SNMP4J_LOG_FACTORY_SYSTEM_PROPERTY, null);
if (factory != null) {
try {
Class extends LogFactory> c = (Class extends LogFactory>)Class.forName(factory);
snmp4jLogFactory = c.getDeclaredConstructor().newInstance();
}
catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
ClassNotFoundException | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
}
catch (SecurityException sec) {
throw new RuntimeException(sec);
}
}
/**
* Returns the top level logger.
* @return
* a LogAdapter instance.
* @since 1.7
*/
public LogAdapter getRootLogger() {
return NoLogger.instance;
}
/**
* Gets the logger for the supplied class name.
*
* @param className
* the class name for which a logger needs to be created.
* @return
* the {@code LogAdapter} instance.
* @since 1.7
*/
public static LogAdapter getLogger(String className) {
checkConfig();
if (snmp4jLogFactory == null) {
return NoLogger.instance;
}
else {
return snmp4jLogFactory.createLogger(className);
}
}
/**
* Creates a Logger for the specified class. This method returns the
* {@link NoLogger} logger instance which disables logging.
* Overwrite this method the return a custom logger to enable logging for
* SNMP4J.
*
* @param c
* the class for which a logger needs to be created.
* @return
* the {@code LogAdapter} instance.
*/
protected LogAdapter createLogger(Class> c) {
return NoLogger.instance;
}
/**
* Creates a Logger for the specified class. This method returns the
* {@link NoLogger} logger instance which disables logging.
* Overwrite this method the return a custom logger to enable logging for
* SNMP4J.
*
* @param className
* the class name for which a logger needs to be created.
* @return
* the {@code LogAdapter} instance.
* @since 1.7
*/
protected LogAdapter createLogger(String className) {
return NoLogger.instance;
}
/**
* Sets the log factory to be used by SNMP4J. Call this method before
* any other SNMP4J class is referenced or created to set and use a custom
* log factory.
*
* @param factory
* a {@code LogFactory} instance.
*/
public static void setLogFactory(LogFactory factory) {
configChecked = true;
if (snmp4jLogFactory != null && snmp4jLogFactory.getRootLogger().isWarnEnabled()) {
snmp4jLogFactory.getRootLogger().warn("LogFactory "+snmp4jLogFactory+" is being reset by "+factory);
}
snmp4jLogFactory = factory;
}
/**
* Gets the log factory to be used by SNMP4J. If the log factory has not been
* initialized by {@link #setLogFactory} a new instance of {@link LogFactory}
* is returned.
*
* @return
* a {@code LogFactory} instance.
* @since 1.7
*/
public static LogFactory getLogFactory() {
if (snmp4jLogFactory == null) {
return new LogFactory();
}
return snmp4jLogFactory;
}
/**
* Returns all available LogAdapters in depth first order.
* @return
* a read-only Iterator.
* @since 1.7
*/
public Iterator loggers() {
return Collections.singletonList((LogAdapter)NoLogger.instance).iterator();
}
/**
* Close all handlers of a logger and set its level to {@code null} if it is not the root logger.
* @param logger
* the logger to be reset.
* @since 3.4.1
*/
public void resetLogger(LogAdapter logger) {
}
public String getLoggerConfigPrefix() {
return loggerConfigPrefix;
}
/**
* Set the properties name prefix, including the trailing ".", used by {@link #updateConfiguration(Properties)} and
* {@link #writeConfiguration(Properties)} for logger properties.
* @param loggerConfigPrefix
* the prefix for {@link LogAdapter} configuration properties.
* @since 3.4.1
*/
public void setLoggerConfigPrefix(String loggerConfigPrefix) {
this.loggerConfigPrefix = loggerConfigPrefix;
}
public String getLogHandlerConfigPrefix() {
return logHandlerConfigPrefix;
}
/**
* Set the properties name prefix, including the trailing ".", used by {@link #updateConfiguration(Properties)} and
* {@link #writeConfiguration(Properties)} for log handler properties.
* @param logHandlerConfigPrefix
* the prefix for log handler configuration properties.
* @since 3.4.1
*/
public void setLogHandlerConfigPrefix(String logHandlerConfigPrefix) {
this.logHandlerConfigPrefix = logHandlerConfigPrefix;
}
/**
* Reset the logging configuration. For all named log adapters, the reset operation removes and closes all handlers
* (log factory specific) and (except for the root logger) sets the level to {@code null}.
* The root logger's level is set to
* {@link LogLevel#INFO}.
* @since 3.4.1
*/
public void reset() {
configurationLock.lock();
try {
LogAdapter rootLogger = getRootLogger();
for (Iterator it = loggers(); it.hasNext(); ) {
LogAdapter logAdapter = it.next();
logAdapter.setLogLevel(null);
}
rootLogger.setLogLevel(LogLevel.INFO);
}
finally {
configurationLock.unlock();
}
}
/**
* Configure the log levels of the {@link LogAdapter} specified in the {@link java.util.Properties} provided by
* the {@code propertiesReader} parameter. For example:
*
* snmp4j.log.level.<loggerName>=<LogLevel>
*
*
* @param config
* the {@link java.util.Properties} that contain properties with the prefixes {@link #getLoggerConfigPrefix()}
* and {@link #getLogHandlerConfigPrefix()}.
*/
public void updateConfiguration(Properties config) {
Map> loggerConfig = new HashMap<>();
Map> logHandlerConfig = new HashMap<>();
String loggerConfigPrefix = getLoggerConfigPrefix();
String logHandlerConfigPrefix = getLogHandlerConfigPrefix();
for (Object key : config.keySet()) {
if (key instanceof String) {
if (((String)key).startsWith(loggerConfigPrefix)) {
extractConfigProperty(config, loggerConfig, (String) key);
}
else if (((String)key).startsWith(logHandlerConfigPrefix)) {
extractConfigProperty(config, logHandlerConfig, (String)key);
}
}
}
configurationLock.lock();
try {
for (Iterator it = loggers(); it.hasNext(); ) {
LogAdapter logAdapter = it.next();
if (loggerConfig.containsKey(logAdapter.getName())) {
Map newConfigAttributes =
loggerConfig.getOrDefault(logAdapter.getName(), Collections.emptyMap());
updateLogger(logAdapter, newConfigAttributes);
if (newConfigAttributes.containsKey(SNMP4J_LOG_HANDLER_LIST)) {
String handlerList = newConfigAttributes.get(SNMP4J_LOG_HANDLER_LIST);
String[] handlerNames = handlerList.split("(\\s|,)*");
for (String handlerName : handlerNames) {
addHandler(logAdapter, handlerName, logHandlerConfig.get(handlerName));
}
}
loggerConfig.remove(logAdapter.getName());
}
else {
resetLogger(logAdapter);
}
}
for (Map.Entry> newLogger : loggerConfig.entrySet()) {
LogAdapter logAdapter = createLogger(newLogger.getKey());
logAdapter.setLogLevel(LogLevel.toLevel(newLogger.getValue().get(SNMP4J_LOG_LEVEL)));
}
}
finally {
configurationLock.unlock();
}
}
private void extractConfigProperty(Properties newProperties, Map> config, String key) {
try {
int endOfPrefixPos = getLoggerConfigPrefix().length();
String attribute = key.substring(endOfPrefixPos, key.indexOf('.', endOfPrefixPos));
String id = key.substring(endOfPrefixPos+attribute.length()+1);
Map attributes = config.computeIfAbsent(id, k -> new TreeMap<>());
attributes.put(attribute, newProperties.getProperty(key));
}
catch (RuntimeException rex) {
// ignore
}
}
protected void removeAllHandlers(LogAdapter logAdapter) {
}
protected void addHandler(LogAdapter logAdapter, String handlerName, Map handlerConfig) {
}
protected void updateLogger(LogAdapter logAdapter, Map loggerConfig) {
logAdapter.setLogLevel(LogLevel.toLevel(loggerConfig.get(SNMP4J_LOG_LEVEL)));
}
public void writeConfiguration(Properties config) {
configurationLock.lock();
try {
for (Iterator it = loggers(); it.hasNext(); ) {
LogAdapter logAdapter = it.next();
writeConfiguration(config, logAdapter);
}
}
finally {
configurationLock.unlock();
}
}
protected void writeConfiguration(Properties config, LogAdapter logAdapter) {
config.put(getLoggerConfigPrefix()+SNMP4J_LOG_LEVEL+"."+logAdapter.getName(), logAdapter.getLogLevel().toString());
Iterator> handler = logAdapter.getLogHandler();
StringBuilder stringBuilder = new StringBuilder();
while (handler.hasNext()) {
String handlerName = writeConfiguration(config, logAdapter, handler.next());
stringBuilder.append(handlerName);
if (handler.hasNext()) {
stringBuilder.append(' ');
}
}
if (!stringBuilder.toString().trim().isEmpty()) {
config.put(getLoggerConfigPrefix()+logAdapter.getName()+"."+SNMP4J_LOG_HANDLER_LIST, stringBuilder.toString());
}
else {
config.remove(getLoggerConfigPrefix()+logAdapter.getName()+"."+SNMP4J_LOG_HANDLER_LIST);
}
}
protected String writeConfiguration(Properties config, LogAdapter logAdapter, Object handler) {
return "";
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy