/**
* 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.fuseki;
import java.io.File ;
import java.net.URL ;
import org.apache.jena.atlas.lib.StrUtils ;
import org.apache.jena.atlas.logging.LogCtl ;
import org.apache.jena.fuseki.server.FusekiEnv ;
import org.apache.jena.riot.SysRIOT ;
import org.apache.log4j.PropertyConfigurator ;
import org.apache.log4j.helpers.Loader ;
public class FusekiLogging
{
// This class must not have static constants, or otherwise not "Fuseki.*"
// or any class else where that might kick off logging. Otherwise, the
// setLogging is pointless (it's already set).
// PlanB - reinitialize logging regardless on first call.
// Set logging.
// 1/ Use log4j.configuration if defined.
// 2/ Use file:log4j.properties if exists
// 3/ Use log4j.properties on the classpath.
// 4/ Use built-in org/apache/jena/fuseki/log4j.properties on the classpath.
// 5/ Use Built in string
/** Places for the log4j properties file at (3) */
private static final String[] resourcesForLog4jProperties = {
// Hmm -
"log4j.properties",
"org/apache/jena/fuseki/log4j.properties"
} ;
private static final boolean LogLogging = false ;
private static boolean loggingInitialized = false ;
private static boolean allowLoggingReset = true ;
/**
* Switch off logging setting.
* Used by the embedded server so that the application's
* logging setup is not overwritten.
*/
public static synchronized void allowLoggingReset(boolean value) {
allowLoggingReset = value ;
}
/** Set up logging - standalone and war packaging */
public static synchronized void setLogging() {
if ( ! allowLoggingReset )
return ;
if ( loggingInitialized )
return ;
loggingInitialized = true ;
FusekiEnv.setEnvironment() ;
logLogging("Fuseki logging") ;
// No loggers have been created but configuration may have been set up.
String x = System.getProperty("log4j.configuration", null) ;
logLogging("log4j.configuration = %s", x) ;
if ( x != null ) {
// log4j will initialize in the usual way. This includes a value of
// "set", which indicates that logging was set before by some other Jena code.
if ( x.equals("set") )
Fuseki.serverLog.warn("Fuseki logging: Unexpected: Log4j was setup by some other part of Jena") ;
return ;
}
logLogging("Fuseki logging - setup") ;
// Look for a log4j.properties in the current working directory
// and an existing FUSEKI_BASE for easy customization.
String fn1 = "log4j.properties" ;
String fn2 = null ;
if ( FusekiEnv.FUSEKI_BASE != null )
fn2 = FusekiEnv.FUSEKI_BASE.toString()+"/log4j.properties" ;
if ( attempt(fn1) ) return ;
if ( attempt(fn2) ) return ;
// Try classpath
for ( String resourceName : resourcesForLog4jProperties ) {
// The log4j general initialization is done in a class static
// in LogManager so it can't be called again in any sensible manner.
// Instead, we include the same basic mechanism ...
logLogging("Fuseki logging - classpath %s", resourceName) ;
URL url = Loader.getResource(resourceName) ;
if ( url != null ) {
// Problem - test classes can be on the classpath (development mainly).
if ( url.toString().contains("-tests.jar") || url.toString().contains("test-classes") )
url = null ;
}
if ( url != null ) {
PropertyConfigurator.configure(url) ;
logLogging("Fuseki logging - found via classpath %s", url) ;
System.setProperty("log4j.configuration", url.toString()) ;
return ;
}
}
// Use builtin.
logLogging("Fuseki logging - Fallback log4j.properties string") ;
String dftLog4j = log4JsetupFallback() ;
LogCtl.resetLogging(dftLog4j);
// Stop anything attempting to do it again.
System.setProperty("log4j.configuration", "set") ;
}
private static boolean attempt(String fn) {
try {
File f = new File(fn) ;
if ( f.exists() ) {
logLogging("Fuseki logging - found file:log4j.properties") ;
PropertyConfigurator.configure(fn) ;
System.setProperty("log4j.configuration", "file:" + fn) ;
return true ;
}
}
catch (Throwable th) {}
return false ;
}
private static void logLogging(String fmt, Object ... args) {
if ( LogLogging ) {
System.out.printf(fmt, args) ;
System.out.println() ;
}
}
private static String log4JsetupFallback() {
return StrUtils.strjoinNL
// Preferred: classes/log4j.properties, from src/main/resources/log4j.properties
// Keep these in-step. Different usages cause different logging initalizations;
// if the jar is rebundled, it may loose the associated log4.properties file.
("## Plain output to stdout",
"log4j.appender.jena.plainstdout=org.apache.log4j.ConsoleAppender",
"log4j.appender.jena.plainstdout.target=System.out",
"log4j.appender.jena.plainstdout.layout=org.apache.log4j.PatternLayout",
"log4j.appender.jena.plainstdout.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss}] %-10c{1} %-5p %m%n",
//"log4j.appender.jena.plainstdout.layout.ConversionPattern=%d{HH:mm:ss} %-10c{1} %-5p %m%n",
"# Unadorned, for the requests log.",
"log4j.appender.fuseki.plain=org.apache.log4j.ConsoleAppender",
"log4j.appender.fuseki.plain.target=System.out",
"log4j.appender.fuseki.plain.layout=org.apache.log4j.PatternLayout",
"log4j.appender.fuseki.plain.layout.ConversionPattern=%m%n",
"## Most things",
"log4j.rootLogger=INFO, jena.plainstdout",
"log4j.logger.com.hp.hpl.jena=WARN",
"log4j.logger.org.apache.jena=WARN",
"# Fuseki System logs.",
"log4j.logger." + Fuseki.serverLogName + "=INFO",
"log4j.logger." + Fuseki.actionLogName + "=INFO",
"log4j.logger." + Fuseki.adminLogName + "=INFO",
"log4j.logger." + Fuseki.validationLogName + "=INFO",
"log4j.logger." + Fuseki.configLogName + "=INFO",
"log4j.logger.org.apache.jena.tdb.loader=INFO",
"log4j.logger.org.eclipse.jetty=WARN" ,
"log4j.logger.org.apache.shiro=WARN",
"# NCSA Request Access log",
"log4j.additivity."+Fuseki.requestLogName + "=false",
"log4j.logger."+Fuseki.requestLogName + "=OFF, fuseki.plain",
"## Parser output",
"log4j.additivity" + SysRIOT.riotLoggerName + "=false",
"log4j.logger." + SysRIOT.riotLoggerName + "=INFO, plainstdout"
) ;
}
}