View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2011, 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.io.ObjectInputStream;
19  import java.net.Socket;
20  import java.net.SocketAddress;
21  
22  import ch.qos.logback.classic.Logger;
23  
24  import ch.qos.logback.classic.LoggerContext;
25  import ch.qos.logback.classic.spi.ILoggingEvent;
26  
27  // Contributors: Moses Hohman <mmhohman@rainbow.uchicago.edu>
28  
29  /**
30   * Read {@link ILoggingEvent} objects sent from a remote client using Sockets
31   * (TCP). These logging events are logged according to local policy, as if they
32   * were generated locally.
33   * 
34   * <p>
35   * For example, the socket node might decide to log events to a local file and
36   * also resent them to a second socket node.
37   * 
38   * @author Ceki G&uuml;lc&uuml;
39   * @author S&eacute;bastien Pennec
40   * 
41   * @since 0.8.4
42   */
43  public class SocketNode implements Runnable {
44  
45    Socket socket;
46    LoggerContext context;
47    ObjectInputStream ois;
48    SocketAddress remoteSocketAddress;
49    
50    Logger logger;
51    boolean closed = false;
52    SimpleSocketServer socketServer;
53    
54    public SocketNode(SimpleSocketServer socketServer, Socket socket, LoggerContext context) {
55      this.socketServer = socketServer;
56      this.socket = socket;
57      remoteSocketAddress = socket.getRemoteSocketAddress();
58      this.context = context;
59      logger = context.getLogger(SocketNode.class);
60  
61      try {
62        ois = new ObjectInputStream(new BufferedInputStream(socket
63            .getInputStream()));
64      } catch (Exception e) {
65        logger.error("Could not open ObjectInputStream to " + socket, e);
66      }
67    }
68  
69    // public
70    // void finalize() {
71    // System.err.println("-------------------------Finalize called");
72    // System.err.flush();
73    // }
74  
75    public void run() {
76      ILoggingEvent event;
77      Logger remoteLogger;
78  
79      try {
80        while (!closed) {
81          // read an event from the wire
82          event = (ILoggingEvent) ois.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 (ois != null) {
113       try {
114         ois.close();
115       } catch (IOException e) {
116         logger.warn("Could not close connection.", e);
117       } finally {
118         ois = null;
119       }
120     }
121   }
122   
123   @Override
124   public String toString() {
125     return this.getClass().getName()+remoteSocketAddress.toString();
126   }
127 }