[logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.27-20-g3c12be5

added by portage for gitosis-gentoo git-noreply at pixie.qos.ch
Tue Jan 18 18:09:47 CET 2011


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Logback: the generic, reliable, fast and flexible logging framework.".

The branch, master has been updated
       via  3c12be5cf378d4ab92d182e1a539132cfa13d6cb (commit)
      from  7fbeda0f115752a2042515c83f4fd77a7077527f (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=3c12be5cf378d4ab92d182e1a539132cfa13d6cb
http://github.com/ceki/logback/commit/3c12be5cf378d4ab92d182e1a539132cfa13d6cb

commit 3c12be5cf378d4ab92d182e1a539132cfa13d6cb
Author: Ceki Gulcu <ceki at qos.ch>
Date:   Tue Jan 18 18:06:47 2011 +0100

    adding support for watching multiple files in ReconfigureOnChangeFilter

diff --git a/logback-classic/src/main/groovy/ch/qos/logback/classic/gaffer/GafferConfigurator.groovy b/logback-classic/src/main/groovy/ch/qos/logback/classic/gaffer/GafferConfigurator.groovy
index 3d7811c..7736256 100644
--- a/logback-classic/src/main/groovy/ch/qos/logback/classic/gaffer/GafferConfigurator.groovy
+++ b/logback-classic/src/main/groovy/ch/qos/logback/classic/gaffer/GafferConfigurator.groovy
@@ -15,7 +15,8 @@ package ch.qos.logback.classic.gaffer
 
 import ch.qos.logback.classic.LoggerContext
 import ch.qos.logback.core.util.ContextUtil
-import ch.qos.logback.core.CoreConstants
+
+import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil
 
 class GafferConfigurator {
 
@@ -28,7 +29,7 @@ class GafferConfigurator {
   }
 
   protected void informContextOfURLUsedForConfiguration(URL url) {
-    context.putObject(CoreConstants.URL_OF_LAST_CONFIGURATION_VIA_JORAN, url);
+    ConfigurationWatchListUtil.updateWatchList(context, url);
   }
 
   void run(URL url) {
diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.java b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.java
index e72d4b3..5af7435 100644
--- a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.java
+++ b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.java
@@ -15,19 +15,18 @@ package ch.qos.logback.classic.turbo;
 
 import java.io.File;
 import java.net.URL;
-import java.net.URLDecoder;
+import java.util.List;
 
 import ch.qos.logback.classic.gaffer.GafferUtil;
 import ch.qos.logback.classic.util.EnvUtil;
-import ch.qos.logback.core.status.ErrorStatus;
-import ch.qos.logback.core.status.StatusManager;
+import ch.qos.logback.core.joran.spi.ConfigurationWatchList;
+import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil;
 import org.slf4j.Marker;
 
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.classic.joran.JoranConfigurator;
-import ch.qos.logback.core.CoreConstants;
 import ch.qos.logback.core.joran.spi.JoranException;
 import ch.qos.logback.core.spi.FilterReply;
 import ch.qos.logback.core.status.InfoStatus;
@@ -49,42 +48,26 @@ public class ReconfigureOnChangeFilter extends TurboFilter {
   public final static long DEFAULT_REFRESH_PERIOD = 60 * 1000;
 
   long refreshPeriod = DEFAULT_REFRESH_PERIOD;
-  File fileToScan;
-  protected long nextCheck;
-  volatile long lastModified;
+  URL mainConfigurationURL;
+  protected volatile long nextCheck;
 
-  Object lock = new Object();
+  ConfigurationWatchList cwl;
 
   @Override
   public void start() {
-    URL url = (URL) context
-            .getObject(CoreConstants.URL_OF_LAST_CONFIGURATION_VIA_JORAN);
-    if (url != null) {
-      fileToScan = convertToFile(url);
-      if (fileToScan != null) {
-        synchronized (lock) {
-          long inSeconds = refreshPeriod / 1000;
-          addInfo("Will scan for changes in file [" + fileToScan + "] every "
-                  + inSeconds + " seconds. ");
-          lastModified = fileToScan.lastModified();
-          updateNextCheck(System.currentTimeMillis());
-        }
-        super.start();
+    cwl = ConfigurationWatchListUtil.getConfigurationWatchList(context);
+    if (cwl != null) {
+      mainConfigurationURL = cwl.getMainURL();
+      List<File> watchList = cwl.getCopyOfFileWatchList();
+      long inSeconds = refreshPeriod / 1000;
+      addInfo("Will scan for changes in [" + watchList + "] every "
+              + inSeconds + " seconds. ");
+      synchronized (cwl) {
+        updateNextCheck(System.currentTimeMillis());
       }
-    } else {
-      addError("Could not find URL of file to scan.");
-    }
-  }
-
-  @SuppressWarnings("deprecation")
-  File convertToFile(URL url) {
-    String protocol = url.getProtocol();
-    if ("file".equals(protocol)) {
-      File file = new File(URLDecoder.decode(url.getFile()));
-      return file;
-    } else {
-      addError("URL [" + url + "] is not of type file");
-      return null;
+      super.start();
+    }  else {
+      addWarn("Empty ConfigurationWatchList in context");
     }
   }
 
@@ -108,12 +91,14 @@ public class ReconfigureOnChangeFilter extends TurboFilter {
       return FilterReply.NEUTRAL;
     }
 
-    //System.out.println(".");
-    synchronized (lock) {
-      boolean changed = changeDetected();
-      if (changed) {
+    synchronized (cwl) {
+      if (changeDetected()) {
+        // Even though reconfiguration involves resetting the loggerContext,
+        // which clears the list of turbo filters including this instance, it is
+        // still possible for this instance to be subsequently invoked by another
+        // thread if it was already executing when the context was reset.
+        disableSubsequentReconfiguration();
         detachReconfigurationToNewThread();
-
       }
     }
 
@@ -123,14 +108,8 @@ public class ReconfigureOnChangeFilter extends TurboFilter {
   // by detaching reconfiguration to a new thread, we release the various
   // locks held by the current thread, in particular, the AppenderAttachable
   // reader lock.
-
   private void detachReconfigurationToNewThread() {
-    // Even though this method resets the loggerContext, which clears the
-    // list of turbo filters including this instance, it is still possible
-    // for this instance to be subsequently invoked by another thread if it
-    // was already executing when the context was reset.
-    disableSubsequentRecofiguration();
-    addInfo("Detected change in [" + fileToScan + "]");
+    addInfo("Detected change in [" + cwl.getCopyOfFileWatchList() + "]");
     addInfo("Resetting and reconfiguring context [" + context.getName() + "]");
     new ReconfiguringThread().start();
   }
@@ -139,23 +118,17 @@ public class ReconfigureOnChangeFilter extends TurboFilter {
     nextCheck = now + refreshPeriod;
   }
 
-  // This method is synchronized to prevent near-simultaneous re-configurations
-
   protected boolean changeDetected() {
     long now = System.currentTimeMillis();
     if (now >= nextCheck) {
       updateNextCheck(now);
-      return (lastModified != fileToScan.lastModified() && lastModified != SENTINEL);
+      return cwl.changeDetected();
     }
     return false;
   }
 
-  String currentThreadName() {
-    return Thread.currentThread().getName();
-  }
-
-  void disableSubsequentRecofiguration() {
-    lastModified = SENTINEL;
+  void disableSubsequentReconfiguration() {
+    nextCheck = Long.MAX_VALUE;
   }
 
   public long getRefreshPeriod() {
@@ -169,22 +142,21 @@ public class ReconfigureOnChangeFilter extends TurboFilter {
   class ReconfiguringThread extends Thread {
     public void run() {
       LoggerContext lc = (LoggerContext) context;
-
-      if (fileToScan.toString().endsWith("groovy")) {
+      if (mainConfigurationURL.toString().endsWith("groovy")) {
         if (EnvUtil.isGroovyAvailable()) {
           lc.reset();
           // avoid directly referring to GafferConfigurator so as to avoid
           // loading  groovy.lang.GroovyObject . See also http://jira.qos.ch/browse/LBCLASSIC-214
-          GafferUtil.runGafferConfiguratorOn(lc, this, fileToScan);
+          GafferUtil.runGafferConfiguratorOn(lc, this, mainConfigurationURL);
         } else {
           addError("Groovy classes are not available on the class path. ABORTING INITIALIZATION.");
         }
-      } else if (fileToScan.toString().endsWith("xml")) {
+      } else if (mainConfigurationURL.toString().endsWith("xml")) {
         JoranConfigurator jc = new JoranConfigurator();
         jc.setContext(context);
         lc.reset();
         try {
-          jc.doConfigure(fileToScan);
+          jc.doConfigure(mainConfigurationURL);
           lc.getStatusManager().add(
                   new InfoStatus("done resetting the logging context", this));
         } catch (JoranException e) {
diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java
index 4fbbf58..36e86af 100644
--- a/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java
+++ b/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java
@@ -295,7 +295,7 @@ public class JoranConfiguratorTest {
       logger.debug("after " + i);
     }
 
-    // StatusPrinter.print(loggerContext);
+    StatusPrinter.print(loggerContext);
     StatusChecker checker = new StatusChecker(loggerContext);
     assertTrue(checker.isErrorFree());
     assertTrue(checker.containsMatch("Resetting and reconfiguring context"));
diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java
index d1e472c..ee96b45 100644
--- a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java
+++ b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java
@@ -19,9 +19,9 @@ import static org.junit.Assert.assertTrue;
 import java.io.File;
 import java.io.IOException;
 import java.net.MalformedURLException;
-import java.net.URL;
 
 import ch.qos.logback.classic.gaffer.GafferConfigurator;
+import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -108,15 +108,6 @@ public class ReconfigureOnChangeTest {
     return rArray;
   }
 
-  @Test
-  // See http://jira.qos.ch/browse/LBCORE-119
-  public void fileToURLAndBack() throws MalformedURLException {
-    File file = new File("a b.xml");
-    URL url = file.toURI().toURL();
-    ReconfigureOnChangeFilter rocf = new ReconfigureOnChangeFilter();
-    File back = rocf.convertToFile(url);
-    assertEquals(file.getName(), back.getName());
-  }
 
   // Tests whether ConfigurationAction is installing ReconfigureOnChangeFilter
   @Test
@@ -187,8 +178,7 @@ public class ReconfigureOnChangeTest {
     ReconfigureOnChangeFilter rocf = new ReconfigureOnChangeFilter();
     rocf.setContext(loggerContext);
     File file = new File(SCAN1_FILE_AS_STR);
-    loggerContext.putObject(CoreConstants.URL_OF_LAST_CONFIGURATION_VIA_JORAN,
-        file.toURI().toURL());
+    ConfigurationWatchListUtil.updateWatchList(loggerContext, file.toURI().toURL());
     rocf.start();
     return rocf;
   }
diff --git a/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java b/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java
index 181da69..0989645 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java
@@ -110,9 +110,7 @@ public class CoreConstants {
 
   static public final String SEE_FNP_NOT_SET = "See also http://logback.qos.ch/codes.html#tbr_fnp_not_set";
 
-  // The url used for the last configuration via Joran. If a file is used for the
-  // configuration, then file.getURL() is registered
-  public static String URL_OF_LAST_CONFIGURATION_VIA_JORAN = "URL_OF_LAST_CONFIGURATION_VIA_JORAN";
+  public static String CONFIGURATION_WATCH_LIST = "CONFIGURATION_WATCH_LIST";
 
 
   /**
diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/GenericConfigurator.java b/logback-core/src/main/java/ch/qos/logback/core/joran/GenericConfigurator.java
index be9f466..8f16313 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/joran/GenericConfigurator.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/joran/GenericConfigurator.java
@@ -21,9 +21,9 @@ import java.net.URL;
 import java.net.URLConnection;
 import java.util.List;
 
+import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil;
 import org.xml.sax.InputSource;
 
-import ch.qos.logback.core.CoreConstants;
 import ch.qos.logback.core.joran.event.SaxEvent;
 import ch.qos.logback.core.joran.event.SaxEventRecorder;
 import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry;
@@ -86,9 +86,9 @@ public abstract class GenericConfigurator extends ContextAwareBase {
   }
 
   protected void informContextOfURLUsedForConfiguration(URL url) {
-    getContext().putObject(CoreConstants.URL_OF_LAST_CONFIGURATION_VIA_JORAN, url);
+    ConfigurationWatchListUtil.updateWatchList(context, url);
   }
-  
+
   final public void doConfigure(InputStream inputStream) throws JoranException {
     doConfigure(new InputSource(inputStream));
   }
diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/ConfigurationWatchList.java b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/ConfigurationWatchList.java
new file mode 100644
index 0000000..953f890
--- /dev/null
+++ b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/ConfigurationWatchList.java
@@ -0,0 +1,76 @@
+package ch.qos.logback.core.joran.spi;
+
+
+import ch.qos.logback.core.spi.ContextAwareBase;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Ceki G&uuml;c&uuml;
+ */
+public class ConfigurationWatchList extends ContextAwareBase {
+
+  URL mainURL;
+  List<File> fileWatchList = new ArrayList<File>();
+  List<Long> lastModifiedList = new ArrayList<Long>();
+
+  public void clear() {
+    this.mainURL = null;
+    lastModifiedList.clear();
+    fileWatchList.clear();
+  }
+
+  public void setMainURL(URL mainURL) {
+    this.mainURL = mainURL;
+    addAsFileToWatch(mainURL);
+  }
+
+  private void addAsFileToWatch(URL url) {
+    File file = convertToFile(url);
+    if (file != null) {
+      fileWatchList.add(file);
+      lastModifiedList.add(file.lastModified());
+    }
+  }
+
+  void addToWatchList(URL url) {
+    addAsFileToWatch(url);
+  }
+
+  public URL getMainURL() {
+    return mainURL;
+  }
+
+  public List<File>  getCopyOfFileWatchList() {
+    return new ArrayList<File>(fileWatchList);
+  }
+  public boolean changeDetected() {
+    int len = fileWatchList.size();
+    for (int i = 0; i < len; i++) {
+      long lastModified = lastModifiedList.get(i);
+      File file = fileWatchList.get(i);
+      if (lastModified != file.lastModified()) {
+        return true;
+      }
+    }
+    return false;
+    //return (lastModified != fileToScan.lastModified() && lastModified != SENTINEL);
+  }
+
+  @SuppressWarnings("deprecation")
+  File convertToFile(URL url) {
+    String protocol = url.getProtocol();
+    if ("file".equals(protocol)) {
+      File file = new File(URLDecoder.decode(url.getFile()));
+      return file;
+    } else {
+      addError("URL [" + url + "] is not of type file");
+      return null;
+    }
+  }
+
+}
diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/util/ConfigurationWatchListUtil.java b/logback-core/src/main/java/ch/qos/logback/core/joran/util/ConfigurationWatchListUtil.java
new file mode 100644
index 0000000..278e5f4
--- /dev/null
+++ b/logback-core/src/main/java/ch/qos/logback/core/joran/util/ConfigurationWatchListUtil.java
@@ -0,0 +1,30 @@
+package ch.qos.logback.core.joran.util;
+
+import ch.qos.logback.core.Context;
+import ch.qos.logback.core.CoreConstants;
+import ch.qos.logback.core.joran.spi.ConfigurationWatchList;
+
+import java.net.URL;
+
+/**
+ * @author Ceki G&uuml;c&uuml;
+ */
+public class ConfigurationWatchListUtil {
+
+
+  public static void updateWatchList(Context context, URL url) {
+    ConfigurationWatchList cwl = getConfigurationWatchList(context);
+    if(cwl == null) {
+      cwl = new ConfigurationWatchList();
+      cwl.setContext(context);
+      context.putObject(CoreConstants.CONFIGURATION_WATCH_LIST, cwl);
+    } else {
+      cwl.clear();
+    }
+    cwl.setMainURL(url);
+  }
+
+   public static ConfigurationWatchList getConfigurationWatchList(Context context) {
+     return  (ConfigurationWatchList) context.getObject(CoreConstants.CONFIGURATION_WATCH_LIST);
+  }
+}
diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/ConfigurationWatchListTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/ConfigurationWatchListTest.java
new file mode 100644
index 0000000..40031fc
--- /dev/null
+++ b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/ConfigurationWatchListTest.java
@@ -0,0 +1,25 @@
+package ch.qos.logback.core.joran.spi;
+
+import org.junit.Test;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Ceki G&uuml;c&uuml;
+ */
+public class ConfigurationWatchListTest {
+
+  @Test
+  // See http://jira.qos.ch/browse/LBCORE-119
+  public void fileToURLAndBack() throws MalformedURLException {
+    File file = new File("a b.xml");
+    URL url = file.toURI().toURL();
+    ConfigurationWatchList cwl = new ConfigurationWatchList();
+    File back = cwl.convertToFile(url);
+    assertEquals(file.getName(), back.getName());
+  }
+}
diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PackageTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PackageTest.java
index 92bd15a..66286cd 100644
--- a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PackageTest.java
+++ b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PackageTest.java
@@ -19,7 +19,7 @@ import org.junit.runners.Suite.SuiteClasses;
 
 @RunWith(Suite.class)
 @SuiteClasses( { PatternTest.class, SimpleRuleStoreTest.class,
-    NoAutoStartUtilTest.class,
+    NoAutoStartUtilTest.class,  ConfigurationWatchListTest.class,
     DefaultNestedComponentRegistryTest.class, CaseCombinatorTest.class })
 public class PackageTest {
 }
diff --git a/logback-site/src/site/pages/codes.html b/logback-site/src/site/pages/codes.html
index 72d04d1..e80c770 100644
--- a/logback-site/src/site/pages/codes.html
+++ b/logback-site/src/site/pages/codes.html
@@ -370,8 +370,9 @@
   href="http://technet.microsoft.com/en-us/sysinternals/bb896653">Process
   Explorer</a> can help you locate the processes which reference a
   given file (Find -&gt; Find Handle or DLL). On Linux, you can use
-  the <a href="http://www.manpagez.com/man/8/lsof/">lsof</a> command
-  to find which process has a file open.</p>
+  the <code><a href="http://www.manpagez.com/man/8/lsof/">lsof </a>
+  <em>pathToFile</em></code> command to find which process has the
+  file given by <em>pathToFile</em> open. </p>
 
   <p>In practice, it can be hard to ensure that there are no file
   handle references to log files. It can be easier to avoid file
diff --git a/test.txt b/test.txt
deleted file mode 100644
index e69de29..0000000

-----------------------------------------------------------------------

Summary of changes:
 .../classic/gaffer/GafferConfigurator.groovy       |    5 +-
 .../classic/turbo/ReconfigureOnChangeFilter.java   |   94 +++++++-------------
 .../classic/joran/JoranConfiguratorTest.java       |    2 +-
 .../classic/turbo/ReconfigureOnChangeTest.java     |   14 +---
 .../java/ch/qos/logback/core/CoreConstants.java    |    4 +-
 .../logback/core/joran/GenericConfigurator.java    |    6 +-
 .../core/joran/spi/ConfigurationWatchList.java     |   76 ++++++++++++++++
 .../joran/util/ConfigurationWatchListUtil.java     |   30 ++++++
 .../core/joran/spi/ConfigurationWatchListTest.java |   25 +++++
 .../ch/qos/logback/core/joran/spi/PackageTest.java |    2 +-
 logback-site/src/site/pages/codes.html             |    5 +-
 11 files changed, 178 insertions(+), 85 deletions(-)
 create mode 100644 logback-core/src/main/java/ch/qos/logback/core/joran/spi/ConfigurationWatchList.java
 create mode 100644 logback-core/src/main/java/ch/qos/logback/core/joran/util/ConfigurationWatchListUtil.java
 create mode 100644 logback-core/src/test/java/ch/qos/logback/core/joran/spi/ConfigurationWatchListTest.java
 delete mode 100644 test.txt


hooks/post-receive
-- 
Logback: the generic, reliable, fast and flexible logging framework.


More information about the logback-dev mailing list