blob: 4134065b2fee57cd6fb78345bacb9594c857920c [file] [log] [blame]
/**
* 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.jena.atlas.logging;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import org.apache.jena.atlas.AtlasException;
import org.slf4j.Logger;
/**
* Setup and control of logging - needs access to log4j2 binaries.
* Sources of configuration:
* <ul>
* <li>Standard setup (e.g. for log4j2, property {@code log4j.configurationFile}
* <li>jena-cmds: the shell scripts set logging to "apache-jena/log4j2.properties." (uses stderr)
* <li>Default logging for log4j2: java resource src/main/resources/log4j-jena.properties (uses stdout)
* </ul>
*/
public class LogCtl {
private static final boolean hasLog4j2 = hasClass("org.apache.logging.slf4j.Log4jLoggerFactory");
private static final boolean hasLog4j1 = hasClass("org.slf4j.impl.Log4jLoggerFactory");
private static final boolean hasJUL = hasClass("org.slf4j.impl.JDK14LoggerFactory");
// JUL always present but needs slf4j adapter.
private static boolean hasClass(String className) {
try {
Class.forName(className);
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
static public void set(Logger logger, String level) {
setLevel(logger.getName(), level);
}
static public void setLevel(Class<? > logger, String level) {
setLevel(logger.getName(), level);
}
static public void setLevel(Logger logger, String level) {
setLevel(logger.getName(), level);
}
static public void setLevel(String logger, String level) {
// setLevelLog4j1(logger,level);
setLevelLog4j2(logger, level);
setLevelJUL(logger, level);
}
static public String getLevel(Logger logger) {
return getLevel(logger.getName());
}
static public String getLevel(Class<? > logger) {
return getLevel(logger.getName());
}
static public String getLevel(String logger) {
String s2 = getLevelLog4j2(logger);
if ( s2 != null )
return s2;
// Always present.
String s3 = getLevelJUL(logger);
if ( s3 != null )
return s3;
return null;
}
static private String getLevelJUL(String logger) {
java.util.logging.Level level = java.util.logging.Logger.getLogger(logger).getLevel();
if ( level == null )
return null;
if ( level == java.util.logging.Level.SEVERE )
return "ERROR";
return level.getName();
}
static private String getLevelLog4j2(String logger) {
if ( !hasLog4j2 )
return null;
org.apache.logging.log4j.Level level = org.apache.logging.log4j.LogManager.getLogger(logger).getLevel();
if ( level != null )
return level.toString();
return null;
}
private static void setLevelJUL(String logger, String levelName) {
java.util.logging.Level level = java.util.logging.Level.ALL;
if ( levelName == null )
level = null;
else if ( levelName.equalsIgnoreCase("info") )
level = java.util.logging.Level.INFO;
else if ( levelName.equalsIgnoreCase("debug") )
level = java.util.logging.Level.FINE;
else if ( levelName.equalsIgnoreCase("warn") || levelName.equalsIgnoreCase("warning") )
level = java.util.logging.Level.WARNING;
else if ( levelName.equalsIgnoreCase("error") || levelName.equalsIgnoreCase("severe") )
level = java.util.logging.Level.SEVERE;
else if ( levelName.equalsIgnoreCase("OFF") )
level = java.util.logging.Level.OFF;
java.util.logging.Logger.getLogger(logger).setLevel(level);
}
private static void setLevelLog4j2(String logger, String levelName) {
if ( !hasLog4j2 )
return;
org.apache.logging.log4j.Level level = org.apache.logging.log4j.Level.ALL;
if ( levelName == null )
level = null;
else if ( levelName.equalsIgnoreCase("info") )
level = org.apache.logging.log4j.Level.INFO;
else if ( levelName.equalsIgnoreCase("debug") )
level = org.apache.logging.log4j.Level.DEBUG;
else if ( levelName.equalsIgnoreCase("warn") || levelName.equalsIgnoreCase("warning") )
level = org.apache.logging.log4j.Level.WARN;
else if ( levelName.equalsIgnoreCase("error") || levelName.equalsIgnoreCase("severe") )
level = org.apache.logging.log4j.Level.ERROR;
else if ( levelName.equalsIgnoreCase("fatal") )
level = org.apache.logging.log4j.Level.FATAL;
else if ( levelName.equalsIgnoreCase("OFF") )
level = org.apache.logging.log4j.Level.OFF;
try {
// "try" : If log4j2 core is not on the path (everything else is
// log4j-api).
if ( !logger.equals("") )
org.apache.logging.log4j.core.config.Configurator.setLevel(logger, level);
else
org.apache.logging.log4j.core.config.Configurator.setRootLevel(level);
} catch (NoClassDefFoundError ex) {
Log.warnOnce(LogCtl.class, "Log4j2 Configurator not found", LogCtl.class);
}
}
/**
* Turn on a logger (all levels). Works for Log4j and Java logging as the logging
* provider to Apache common logging or slf4j.
*/
static public void enable(Logger logger) {
enable(logger.getName());
}
static public void enable(String logger) {
setLevel(logger, "all");
}
/**
* Turn on a logger (all levels). Works for Log4j and Java logging as the logging
* provider to Apache common logging or slf4j.
*/
static public void enable(Class<? > logger) {
setLevel(logger.getName(), "ALL");
}
/**
* Turn on a logger (all levels). Works for Log4j and Java logging as the logging
* provider to Apache common logging or slf4j.
*/
static public void disable(Logger logger) {
setLevel(logger.getName(), "OFF");
}
/**
* Turn on a logger (all levels). Works for Log4j and Java logging as the logging
* provider to Apache common logging or slf4j.
*/
static public void disable(String logger) {
setLevel(logger, "OFF");
}
/**
* Turn on a logger (all levels). Works for Log4j and Java logging as the logging
* provider to Apache common logging or slf4j.
*/
static public void disable(Class<? > logger) {
setLevel(logger.getName(), "OFF");
}
/**
* Set to info level. Works for Log4j and Java logging as the logging provider to
* Apache common logging or slf4j.
*/
static public void setInfo(String logger) {
setLevel(logger, "info");
}
/**
* Set to info level. Works for Log4j and Java logging as the logging provider to
* Apache common logging or slf4j.
*/
static public void setInfo(Class<? > logger) {
setLevel(logger.getName(), "info");
}
/**
* Set to warning level. Works for Log4j and Java logging as the logging provider
* to Apache common logging or slf4j.
*/
static public void setWarn(String logger) {
setLevel(logger, "warn");
}
/**
* Set to warning level. Works for Log4j and Java logging as the logging provider
* to Apache common logging or slf4j.
*/
static public void setWarn(Class<? > logger) {
setLevel(logger.getName(), "warn");
}
/**
* Set to error level. Works for Log4j and Java logging as the logging provider
* to Apache common logging or slf4j.
*/
static public void setError(String logger) {
setLevel(logger, "error");
}
/**
* Set to error level. Works for Log4j and Java logging as the logging provider
* to Apache common logging or slf4j.
*/
static public void setError(Class<? > logger) {
setLevel(logger.getName(), "error");
}
// ---- Setup
/**
* Set logging.
* <p>
* Normally, the logging provider mechanism should be used.
* This call will insert some kind of logging set for JUL and Log4j2
* when no configuration is setup; output is to stdout.
* <p>
* Ideally, initialize the logging provider using the mechanism specific to that provider.
* For example, see the <a href="https://logging.apache.org/log4j/2.x/manual/configuration.html">log4j2 configuration documentation</a>.
* <p>
* To set application logging, choose one of:
* <ul>
* <li>For JUL logging, have a dependency on artifact {@code org.slf4j:slf4j-jdk14}.
* <li>For log4j2 logging, have a dependency on artifact {@code org.apache.logging.log4j:log4j-slf4j-impl}.
* </ul>
*/
public static void setLogging() {
// Assumes log4j2 or JUL (and slf4j adapters) on the classpath.
if ( hasLog4j2 ) {
setLog4j2();
return;
}
if ( hasJUL ) {
setJavaLogging();
return;
}
}
/**
* @deprecated Use {@link #setLogging}.
*/
@Deprecated
public static void setCmdLogging() {
setLogging();
}
/**
* @deprecated Use {@link #setLog4j2}
*/
@Deprecated
public static void setLog4j() {
System.err.println("Log4j1 supported removed. Please use setLog4j2.");
}
/**
* @deprecated Use logging provider setup. For log4j2, use system property "log4j.configurationFile"
*/
@Deprecated
public static void setLog4j(String filename) {
System.err.println("Log4j1 supported removed. Please use setLog4j2.");
}
// ---- log4j2.
/** The log4j2 configuration file - must be a file or URL, not a classpath java resource */
public static final String log4j2ConfigProperty = "log4j.configurationFile";
private static final String[] log4j2files = {"log4j2.properties", "log4j2.xml"};
/**
* Setup log4j2, including looking for a file "log4j2.properties" or "log4j2.xml"
* in the current working directory.
* @see #setLogging()
*/
public static void setLog4j2() {
if ( ! isSetLog4j2property() ) {
setLog4j2property();
if ( isSetLog4j2property() )
return;
// Nothing found - built-in default.
LogCmd.resetLogging(LogCmd.log4j2setup);
}
}
/* package */ static boolean isSetLog4j2property() {
return System.getProperty(log4j2ConfigProperty) != null;
}
/** Set log4j, looking for files */
/*package*/ static void setLog4j2property() {
if ( isSetLog4j2property() )
return;
for ( String fn : log4j2files ) {
File f = new File(fn);
if ( f.exists() ) {
System.setProperty(log4j2ConfigProperty, "file:" + fn);
return;
}
}
}
// ---- java.util.logging - because that's always present.
// Need: org.slf4j:slf4j-jdk14
private static String JUL_PROPERTY = "java.util.logging.configuration";
/**
* Setup java.util.logging if it has not been set before; otherwise do nothing.
*/
public static void setJavaLogging() {
if ( System.getProperty(JUL_PROPERTY) != null )
return;
LogJUL.resetJavaLogging();
}
/**
* Setup java.util.logging with the configuration from a file.
* @param filename
*/
public static void setJavaLogging(String filename) {
try {
InputStream details = new FileInputStream(filename);
details = new BufferedInputStream(details);
LogJUL.readJavaLoggingConfiguration(details);
} catch (Exception ex) {
throw new AtlasException(ex);
}
}
}