//# 0 errors, 175 messages
//#
/*
    //#DCCChat.java:1:1: class: com.dmdirc.addons.dcc.DCCChat
    //#DCCChat.java:1:1: method: com.dmdirc.addons.dcc.DCCChat.com.dmdirc.addons.dcc.DCCChat__static_init
 * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package com.dmdirc.addons.dcc;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

/**
 * This class handles a DCC Chat
 *
 * @author Shane 'Dataforce' McCormack
 */
public class DCCChat extends DCC {
	/** The handler for this DCCChat. */
	private DCCChatInterface handler = null;
	/** Used to send data out the socket. */
	private PrintWriter out;
	/** Used to read data from the socket. */
	private BufferedReader in;
	
	
	/**
	 * Creates a new instance of DCCChat.
	 */
	public DCCChat() {
		super();
    //#DCCChat.java:48: method: void com.dmdirc.addons.dcc.DCCChat.com.dmdirc.addons.dcc.DCCChat()
    //#input(void com.dmdirc.addons.dcc.DCCChat()): this
    //#output(void com.dmdirc.addons.dcc.DCCChat()): new Semaphore(DCC#1) num objects
    //#output(void com.dmdirc.addons.dcc.DCCChat()): new Semaphore(DCC#2) num objects
    //#output(void com.dmdirc.addons.dcc.DCCChat()): this.address
    //#output(void com.dmdirc.addons.dcc.DCCChat()): this.handler
    //#output(void com.dmdirc.addons.dcc.DCCChat()): this.listen
    //#output(void com.dmdirc.addons.dcc.DCCChat()): this.port
    //#output(void com.dmdirc.addons.dcc.DCCChat()): this.running
    //#output(void com.dmdirc.addons.dcc.DCCChat()): this.serverListeningSem
    //#output(void com.dmdirc.addons.dcc.DCCChat()): this.serverSocketSem
    //#new obj(void com.dmdirc.addons.dcc.DCCChat()): new Semaphore(DCC#1)
    //#new obj(void com.dmdirc.addons.dcc.DCCChat()): new Semaphore(DCC#2)
    //#post(void com.dmdirc.addons.dcc.DCCChat()): this.address == 0
    //#post(void com.dmdirc.addons.dcc.DCCChat()): this.listen == 0
    //#post(void com.dmdirc.addons.dcc.DCCChat()): this.port == 0
    //#post(void com.dmdirc.addons.dcc.DCCChat()): this.running == 0
    //#post(void com.dmdirc.addons.dcc.DCCChat()): this.handler == null
    //#post(void com.dmdirc.addons.dcc.DCCChat()): this.serverListeningSem == &new Semaphore(DCC#2)
    //#post(void com.dmdirc.addons.dcc.DCCChat()): this.serverSocketSem == &new Semaphore(DCC#1)
    //#post(void com.dmdirc.addons.dcc.DCCChat()): new Semaphore(DCC#1) num objects == 1
    //#post(void com.dmdirc.addons.dcc.DCCChat()): new Semaphore(DCC#2) num objects == 1
    //#unanalyzed(void com.dmdirc.addons.dcc.DCCChat()): Effects-of-calling:java.util.concurrent.Semaphore
	}
    //#DCCChat.java:49: end of method: void com.dmdirc.addons.dcc.DCCChat.com.dmdirc.addons.dcc.DCCChat()
	
	/**
	 * Change the handler for this DCC Chat.
	 *
	 * @param handler A class implementing DCCChatInterface
	 */
	public void setHandler(final DCCChatInterface handler) {
		this.handler = handler;
    //#DCCChat.java:57: method: void com.dmdirc.addons.dcc.DCCChat.setHandler(DCCChatInterface)
    //#input(void setHandler(DCCChatInterface)): handler
    //#input(void setHandler(DCCChatInterface)): this
    //#output(void setHandler(DCCChatInterface)): this.handler
    //#post(void setHandler(DCCChatInterface)): this.handler == handler
    //#post(void setHandler(DCCChatInterface)): init'ed(this.handler)
	}
    //#DCCChat.java:58: end of method: void com.dmdirc.addons.dcc.DCCChat.setHandler(DCCChatInterface)
	
	/**
	 * Called when the socket is first opened, before any data is handled.
	 */
	@Override
	protected void socketOpened() {
		try {
			out = new PrintWriter(socket.getOutputStream(), true);
    //#DCCChat.java:66: method: void com.dmdirc.addons.dcc.DCCChat.socketOpened()
    //#DCCChat.java:66: Warning: suspicious precondition
    //#    The precondition for this.handler.__Tag is not a contiguous range of values
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.addons.dcc.DCCChat
    //#    method: void socketOpened()
    //#    suspicious precondition index: [4]
    //#    Attribs:  Soft
    //#input(void socketOpened()): __Descendant_Table[com/dmdirc/addons/dcc/DCCChat]
    //#input(void socketOpened()): __Descendant_Table[others]
    //#input(void socketOpened()): __Dispatch_Table.socketClosed()V
    //#input(void socketOpened()): com/dmdirc/addons/dcc/DCCChatInterface.__Descendant_Table[com/dmdirc/addons/dcc/DCCChatInterface]
    //#input(void socketOpened()): com/dmdirc/addons/dcc/DCCChatInterface.__Descendant_Table[com/dmdirc/addons/dcc/DCCChatWindow]
    //#input(void socketOpened()): com/dmdirc/addons/dcc/DCCChatInterface.__Descendant_Table[others]
    //#input(void socketOpened()): com/dmdirc/addons/dcc/DCCChatInterface.__Dispatch_Table.socketClosed(Lcom/dmdirc/addons/dcc/DCCChat;)V
    //#input(void socketOpened()): com/dmdirc/addons/dcc/DCCChatInterface.__Dispatch_Table.socketOpened(Lcom/dmdirc/addons/dcc/DCCChat;)V
    //#input(void socketOpened()): com/dmdirc/addons/dcc/DCCChatWindow.__Dispatch_Table.socketClosed(Lcom/dmdirc/addons/dcc/DCCChat;)V
    //#input(void socketOpened()): com/dmdirc/addons/dcc/DCCChatWindow.__Dispatch_Table.socketOpened(Lcom/dmdirc/addons/dcc/DCCChat;)V
    //#input(void socketOpened()): this
    //#input(void socketOpened()): this.__Tag
    //#input(void socketOpened()): this.handler
    //#input(void socketOpened()): this.handler.__Tag
    //#input(void socketOpened()): this.socket
    //#output(void socketOpened()): new BufferedReader(socketOpened#2) num objects
    //#output(void socketOpened()): new PrintWriter(socketOpened#1) num objects
    //#output(void socketOpened()): this.in
    //#output(void socketOpened()): this.out
    //#new obj(void socketOpened()): new BufferedReader(socketOpened#2)
    //#new obj(void socketOpened()): new PrintWriter(socketOpened#1)
    //#pre[3] (void socketOpened()): init'ed(this.handler)
    //#pre[2] (void socketOpened()): (soft) this.__Tag == com/dmdirc/addons/dcc/DCCChat
    //#pre[4] (void socketOpened()): (soft) this.handler.__Tag in {com/dmdirc/addons/dcc/DCCChatInterface, com/dmdirc/addons/dcc/DCCChatWindow}
    //#pre[5] (void socketOpened()): (soft) this.socket != null
    //#post(void socketOpened()): this.in in Addr_Set{null,&new BufferedReader(socketOpened#2)}
    //#post(void socketOpened()): this.out in Addr_Set{null,&new PrintWriter(socketOpened#1)}
    //#post(void socketOpened()): new BufferedReader(socketOpened#2) num objects <= 1
    //#post(void socketOpened()): new PrintWriter(socketOpened#1) num objects <= 1
    //#unanalyzed(void socketOpened()): Effects-of-calling:socketClosed
    //#unanalyzed(void socketOpened()): Effects-of-calling:java.lang.StringBuffer
    //#unanalyzed(void socketOpened()): Effects-of-calling:com.dmdirc.logger.Logger:assertTrue
    //#unanalyzed(void socketOpened()): Effects-of-calling:getType
    //#unanalyzed(void socketOpened()): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(void socketOpened()): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(void socketOpened()): Effects-of-calling:com.dmdirc.util.MapList:containsKey
    //#unanalyzed(void socketOpened()): Effects-of-calling:com.dmdirc.util.MapList:get
    //#unanalyzed(void socketOpened()): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(void socketOpened()): Effects-of-calling:java.util.ArrayList:iterator
    //#unanalyzed(void socketOpened()): Effects-of-calling:trigger
    //#unanalyzed(void socketOpened()): Effects-of-calling:getArity
    //#unanalyzed(void socketOpened()): Effects-of-calling:com.dmdirc.interfaces.ActionListener:processEvent
    //#unanalyzed(void socketOpened()): Effects-of-calling:addLine
    //#unanalyzed(void socketOpened()): Effects-of-calling:setIcon
    //#test_vector(void socketOpened()): this.handler: Addr_Set{null}, Inverse{null}
			in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			if (handler != null) {
				handler.socketOpened(this);
    //#DCCChat.java:69: Warning: call too complex - analysis skipped
    //#    call on void socketOpened(DCCChat)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.addons.dcc.DCCChat
    //#    method: void socketOpened()
    //#    unanalyzed callee: void socketOpened(DCCChat)
			}
		} catch (IOException ioe) {
            socketClosed();
        }
	}
    //#DCCChat.java:74: end of method: void com.dmdirc.addons.dcc.DCCChat.socketOpened()
	
	/**
	 * Called when the socket is closed, before the thread terminates.
	 */
	@Override
	protected void socketClosed() {
		out = null;
    //#DCCChat.java:81: method: void com.dmdirc.addons.dcc.DCCChat.socketClosed()
    //#DCCChat.java:81: Warning: suspicious precondition
    //#    The precondition for this.handler.__Tag is not a contiguous range of values
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.addons.dcc.DCCChat
    //#    method: void socketClosed()
    //#    suspicious precondition index: [4]
    //#    Attribs:  Soft
    //#input(void socketClosed()): com/dmdirc/addons/dcc/DCCChatInterface.__Descendant_Table[com/dmdirc/addons/dcc/DCCChatInterface]
    //#input(void socketClosed()): com/dmdirc/addons/dcc/DCCChatInterface.__Descendant_Table[com/dmdirc/addons/dcc/DCCChatWindow]
    //#input(void socketClosed()): com/dmdirc/addons/dcc/DCCChatInterface.__Descendant_Table[others]
    //#input(void socketClosed()): com/dmdirc/addons/dcc/DCCChatInterface.__Dispatch_Table.socketClosed(Lcom/dmdirc/addons/dcc/DCCChat;)V
    //#input(void socketClosed()): com/dmdirc/addons/dcc/DCCChatWindow.__Dispatch_Table.socketClosed(Lcom/dmdirc/addons/dcc/DCCChat;)V
    //#input(void socketClosed()): this
    //#input(void socketClosed()): this.handler
    //#input(void socketClosed()): this.handler.__Tag
    //#output(void socketClosed()): this.in
    //#output(void socketClosed()): this.out
    //#pre[3] (void socketClosed()): init'ed(this.handler)
    //#pre[4] (void socketClosed()): (soft) this.handler.__Tag in {com/dmdirc/addons/dcc/DCCChatInterface, com/dmdirc/addons/dcc/DCCChatWindow}
    //#post(void socketClosed()): this.in == null
    //#post(void socketClosed()): this.out == null
    //#test_vector(void socketClosed()): this.handler: Addr_Set{null}, Inverse{null}
		in = null;
		if (handler != null) {
			handler.socketClosed(this);
    //#DCCChat.java:84: Warning: call too complex - analysis skipped
    //#    call on void socketClosed(DCCChat)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.addons.dcc.DCCChat
    //#    method: void socketClosed()
    //#    unanalyzed callee: void socketClosed(DCCChat)
		}
	}
    //#DCCChat.java:86: end of method: void com.dmdirc.addons.dcc.DCCChat.socketClosed()
	
	/**
	 * Handle the socket.
	 *
	 * @return false when socket is closed, true will cause the method to be
	 *         called again.
	 */
	@Override
	protected boolean handleSocket() {
		if (out == null || in == null) { return false; }
    //#DCCChat.java:96: method: bool com.dmdirc.addons.dcc.DCCChat.handleSocket()
    //#DCCChat.java:96: Warning: suspicious precondition
    //#    The precondition for this.handler.__Tag is not a contiguous range of values
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.addons.dcc.DCCChat
    //#    method: bool handleSocket()
    //#    suspicious precondition index: [7]
    //#    Attribs:  Soft
    //#input(bool handleSocket()): com/dmdirc/addons/dcc/DCCChatInterface.__Descendant_Table[com/dmdirc/addons/dcc/DCCChatInterface]
    //#input(bool handleSocket()): com/dmdirc/addons/dcc/DCCChatInterface.__Descendant_Table[com/dmdirc/addons/dcc/DCCChatWindow]
    //#input(bool handleSocket()): com/dmdirc/addons/dcc/DCCChatInterface.__Descendant_Table[others]
    //#input(bool handleSocket()): com/dmdirc/addons/dcc/DCCChatInterface.__Dispatch_Table.handleChatMessage(Lcom/dmdirc/addons/dcc/DCCChat;Ljava/lang/String;)V
    //#input(bool handleSocket()): com/dmdirc/addons/dcc/DCCChatWindow.__Dispatch_Table.handleChatMessage(Lcom/dmdirc/addons/dcc/DCCChat;Ljava/lang/String;)V
    //#input(bool handleSocket()): this
    //#input(bool handleSocket()): this.handler
    //#input(bool handleSocket()): this.handler.__Tag
    //#input(bool handleSocket()): this.in
    //#input(bool handleSocket()): this.out
    //#output(bool handleSocket()): return_value
    //#pre[10] (bool handleSocket()): init'ed(this.out)
    //#pre[6] (bool handleSocket()): (soft) init'ed(this.handler)
    //#pre[7] (bool handleSocket()): (soft) this.handler.__Tag in {com/dmdirc/addons/dcc/DCCChatInterface, com/dmdirc/addons/dcc/DCCChatWindow}
    //#pre[9] (bool handleSocket()): (soft) init'ed(this.in)
    //#post(bool handleSocket()): init'ed(return_value)
    //#test_vector(bool handleSocket()): this.handler: Addr_Set{null}, Inverse{null}
    //#test_vector(bool handleSocket()): this.in: Inverse{null}, Addr_Set{null}
    //#test_vector(bool handleSocket()): this.out: Addr_Set{null}, Inverse{null}
    //#test_vector(bool handleSocket()): java.io.BufferedReader:readLine(...)@99: Inverse{null}, Addr_Set{null}
		final String inLine;
		try {
			inLine = in.readLine();
			if (inLine == null) {
				return false;
			} else {
				if (handler != null) {
					handler.handleChatMessage(this, inLine);
    //#DCCChat.java:104: Warning: call too complex - analysis skipped
    //#    call on void handleChatMessage(DCCChat, String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.addons.dcc.DCCChat
    //#    method: bool handleSocket()
    //#    unanalyzed callee: void handleChatMessage(DCCChat, String)
				}
				return true;
			}
		} catch (IOException e) {
			return false;
    //#DCCChat.java:109: end of method: bool com.dmdirc.addons.dcc.DCCChat.handleSocket()
		}
	}
	
	/**
	 * Check if this socket can be written to.
	 */
	@Override
	public boolean isWriteable() {
		return out != null;
    //#DCCChat.java:118: method: bool com.dmdirc.addons.dcc.DCCChat.isWriteable()
    //#input(bool isWriteable()): this
    //#input(bool isWriteable()): this.out
    //#output(bool isWriteable()): return_value
    //#pre[2] (bool isWriteable()): init'ed(this.out)
    //#post(bool isWriteable()): init'ed(return_value)
    //#DCCChat.java:118: end of method: bool com.dmdirc.addons.dcc.DCCChat.isWriteable()
	}
	
	/**
	 * Send a line out the socket.
	 *
	 * @param line The line to be sent
	 */
	public void sendLine(final String line) {
		if (out != null) {
    //#DCCChat.java:127: method: void com.dmdirc.addons.dcc.DCCChat.sendLine(String)
    //#input(void sendLine(String)): line
    //#input(void sendLine(String)): this
    //#input(void sendLine(String)): this.out
    //#pre[3] (void sendLine(String)): init'ed(this.out)
    //#test_vector(void sendLine(String)): this.out: Addr_Set{null}, Inverse{null}
			out.printf("%s\r\n", line);
		}
	}
    //#DCCChat.java:130: end of method: void com.dmdirc.addons.dcc.DCCChat.sendLine(String)
}
    //#output(com.dmdirc.addons.dcc.DCCChat__static_init): __Descendant_Table[com/dmdirc/addons/dcc/DCCChat]
    //#output(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.close()V
    //#output(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.connect()V
    //#output(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.getHost()Ljava/lang/String;
    //#output(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.getPort()I
    //#output(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.handleSocket()Z
    //#output(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.isListenSocket()Z
    //#output(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.isWriteable()Z
    //#output(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.listen()V
    //#output(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.listen(II)V
    //#output(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.run()V
    //#output(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.sendLine(Ljava/lang/String;)V
    //#output(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.setAddress(JI)V
    //#output(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.setHandler(Lcom/dmdirc/addons/dcc/DCCChatInterface;)V
    //#output(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.socketClosed()V
    //#output(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.socketOpened()V
    //#output(com.dmdirc.addons.dcc.DCCChat__static_init): com/dmdirc/addons/dcc/DCC.__Descendant_Table[com/dmdirc/addons/dcc/DCCChat]
    //#post(com.dmdirc.addons.dcc.DCCChat__static_init): __Descendant_Table[com/dmdirc/addons/dcc/DCCChat] == &__Dispatch_Table
    //#post(com.dmdirc.addons.dcc.DCCChat__static_init): com/dmdirc/addons/dcc/DCC.__Descendant_Table[com/dmdirc/addons/dcc/DCCChat] == &__Dispatch_Table
    //#post(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.close()V == &com/dmdirc/addons/dcc/DCC.close
    //#post(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.connect()V == &com/dmdirc/addons/dcc/DCC.connect
    //#post(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.getHost()Ljava/lang/String; == &com/dmdirc/addons/dcc/DCC.getHost
    //#post(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.getPort()I == &com/dmdirc/addons/dcc/DCC.getPort
    //#post(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.handleSocket()Z == &handleSocket
    //#post(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.isListenSocket()Z == &com/dmdirc/addons/dcc/DCC.isListenSocket
    //#post(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.isWriteable()Z == &isWriteable
    //#post(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.listen()V == &com/dmdirc/addons/dcc/DCC.listen
    //#post(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.listen(II)V == &com/dmdirc/addons/dcc/DCC.listen
    //#post(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.run()V == &com/dmdirc/addons/dcc/DCC.run
    //#post(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.sendLine(Ljava/lang/String;)V == &sendLine
    //#post(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.setAddress(JI)V == &com/dmdirc/addons/dcc/DCC.setAddress
    //#post(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.setHandler(Lcom/dmdirc/addons/dcc/DCCChatInterface;)V == &setHandler
    //#post(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.socketClosed()V == &socketClosed
    //#post(com.dmdirc.addons.dcc.DCCChat__static_init): __Dispatch_Table.socketOpened()V == &socketOpened
    //#DCCChat.java:: end of method: com.dmdirc.addons.dcc.DCCChat.com.dmdirc.addons.dcc.DCCChat__static_init
    //#DCCChat.java:: end of class: com.dmdirc.addons.dcc.DCCChat
