
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 { +@RunWith(Suite.class) +@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; - } +@RunWith(Suite.class) +@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 { +@RunWith(Suite.class) +@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; - } +@RunWith(Suite.class) +@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; + +@RunWith(Suite.class) +@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; + +@RunWith(Suite.class) +@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; - } +@RunWith(Suite.class) +@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; + } + }