package ch.qos.logback.classic.servlet;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.slf4j.ILoggerFactory;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.util.OptionHelper;
import ch.qos.logback.core.util.StatusPrinter;
/**
* {@link ServletContextListener} that can be used in web applications to define
* the location of the logback configuration.
*
*
* Should be the first listener to configure logback before using it. Location
* is defined in the logbackConfigLocation
context param.
* Placeholders (ex: ${user.home}) are supported. Location examples:
* /WEB-INF/log-sc.xml -> loaded from servlet context
* classpath:foo/log-cp.xml -> loaded from classpath
* file:/D:/log-absfile.xml -> loaded as url
* D:/log-absfile.xml -> loaded as absolute file
* log-relfile.xml -> loaded as file relative to the servlet container working
* directory
*
*/
public class LogbackConfigListener implements ServletContextListener {
/**
* Context param name.
*/
public static final String CONFIG_LOCATION_PARAM = "logbackConfigLocation";
/**
* Prefix for classpath urls.
*/
public static final String LOCATION_PREFIX_CLASSPATH = "classpath:";
public void contextInitialized(ServletContextEvent sce) {
ServletContext sc = sce.getServletContext();
ILoggerFactory ilc = LoggerFactory.getILoggerFactory();
if (!(ilc instanceof LoggerContext)) {
sc.log("Can not configure logback. " + LoggerFactory.class
+ " is using " + ilc + " which is not an instance of "
+ LoggerContext.class);
return;
}
LoggerContext lc = (LoggerContext) ilc;
String location = sc.getInitParameter(CONFIG_LOCATION_PARAM);
if (location != null)
location = OptionHelper.substVars(location, lc);
if (location == null) {
sc.log("Can not configure logback. Location is null."
+ " Maybe context param \"" + CONFIG_LOCATION_PARAM
+ "\" is not set or is not correct.");
return;
}
URL url = toUrl(sc, location);
if (url == null) {
sc.log("Can not configure logback. Could not find logback"
+ " config neither as servlet context-, nor as"
+ " classpath-, nor as url-, nor as file system"
+ " resource. Config location = \"" + location + "\".");
return;
}
sc.log("Configuring logback. Config location = \"" + location
+ "\", full url = \"" + url + "\".");
configure(sc, url, lc);
}
protected void configure(ServletContext sc, URL location, LoggerContext lc) {
JoranConfigurator configurator = new JoranConfigurator();
configurator.setContext(lc);
lc.stop();
try {
configurator.doConfigure(location);
} catch (JoranException e) {
sc.log("Failed to configure logback.", e);
}
StatusPrinter.printInCaseOfErrorsOrWarnings(lc);
}
protected URL toUrl(ServletContext sc, String location) {
URL url = null;
if (location.startsWith("/"))
try {
url = sc.getResource(location);
} catch (MalformedURLException e1) {
// NO-OP
}
if (url == null && location.startsWith(LOCATION_PREFIX_CLASSPATH))
url = Thread
.currentThread()
.getContextClassLoader()
.getResource(
location.substring(LOCATION_PREFIX_CLASSPATH
.length()));
if (url == null)
try {
url = new URL(location);
} catch (MalformedURLException e) {
// NO-OP
}
if (url == null) {
File file = new File(location);
if (!file.isAbsolute())
file = file.getAbsoluteFile();
if (file.isFile())
try {
url = file.toURI().normalize().toURL();
} catch (MalformedURLException e) {
// NO-OP
}
}
return url;
}
public void contextDestroyed(ServletContextEvent sce) {
ILoggerFactory ilc = LoggerFactory.getILoggerFactory();
if (!(ilc instanceof LoggerContext))
return;
LoggerContext lc = (LoggerContext) ilc;
lc.stop();
}
}