001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.log4j.chainsaw; 018 019import java.io.EOFException; 020import java.io.IOException; 021import java.io.ObjectInputStream; 022import java.net.ServerSocket; 023import java.net.Socket; 024import java.net.SocketException; 025import org.apache.log4j.Logger; 026import org.apache.log4j.spi.LoggingEvent; 027 028/** 029 * A daemon thread the processes connections from a 030 * <code>org.apache.log4j.net.SocketAppender.html</code>. 031 * 032 * @author <a href="mailto:oliver@puppycrawl.com">Oliver Burn</a> 033 */ 034class LoggingReceiver extends Thread { 035 /** used to log messages **/ 036 private static final Logger LOG = Logger.getLogger(LoggingReceiver.class); 037 038 /** 039 * Helper that actually processes a client connection. It receives events 040 * and adds them to the supplied model. 041 * 042 * @author <a href="mailto:oliver@puppycrawl.com">Oliver Burn</a> 043 */ 044 private class Slurper implements Runnable { 045 /** socket connection to read events from **/ 046 private final Socket mClient; 047 048 /** 049 * Creates a new <code>Slurper</code> instance. 050 * 051 * @param aClient socket to receive events from 052 */ 053 Slurper(Socket aClient) { 054 mClient = aClient; 055 } 056 057 /** loops getting the events **/ 058 public void run() { 059 LOG.debug("Starting to get data"); 060 try { 061 final ObjectInputStream ois = 062 new ObjectInputStream(mClient.getInputStream()); 063 while (true) { 064 final LoggingEvent event = (LoggingEvent) ois.readObject(); 065 mModel.addEvent(new EventDetails(event)); 066 } 067 } catch (EOFException e) { 068 LOG.info("Reached EOF, closing connection"); 069 } catch (SocketException e) { 070 LOG.info("Caught SocketException, closing connection"); 071 } catch (IOException e) { 072 LOG.warn("Got IOException, closing connection", e); 073 } catch (ClassNotFoundException e) { 074 LOG.warn("Got ClassNotFoundException, closing connection", e); 075 } 076 077 try { 078 mClient.close(); 079 } catch (IOException e) { 080 LOG.warn("Error closing connection", e); 081 } 082 } 083 } 084 085 /** where to put the events **/ 086 private MyTableModel mModel; 087 088 /** server for listening for connections **/ 089 private ServerSocket mSvrSock; 090 091 /** 092 * Creates a new <code>LoggingReceiver</code> instance. 093 * 094 * @param aModel model to place put received into 095 * @param aPort port to listen on 096 * @throws IOException if an error occurs 097 */ 098 LoggingReceiver(MyTableModel aModel, int aPort) throws IOException { 099 setDaemon(true); 100 mModel = aModel; 101 mSvrSock = new ServerSocket(aPort); 102 } 103 104 /** Listens for client connections **/ 105 public void run() { 106 LOG.info("Thread started"); 107 try { 108 while (true) { 109 LOG.debug("Waiting for a connection"); 110 final Socket client = mSvrSock.accept(); 111 LOG.debug("Got a connection from " + 112 client.getInetAddress().getHostName()); 113 final Thread t = new Thread(new Slurper(client)); 114 t.setDaemon(true); 115 t.start(); 116 } 117 } catch (IOException e) { 118 LOG.error("Error in accepting connections, stopping.", e); 119 } 120 } 121}