View Javadoc

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