/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _LOG4CXX_NET_TELNET_APPENDER_H
#define _LOG4CXX_NET_TELNET_APPENDER_H

#if defined(_MSC_VER)
#pragma warning ( push )
#pragma warning ( disable: 4231 4251 4275 4786 )
#endif



#include <log4cxx/appenderskeleton.h>
#include <log4cxx/helpers/socket.h>
#include <log4cxx/helpers/serversocket.h>
#include <log4cxx/helpers/thread.h>
#include <vector>
#include <log4cxx/helpers/charsetencoder.h>

namespace log4cxx
{
        namespace helpers {
             class ByteBuffer;
        }
        namespace net
        {
            typedef log4cxx::helpers::SocketPtr Connection;
            LOG4CXX_LIST_DEF(ConnectionList, Connection);

/**
<p>The TelnetAppender is a log4cxx appender that specializes in
writing to a read-only socket.  The output is provided in a
telnet-friendly way so that a log can be monitored over TCP/IP.
Clients using telnet connect to the socket and receive log data.
This is handy for remote monitoring, especially when monitoring a
servlet.

<p>Here is a list of the available configuration options:

<table border=1>
<tr>
<td align=center><b>Name</b></td>
<td align=center><b>Requirement</b></td>
<td align=center><b>Description</b></td>
<td align=center><b>Sample Value</b></td>
</tr>

<tr>
<td>Port</td>
<td>optional</td>
<td>This parameter determines the port to use for announcing log events.  The default port is 23 (telnet).</td>
<td>5875</td>
</table>
*/
        class LOG4CXX_EXPORT TelnetAppender : public AppenderSkeleton
                {
                class SocketHandler;
                friend class SocketHandler;
                private:
                        static const int DEFAULT_PORT;
                        static const int MAX_CONNECTIONS;
                        int port;

                public:
                        DECLARE_LOG4CXX_OBJECT(TelnetAppender)
                        BEGIN_LOG4CXX_CAST_MAP()
                                LOG4CXX_CAST_ENTRY(TelnetAppender)
                                LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
                        END_LOG4CXX_CAST_MAP()

                        TelnetAppender();
                        ~TelnetAppender();

                        /**
                        This appender requires a layout to format the text to the
                        attached client(s). */
                        virtual bool requiresLayout() const
                                { return true; }
                                
                        LogString getEncoding() const;
                        void setEncoding(const LogString& value);
        

                        /** all of the options have been set, create the socket handler and
                        wait for connections. */
                        void activateOptions(log4cxx::helpers::Pool& p);

                                                /**
                                                Set options
                                                */
                        virtual void setOption(const LogString& option, const LogString& value);

                                                /**
                                                Returns value of the <b>Port</b> option.
                                                */
                        int getPort() const
                                { return port; }

                                                /**
                                                The <b>Port</b> option takes a positive integer representing
                                                the port where the server is waiting for connections.
                                                */
                        void setPort(int port1)
                        { this->port = port1; }


                        /** shuts down the appender. */
                        void close();

                protected:
                        /** Handles a log event.  For this appender, that means writing the
                        message to each connected client.  */
                        virtual void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p) ;

                        //---------------------------------------------------------- SocketHandler:

                private:
                        //   prevent copy and assignment statements
                        TelnetAppender(const TelnetAppender&);
                        TelnetAppender& operator=(const TelnetAppender&);

                        void write(log4cxx::helpers::ByteBuffer&);
                        void writeStatus(const log4cxx::helpers::SocketPtr& socket, const LogString& msg, log4cxx::helpers::Pool& p);
                        ConnectionList connections;
                        LogString encoding;
                        log4cxx::helpers::CharsetEncoderPtr encoder;
                        helpers::ServerSocket* serverSocket;
                        helpers::Thread sh;
                        size_t activeConnections;
                        static void* LOG4CXX_THREAD_FUNC acceptConnections(apr_thread_t* thread, void* data);
                }; // class TelnetAppender
                
                LOG4CXX_PTR_DEF(TelnetAppender);
    } // namespace net
} // namespace log4cxx


#if defined(_MSC_VER)
#pragma warning ( pop )
#endif

#endif // _LOG4CXX_NET_TELNET_APPENDER_H

