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.net.server;
15  
16  import java.io.EOFException;
17  import java.io.IOException;
18  import java.io.InputStream;
19  import java.net.Socket;
20  
21  import ch.qos.logback.classic.Logger;
22  import ch.qos.logback.classic.LoggerContext;
23  import ch.qos.logback.classic.spi.ILoggingEvent;
24  import ch.qos.logback.core.net.HardenedObjectInputStream;
25  import ch.qos.logback.core.util.CloseUtil;
26  
27  /**
28   * A {@link RemoteAppenderClient} that reads serialized {@link ILoggingEvent}
29   * objects from an {@link InputStream}.
30   *
31   * @author Carl Harris
32   */
33  class RemoteAppenderStreamClient implements RemoteAppenderClient {
34  
35      private final String id;
36      private final Socket socket;
37      private final InputStream inputStream;
38  
39      private LoggerContext lc;
40      private Logger logger;
41  
42      /**
43       * Constructs a new client.
44       * 
45       * @param id          a display name for the client
46       * @param inputStream input stream from which events will be read
47       */
48      public RemoteAppenderStreamClient(String id, Socket socket) {
49          this.id = id;
50          this.socket = socket;
51          this.inputStream = null;
52      }
53  
54      /**
55       * Constructs a new client.
56       * <p>
57       * This constructor is provided primarily to support unit tests for which it is
58       * inconvenient to create a socket.
59       * 
60       * @param id          a display name for the client
61       * @param inputStream input stream from which events will be read
62       */
63      public RemoteAppenderStreamClient(String id, InputStream inputStream) {
64          this.id = id;
65          this.socket = null;
66          this.inputStream = inputStream;
67      }
68  
69      /**
70       * {@inheritDoc}
71       */
72      public void setLoggerContext(LoggerContext lc) {
73          this.lc = lc;
74          this.logger = lc.getLogger(getClass().getPackage().getName());
75      }
76  
77      /**
78       * {@inheritDoc}
79       */
80      public void close() {
81          if (socket == null)
82              return;
83          CloseUtil.closeQuietly(socket);
84      }
85  
86      /**
87       * {@inheritDoc}
88       */
89      public void run() {
90          logger.info(this + ": connected");
91          HardenedObjectInputStream ois = null;
92          try {
93              ois = createObjectInputStream();
94              while (true) {
95                  // read an event from the wire
96                  ILoggingEvent event = (ILoggingEvent) ois.readObject();
97                  // get a logger from the hierarchy. The name of the logger is taken to
98                  // be the name contained in the event.
99                  Logger remoteLogger = lc.getLogger(event.getLoggerName());
100                 // apply the logger-level filter
101                 if (remoteLogger.isEnabledFor(event.getLevel())) {
102                     // finally log the event as if was generated locally
103                     remoteLogger.callAppenders(event);
104                 }
105             }
106         } catch (EOFException ex) {
107             // this is normal and expected
108             assert true;
109         } catch (IOException ex) {
110             logger.info(this + ": " + ex);
111         } catch (ClassNotFoundException ex) {
112             logger.error(this + ": unknown event class");
113         } catch (RuntimeException ex) {
114             logger.error(this + ": " + ex);
115         } finally {
116             if (ois != null) {
117                 CloseUtil.closeQuietly(ois);
118             }
119             close();
120             logger.info(this + ": connection closed");
121         }
122     }
123 
124     private HardenedObjectInputStream createObjectInputStream() throws IOException {
125         if (inputStream != null) {
126             return new HardenedLoggingEventInputStream(inputStream);
127         }
128         return new HardenedLoggingEventInputStream(socket.getInputStream());
129     }
130 
131     /**
132      * {@inheritDoc}
133      */
134     @Override
135     public String toString() {
136         return "client " + id;
137     }
138 
139 }