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;
15  
16  import java.io.BufferedInputStream;
17  import java.io.IOException;
18  import java.net.Socket;
19  import java.net.SocketAddress;
20  
21  import ch.qos.logback.classic.Logger;
22  import ch.qos.logback.classic.LoggerContext;
23  import ch.qos.logback.classic.net.server.HardenedLoggingEventInputStream;
24  import ch.qos.logback.classic.spi.ILoggingEvent;
25  
26  // Contributors: Moses Hohman <mmhohman@rainbow.uchicago.edu>
27  
28  /**
29   * Read {@link ILoggingEvent} objects sent from a remote client using Sockets
30   * (TCP). These logging events are logged according to local policy, as if they
31   * were generated locally.
32   * 
33   * <p>
34   * For example, the socket node might decide to log events to a local file and
35   * also resent them to a second socket node.
36   * 
37   * @author Ceki G&uuml;lc&uuml;
38   * @author S&eacute;bastien Pennec
39   * 
40   * @since 0.8.4
41   */
42  public class SocketNode implements Runnable {
43  
44      Socket socket;
45      LoggerContext context;
46      HardenedLoggingEventInputStream hardenedLoggingEventInputStream;
47      SocketAddress remoteSocketAddress;
48  
49      Logger logger;
50      boolean closed = false;
51      SimpleSocketServer socketServer;
52  
53      public SocketNode(SimpleSocketServer socketServer, Socket socket, LoggerContext context) {
54          this.socketServer = socketServer;
55          this.socket = socket;
56          remoteSocketAddress = socket.getRemoteSocketAddress();
57          this.context = context;
58          logger = context.getLogger(SocketNode.class);
59      }
60  
61      // public
62      // void finalize() {
63      // System.err.println("-------------------------Finalize called");
64      // System.err.flush();
65      // }
66  
67      public void run() {
68  
69          try {
70              hardenedLoggingEventInputStream = new HardenedLoggingEventInputStream(
71                      new BufferedInputStream(socket.getInputStream()));
72          } catch (Exception e) {
73              logger.error("Could not open ObjectInputStream to " + socket, e);
74              closed = true;
75          }
76  
77          ILoggingEvent event;
78          Logger remoteLogger;
79  
80          try {
81              while (!closed) {
82                  // read an event from the wire
83                  event = (ILoggingEvent) hardenedLoggingEventInputStream.readObject();
84                  // get a logger from the hierarchy. The name of the logger is taken to
85                  // be the name contained in the event.
86                  remoteLogger = context.getLogger(event.getLoggerName());
87                  // apply the logger-level filter
88                  if (remoteLogger.isEnabledFor(event.getLevel())) {
89                      // finally log the event as if was generated locally
90                      remoteLogger.callAppenders(event);
91                  }
92              }
93          } catch (java.io.EOFException e) {
94              logger.info("Caught java.io.EOFException closing connection.");
95          } catch (java.net.SocketException e) {
96              logger.info("Caught java.net.SocketException closing connection.");
97          } catch (IOException e) {
98              logger.info("Caught java.io.IOException: " + e);
99              logger.info("Closing connection.");
100         } catch (Exception e) {
101             logger.error("Unexpected exception. Closing connection.", e);
102         }
103 
104         socketServer.socketNodeClosing(this);
105         close();
106     }
107 
108     void close() {
109         if (closed) {
110             return;
111         }
112         closed = true;
113         if (hardenedLoggingEventInputStream != null) {
114             try {
115                 hardenedLoggingEventInputStream.close();
116             } catch (IOException e) {
117                 logger.warn("Could not close connection.", e);
118             } finally {
119                 hardenedLoggingEventInputStream = null;
120             }
121         }
122     }
123 
124     @Override
125     public String toString() {
126         return this.getClass().getName() + remoteSocketAddress.toString();
127     }
128 }