svn commit: r1897 - in logback/trunk/logback-classic/src: main/java/ch/qos/logback/classic test/java/ch/qos/logback/classic

Author: ceki Date: Tue Oct 28 19:07:19 2008 New Revision: 1897 Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/Foo.java logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/Logger.java logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/LoggerTestHelper.java logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/PackageTest.java Log: fixes LBCLASSIC-74 Make ch.qos.logback.classic.Logger instances deserialize with a valid LoggerContext reference. This is accomplished by the readResolve() method which returns a Logger generated by org.slf4j.LoggerFactory which may or not be using the correct LoggerContext. However, that is probably the best we can do at that stage. Associated test case. Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/Logger.java ============================================================================== --- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/Logger.java (original) +++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/Logger.java Tue Oct 28 19:07:19 2008 @@ -10,12 +10,14 @@ package ch.qos.logback.classic; +import java.io.ObjectStreamException; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; +import org.slf4j.LoggerFactory; import org.slf4j.Marker; import org.slf4j.spi.LocationAwareLogger; @@ -73,18 +75,12 @@ * synchronized on 'this' (Logger) protecting against simultaneous * re-configuration of this logger (a very unlikely scenario). * - * <p> - * It is further assumed that the AppenderAttachableImpl is responsible for - * its internal synchronization and thread safety. Thus, we can get away with - * *not* synchronizing on the 'aai' (check null/ read) because - * <p> - * 1) the 'aai' variable is immutable once set to non-null - * <p> - * 2) 'aai' is getAndSet only within addAppender which is synchronized - * <p> - * 3) all the other methods check whether 'aai' is null - * <p> - * 4) AppenderAttachableImpl is thread safe + * <p> It is further assumed that the AppenderAttachableImpl is responsible + * for its internal synchronization and thread safety. Thus, we can get away + * with *not* synchronizing on the 'aai' (check null/ read) because <p> 1) the + * 'aai' variable is immutable once set to non-null <p> 2) 'aai' is getAndSet + * only within addAppender which is synchronized <p> 3) all the other methods + * check whether 'aai' is null <p> 4) AppenderAttachableImpl is thread safe */ private transient AppenderAttachableImpl<LoggingEvent> aai; /** @@ -134,9 +130,8 @@ /** * Get a child by its suffix. * - * <p> - * IMPORTANT: Calls to this method must be within a synchronized block on this - * logger! + * <p> IMPORTANT: Calls to this method must be within a synchronized block on + * this logger! * * @param suffix * @return @@ -315,9 +310,8 @@ * extending this logger. For example, if this logger is named "x.y" and the * lastPart is "z", then the created child logger will be named "x.y.z". * - * <p> - * IMPORTANT: Calls to this method must be within a syncronized block on this - * logger. + * <p> IMPORTANT: Calls to this method must be within a syncronized block on + * this logger. * * @param lastPart * the suffix (i.e. last part) of the child logger name. This @@ -833,4 +827,16 @@ } filterAndLog(fqcn, marker, level, message, null, t); } + + /** + * After serialization, the logger instance does not know its LoggerContext. + * The best we can do here, is to return a logger with the same name as + * generated by LoggerFactory. + * + * @return Logger instance with the same name + * @throws ObjectStreamException + */ + protected Object readResolve() throws ObjectStreamException { + return LoggerFactory.getLogger(getName()); + } } Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/Foo.java ============================================================================== --- (empty file) +++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/Foo.java Tue Oct 28 19:07:19 2008 @@ -0,0 +1,17 @@ +package ch.qos.logback.classic; + +import java.io.Serializable; + +class Foo implements Serializable { + private static final long serialVersionUID = 1L; + final Logger logger; + + Foo(Logger logger) { + this.logger = logger; + } + + void doFoo() { + logger.debug("hello"); + } +} + Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java ============================================================================== --- (empty file) +++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java Tue Oct 28 19:07:19 2008 @@ -0,0 +1,55 @@ +package ch.qos.logback.classic; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class LoggerSerializationTest { + + LoggerContext lc; + Logger logger; + + ByteArrayOutputStream bos; + ObjectOutputStream oos; + ObjectInputStream inputStream; + + @Before + public void setUp() throws Exception { + lc = new LoggerContext(); + lc.setName("testContext"); + logger = lc.getLogger(LoggerSerializationTest.class); + // create the byte output stream + bos = new ByteArrayOutputStream(); + oos = new ObjectOutputStream(bos); + } + + @After + public void tearDown() throws Exception { + lc = null; + logger = null; + oos.close(); + } + + @Test + public void serialization() throws IOException, ClassNotFoundException { + Foo foo = new Foo(logger); + foo.doFoo(); + Foo fooBack = writeAndRead(foo); + fooBack.doFoo(); + } + + private Foo writeAndRead(Foo foo) throws IOException, + ClassNotFoundException { + oos.writeObject(foo); + ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); + inputStream = new ObjectInputStream(bis); + + return (Foo) inputStream.readObject(); + } +} Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/LoggerTestHelper.java ============================================================================== --- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/LoggerTestHelper.java (original) +++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/LoggerTestHelper.java Tue Oct 28 19:07:19 2008 @@ -19,7 +19,4 @@ } assertEquals(effectiveLevel, logger.getEffectiveLevel()); } - - - } \ No newline at end of file Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/PackageTest.java ============================================================================== --- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/PackageTest.java (original) +++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/PackageTest.java Tue Oct 28 19:07:19 2008 @@ -20,6 +20,7 @@ suite.addTest(new JUnit4TestAdapter(DynamicLoggerContextTest.class)); suite.addTest(new JUnit4TestAdapter(PatternLayoutTest.class)); suite.addTestSuite(BasicLoggerTest.class); + suite.addTest(new JUnit4TestAdapter(LoggerSerializationTest.class)); suite.addTestSuite(MessageFormattingTest.class); suite.addTestSuite(MDCTest.class); suite.addTestSuite(TurboFilteringInLoggerTest.class);
participants (1)
-
noreply.ceki@qos.ch