Classes | Public Member Functions | Private Member Functions | Static Private Member Functions | Private Attributes

ChatClient Class Reference

Threaded chat client. More...

Collaboration diagram for ChatClient:
Collaboration graph
[legend]

List of all members.

Classes

interface  Context
 Provides message presentation context to instance of ChatClient. More...

Public Member Functions

 ChatClient (String host, int port, Context context)
 Creates new instance of ChatClient that posts messages to specified Context.
void start ()
 Starts the thread.
void send (String message)
 Sends message (appended with new-line) to chat server.
void send (String message, String userId)
 Sends message (appended with new-line) to chat server prefixed with userID.
void close ()
 Closes the connection gracefully.
void run ()
 Connects socket, then reads messages from server while running flag is enabled.

Private Member Functions

void reportError (String str)
 Reports an error message to log.
void reportInfo (String str)
 Reports an info message to log.

Static Private Member Functions

static String EscapeHTML (String str)
 Escapes HTML reserved characters (as we are logging HTML tagged messages)
static String now ()
 Gets current time stamp.

Private Attributes

String host
 Host name or IP address of the remote chat server.
int port
 TCP port where to connect to on remote chat server.
PrintWriter out
 Output stream to remote server.
Socket socket
 Instance of the TCP socket to chat server.
volatile boolean running
 Indicates if thread is (or should be) running.
Context context
 Event (call-back) context for the instance.

Detailed Description

Threaded chat client.

Author:
Mikica B Kocic

Definition at line 17 of file ChatClient.java.


Constructor & Destructor Documentation

ChatClient.ChatClient ( String  host,
int  port,
Context  context 
)

Creates new instance of ChatClient that posts messages to specified Context.

Parameters:
hosthost name or ip address of the chat server
porttcp port
contextwhere to log messages (also error and info messages)

Definition at line 81 of file ChatClient.java.

References context, host, out, port, running, and socket.

    {
        assert( context != null );

        this.socket   = null;
        this.host     = host;
        this.port     = port;
        this.context  = context;
        this.out      = null;   
        this.running  = false;
    }

Member Function Documentation

void ChatClient.close (  )

Closes the connection gracefully.

Definition at line 139 of file ChatClient.java.

References running, and socket.

Referenced by ChatClientFrame.parseInputMessage().

    {
        synchronized( this )
        {
            running = false;

            if ( socket != null && ! socket.isClosed () ) {
                try {
                    socket.close ();
                } catch( IOException e ) {
                    /* ignore */
                }
            }
        }
    }
static String ChatClient.EscapeHTML ( String  str ) [static, private]

Escapes HTML reserved characters (as we are logging HTML tagged messages)

Definition at line 158 of file ChatClient.java.

Referenced by reportError(), reportInfo(), and run().

    {
        return str.replaceAll( "&",  "&"  ) 
                  .replaceAll( "<",  "&lt;"   )
                  .replaceAll( ">",  "&gt;"   ) 
                  .replaceAll( "\"", "&quot;" );
    }
static String ChatClient.now (  ) [static, private]

Gets current time stamp.

Returns:
time in ISO format

Definition at line 197 of file ChatClient.java.

Referenced by reportError(), reportInfo(), and run().

    {
        Calendar cal = Calendar.getInstance ();
        SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
        return sdf.format( cal.getTime() );
    }
void ChatClient.reportError ( String  str ) [private]

Reports an error message to log.

Definition at line 169 of file ChatClient.java.

References context, EscapeHTML(), ChatClient.Context.logMessage(), and now().

Referenced by run().

    {
        context.logMessage(
            "<code>" + now () 
                     + "&nbsp;&nbsp;<span style='color:red'>" 
                     + EscapeHTML( str ) 
                     + "</span></code><br/>"
            );
    }
void ChatClient.reportInfo ( String  str ) [private]

Reports an info message to log.

Definition at line 182 of file ChatClient.java.

References context, EscapeHTML(), ChatClient.Context.logMessage(), and now().

Referenced by run().

    {
        context.logMessage(
            "<code>" + now () 
                     + "&nbsp;&nbsp;<span style='color:green'>"
                     + EscapeHTML( str )
                     + "</span></code><br/>"
            );
    }
void ChatClient.run (  )

Connects socket, then reads messages from server while running flag is enabled.

Finally, closes connection in graceful manner.

Definition at line 209 of file ChatClient.java.

References context, EscapeHTML(), host, ChatClient.Context.logMessage(), ChatClient.Context.logStatus(), now(), out, port, reportError(), reportInfo(), running, and socket.

    {
        reportInfo( "Connecting to " + host + ":" + port + "..." );
        context.logStatus( "Connecting to " + host + ":" + port + "..." );

        //////////////////////////////////////////////////////////////////////////////////
        /* Open connection
         */
        try
        {
            synchronized( this ) {
                socket = new Socket( host, port );
            }
        }
        catch( UnknownHostException e )
        {
            reportError( "'Unknown host' exception while creating socket" );
            reportError( e.toString () );
            running = false;
        }
        catch( IOException e )
        {
            reportError( "I/O exception while connecting" );
            reportError( e.toString () );
            running = false;
        }

        //////////////////////////////////////////////////////////////////////////////////
        /* Get input stream. Consider input characters UTF-8 encoded.
         * TODO: It would be nice to have this as a parameter.
         */
        InputStreamReader reader = null;
        try
        {
            if ( socket != null ) {
                reader = new InputStreamReader( socket.getInputStream (), "utf-8" );
            }
        }
        catch( IOException e )
        {
            reportError( "I/O exception while getting input stream" );
            reportError( e.toString () );
            running = false;
            reader = null;
        }
        
        //////////////////////////////////////////////////////////////////////////////////
        /* Get output stream. Encode our character strings as UTF-8.
         */
        try 
        {
            if ( socket != null ) {
                out = new PrintWriter(
                        new OutputStreamWriter( socket.getOutputStream(), "utf-8" ),
                        /*autoflush*/ true );
            }
        }
        catch( IOException e )
        {
            reportError( "I/O exception while getting output stream" );
            reportError( e.toString () );
            running = false;
            out = null;
        }

        //////////////////////////////////////////////////////////////////////////////////
        /* Finally connected... (if running == true survived until here)
         */
        BufferedReader in = null;
        if ( running ) {
            context.logStatus( "Connected to " + host + ":" + port );
            reportInfo( "Connected; type a message, then press Enter or click 'Send'" );
            reportInfo( "All your messages will be prefixed with your ID..." );
            in = new BufferedReader( reader );
        }
        
        //////////////////////////////////////////////////////////////////////////////////
        /* Read messages from the socket and dump them on log area
         */
        while( running )
        {
            try
            {
                String message = in.readLine ();

                /* Parse input with syntax: [ [ <userId> ] ":: " ] <message>
                 * where default userId is [Anonymous].
                 */
                String[] parts = message.split( ":: ", 2 );
                String userId = "[Anonymous]";
                
                if ( message.startsWith( "WWHHOO: " ) ) {
                    userId = "WWHHOO";
                    message = message.substring( 8 );
                } else if ( parts.length == 0 ) {
                    message = parts[0];
                } else if ( parts[0].trim().length () == 0 && parts.length >= 2 ) {
                    message = parts[1];
                } else if ( parts.length >= 2 ) {
                    userId  = parts[0].trim ();
                    message = parts[1];
                } else {
                    message = parts[0];
                }

                context.logMessage(
                    "<code>" + now () 
                             + "&nbsp;&nbsp;" 
                             + EscapeHTML( userId ).trim () 
                             + ": <span style='"
                             + ( userId.equals( "Eliza" ) ? "color:red" : "color:blue" )
                             + "'>"
                             + EscapeHTML( message ).trim ()
                             + "</span></code><br/>"
                    );
            }
            catch( IOException e )
            {
                reportError( "Connection lost!" );
                reportError( e.toString () );
                running = false;
            }
        }

        reportInfo( "Closing connection " + host + ":" + port + "..." );

        //////////////////////////////////////////////////////////////////////////////////
        /* Close connection gracefully
         */
        try
        {
            if ( out != null ) {
                out.close ();
            }
            if ( in != null ) {
                in.close ();
            }
            synchronized( this )
            {
                if ( socket != null && ! socket.isClosed () ) {
                    socket.close ();
                }
            }
        }
        catch( IOException e )
        {
            reportError( "I/O exception while closing connection" );
            reportError( e.toString () );
        }
        
        reportInfo( "Thread " + host + ":" + port + " completed." );
    }
void ChatClient.send ( String  message )

Sends message (appended with new-line) to chat server.

Parameters:
messagemessage to be sent

Definition at line 112 of file ChatClient.java.

References out.

Referenced by ChatClientFrame.parseInputMessage(), and send().

    {
        synchronized( this )
        {
            if ( out == null || message == null ) {
                return;
            }
            
            out.println( message );
            out.flush ();
        }
    }
void ChatClient.send ( String  message,
String  userId 
)

Sends message (appended with new-line) to chat server prefixed with userID.

Parameters:
messagemessage to be sent
userIduser identifier

Definition at line 131 of file ChatClient.java.

References send().

    {
        send( userId + " :: " + message );
    }
void ChatClient.start (  )

Starts the thread.

Definition at line 97 of file ChatClient.java.

References running.

Referenced by ChatClientFrame.actionPerformed(), ChatClientFrame.ChatClientFrame(), and ChatClientFrame.parseInputMessage().

    {
        if ( isAlive () || running ) {
            return;  // Allow only one thread per instance
        }

        running = true;
        super.start ();
    }

Member Data Documentation

Event (call-back) context for the instance.

Definition at line 69 of file ChatClient.java.

Referenced by ChatClient(), reportError(), reportInfo(), and run().

String ChatClient.host [private]

Host name or IP address of the remote chat server.

Definition at line 44 of file ChatClient.java.

Referenced by ChatClient(), and run().

PrintWriter ChatClient.out [private]

Output stream to remote server.

Definition at line 54 of file ChatClient.java.

Referenced by ChatClient(), run(), and send().

int ChatClient.port [private]

TCP port where to connect to on remote chat server.

Definition at line 49 of file ChatClient.java.

Referenced by ChatClient(), and run().

volatile boolean ChatClient.running [private]

Indicates if thread is (or should be) running.

Definition at line 64 of file ChatClient.java.

Referenced by ChatClient(), close(), run(), and start().

Socket ChatClient.socket [private]

Instance of the TCP socket to chat server.

Definition at line 59 of file ChatClient.java.

Referenced by ChatClient(), close(), and run().


The documentation for this class was generated from the following file: