[logback-dev] svn commit: r2094 - in logback/trunk: logback-access logback-access/src/main/java/ch/qos/logback/access/jetty logback-access/src/main/java/ch/qos/logback/access/joran logback-access/src/main/java/ch/qos/logback/access/sift logback-access/src/test/input/jetty logback-access/src/test/java/ch/qos/logback/access logback-access/src/test/java/ch/qos/logback/access/filter logback-access/src/test/java/ch/qos/logback/access/jetty logback-access/src/test/java/ch/qos/logback/access/net logback-access/src/test/java/ch/qos/logback/access/pattern logback-access/src/test/java/ch/qos/logback/access/sift logback-access/src/test/java/ch/qos/logback/access/spi logback-classic/src/main/java/ch/qos/logback/classic/sift logback-core/src/main/java/ch/qos/logback/core/sift

noreply.ceki at qos.ch noreply.ceki at qos.ch
Mon Dec 22 19:54:44 CET 2008


Author: ceki
Date: Mon Dec 22 19:54:44 2008
New Revision: 2094

Added:
   logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/
   logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java
   logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AppenderFactory.java
   logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftAction.java
   logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingAppender.java
   logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingJoranConfigurator.java
   logback/trunk/logback-access/src/test/input/jetty/
   logback/trunk/logback-access/src/test/input/jetty/sifting.xml
   logback/trunk/logback-access/src/test/java/ch/qos/logback/access/AllAccessTest.java
      - copied, changed from r1859, /logback/trunk/logback-access/src/test/java/ch/qos/logback/access/AllTest.java
   logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixtureBase.java
   logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/
   logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/JettyFixture.java
   logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/PackageTest.java
   logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/SiftingAppenderTest.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/Discriminator.java
Removed:
   logback/trunk/logback-access/src/test/java/ch/qos/logback/access/AllTest.java
   logback/trunk/logback-access/src/test/java/ch/qos/logback/access/filter/AccessStatsTest.java
Modified:
   logback/trunk/logback-access/pom.xml
   logback/trunk/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogImpl.java
   logback/trunk/logback-access/src/main/java/ch/qos/logback/access/joran/JoranConfigurator.java
   logback/trunk/logback-access/src/test/java/ch/qos/logback/access/filter/PackageTest.java
   logback/trunk/logback-access/src/test/java/ch/qos/logback/access/filter/StatsByDayTest.java
   logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixture.java
   logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/PackageTest.java
   logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/PackageTest.java
   logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/SocketAppenderTest.java
   logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/URLEvaluatorTest.java
   logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java
   logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/PackageTest.java
   logback/trunk/logback-access/src/test/java/ch/qos/logback/access/spi/PackageTest.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactoryBase.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java

Log:
- Added support for SiftingAppender in logback-access
- logback-access tests are now all JUnit4

Modified: logback/trunk/logback-access/pom.xml
==============================================================================
--- logback/trunk/logback-access/pom.xml	(original)
+++ logback/trunk/logback-access/pom.xml	Mon Dec 22 19:54:44 2008
@@ -109,7 +109,7 @@
           <reportFormat>plain</reportFormat>
           <disableXmlReport>true</disableXmlReport>
           <excludes>
-            <exclude>**/AllTest.java</exclude>
+            <exclude>**/AllAccessTest.java</exclude>
             <exclude>**/PackageTest.java</exclude>
             <exclude>**/SerializationPerfTest.java</exclude>
           </excludes>

Modified: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogImpl.java
==============================================================================
--- logback/trunk/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogImpl.java	(original)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/jetty/RequestLogImpl.java	Mon Dec 22 19:54:44 2008
@@ -133,12 +133,10 @@
     if (getFilterChainDecision(accessEvent) == FilterReply.DENY) {
       return;
     }
-    // TODO better exception handling
     aai.appendLoopOnAppenders(accessEvent);
   }
 
   public void start() {
-
     if (filename == null) {
       String jettyHomeProperty = OptionHelper.getSystemProperty("jetty.home");
 

Modified: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/joran/JoranConfigurator.java
==============================================================================
--- logback/trunk/logback-access/src/main/java/ch/qos/logback/access/joran/JoranConfigurator.java	(original)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/joran/JoranConfigurator.java	Mon Dec 22 19:54:44 2008
@@ -13,9 +13,11 @@
 
 import ch.qos.logback.access.joran.action.ConfigurationAction;
 import ch.qos.logback.access.joran.action.EvaluatorAction;
+import ch.qos.logback.access.sift.SiftAction;
 import ch.qos.logback.core.joran.JoranConfiguratorBase;
 import ch.qos.logback.core.joran.action.AppenderRefAction;
 import ch.qos.logback.core.joran.action.MatcherAction;
+import ch.qos.logback.core.joran.action.NOPAction;
 import ch.qos.logback.core.joran.spi.Pattern;
 import ch.qos.logback.core.joran.spi.RuleStore;
 
@@ -34,6 +36,9 @@
     rs.addRule(new Pattern("configuration"), new ConfigurationAction());
     rs.addRule(new Pattern("configuration/appender-ref"), new AppenderRefAction());
     
+    rs.addRule(new Pattern("configuration/appender/sift"), new SiftAction());
+    rs.addRule(new Pattern("configuration/appender/sift/*"), new NOPAction());
+    
     rs.addRule(new Pattern("*/evaluator"), new EvaluatorAction());
     rs.addRule(new Pattern("*/evaluator/matcher"), new MatcherAction());
 

Added: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AccessEventDiscriminator.java	Mon Dec 22 19:54:44 2008
@@ -0,0 +1,160 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ * 
+ * Copyright (C) 2000-2008, QOS.ch
+ * 
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.access.sift;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import ch.qos.logback.access.spi.AccessEvent;
+import ch.qos.logback.core.sift.Discriminator;
+import ch.qos.logback.core.spi.ContextAwareBase;
+
+public class AccessEventDiscriminator extends ContextAwareBase implements
+    Discriminator<AccessEvent> {
+
+  boolean started = false;
+
+  /**
+   * Allowed field names are: COOKIE, REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE,
+   * REMOTE_ADDRESS, LOCAL_PORT,REQUEST_URI
+   * 
+   * <p> The first three field names require a key attribute.
+   */
+  public enum FieldName {
+    COOKIE, REQUEST_ATTRIBUTE, SESSION_ATTRIBUTE, REMOTE_ADDRESS, LOCAL_PORT, REQUEST_URI
+  }
+
+  String defaultValue;
+  FieldName fieldName;
+  String optionalKey;
+
+  public String getDiscriminatingValue(AccessEvent acccessEvent) {
+    String rawValue = getRawDiscriminatingValue(acccessEvent);
+    if (rawValue == null || rawValue.length() == 0) {
+      return defaultValue;
+    } else {
+      return rawValue;
+    }
+  }
+
+  public String getRawDiscriminatingValue(AccessEvent acccessEvent) {
+    switch (fieldName) {
+    case COOKIE:
+      return acccessEvent.getCookie(optionalKey);
+    case LOCAL_PORT:
+      return String.valueOf(acccessEvent.getLocalPort());
+    case REQUEST_ATTRIBUTE:
+      return acccessEvent.getAttribute(optionalKey);
+    case SESSION_ATTRIBUTE:
+      return getSessionAttribute(acccessEvent);
+    case REMOTE_ADDRESS:
+      return acccessEvent.getRemoteAddr();
+    case REQUEST_URI:
+      return getRequestURI(acccessEvent);
+    default:
+      return null;
+    }
+  }
+
+  private String getRequestURI(AccessEvent acccessEvent) {
+    String uri = acccessEvent.getRequestURI();
+    if (uri != null && uri.length() >= 1 && uri.charAt(0) == '/') {
+      return uri.substring(1);
+    } else {
+      return uri;
+    }
+  }
+
+  private String getSessionAttribute(AccessEvent acccessEvent) {
+    HttpServletRequest req = acccessEvent.getRequest();
+    if (req != null) {
+      HttpSession session = req.getSession(false);
+      if (session != null) {
+        Object v = session.getAttribute(optionalKey);
+        if (v != null) {
+          return v.toString();
+        }
+      }
+    }
+    return null;
+  }
+
+  public boolean isStarted() {
+    return started;
+  }
+
+  public void start() {
+
+    int errorCount = 0;
+
+    if (defaultValue == null) {
+      addError("\"DefaultValue\" property must be set.");
+    }
+    if (fieldName == null) {
+      addError("\"FieldName\" property must be set.");
+      errorCount++;
+    }
+
+    switch (fieldName) {
+    case SESSION_ATTRIBUTE:
+    case REQUEST_ATTRIBUTE:
+    case COOKIE:
+      if (optionalKey == null) {
+        addError("\"OptionalKey\" property is mandatory for field name "+fieldName.toString());
+        errorCount++;
+      }
+    }
+
+    if (errorCount == 0) {
+      started = true;
+    }
+  }
+
+  public void stop() {
+    started = false;
+  }
+
+  public void setFieldName(FieldName fieldName) {
+    this.fieldName = fieldName;
+  }
+
+  public FieldName getFieldName() {
+    return fieldName;
+  }
+
+  public String getOptionalKey() {
+    return optionalKey;
+  }
+
+  public void setOptionalKey(String optionalKey) {
+    this.optionalKey = optionalKey;
+  }
+
+  
+  /**
+   * @see #setDefaultValue(String)
+   * @return
+   */
+  public String getDefaultValue() {
+    return defaultValue;
+  }
+
+  /**
+   * The default value returned by this discriminator in case it cannot compute
+   * the discriminating value from the access event.
+   * 
+   * @param defaultValue
+   */
+  public void setDefaultValue(String defaultValue) {
+    this.defaultValue = defaultValue;
+  }
+
+  
+}

Added: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AppenderFactory.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/AppenderFactory.java	Mon Dec 22 19:54:44 2008
@@ -0,0 +1,34 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ * 
+ * Copyright (C) 2000-2008, QOS.ch
+ * 
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.access.sift;
+
+import java.util.List;
+
+import ch.qos.logback.access.spi.AccessEvent;
+import ch.qos.logback.core.Context;
+import ch.qos.logback.core.joran.event.SaxEvent;
+import ch.qos.logback.core.sift.AppenderFactoryBase;
+import ch.qos.logback.core.sift.SiftingJoranConfiguratorBase;
+
+public class AppenderFactory extends AppenderFactoryBase<AccessEvent> {
+
+  String keyName;
+
+  AppenderFactory(Context context, List<SaxEvent> eventList, String keyName) {
+    super(context, eventList);
+    this.keyName = keyName;
+  }
+
+  public SiftingJoranConfiguratorBase<AccessEvent> getSiftingJoranConfigurator(
+      String keyValue) {
+    return new SiftingJoranConfigurator(keyName, keyValue);
+  }
+
+}

Added: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftAction.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftAction.java	Mon Dec 22 19:54:44 2008
@@ -0,0 +1,55 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ * 
+ * Copyright (C) 2000-2008, QOS.ch
+ * 
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.access.sift;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.xml.sax.Attributes;
+
+import ch.qos.logback.core.joran.action.Action;
+import ch.qos.logback.core.joran.event.InPlayListener;
+import ch.qos.logback.core.joran.event.SaxEvent;
+import ch.qos.logback.core.joran.spi.ActionException;
+import ch.qos.logback.core.joran.spi.InterpretationContext;
+
+public class SiftAction  extends Action implements InPlayListener {
+  List<SaxEvent> seList;
+  
+  @Override
+  public void begin(InterpretationContext ec, String name, Attributes attributes)
+      throws ActionException {
+    seList = new ArrayList<SaxEvent>();
+    ec.addInPlayListener(this);
+  }
+
+  @Override
+  public void end(InterpretationContext ec, String name) throws ActionException {
+    ec.removeInPlayListener(this);
+    Object o = ec.peekObject();
+    if (o instanceof SiftingAppender) {
+      SiftingAppender siftingAppender = (SiftingAppender) o; 
+      AppenderFactory appenderFactory = new AppenderFactory(context, seList, siftingAppender.getKeyName());
+      siftingAppender.setAppenderFactory(appenderFactory);
+    }
+  }
+
+  public void inPlay(SaxEvent event) {
+    seList.add(event);
+  }
+
+  public List<SaxEvent> getSeList() {
+    return seList;
+  }
+
+    
+
+
+}

Added: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingAppender.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingAppender.java	Mon Dec 22 19:54:44 2008
@@ -0,0 +1,60 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ * 
+ * Copyright (C) 2000-2008, QOS.ch
+ * 
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.access.sift;
+
+import ch.qos.logback.access.spi.AccessEvent;
+import ch.qos.logback.core.sift.AppenderTracker;
+import ch.qos.logback.core.sift.SiftingAppenderBase;
+import ch.qos.logback.core.util.OptionHelper;
+
+/**
+ * This appender can contains other appenders which it can build dynamically
+ * depending on MDC values. The built appender is specified as part of a
+ * configuration file.
+ * 
+ * <p>See the logback manual for further details.
+ * 
+ * 
+ * @author Ceki Gulcu
+ */
+public class SiftingAppender extends SiftingAppenderBase<AccessEvent> {
+
+  String keyName;
+
+  @Override
+  public void start() {
+    int errors = 0;
+    if (OptionHelper.isEmpty(keyName)) {
+      errors++;
+      addError("The \"keyName\" property must be set");
+    }
+    if (errors == 0) {
+      super.start();
+    }
+  }
+
+  AppenderTracker<AccessEvent> getAppenderTracker() {
+    return appenderTracker;
+  }
+
+  @Override
+  protected long getTimestamp(AccessEvent event) {
+    return event.getTimeStamp();
+  }
+
+  public String getKeyName() {
+    return keyName;
+  }
+
+  public void setKeyName(String keyName) {
+    this.keyName = keyName;
+  }
+
+}

Added: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingJoranConfigurator.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/sift/SiftingJoranConfigurator.java	Mon Dec 22 19:54:44 2008
@@ -0,0 +1,53 @@
+package ch.qos.logback.access.sift;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import ch.qos.logback.access.spi.AccessEvent;
+import ch.qos.logback.core.Appender;
+import ch.qos.logback.core.joran.action.ActionConst;
+import ch.qos.logback.core.joran.action.AppenderAction;
+import ch.qos.logback.core.joran.spi.Pattern;
+import ch.qos.logback.core.joran.spi.RuleStore;
+import ch.qos.logback.core.sift.SiftingJoranConfiguratorBase;
+
+public class SiftingJoranConfigurator  extends SiftingJoranConfiguratorBase<AccessEvent> {
+
+  String key;
+  String value;
+  
+  SiftingJoranConfigurator(String key, String value) {
+    this.key = key;
+    this.value = value;
+  }
+  
+  @Override
+  protected Pattern initialPattern() {
+    return new Pattern("configuration");
+  }
+  
+  @Override
+  protected void addInstanceRules(RuleStore rs) {
+    rs.addRule(new Pattern("configuration/appender"), new AppenderAction());
+  }
+
+  @Override
+  protected void buildInterpreter() {
+    super.buildInterpreter();
+    Map<String, Object> omap = interpreter.getInterpretationContext().getObjectMap();
+    omap.put(ActionConst.APPENDER_BAG, new HashMap());
+    omap.put(ActionConst.FILTER_CHAIN_BAG, new HashMap());
+    Map<String, String> propertiesMap = new HashMap<String, String>();
+    propertiesMap.put(key, value);
+    interpreter.setInterpretationContextPropertiesMap(propertiesMap);
+  }
+
+  @SuppressWarnings("unchecked")
+  public Appender<AccessEvent> getAppender() {
+    Map<String, Object> omap = interpreter.getInterpretationContext().getObjectMap();
+    HashMap map = (HashMap) omap.get(ActionConst.APPENDER_BAG);
+    Collection values = map.values();
+    return (Appender<AccessEvent>) values.iterator().next();
+  }
+}

Added: logback/trunk/logback-access/src/test/input/jetty/sifting.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/test/input/jetty/sifting.xml	Mon Dec 22 19:54:44 2008
@@ -0,0 +1,15 @@
+<configuration>
+
+  <appender name="SIFTING" class="ch.qos.logback.access.sift.SiftingAppender">
+    <KeyName>uri</KeyName>
+    <Discriminator class="ch.qos.logback.access.sift.AccessEventDiscriminator">
+      <FieldName>REQUEST_URI</FieldName>
+      <DefaultValue>NA</DefaultValue>
+    </Discriminator>
+    <sift>
+      <appender name="${uri}" class="ch.qos.logback.core.read.ListAppender"/>
+    </sift>
+  </appender>
+
+  <appender-ref ref="SIFTING" />
+</configuration>
\ No newline at end of file

Copied: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/AllAccessTest.java (from r1859, /logback/trunk/logback-access/src/test/java/ch/qos/logback/access/AllTest.java)
==============================================================================
--- /logback/trunk/logback-access/src/test/java/ch/qos/logback/access/AllTest.java	(original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/AllAccessTest.java	Mon Dec 22 19:54:44 2008
@@ -9,19 +9,17 @@
  */
 package ch.qos.logback.access;
 
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
 
-public class AllTest extends TestCase {
+ at RunWith(Suite.class)
+ at SuiteClasses( { ch.qos.logback.access.spi.PackageTest.class,
+    ch.qos.logback.access.net.PackageTest.class,
+    ch.qos.logback.access.pattern.PackageTest.class,
+    ch.qos.logback.access.jetty.PackageTest.class,
+    ch.qos.logback.access.filter.PackageTest.class,
+    ch.qos.logback.access.sift.PackageTest.class })
+public class AllAccessTest {
 
-  public static Test suite() {
-    TestSuite suite = new TestSuite();
-    suite.addTest(ch.qos.logback.access.spi.PackageTest.suite());
-    suite.addTest(ch.qos.logback.access.net.PackageTest.suite());
-    suite.addTest(ch.qos.logback.access.pattern.PackageTest.suite());
-    suite.addTest(ch.qos.logback.access.jetty.PackageTest.suite());
-    suite.addTest(ch.qos.logback.access.filter.PackageTest.suite());
-    return suite;
-  }
 }

Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/filter/PackageTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/filter/PackageTest.java	(original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/filter/PackageTest.java	Mon Dec 22 19:54:44 2008
@@ -10,14 +10,13 @@
 
 package ch.qos.logback.access.filter;
 
-import junit.framework.*;
+import junit.framework.TestCase;
 
-public class PackageTest extends TestCase {
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
 
-  public static Test suite() {
-    TestSuite suite = new TestSuite();
-    suite.addTestSuite(StatsByDayTest.class);
-    suite.addTestSuite(AccessStatsTest.class);
-    return suite;
-  }
+ at RunWith(Suite.class)
+ at SuiteClasses({StatsByDayTest.class})
+public class PackageTest extends TestCase {
 }
\ No newline at end of file

Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/filter/StatsByDayTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/filter/StatsByDayTest.java	(original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/filter/StatsByDayTest.java	Mon Dec 22 19:54:44 2008
@@ -1,34 +1,25 @@
 package ch.qos.logback.access.filter;
 
-import ch.qos.logback.core.util.TimeUtil;
-import junit.framework.TestCase;
+import static org.junit.Assert.assertEquals;
 
-public class StatsByDayTest extends TestCase {
+import org.junit.Test;
 
-  public StatsByDayTest(String name) {
-    super(name);
-  }
+import ch.qos.logback.core.util.TimeUtil;
 
-  protected void setUp() throws Exception {
-    super.setUp();
-  }
+public class StatsByDayTest {
 
-  protected void tearDown() throws Exception {
-    super.tearDown();
-  }
-  
- public void testBasic() {
-   // Tue Nov 21 18:05:36 CET 2006
+  @Test
+  public void testBasic() {
+    // Tue Nov 21 18:05:36 CET 2006
     long now = 1164128736369L;
     StatsByDay statsByDay = new StatsByDay(now);
-    
+
     int total = 0;
     // test fresh start
     statsByDay.update(now, 0);
     assertEquals(0, statsByDay.getLastCount());
     assertEquals(0, statsByDay.getAverage(), 0.01);
 
-  
     total++;
     statsByDay.update(now, total);
     assertEquals(0, statsByDay.getLastCount());
@@ -36,14 +27,14 @@
 
     long nextDay0 = TimeUtil.computeStartOfNextDay(now);
     nextDay0 += 99;
-    
+
     // there should be one event the next day, avg should also be 1
     statsByDay.update(nextDay0, total);
     assertEquals(1.0, statsByDay.getLastCount(), 0.01);
     assertEquals(1.0, statsByDay.getAverage(), 0.01);
 
     total += 2;
-    
+
     statsByDay.update(nextDay0, total);
     assertEquals(1, statsByDay.getLastCount());
     assertEquals(1.0, statsByDay.getAverage(), 0.01);
@@ -55,19 +46,18 @@
 
     nextDay1 += 4444;
     total += 4;
-    
+
     statsByDay.update(nextDay1, total);
     // values should remain unchanged
     assertEquals(2, statsByDay.getLastCount());
     assertEquals(1.5, statsByDay.getAverage(), 0.01);
 
-    
     long nextDay2 = TimeUtil.computeStartOfNextDay(nextDay1) + 11177;
 
     statsByDay.update(nextDay2, total);
     // values should remain unchanged
     assertEquals(4, statsByDay.getLastCount());
-    assertEquals(7.0/3, statsByDay.getAverage(), 0.01);
+    assertEquals(7.0 / 3, statsByDay.getAverage(), 0.01);
   }
 
 }

Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixture.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixture.java	(original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixture.java	Mon Dec 22 19:54:44 2008
@@ -1,3 +1,12 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ * 
+ * Copyright (C) 2000-2008, QOS.ch
+ * 
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
 package ch.qos.logback.access.jetty;
 
 import java.io.IOException;
@@ -7,15 +16,10 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.mortbay.jetty.Connector;
 import org.mortbay.jetty.Handler;
 import org.mortbay.jetty.HttpConnection;
 import org.mortbay.jetty.Request;
-import org.mortbay.jetty.Server;
 import org.mortbay.jetty.handler.AbstractHandler;
-import org.mortbay.jetty.handler.ContextHandler;
-import org.mortbay.jetty.handler.RequestLogHandler;
-import org.mortbay.jetty.nio.SelectChannelConnector;
 import org.mortbay.util.ByteArrayISO8859Writer;
 
 import ch.qos.logback.access.PatternLayout;
@@ -23,62 +27,26 @@
 import ch.qos.logback.access.testUtil.NotifyingListAppender;
 import ch.qos.logback.core.ConsoleAppender;
 
-public class JettyFixture {
-  RequestLogImpl requestLogImpl;
-
-  private final int port;
-  Server server;
-  String url;
+public class JettyFixture extends JettyFixtureBase {
+  
+  Handler handler = new BasicHandler();
   
   public JettyFixture(RequestLogImpl impl, int port) {
-    requestLogImpl = impl;
-    this.port = port;
+    super(impl, port);
     url = "http://localhost:" + port + "/";
   }
 
-  public String getName() {
-    return "Jetty Test Setup";
-  }
-
-  public String getUrl() {
-    return url;
-  }
-
   public void start() throws Exception {
-    server = new Server();
-    Connector connector = new SelectChannelConnector();
-    connector.setPort(port);
-    server.setConnectors(new Connector[] { connector });
-
-    ContextHandler context = new ContextHandler();
-    context.setContextPath("/");
-    context.setResourceBase(".");
-    context.setClassLoader(Thread.currentThread().getContextClassLoader());
-    server.addHandler(context);
-
-    RequestLogHandler requestLogHandler = new RequestLogHandler();
-    buildContext();
-    requestLogHandler.setRequestLog(requestLogImpl);
-    server.addHandler(requestLogHandler);
-
-    Handler handler = new BasicHandler();
-    context.addHandler(handler);
-
-    server.start();
-    
+    super.start();
     Thread.yield();
   }
 
   public void stop() throws Exception {
-    // System.out.println("into tearDown");
-    server.stop();
-    Thread.sleep(1000);
-    server = null;
-    requestLogImpl = null;
+    super.stop();
+    Thread.sleep(500);
   }
 
-  private void buildContext() {
-
+  protected void buildContext() {
     NotifyingListAppender appender = new NotifyingListAppender();
     appender.setContext(requestLogImpl);
     appender.setName("list");
@@ -98,6 +66,11 @@
     requestLogImpl.addAppender(console);
   }
 
+  @Override
+  protected Handler getHandler() {
+    return handler;
+  }
+
 }
 
 class BasicHandler extends AbstractHandler {

Added: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixtureBase.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/JettyFixtureBase.java	Mon Dec 22 19:54:44 2008
@@ -0,0 +1,72 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ * 
+ * Copyright (C) 2000-2008, QOS.ch
+ * 
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.access.jetty;
+
+import org.mortbay.jetty.Connector;
+import org.mortbay.jetty.Handler;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.handler.ContextHandler;
+import org.mortbay.jetty.handler.RequestLogHandler;
+import org.mortbay.jetty.nio.SelectChannelConnector;
+
+abstract public class JettyFixtureBase {
+  protected RequestLogImpl requestLogImpl;
+
+  private final int port;
+  Server server;
+  String url;
+  
+  public JettyFixtureBase(RequestLogImpl impl, int port) {
+    requestLogImpl = impl;
+    this.port = port;
+    url = "http://localhost:" + port + "/";
+  }
+
+  public String getName() {
+    return "Jetty Test Setup";
+  }
+
+  public String getUrl() {
+    return url;
+  }
+
+  public void start() throws Exception {
+    server = new Server();
+    Connector connector = new SelectChannelConnector();
+    connector.setPort(port);
+    server.setConnectors(new Connector[] { connector });
+
+    ContextHandler context = new ContextHandler();
+    context.setContextPath("/");
+    context.setResourceBase(".");
+    context.setClassLoader(Thread.currentThread().getContextClassLoader());
+    server.addHandler(context);
+
+    RequestLogHandler requestLogHandler = new RequestLogHandler();
+    buildContext();
+    requestLogHandler.setRequestLog(requestLogImpl);
+    server.addHandler(requestLogHandler);
+
+    Handler handler = getHandler();
+    context.addHandler(handler);
+
+    server.start();
+  }
+
+  public void stop() throws Exception {
+    // System.out.println("into tearDown");
+    server.stop();
+    server = null;
+    requestLogImpl = null;
+  }
+
+  abstract protected void buildContext();
+  abstract protected Handler getHandler();
+}

Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/PackageTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/PackageTest.java	(original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/jetty/PackageTest.java	Mon Dec 22 19:54:44 2008
@@ -10,13 +10,12 @@
 
 package ch.qos.logback.access.jetty;
 
-import junit.framework.*;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
 
-public class PackageTest extends TestCase {
+ at RunWith(Suite.class)
+ at SuiteClasses({JettyBasicTest.class})
+public class PackageTest  {
 
-  public static Test suite() {
-    TestSuite suite = new TestSuite();
-    suite.addTest(new JUnit4TestAdapter(JettyBasicTest.class));
-    return suite;
-  }
 }
\ No newline at end of file

Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/PackageTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/PackageTest.java	(original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/PackageTest.java	Mon Dec 22 19:54:44 2008
@@ -9,14 +9,13 @@
  */
 package ch.qos.logback.access.net;
 
-import junit.framework.*;
+import junit.framework.TestCase;
 
-public class PackageTest extends TestCase {
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
 
-  public static Test suite() {
-    TestSuite suite = new TestSuite();
-    suite.addTestSuite(URLEvaluatorTest.class);
-    suite.addTestSuite(SocketAppenderTest.class);
-    return suite;
-  }
+ at RunWith(Suite.class)
+ at SuiteClasses({URLEvaluatorTest.class, SocketAppenderTest.class})
+public class PackageTest extends TestCase {
 }
\ No newline at end of file

Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/SocketAppenderTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/SocketAppenderTest.java	(original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/SocketAppenderTest.java	Mon Dec 22 19:54:44 2008
@@ -9,19 +9,24 @@
  */
 package ch.qos.logback.access.net;
 
-import junit.framework.TestCase;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
 import ch.qos.logback.access.dummy.DummyRequest;
 import ch.qos.logback.access.dummy.DummyResponse;
 import ch.qos.logback.access.dummy.DummyServerAdapter;
-import ch.qos.logback.access.spi.AccessEvent;
 import ch.qos.logback.access.spi.AccessContext;
+import ch.qos.logback.access.spi.AccessEvent;
 
 
-public class SocketAppenderTest extends TestCase {
+public class SocketAppenderTest {
 
   private AccessContext context;
   private MockSocketServer mockSocketServer;
 
+  @Test
   public void testStartFailNoRemoteHost() {
     context = new AccessContext();
     SocketAppender appender = new SocketAppender();
@@ -31,6 +36,7 @@
     assertEquals(1, context.getStatusManager().getCount());
   }
 
+  @Test
   public void testRecieveMessage() throws InterruptedException {
     startServer(1);
     configureClient();

Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/URLEvaluatorTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/URLEvaluatorTest.java	(original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/net/URLEvaluatorTest.java	Mon Dec 22 19:54:44 2008
@@ -1,6 +1,11 @@
 package ch.qos.logback.access.net;
 
-import junit.framework.TestCase;
+import static org.junit.Assert.*;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
 import ch.qos.logback.access.dummy.DummyRequest;
 import ch.qos.logback.access.dummy.DummyResponse;
 import ch.qos.logback.access.dummy.DummyServerAdapter;
@@ -9,7 +14,7 @@
 import ch.qos.logback.core.ContextBase;
 import ch.qos.logback.core.boolex.EvaluationException;
 
-public class URLEvaluatorTest extends TestCase {
+public class URLEvaluatorTest  {
 
   final String expectedURL1 = "testUrl1";
   final String expectedURL2 = "testUrl2";
@@ -19,6 +24,7 @@
   DummyResponse response;
   DummyServerAdapter serverAdapter;
   
+  @Before
   public void setUp() throws Exception {
     evaluator = new URLEvaluator();
     evaluator.setContext(context);
@@ -27,9 +33,9 @@
     request = new DummyRequest();
     response = new DummyResponse();
     serverAdapter = new DummyServerAdapter(request, response);
-    super.setUp();
   }
   
+  @After
   public void tearDown() throws Exception {
     evaluator.stop();
     evaluator = null;
@@ -39,18 +45,21 @@
     context = null;
   }
   
+  @Test
   public void testExpectFalse() throws EvaluationException {
     request.setRequestUri("test");
     AccessEvent ae = new AccessEvent(request, response, serverAdapter);
     assertFalse(evaluator.evaluate(ae));
   }
   
+  @Test
   public void testExpectTrue() throws EvaluationException {
     request.setRequestUri(expectedURL1);   
     AccessEvent ae = new AccessEvent(request, response, serverAdapter);
     assertTrue(evaluator.evaluate(ae));    
   }
   
+  @Test
   public void testExpectTrueMultiple() throws EvaluationException {
     evaluator.addURL(expectedURL2);
     request.setRequestUri(expectedURL2);    

Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java	(original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/ConverterTest.java	Mon Dec 22 19:54:44 2008
@@ -1,36 +1,42 @@
 package ch.qos.logback.access.pattern;
 
+import static org.junit.Assert.assertEquals;
+
 import java.util.ArrayList;
 import java.util.List;
 
 import javax.servlet.http.Cookie;
 
-import junit.framework.TestCase;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
 import ch.qos.logback.access.dummy.DummyRequest;
 import ch.qos.logback.access.dummy.DummyResponse;
 import ch.qos.logback.access.dummy.DummyServerAdapter;
 import ch.qos.logback.access.spi.AccessEvent;
 
-public class ConverterTest extends TestCase {
+public class ConverterTest  {
 
   AccessEvent event;
   DummyRequest request;
   DummyResponse response;
 
+  @Before
   public void setUp() throws Exception {
-    super.setUp();
     request = new DummyRequest();
     response = new DummyResponse();
     event = createEvent();
   }
 
+  @After
   public void tearDown() throws Exception {
-    super.tearDown();
     event = null;
     request = null;
     response = null;
   }
 
+  @Test
   public void testContentLengthConverter() {
     ContentLengthConverter converter = new ContentLengthConverter();
     converter.start();
@@ -38,6 +44,7 @@
     assertEquals(Long.toString(event.getServerAdapter().getContentLength()), result);
   }
 
+  @Test
   public void testDateConverter() {
     DateConverter converter = new DateConverter();
     converter.start();
@@ -52,6 +59,7 @@
     assertEquals(Integer.toString(request.getLocalPort()), result);
   }
 
+  @Test
   public void testRemoteHostConverter() {
     RemoteHostConverter converter = new RemoteHostConverter();
     converter.start();
@@ -59,6 +67,7 @@
     assertEquals(request.getRemoteHost(), result);
   }
 
+  @Test
   public void testRemoteIPAddressConverter() {
     RemoteIPAddressConverter converter = new RemoteIPAddressConverter();
     converter.start();
@@ -66,6 +75,7 @@
     assertEquals(request.getRemoteAddr(), result);
   }
 
+  @Test
   public void testRemoteUserConverter() {
     RemoteUserConverter converter = new RemoteUserConverter();
     converter.start();
@@ -73,6 +83,7 @@
     assertEquals(request.getRemoteUser(), result);
   }
 
+  @Test
   public void testRequestAttributeConverter() {
     RequestAttributeConverter converter = new RequestAttributeConverter();
     List<String> optionList = new ArrayList<String>();
@@ -83,6 +94,7 @@
     assertEquals(request.getAttribute("testKey"), result);
   }
 
+  @Test
   public void testRequestCookieConverter() {
     RequestCookieConverter converter = new RequestCookieConverter();
     List<String> optionList = new ArrayList<String>();
@@ -94,6 +106,7 @@
     assertEquals(cookie.getValue(), result);
   }
 
+  @Test
   public void testRequestHeaderConverter() {
     RequestHeaderConverter converter = new RequestHeaderConverter();
     List<String> optionList = new ArrayList<String>();
@@ -104,6 +117,7 @@
     assertEquals(request.getHeader("headerName1"), result);
   }
 
+  @Test
   public void testRequestMethodConverter() {
     RequestMethodConverter converter = new RequestMethodConverter();
     converter.start();
@@ -111,6 +125,7 @@
     assertEquals(request.getMethod(), result);
   }
 
+  @Test
   public void testRequestProtocolConverter() {
     RequestProtocolConverter converter = new RequestProtocolConverter();
     converter.start();
@@ -118,6 +133,7 @@
     assertEquals(request.getProtocol(), result);
   }
 
+  @Test
   public void testRequestURIConverter() {
     RequestURIConverter converter = new RequestURIConverter();
     converter.start();
@@ -125,6 +141,7 @@
     assertEquals(request.getRequestURI(), result);
   }
 
+  @Test
   public void testRequestURLConverter() {
     RequestURLConverter converter = new RequestURLConverter();
     converter.start();
@@ -134,6 +151,7 @@
     assertEquals(expected, result);
   }
 
+  @Test
   public void testResponseHeaderConverter() {
      ResponseHeaderConverter converter = new ResponseHeaderConverter();
      List<String> optionList = new ArrayList<String>();
@@ -144,6 +162,7 @@
      assertEquals(request.getHeader("headerName1"), result);
   }
 
+  @Test
   public void testServerNameConverter() {
     ServerNameConverter converter = new ServerNameConverter();
     converter.start();
@@ -151,6 +170,7 @@
     assertEquals(request.getServerName(), result);
   }
   
+  @Test
   public void testStatusCodeConverter() {
     StatusCodeConverter converter = new StatusCodeConverter();
     converter.start();

Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/PackageTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/PackageTest.java	(original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/pattern/PackageTest.java	Mon Dec 22 19:54:44 2008
@@ -9,13 +9,13 @@
  */
 package ch.qos.logback.access.pattern;
 
-import junit.framework.*;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+ at RunWith(Suite.class)
+ at SuiteClasses({ConverterTest.class})
+public class PackageTest  {
 
-public class PackageTest extends TestCase {
 
-  public static Test suite() {
-    TestSuite suite = new TestSuite();
-    suite.addTestSuite(ConverterTest.class);
-    return suite;
-  }
 }
\ No newline at end of file

Added: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/JettyFixture.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/JettyFixture.java	Mon Dec 22 19:54:44 2008
@@ -0,0 +1,59 @@
+package ch.qos.logback.access.sift;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.mortbay.jetty.Handler;
+import org.mortbay.jetty.HttpConnection;
+import org.mortbay.jetty.Request;
+import org.mortbay.jetty.handler.AbstractHandler;
+import org.mortbay.util.ByteArrayISO8859Writer;
+
+import ch.qos.logback.access.jetty.JettyFixtureBase;
+import ch.qos.logback.access.jetty.RequestLogImpl;
+
+public class JettyFixture extends JettyFixtureBase {
+
+  Handler handler = new BasicHandler();
+
+  public JettyFixture(RequestLogImpl impl, int port) {
+    super(impl, port);
+  }
+
+  @Override
+  protected void buildContext() {
+    requestLogImpl.start();
+  }
+
+  @Override
+  protected Handler getHandler() {
+    return handler;
+  }
+
+  class BasicHandler extends AbstractHandler {
+    public void handle(String target, HttpServletRequest request,
+        HttpServletResponse response, int dispatch) throws IOException,
+        ServletException {
+
+      // String requestContent = Util.readToString(request.getInputStream());
+      // System.out.println("request content: " + requestContent);
+
+      OutputStream out = response.getOutputStream();
+      ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer();
+      writer.write("hello world");
+      writer.flush();
+      response.setContentLength(writer.size());
+      writer.writeTo(out);
+      out.flush();
+
+      Request base_request = (request instanceof Request) ? (Request) request
+          : HttpConnection.getCurrentConnection().getRequest();
+      base_request.setHandled(true);
+
+    }
+  }
+}

Added: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/PackageTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/PackageTest.java	Mon Dec 22 19:54:44 2008
@@ -0,0 +1,20 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework for Java.
+ * 
+ * Copyright (C) 2000-2006, QOS.ch
+ * 
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.access.sift;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+ at RunWith(Suite.class)
+ at SuiteClasses({SiftingAppenderTest.class})
+public class PackageTest  {
+
+}
\ No newline at end of file

Added: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/SiftingAppenderTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/sift/SiftingAppenderTest.java	Mon Dec 22 19:54:44 2008
@@ -0,0 +1,96 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ * 
+ * Copyright (C) 2000-2008, QOS.ch
+ * 
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.access.sift;
+
+import static org.junit.Assert.assertEquals;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import ch.qos.logback.access.jetty.RequestLogImpl;
+import ch.qos.logback.access.spi.AccessEvent;
+import ch.qos.logback.access.spi.Util;
+import ch.qos.logback.core.read.ListAppender;
+import ch.qos.logback.core.testUtil.RandomUtil;
+
+public class SiftingAppenderTest {
+  static final String PREFIX = "src/test/input/jetty/";
+  static int RANDOM_SERVER_PORT = RandomUtil.getRandomServerPort();
+
+  JettyFixture jettyFixture;
+  RequestLogImpl rli = new RequestLogImpl();
+
+  @Before
+  public void startServer() throws Exception {
+    jettyFixture = new JettyFixture(rli, RANDOM_SERVER_PORT);
+
+  }
+
+  @After
+  public void stopServer() throws Exception {
+    if (jettyFixture != null) {
+      jettyFixture.stop();
+    }
+  }
+
+  @Test
+  public void test() throws Exception {
+    rli.setFileName(PREFIX + "sifting.xml");
+    jettyFixture.start();
+
+    invokeServer("/");
+    invokeServer("/x");
+    invokeServer("/x");
+    invokeServer("/y");
+
+    SiftingAppender siftingAppender = (SiftingAppender) rli
+        .getAppender("SIFTING");
+    List<String> keyList = siftingAppender.getAppenderTracker().keyList();
+    assertEquals(3, keyList.size());
+
+    List<String> witnessList = new ArrayList<String>();
+    witnessList.add("NA");
+    witnessList.add("x");
+    witnessList.add("y");
+    assertEquals(witnessList, keyList);
+
+    long now = System.currentTimeMillis();
+    {
+      ListAppender<AccessEvent> listAppender = (ListAppender<AccessEvent>) siftingAppender
+          .getAppenderTracker().get("NA", now);
+      assertEquals(1, listAppender.list.size());
+    }
+    
+    {
+      ListAppender<AccessEvent> listAppender = (ListAppender<AccessEvent>) siftingAppender
+          .getAppenderTracker().get("x", now);
+      assertEquals(2, listAppender.list.size());
+    }
+    {
+      ListAppender<AccessEvent> listAppender = (ListAppender<AccessEvent>) siftingAppender
+          .getAppenderTracker().get("y", now);
+      assertEquals(1, listAppender.list.size());
+    }
+  }
+
+  void invokeServer(String uri) throws Exception {
+    URL url = new URL("http://localhost:" + RANDOM_SERVER_PORT + uri);
+    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+    connection.setDoInput(true);
+    Util.readToString(connection.getInputStream());
+    Thread.sleep(30);
+  }
+}

Modified: logback/trunk/logback-access/src/test/java/ch/qos/logback/access/spi/PackageTest.java
==============================================================================
--- logback/trunk/logback-access/src/test/java/ch/qos/logback/access/spi/PackageTest.java	(original)
+++ logback/trunk/logback-access/src/test/java/ch/qos/logback/access/spi/PackageTest.java	Mon Dec 22 19:54:44 2008
@@ -9,13 +9,13 @@
  */
 package ch.qos.logback.access.spi;
 
-import junit.framework.*;
+import junit.framework.TestCase;
 
-public class PackageTest extends TestCase {
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
 
-  public static Test suite() {
-    TestSuite suite = new TestSuite();
-    suite.addTest(new JUnit4TestAdapter(AccessEventSerializationTest.class));
-    return suite;
-  }
+ at RunWith(Suite.class)
+ at SuiteClasses({AccessEventSerializationTest.class})
+public class PackageTest extends TestCase {
 }
\ No newline at end of file

Added: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java	Mon Dec 22 19:54:44 2008
@@ -0,0 +1,50 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ * 
+ * Copyright (C) 2000-2008, QOS.ch
+ * 
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.classic.sift;
+
+import org.slf4j.MDC;
+
+import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.core.sift.Discriminator;
+
+public class MDCBasedDiscriminator implements Discriminator<LoggingEvent> {
+
+  final String mdcKey;
+  final String defaultValue;
+
+  boolean started = true;
+
+  MDCBasedDiscriminator(String mdcKey, String defaultValue) {
+    this.mdcKey = mdcKey;
+    this.defaultValue = defaultValue;
+  }
+
+  public String getDiscriminatingValue(LoggingEvent event) {
+    String mdcValue = MDC.get(mdcKey);
+    if (mdcValue == null) {
+      return defaultValue;
+    } else {
+      return mdcValue;
+    }
+  }
+
+  public boolean isStarted() {
+    return started;
+  }
+
+  public void start() {
+    started = true;
+  }
+
+  public void stop() {
+    started = false;
+  }
+
+}

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/sift/SiftingAppender.java	Mon Dec 22 19:54:44 2008
@@ -9,8 +9,6 @@
  */
 package ch.qos.logback.classic.sift;
 
-import org.slf4j.MDC;
-
 import ch.qos.logback.classic.spi.LoggingEvent;
 import ch.qos.logback.core.sift.AppenderTracker;
 import ch.qos.logback.core.sift.SiftingAppenderBase;
@@ -44,21 +42,12 @@
       errors++;
       addError("The \"defaultValue\" property must be set");
     }
+    setDiscriminator(new MDCBasedDiscriminator(mdcKey, defaultValue));
     if (errors == 0) {
       super.start();
     }
   }
 
-  @Override
-  protected String getDiscriminatingValue(LoggingEvent event) {
-    String mdcValue = MDC.get(mdcKey);
-    if (mdcValue == null) {
-      return defaultValue;
-    } else {
-      return mdcValue;
-    }
-  }
-  
   AppenderTracker<LoggingEvent> getAppenderTracker() {
     return appenderTracker;
   }

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactoryBase.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactoryBase.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/AppenderFactoryBase.java	Mon Dec 22 19:54:44 2008
@@ -32,7 +32,6 @@
   void removeHoardElement() {
     eventList.remove(0);
     eventList.remove(eventList.size() - 1);
-    System.out.println(eventList);
   }
 
   public abstract SiftingJoranConfiguratorBase<E> getSiftingJoranConfigurator(String k);

Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/Discriminator.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/Discriminator.java	Mon Dec 22 19:54:44 2008
@@ -0,0 +1,17 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ * 
+ * Copyright (C) 2000-2008, QOS.ch
+ * 
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.core.sift;
+
+import ch.qos.logback.core.spi.LifeCycle;
+
+
+public interface Discriminator<E> extends LifeCycle {
+  String getDiscriminatingValue(E e);
+}

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/sift/SiftingAppenderBase.java	Mon Dec 22 19:54:44 2008
@@ -28,13 +28,22 @@
 
   protected AppenderTracker<E> appenderTracker = new AppenderTrackerImpl<E>();
   AppenderFactoryBase<E> appenderFactory;
-
+  
+  Discriminator<E> discriminator;
+  
   public void setAppenderFactory(AppenderFactoryBase<E> appenderFactory) {
     this.appenderFactory = appenderFactory;
   }
 
   @Override
   public void start() {
+    if(discriminator == null) {
+      addError("Missing discriminator. Aborting");
+      return;
+    }
+    if(!discriminator.isStarted()) {
+      addError("Discriminator has not started successfully. Aborting");
+    }
     super.start();
   }
 
@@ -45,7 +54,6 @@
     }
   }
 
-  abstract protected String getDiscriminatingValue(E event);
   abstract protected long getTimestamp(E event);
 
   @Override
@@ -54,7 +62,7 @@
       return;
     }
 
-    String value = getDiscriminatingValue(event);
+    String value = discriminator.getDiscriminatingValue(event);
     long timestamp = getTimestamp(event);
 
     Appender<E> appender = appenderTracker.get(value, timestamp);
@@ -74,4 +82,12 @@
     appender.doAppend(event);
   }
 
+  public Discriminator<E> getDiscriminator() {
+    return discriminator;
+  }
+
+  public void setDiscriminator(Discriminator<E> discriminator) {
+    this.discriminator = discriminator;
+  }
+
 }


More information about the logback-dev mailing list