[logback-dev] svn commit: r2111 - in logback/trunk: logback-classic/src/main/java/ch/qos/logback/classic/selector logback-classic/src/main/java/ch/qos/logback/classic/util logback-classic/src/main/java/org/slf4j/impl logback-classic/src/test/java/org/slf4j/impl logback-core/src/main/java/ch/qos/logback/core/util logback-examples/src/main/java/chapter3 logback-examples/src/main/java/chapter4/mail logback-site/src/site/pages logback-site/src/site/pages/manual

noreply.ceki at qos.ch noreply.ceki at qos.ch
Mon Dec 29 17:30:39 CET 2008


Author: ceki
Date: Mon Dec 29 17:30:39 2008
New Revision: 2111

Modified:
   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/util/ContextInitializer.java
   logback/trunk/logback-classic/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
   logback/trunk/logback-classic/src/test/java/org/slf4j/impl/RecursiveInitializationTest.java
   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/StatusPrinter.java
   logback/trunk/logback-examples/src/main/java/chapter3/MyApp3.java
   logback/trunk/logback-examples/src/main/java/chapter4/mail/EMail.java
   logback/trunk/logback-site/src/site/pages/manual/appenders.html
   logback/trunk/logback-site/src/site/pages/manual/joran.html
   logback/trunk/logback-site/src/site/pages/news.html

Log:
- Logback-classic default configration process will now
  automatically print status data on the console in case of warnings
  as well as errors. Previously, status data was printed only in
  case of errors.

- In case multiple configuration files are found on the class
  path, ContextInitializer will now emit a warning. This fixes 
  LBCLASSIC-85.

Modified: 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/ContextJNDISelector.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/selector/ContextJNDISelector.java	Mon Dec 29 17:30:39 2008
@@ -105,7 +105,7 @@
           } catch (JoranException je) {
           }
         }
-        StatusPrinter.printIfErrorsOccured(loggerContext);
+        StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext);
       }
       return loggerContext;
     }
@@ -157,7 +157,7 @@
       configurator.doConfigure(url);
     } catch (JoranException e) {
     }
-    StatusPrinter.printIfErrorsOccured(context);
+    StatusPrinter.printInCaseOfErrorsOrWarnings(context);
   }
 
   public List<String> getContextNames() {

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/util/ContextInitializer.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/util/ContextInitializer.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/util/ContextInitializer.java	Mon Dec 29 17:30:39 2008
@@ -1,15 +1,19 @@
 package ch.qos.logback.classic.util;
 
 import java.io.File;
+import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.List;
 
 import ch.qos.logback.classic.BasicConfigurator;
 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.status.ErrorStatus;
 import ch.qos.logback.core.status.InfoStatus;
 import ch.qos.logback.core.status.StatusManager;
+import ch.qos.logback.core.status.WarnStatus;
 import ch.qos.logback.core.util.Loader;
 import ch.qos.logback.core.util.OptionHelper;
 
@@ -43,8 +47,9 @@
     configurator.doConfigure(url);
   }
 
-  private URL findConfigFileURLFromSystemProperties(boolean updateStatus) {
+  private URL findConfigFileURLFromSystemProperties(ClassLoader classLoader, boolean updateStatus) {
     String logbackConfigFile = OptionHelper.getSystemProperty(CONFIG_FILE_PROPERTY);
+    
     if (logbackConfigFile != null) {
       URL result = null;
       try {
@@ -53,7 +58,7 @@
       } catch (MalformedURLException e) {
         // so, resource is not a URL:
         // attempt to get the resource from the class path
-        result = Loader.getResourceBySelfClassLoader(logbackConfigFile);
+        result = Loader.getResource(logbackConfigFile, classLoader);
         if (result != null) {
           return result;
         }
@@ -67,7 +72,7 @@
         }
       } finally {
         if (updateStatus) {
-          statusOnResourceSearch(logbackConfigFile, result);
+          statusOnResourceSearch(logbackConfigFile, classLoader, result);
         }
       }
     }
@@ -75,22 +80,23 @@
   }
 
   public URL findURLOfDefaultConfigurationFile(boolean updateStatus) {
-    URL url = findConfigFileURLFromSystemProperties(updateStatus);
+    ClassLoader myClassLoader = this.getClass().getClassLoader();
+    URL url = findConfigFileURLFromSystemProperties(myClassLoader, updateStatus);
     if (url != null) {
       return url;
     }
 
-    url = Loader.getResource(TEST_AUTOCONFIG_FILE, this.getClass().getClassLoader());
+    url = Loader.getResource(TEST_AUTOCONFIG_FILE, myClassLoader);
     if (updateStatus) {
-      statusOnResourceSearch(TEST_AUTOCONFIG_FILE, url);
+      statusOnResourceSearch(TEST_AUTOCONFIG_FILE, myClassLoader, url);
     }
     if (url != null) {
       return url;
     }
 
-    url = Loader.getResource(AUTOCONFIG_FILE, this.getClass().getClassLoader());
+    url = Loader.getResource(AUTOCONFIG_FILE, myClassLoader);
     if (updateStatus) {
-      statusOnResourceSearch(AUTOCONFIG_FILE, url);
+      statusOnResourceSearch(AUTOCONFIG_FILE, myClassLoader, url);
     }
     return url;
   }
@@ -105,7 +111,26 @@
     }
   }
 
-  private void statusOnResourceSearch(String resourceName, URL url) {
+  private void multiplicityWarning(String resourceName, ClassLoader classLoader ) {
+    List<URL> urlList = null;
+    StatusManager sm = loggerContext.getStatusManager();
+    try {
+      urlList = Loader.getResourceOccurenceCount(resourceName, classLoader);
+    } catch (IOException e) {
+      sm.add(new ErrorStatus("Failed to get url list for resource [" + resourceName + "]",
+          loggerContext, e));
+    }
+    if(urlList != null && urlList.size() > 1) {
+      sm.add(new WarnStatus("Resource [" + resourceName + "] occurs multiple times on the classpath.",
+          loggerContext));
+      for(URL url: urlList) {
+      sm.add(new WarnStatus("Resource ["+resourceName+"] occurs at ["+url.toString()+"]",
+          loggerContext));
+      }
+    }
+  }
+  
+  private void statusOnResourceSearch(String resourceName, ClassLoader classLoader, URL url) {
     StatusManager sm = loggerContext.getStatusManager();
     if (url == null) {
       sm.add(new InfoStatus("Could NOT find resource [" + resourceName + "]",
@@ -113,6 +138,7 @@
     } else {
       sm.add(new InfoStatus("Found resource [" + resourceName + "] at ["+url.toString()+"]",
           loggerContext));
+      multiplicityWarning(resourceName, classLoader);
     }
   }
 

Modified: logback/trunk/logback-classic/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/org/slf4j/impl/StaticLoggerBinder.java	(original)
+++ logback/trunk/logback-classic/src/main/java/org/slf4j/impl/StaticLoggerBinder.java	Mon Dec 29 17:30:39 2008
@@ -87,7 +87,7 @@
         Util.reportFailure("Failed to auto configure default logger context",
             je);
       }
-      StatusPrinter.printIfErrorsOccured(defaultLoggerContext);
+      StatusPrinter.printInCaseOfErrorsOrWarnings(defaultLoggerContext);
 
       // See if a special context selector is needed
       String contextSelectorStr = OptionHelper

Modified: logback/trunk/logback-classic/src/test/java/org/slf4j/impl/RecursiveInitializationTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/org/slf4j/impl/RecursiveInitializationTest.java	(original)
+++ logback/trunk/logback-classic/src/test/java/org/slf4j/impl/RecursiveInitializationTest.java	Mon Dec 29 17:30:39 2008
@@ -43,7 +43,7 @@
 
     LoggerContext loggerContext = (LoggerContext) LoggerFactory
         .getILoggerFactory();
-    StatusPrinter.printIfErrorsOccured(loggerContext);
+    StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext);
     StatusManager sm = loggerContext.getStatusManager();
     assertEquals("Was expecting no errors", Status.WARN, sm.getLevel());
   }

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	Mon Dec 29 17:30:39 2008
@@ -9,7 +9,11 @@
  */
 package ch.qos.logback.core.util;
 
+import java.io.IOException;
 import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
 
 import ch.qos.logback.core.Context;
 
@@ -35,6 +39,27 @@
   }
 
   /**
+   * Compute the number of occurrences a resource can be found by a class
+   * loader.
+   * 
+   * @param resource
+   * @param classLoader
+   * @return
+   * @throws IOException
+   */
+  public static List<URL> getResourceOccurenceCount(String resource,
+      ClassLoader classLoader) throws IOException {
+    List<URL> urlList = new ArrayList<URL>();
+    Enumeration<URL> urlEnum = classLoader.getResources(resource);
+    while (urlEnum.hasMoreElements()) {
+      URL url = urlEnum.nextElement();
+      urlList.add(url);
+    }
+
+    return urlList;
+  }
+
+  /**
    * Search for a resource using the classloader passed as parameter.
    * 
    * @param resource
@@ -61,9 +86,9 @@
     return getResource(resource, Loader.class.getClassLoader());
   }
 
-//  private static URL getResourceByTCL(String resource) {
-//    return getResource(resource, getTCL());
-//  }
+  // private 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

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/StatusPrinter.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/StatusPrinter.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/util/StatusPrinter.java	Mon Dec 29 17:30:39 2008
@@ -33,6 +33,28 @@
   public static void setPrintStream(PrintStream printStream) {
     ps = printStream;
   }
+  
+  /**
+   * Print the contents of the context statuses, but only if they contain
+   * warnings or errors.
+   * 
+   * @param context
+   */
+  public static void printInCaseOfErrorsOrWarnings(Context context) {
+    if (context == null) {
+      throw new IllegalArgumentException("Context argument cannot be null");
+    }
+
+    StatusManager sm = context.getStatusManager();
+    if (sm == null) {
+      ps.println("WARN: Context named \"" + context.getName()
+          + "\" has no status manager");
+    } else {
+      if (sm.getLevel() == ErrorStatus.WARN) {
+        print(sm);
+      }
+    }
+  }
 
   /**
    * Print the contents of the context statuses, but only if they contain

Modified: logback/trunk/logback-examples/src/main/java/chapter3/MyApp3.java
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/MyApp3.java	(original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/MyApp3.java	Mon Dec 29 17:30:39 2008
@@ -38,7 +38,7 @@
     } catch (JoranException je) {
       je.printStackTrace();
     }
-    StatusPrinter.printIfErrorsOccured(lc);
+    StatusPrinter.printInCaseOfErrorsOrWarnings(lc);
 
     logger.info("Entering application.");
 

Modified: logback/trunk/logback-examples/src/main/java/chapter4/mail/EMail.java
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter4/mail/EMail.java	(original)
+++ logback/trunk/logback-examples/src/main/java/chapter4/mail/EMail.java	Mon Dec 29 17:30:39 2008
@@ -38,7 +38,7 @@
     lc.reset();
     configurator.setContext(lc);
     configurator.doConfigure(configFile);
-    StatusPrinter.printIfErrorsOccured(lc);
+    StatusPrinter.printInCaseOfErrorsOrWarnings(lc);
     
     Logger logger = LoggerFactory.getLogger(EMail.class);
 
@@ -52,7 +52,7 @@
 
     logger.error("At last an error.", new Exception("Just testing"));
     
-    StatusPrinter.printIfErrorsOccured(lc);
+    StatusPrinter.printInCaseOfErrorsOrWarnings(lc);
   }
 
   static void usage(String msg) {

Modified: logback/trunk/logback-site/src/site/pages/manual/appenders.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/manual/appenders.html	(original)
+++ logback/trunk/logback-site/src/site/pages/manual/appenders.html	Mon Dec 29 17:30:39 2008
@@ -3112,9 +3112,12 @@
     href="#SiftingAppender">SiftingAppender</a></h3>
 
     <p>As its name implies, a <code>SiftingAppender</code> can be used
-    to separate (or sift) logging according to some runtime attribute.
-    For example, <code>SiftingAppender</code> can separate logging
-    events into distinct log files, one file per user. 
+    to separate (or sift) logging according to a given runtime
+    attribute. For example, <code>SiftingAppender</code> can separate
+    logging events according to user sessions, so that the logs
+    generated by every user go into distinct log files, one log file
+    per user.  For example, <code>SiftingAppender</code> can separate
+    logging events into distinct log files, one file per user.
     </p>
 
 

Modified: logback/trunk/logback-site/src/site/pages/manual/joran.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/manual/joran.html	(original)
+++ logback/trunk/logback-site/src/site/pages/manual/joran.html	Mon Dec 29 17:30:39 2008
@@ -233,14 +233,15 @@
    directory accessible from the class path. Running the <em>MyApp1</em>
    application should give identical results to its previous run.</p>
 
-   <p>If and only if there are errors during the parsing of the
-   configuration file, logback will automatically print status data on
-   the console. In the absence of errors, if you still wish to inspect
-   logback's internal status, then you can instruct logback to print
-   status data by invoking the <code>print()</code> of the
-   <code>StatusPrinter</code> class. The <em>MyApp2</em> application
-   shown below is identical to <em>MyApp1</em> except the addition of
-   two lines of code for printing internal status data.</p>
+   <p>If and only if there are warnings or errors during the parsing
+   of the configuration file, logback will automatically print status
+   data on the console. In the absence of warnings or errors, if you
+   still wish to inspect logback's internal status, then you can
+   instruct logback to print status data by invoking the
+   <code>print()</code> of the <code>StatusPrinter</code> class. The
+   <em>MyApp2</em> application shown below is identical to
+   <em>MyApp1</em> except the addition of two lines of code for
+   printing internal status data.</p>
 
     <em>Example 3.<span class="autoEx"/>: Print logback's internal status information
     <a
@@ -347,12 +348,12 @@
 
    <p>Logback relies on a configuration library called Joran which is
    part of logback-core. Logback's default configuration mechanism
-   invokes JoranConfigurator on the default configuration files it
-   finds on the class path. For whatever reason if you wish to
+   invokes <code>JoranConfigurator</code> on the default configuration
+   file it finds on the class path. For whatever reason if you wish to
    override logback's default configuration mechanism, you can do so
-   by invoking JoranConfigurator directly. The next application,
-   <em>MyApp3</em>, invokes JoranConfigurator on a configuration file
-   passed as parameter.</p>
+   by invoking <code>JoranConfigurator</code> directly. The next
+   application, <em>MyApp3</em>, invokes JoranConfigurator on a
+   configuration file passed as parameter.</p>
    
    <p><em>Example 3.<span class="autoEx"/>: Invoking
    <code>JoranConfigurator</code> directly <a
@@ -385,7 +386,7 @@
     } catch (JoranException je) {
        je.printStackTrace();
     }
-    StatusPrinter.printIfErrorsOccured(lc);</b>
+    StatusPrinter.printInCaseOfErrorsOrWarnings(lc);</b>
 
     logger.info("Entering application.");
 
@@ -395,13 +396,14 @@
   }
 }</pre></div>
 
-  <p>This application fetches the <code>LoggerContext</code> currently
-  in effect, creates a new <code>JoranConfigurator</code>, sets the
-  context on which it will operate, resets the logger context, and
-  then finally asks the configurator to configure the context using
-  configuration file passed as parameter to the application. Internal
-  status data is printed in case errors occur.
-  </p>   
+   <p>This application fetches the <code>LoggerContext</code>
+   currently in effect, creates a new <code>JoranConfigurator</code>,
+   sets the context on which it will operate, resets the logger
+   context, and then finally asks the configurator to configure the
+   context using configuration file passed as parameter to the
+   application. Internal status data is printed in case of warnings or
+   errors.
+   </p>   
 
   <h3>
     <a name="statusListener" href="#statusListener">Listening to

Modified: logback/trunk/logback-site/src/site/pages/news.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/news.html	(original)
+++ logback/trunk/logback-site/src/site/pages/news.html	Mon Dec 29 17:30:39 2008
@@ -47,6 +47,15 @@
     a turbo filter which detects duplicate messages, and beyond a
     certain number of repetitions, drops repeated messages.</p>
 
+    <p>Added a new appender called <a
+    href="manual/appenders.html#SiftingAppender"><code>SiftingAppender</code></a>. As
+    its name intimates, a <code><code>SiftingAppender</code></code>
+    can be used to separate (or sift) logging according to a given
+    runtime attribute. For example, <code>SiftingAppender</code> can
+    separate logging events according to user sessions, so that the
+    logs generated by each user go into distinct log files, one log
+    file per user.
+    </p>
     
     <p><code>BasicStatusManager</code>'s internal buffer is now split
     into two parts, the header part and the tail part. The header part
@@ -73,26 +82,50 @@
     <code>JaninoEvaluator</code>.    
     </p>
 
+    <p>Logback-classic default configuration process will now
+    automatically print status data on the console in case of warnings
+    as well as errors. Previously, status data was printed only in
+    case of errors.</p>
+
     <p><code>ContextInitializer</code> will now print the url of the
-    configration it is using. This should help reduce confusion when
+    configuration it is using. This should help reduce confusion when
     multiple config files are found on the class path.  This change
     resolves <a
     href="http://jira.qos.ch/browse/LBCLASSIC-55">LBCLASSIC-55</a>
     reported by Anton Tagunov and Henric Larsson.
     </p>
 
+    <p>In case multiple configuration files are found on the class
+    path, <code>ContextInitializer</code> will now emit a
+    warning. This fixes <a
+    href="http://jira.qos.ch/browse/LBCLASSIC-85">LBCLASSIC-85</a>
+    filed by Szel Zoltan.
+    </p>
+
     <p><code>HTMLLayout</code> now honors custom conversion words,
     thus fixing <a
     href="http://jira.qos.ch/browse/LBCORE-74">LBCORE-74</a> as
     reported by Natan Cox.</p>
 
+    <p>Fixed <a
+    href="http://jira.qos.ch/browse/LBCORE-69">LBCORE-69</a> as
+    reported by Andrey Rybin. <code>SMTPAppenderBase</code> now has
+    support for charset encodings so that email messages can contain
+    characters beyond US-ASCII.
+    </p>
 
-
-    <p>SMTPAppender im logback-classic now defaults to
+    <p><code>SMTPAppender</code> in logback-classic now defaults to
     <code>OnErrorEvaluator</code> instead of a janino-based
     evaluator. Thus, by default <code>SMTPAppender</code> no longer
     depends on Janino.</p>
 
+    <p>Added UnsynchronizedAppenderBase class based on Ralph Goers'
+    contribution in <a
+    href="http://jira.qos.ch/browse/LBCORE-58">LBCORE-58</a>. Note
+    that <code>AppenderBase</code> remains unchanged. Appenders which
+    need to handle synchronization on their own can do so by deriving
+    from <code>UnsynchronizedAppenderBase</code>.</p>
+
     <h3>5th of December 2008 - Release of version 0.9.13</h3>
 
     <p>A <code>NullPointerException</code> was being thrown when a the


More information about the logback-dev mailing list