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(new BufferedInputStream(socket.getInputStream()));
71          } catch (Exception e) {
72              logger.error("Could not open ObjectInputStream to " + socket, e);
73              closed = true;
74          }
75  
76          ILoggingEvent event;
77          Logger remoteLogger;
78  
79          try {
80              while (!closed) {
81                  // read an event from the wire
82                  event = (ILoggingEvent) hardenedLoggingEventInputStream.readObject();
83                  // get a logger from the hierarchy. The name of the logger is taken to
84                  // be the name contained in the event.
85                  remoteLogger = context.getLogger(event.getLoggerName());
86                  // apply the logger-level filter
87                  if (remoteLogger.isEnabledFor(event.getLevel())) {
88                      // finally log the event as if was generated locally
89                      remoteLogger.callAppenders(event);
90                  }
91              }
92          } catch (java.io.EOFException e) {
93              logger.info("Caught java.io.EOFException closing connection.");
94          } catch (java.net.SocketException e) {
95              logger.info("Caught java.net.SocketException closing connection.");
96          } catch (IOException e) {
97              logger.info("Caught java.io.IOException: " + e);
98              logger.info("Closing connection.");
99          } catch (Exception e) {
100             logger.error("Unexpected exception. Closing connection.", e);
101         }
102 
103         socketServer.socketNodeClosing(this);
104         close();
105     }
106 
107     void close() {
108         if (closed) {
109             return;
110         }
111         closed = true;
112         if (hardenedLoggingEventInputStream != null) {
113             try {
114                 hardenedLoggingEventInputStream.close();
115             } catch (IOException e) {
116                 logger.warn("Could not close connection.", e);
117             } finally {
118                 hardenedLoggingEventInputStream = null;
119             }
120         }
121     }
122 
123     @Override
124     public String toString() {
125         return this.getClass().getName() + remoteSocketAddress.toString();
126     }
127 }