/** * 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" ) ; } }