View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.classic;
15  
16  import static org.junit.Assert.assertTrue;
17  import static org.junit.Assert.assertEquals;
18  
19  import java.io.ByteArrayInputStream;
20  import java.io.ByteArrayOutputStream;
21  import java.io.FileInputStream;
22  import java.io.IOException;
23  import java.io.ObjectOutputStream;
24  import java.util.ArrayList;
25  import java.util.List;
26  
27  import org.junit.After;
28  import org.junit.Before;
29  import org.junit.Test;
30  import org.slf4j.LoggerFactory;
31  
32  import ch.qos.logback.classic.net.server.HardenedLoggingEventInputStream;
33  import ch.qos.logback.core.net.HardenedObjectInputStream;
34  import ch.qos.logback.core.testUtil.CoreTestConstants;
35  
36  public class LoggerSerializationTest {
37  
38      static final String SERIALIZATION_PREFIX = CoreTestConstants.TEST_INPUT_PREFIX + "/serialization/";
39  
40      // force SLF4J initialization for subsequent Logger readResolce ooperaiton
41      org.slf4j.Logger unused = LoggerFactory.getLogger(this.getClass());
42      LoggerContext lc;
43      Logger logger;
44  
45      ByteArrayOutputStream bos;
46      ObjectOutputStream oos;
47      HardenedLoggingEventInputStream hardenedLoggingEventInputStream;
48      List<String> whitelist = new ArrayList<String>();
49      
50      @Before
51      public void setUp() throws Exception {
52          lc = new LoggerContext();
53          lc.setName("testContext");
54          logger = lc.getLogger(LoggerSerializationTest.class);
55          // create the byte output stream
56          bos = new ByteArrayOutputStream();
57          oos = new ObjectOutputStream(bos);
58          whitelist.add(Foo.class.getName());
59      }
60  
61      @After
62      public void tearDown() throws Exception {
63          lc = null;
64          logger = null;
65      }
66  
67      @Test
68      public void basicSerialization() throws IOException, ClassNotFoundException {
69          Foo foo = new Foo(logger);
70          foo.doFoo();
71          Foo fooBack = writeAndRead(foo);
72          fooBack.doFoo();
73      }
74  
75      @Test
76      public void deepTreeSerialization() throws IOException {
77          // crate a tree of loggers under "aaaaaaaa"
78          Logger a = lc.getLogger("aaaaaaaa");
79          lc.getLogger("aaaaaaaa.a");
80          lc.getLogger("aaaaaaaa.a.a");
81          lc.getLogger("aaaaaaaa.a.b");
82          lc.getLogger("aaaaaaaa.a.c");
83          lc.getLogger("aaaaaaaa.a.d");
84  
85          lc.getLogger("aaaaaaaa.b");
86          lc.getLogger("aaaaaaaa.b.a");
87          lc.getLogger("aaaaaaaa.b.b");
88          lc.getLogger("aaaaaaaa.b.c");
89          lc.getLogger("aaaaaaaa.b.d");
90  
91          lc.getLogger("aaaaaaaa.c");
92          lc.getLogger("aaaaaaaa.c.a");
93          lc.getLogger("aaaaaaaa.c.b");
94          lc.getLogger("aaaaaaaa.c.c");
95          lc.getLogger("aaaaaaaa.c.d");
96  
97          lc.getLogger("aaaaaaaa.d");
98          lc.getLogger("aaaaaaaa.d.a");
99          lc.getLogger("aaaaaaaa.d.b");
100         lc.getLogger("aaaaaaaa.d.c");
101         lc.getLogger("aaaaaaaa.d.d");
102 
103         Logger b = lc.getLogger("b");
104 
105         writeObject(oos, a);
106         oos.close();
107         int sizeA = bos.size();
108 
109         bos = new ByteArrayOutputStream();
110         oos = new ObjectOutputStream(bos);
111 
112         writeObject(oos, b);
113         oos.close();
114         int sizeB = bos.size();
115 
116         assertTrue("serialized logger should be less than 100 bytes", sizeA < 100);
117         // logger tree should not influnce serialization
118         assertTrue("serialized loggers should be nearly the same size a:" + sizeA + ", sizeB:" + sizeB, (sizeA - sizeB) < 10);
119     }
120 
121     private Foo writeAndRead(Foo foo) throws IOException, ClassNotFoundException {
122         writeObject(oos, foo);
123         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
124         hardenedLoggingEventInputStream =  new HardenedLoggingEventInputStream(bis, whitelist);
125         Foo fooBack = readFooObject(hardenedLoggingEventInputStream);
126         hardenedLoggingEventInputStream.close();
127         return fooBack;
128     }
129 
130     Foo readFooObject(HardenedObjectInputStream inputStream) throws IOException, ClassNotFoundException {
131         return (Foo) readObject(inputStream);
132     }
133 
134     private Object readObject(HardenedObjectInputStream inputStream) throws IOException, ClassNotFoundException {
135         return inputStream.readObject();
136     }
137 
138     private void writeObject(ObjectOutputStream oos, Object o) throws IOException {
139         oos.writeObject(o);
140         oos.flush();
141         oos.close();
142     }
143 
144     @Test
145     public void testCompatibilityWith_v1_0_11() throws IOException, ClassNotFoundException {
146         FileInputStream fis = new FileInputStream(SERIALIZATION_PREFIX + "logger_v1.0.11.ser");
147         HardenedObjectInputStream ois = new HardenedLoggingEventInputStream(fis); // new String[] {Logger.class.getName(), LoggerRemoteView.class.getName()});
148         Logger a = (Logger) ois.readObject();
149         ois.close();
150         assertEquals("a", a.getName());
151     }
152 
153     // interestingly enough, logback 1.0.11 and earlier can also read loggers serialized by 1.0.12.
154     // fields not serialized are set to their default values and since the fields are not
155     // used, it works out nicely
156     @Test
157     public void testCompatibilityWith_v1_0_12() throws IOException, ClassNotFoundException {
158         FileInputStream fis = new FileInputStream(SERIALIZATION_PREFIX + "logger_v1.0.12.ser");
159         HardenedObjectInputStream ois = new HardenedObjectInputStream(fis, new String[] {Logger.class.getName()});
160         Logger a = (Logger) ois.readObject();
161         ois.close();
162         assertEquals("a", a.getName());
163     }
164 
165 }