[logback-dev] svn commit: r1897 - in logback/trunk/logback-classic/src: main/java/ch/qos/logback/classic test/java/ch/qos/logback/classic
noreply.ceki at qos.ch
noreply.ceki at qos.ch
Tue Oct 28 19:07:19 CET 2008
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);
More information about the logback-dev
mailing list