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}