[logback-dev] svn commit: r1284 - in logback/trunk: logback-classic logback-classic/src/main/java/ch/qos/logback/classic logback-classic/src/main/java/ch/qos/logback/classic/selector logback-classic/src/main/java/ch/qos/logback/classic/selector/servlet logback-classic/src/main/java/ch/qos/logback/classic/util logback-classic/src/main/java/org/slf4j logback-core/src/main/java/ch/qos/logback/core/util

noreply.seb at qos.ch noreply.seb at qos.ch
Thu Jan 25 19:25:31 CET 2007


Author: seb
Date: Thu Jan 25 19:25:31 2007
New Revision: 1284

Added:
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/selector/
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/selector/ContextJNDISelector.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/selector/ContextSelector.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/selector/DefaultContextSelector.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/selector/servlet/
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/selector/servlet/ContextDetachingSCL.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/util/JNDIUtil.java
Modified:
   logback/trunk/logback-classic/pom.xml
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/ClassicGlobal.java
   logback/trunk/logback-classic/src/main/java/org/slf4j/LoggerFactory.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/Loader.java

Log:
first commit of a ContextJNDISelector 

Modified: logback/trunk/logback-classic/pom.xml
==============================================================================
--- logback/trunk/logback-classic/pom.xml	(original)
+++ logback/trunk/logback-classic/pom.xml	Thu Jan 25 19:25:31 2007
@@ -85,6 +85,13 @@
       <optional>true</optional>
     </dependency>
 
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <scope>compile</scope>
+      <optional>true</optional>
+    </dependency>
+    
   </dependencies>
 
   <build>

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/ClassicGlobal.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/ClassicGlobal.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/ClassicGlobal.java	Thu Jan 25 19:25:31 2007
@@ -14,4 +14,8 @@
   static public final String CAUSED_BY = "Caused by: ";
   static public final char DOT = '.';
   static public final String USER_MDC_KEY = "user";
+  
+  public static final String LOGBACK_CONTEXT_SELECTOR = "logback.ContextSelector";
+  public static String JNDI_CONFIGURATION_RESOURCE = "java:comp/env/logback/configuration-resource";
+  public static String JNDI_CONTEXT_NAME = "java:comp/env/logback/context-name";
 }

Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/selector/ContextJNDISelector.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/selector/ContextJNDISelector.java	Thu Jan 25 19:25:31 2007
@@ -0,0 +1,112 @@
+package ch.qos.logback.classic.selector;
+
+import static ch.qos.logback.classic.ClassicGlobal.JNDI_CONFIGURATION_RESOURCE;
+import static ch.qos.logback.classic.ClassicGlobal.JNDI_CONTEXT_NAME;
+
+import java.net.URL;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+
+import org.slf4j.Logger;
+
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.classic.util.ContextInitializer;
+import ch.qos.logback.classic.util.JNDIUtil;
+import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.util.Loader;
+import ch.qos.logback.core.util.StatusPrinter;
+
+/**
+ * A class that allows the LoggerFactory to access an environment-based
+ * LoggerContext.
+ * 
+ * To add in catalina.sh
+ * 
+ * JAVA_OPTS="$JAVA_OPTS "-Dlogback.ContextSelector=JNDI""
+ * 
+ * @author Ceki G&uuml;lc&uuml;
+ * @author S&eacute;bastien Pennec
+ */
+public class ContextJNDISelector implements ContextSelector {
+
+  private final Map<String, LoggerContext> contextMap;
+  private final LoggerContext defaultContext;
+
+  public ContextJNDISelector(LoggerContext context) {
+    contextMap = Collections
+        .synchronizedMap(new HashMap<String, LoggerContext>());
+    defaultContext = context;
+  }
+
+  public LoggerContext getLoggerContext() {
+    String contextName = null;
+    Context ctx = null;
+
+    try {
+      // We first try to find the name of our
+      // environment's LoggerContext
+      ctx = JNDIUtil.getInitialContext();
+      contextName = (String) JNDIUtil.lookup(ctx, JNDI_CONTEXT_NAME);
+    } catch (NamingException ne) {
+      // We can't log here
+    }
+
+    if (contextName == null) {
+      // We return the default context
+      return defaultContext;
+    } else {
+      // Let's see if we already know such a context
+      LoggerContext loggerContext = contextMap.get(contextName);
+
+      if (loggerContext == null) {
+        // We have to create a new LoggerContext
+        loggerContext = new LoggerContext();
+        loggerContext.setName(contextName);
+        contextMap.put(contextName, loggerContext);
+
+        // Do we have a dedicated configuration file?
+        String configFilePath = JNDIUtil.lookup(ctx,
+            JNDI_CONFIGURATION_RESOURCE);
+        if (configFilePath != null) {
+          configureLoggerContextByResource(loggerContext, configFilePath);
+        } else {
+          ContextInitializer.autoConfig(loggerContext);
+        }
+      }
+      return loggerContext;
+    }
+  }
+
+  public LoggerContext getDefaultLoggerContext() {
+    return defaultContext;
+  }
+
+  public LoggerContext detachLoggerContext(String loggerContextName) {
+    return contextMap.remove(loggerContextName);
+  }
+
+  private void configureLoggerContextByResource(LoggerContext context,
+      String configFilePath) {
+    URL url = Loader.getResourceByTCL(configFilePath);
+    if (url != null) {
+      try {
+        JoranConfigurator configurator = new JoranConfigurator();
+        context.shutdownAndReset();
+        configurator.setContext(context);
+        configurator.doConfigure(url);
+      } catch (JoranException e) {
+        StatusPrinter.print(context);
+      }
+    } else {
+      Logger logger = defaultContext.getLogger(LoggerContext.ROOT_NAME);
+      logger.warn("The provided URL for context" + context.getName()
+          + " does not lead to a valid file");
+    }
+  }
+
+}

Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/selector/ContextSelector.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/selector/ContextSelector.java	Thu Jan 25 19:25:31 2007
@@ -0,0 +1,22 @@
+package ch.qos.logback.classic.selector;
+
+import ch.qos.logback.classic.LoggerContext;
+
+/**
+ * An interface that provides access to different contexts.
+ * 
+ * It is used by the LoggerFactory to access the context
+ * it will use to retrieve loggers.
+ *
+ * @author Ceki G&uuml;lc&uuml;
+ * @author S&eacute;bastien Pennec
+ */
+public interface ContextSelector {
+
+  public LoggerContext getLoggerContext();
+  
+  public LoggerContext getDefaultLoggerContext();
+  
+  public LoggerContext detachLoggerContext(String loggerContextName);
+  
+}

Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/selector/DefaultContextSelector.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/selector/DefaultContextSelector.java	Thu Jan 25 19:25:31 2007
@@ -0,0 +1,24 @@
+package ch.qos.logback.classic.selector;
+
+import ch.qos.logback.classic.LoggerContext;
+
+public class DefaultContextSelector implements ContextSelector {
+
+  private LoggerContext context;
+  
+  public DefaultContextSelector(LoggerContext context) {
+    this.context = context;
+  }
+  
+  public LoggerContext getLoggerContext() {
+    return getDefaultLoggerContext();
+  }
+
+  public LoggerContext getDefaultLoggerContext() {
+    return context;
+  }
+
+  public LoggerContext detachLoggerContext(String loggerContextName) {
+    return context;
+  }
+}

Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/selector/servlet/ContextDetachingSCL.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/selector/servlet/ContextDetachingSCL.java	Thu Jan 25 19:25:31 2007
@@ -0,0 +1,47 @@
+package ch.qos.logback.classic.selector.servlet;
+
+import static ch.qos.logback.classic.ClassicGlobal.JNDI_CONTEXT_NAME;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.selector.ContextSelector;
+import ch.qos.logback.classic.util.JNDIUtil;
+
+public class ContextDetachingSCL implements ServletContextListener {
+
+  public void contextDestroyed(ServletContextEvent arg0) {
+    String loggerContextName = null;
+    
+    try {
+      Context ctx = JNDIUtil.getInitialContext();
+      loggerContextName = (String) JNDIUtil.lookup(ctx, JNDI_CONTEXT_NAME);
+    } catch (NamingException ne) {
+    }
+    
+    if (loggerContextName != null) {
+      System.out.println("About to detach context named " + loggerContextName);
+      
+      ContextSelector selector = LoggerFactory.getContextSelector();
+      LoggerContext context = selector.detachLoggerContext(loggerContextName);
+      if (context != null) {
+        Logger logger = context.getLogger(LoggerContext.ROOT_NAME);
+        logger.warn("Shutting down context " + loggerContextName);
+        context.shutdownAndReset();
+      } else {
+        System.out.println("No context named " + loggerContextName + " was found.");
+      }
+    }
+  }
+
+  public void contextInitialized(ServletContextEvent arg0) {
+    // do nothing
+  }
+
+}

Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/util/JNDIUtil.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/util/JNDIUtil.java	Thu Jan 25 19:25:31 2007
@@ -0,0 +1,30 @@
+package ch.qos.logback.classic.util;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+/**
+ * A simple utility class to create and use a JNDI Context.
+ *
+ * @author Ceki G&uuml;lc&uuml;
+ * @author S&eacute;bastien Pennec
+ */
+
+public class JNDIUtil {
+  
+  public static Context getInitialContext() throws NamingException {
+    return new InitialContext();
+  }
+
+  public static String lookup(Context ctx, String name) {
+    if (ctx == null) {
+      return null;
+    }
+    try {
+      return (String) ctx.lookup(name);
+    } catch (NamingException e) {
+      return null;
+    }
+  }
+}
\ No newline at end of file

Modified: logback/trunk/logback-classic/src/main/java/org/slf4j/LoggerFactory.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/org/slf4j/LoggerFactory.java	(original)
+++ logback/trunk/logback-classic/src/main/java/org/slf4j/LoggerFactory.java	Thu Jan 25 19:25:31 2007
@@ -34,8 +34,13 @@
 
 import org.slf4j.impl.Util;
 
+import ch.qos.logback.classic.ClassicGlobal;
 import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.selector.ContextJNDISelector;
+import ch.qos.logback.classic.selector.ContextSelector;
+import ch.qos.logback.classic.selector.DefaultContextSelector;
 import ch.qos.logback.classic.util.ContextInitializer;
+import ch.qos.logback.core.util.OptionHelper;
 
 /**
  * The <code>LoggerFactory</code> is a utility class producing Loggers for
@@ -55,7 +60,9 @@
  */
 public final class LoggerFactory {
 
-  static LoggerContext loggerContext;
+  static LoggerContext defaultLoggerContext;
+  
+  private static ContextSelector contextSelector;
 
   // private constructor prevents instantiation
   private LoggerFactory() {
@@ -63,9 +70,19 @@
 
   static {
     try {
-      loggerContext = new LoggerContext();
-      loggerContext.setName("default");
-      ContextInitializer.autoConfig(loggerContext);
+      //let's configure a default context
+      defaultLoggerContext = new LoggerContext();
+      defaultLoggerContext.setName("default");
+      ContextInitializer.autoConfig(defaultLoggerContext);
+      
+      //See if a special context selector is needed
+      String contextSelectorStr = OptionHelper.getSystemProperty(ClassicGlobal.LOGBACK_CONTEXT_SELECTOR, null);
+      if (contextSelectorStr == null) {
+        contextSelector = new DefaultContextSelector(defaultLoggerContext);
+      } else if (contextSelectorStr.equals("JNDI")) {
+        //if jndi is specified, let's use the appropriate class
+        contextSelector = new ContextJNDISelector(defaultLoggerContext);
+      }
     } catch (Exception e) {
       // we should never get here
       Util.reportFailure("Failed to instantiate logger [" + LoggerContext.class
@@ -82,7 +99,7 @@
    * @return logger
    */
   public static Logger getLogger(String name) {
-    return loggerContext.getLogger(name);
+    return contextSelector.getLoggerContext().getLogger(name);
   }
 
   /**
@@ -94,7 +111,7 @@
    * @return logger
    */
   public static Logger getLogger(Class clazz) {
-    return loggerContext.getLogger(clazz.getName());
+    return contextSelector.getLoggerContext().getLogger(clazz.getName());
   }
 
   /**
@@ -106,6 +123,15 @@
    * @return the ILoggerFactory instance in use
    */
   public static ILoggerFactory getILoggerFactory() {
-    return loggerContext;
+    return contextSelector.getLoggerContext();
+  }
+  
+  /**
+   * Return the {@link ContextSelector} instance in use.
+   * 
+   * @return the ContextSelector instance in use
+   */
+  public static ContextSelector getContextSelector() {
+    return contextSelector;
   }
 }

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/Loader.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/Loader.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/Loader.java	Thu Jan 25 19:25:31 2007
@@ -64,9 +64,12 @@
     } catch (Throwable t) {
       return null;
     }
-
   }
 
+  public static URL getResourceByTCL(String resource) {
+    return getResource(resource, getTCL());
+  }
+  
   /**
    * Get the Thread Context Loader which is a JDK 1.2 feature. If we are running
    * under JDK 1.1 or anything else goes wrong the method returns



More information about the logback-dev mailing list