import java.util.*;
import java.io.*;
import java.net.*; 

class BroadcastClientHandler extends Thread {

  protected Socket incoming; 
  protected int id; 
  protected BufferedReader in; 
  protected PrintWriter out;
 
  public BroadcastClientHandler(Socket incoming, int id) {
    this.incoming = incoming; 
    this.id = id; 
    try {
      if (incoming != null) {
        in = new BufferedReader(new InputStreamReader(incoming.getInputStream()));          
        out = new PrintWriter(new OutputStreamWriter(incoming.getOutputStream()));          
      }
    } catch (Exception e) {
      System.out.println("Error: " + e); 
    }
  }

  public synchronized void putMessage(String msg) {
    if (out != null) {
      out.println(msg); 
      out.flush();
    }
  }

  public void run() {
    System.out.println("Client handler " + id + " started."); 
    if (in != null && 
        out != null) {
      putMessage("Hello! This is Java BroadcastEchoServer. Enter BYE to exit.");       
      try {
        for (;;) {
          String str = in.readLine(); 
          if (str == null) {
            break; 
          } else {
            putMessage("Echo: " + str); 
            System.out.println("Received (" + id + "): " + str);

            if (str.trim().equals("BYE")) {
              break; 
            } else {
              Enumeration enum = BroadcastEchoServer.activeThreads.elements(); 
              while  (enum.hasMoreElements()) {
                BroadcastClientHandler t =      
                    (BroadcastClientHandler) enum.nextElement(); 
                if (t != this) {
                  t.putMessage("Broadcast(" + id + "): " + str); 
                }
              }
            }
          }
        }
        incoming.close(); 
        BroadcastEchoServer.activeThreads.removeElement(this); 
      } catch (IOException e) {} 
    }
    System.out.println("Client thread " + id + " stopped."); 
  }

}

public class BroadcastEchoServer {

  static protected Vector activeThreads; 

  public static void main(String[] args) {
    System.out.println("BroadcastEchoServer started."); 
    activeThreads = new Vector(); 
    int i = 1; 
    try {
      ServerSocket s = new ServerSocket(8010); 
      for (;;) {
        Socket incoming = s.accept(); 
        System.out.println("Spawning client thread " + i);
        BroadcastClientHandler newThread = 
          new BroadcastClientHandler(incoming, i); 
        activeThreads.addElement(newThread); 
        newThread.start(); 
        i++; 
      }
    } catch (Exception e) {
      System.out.println("Error: " + e); 
    }

    System.out.println("BroadcastEchoServer stopped."); 
  }
}