
import java.awt.*;
import java.io.*;
import java.net.*;
import java.util.*;


public class NMultiJabberServer {

class ServeOneJabber extends Thread {
  private Socket socketIn;
  private Socket socketOut;
  /*private BufferedReader in;
  private ObjectOutput out;*/
  BufferedReader/*DataInputStream*/ in;
  DataOutputStream out;
  private In inThread;

  //--------------------------------------
  public class In extends Thread {
	public In() {
		try {
		/*	in =
			    new BufferedReader(
			       new InputStreamReader(
			         socketIn.getInputStream()));*/
			in = new BufferedReader(new InputStreamReader(
					new DataInputStream ( socketIn.getInputStream())));
		} catch (Exception e) {
			e.printStackTrace();
		}
		start();
	}
	public void run() {
	    try {
      	  	while (true) {
				System.out.println("before in.readln ");
    			String b;
    			b=in.readLine();
    			//String str=in.readByte/*Line*/();
      			System.out.println("after in.readln ");
      			/*StringTokenizer stringTokenizer=new StringTokenizer(str);
 				String firstToken=stringTokenizer.nextToken();*/
 				//String /*Object */objectBeingSent=str;
 				/*if (firstToken.equals("login")) {
					usersList.add(stringTokenizer.nextToken());
					objectBeingSent=usersList;
				} else if (firstToken.equals("logout")) {
     			  	usersList.remove(stringTokenizer.nextToken());
     			  	objectBeingSent=usersList;
           		}*/
				outMessage=b;//new String(b);//objectBeingSent;
				declareAll2(outMessage);
				//out.writeByte(b);
				//outThread.start();
				System.out.println("Echoing: " + b/*str*/);
      		}
    	} catch (IOException e) {
    	} finally {
    	  try {
    	    socketIn.close();
    	  } catch(IOException e) {}
    	}
  	}
   }
  //--------------------------------------
  public ServeOneJabber(Socket socketIn,Socket socketOut)
      throws IOException {
    this.socketIn = socketIn;
    this.socketOut = socketOut;
    /*out = new ObjectOutputStream(
							new BufferedOutputStream(
						        socketOut.getOutputStream()));*/
	out = new DataOutputStream(socketOut.getOutputStream());
    In inThread=new In();
    start();
  }
}
private void declareAll2(String/*Object*/ message) {
	try {
		for (int i=0;i<serversList.size();i++)
	  	    ((ServeOneJabber)serversList.get(i)).out.writeBytes/*sObject*/(message+"\n");
	} catch (Exception e) {
		e.printStackTrace();
  	}
}
///---------------------------------------------------------------------------
public class Out extends Thread {
	private void declareAll(String/*byte*/ message) {//String //Object message) {
		try {
			for (int i=0;i<serversList.size();i++)
		  	    ((ServeOneJabber)serversList.get(i)).out.writeBytes(message+"\n");//sObject(message+" \n");
		} catch (Exception e) {
			e.printStackTrace();
	  	}
  	}
	public void run() {
		declareAll(outMessage);
		stop();
	}
}
///---------------------------------------------------------------------------
  private ArrayList usersList=new ArrayList();
  private ArrayList serversList=new ArrayList();
  static final int IN_PORT = 8080;
  static final int OUT_PORT = 8081;
  private Out outThread = new Out();
  private /*byte*/String /*Object */outMessage;

  public static void main(String[] args)
      throws IOException {
	NMultiJabberServer multiJabberServer=new NMultiJabberServer();
    ServerSocket sOut = new ServerSocket(OUT_PORT);
    ServerSocket sIn = new ServerSocket(IN_PORT);
    System.out.println("Server Started");
    NMultiJabberServer.Out outThread=multiJabberServer.new Out();
    try {
      while(true) {
        System.out.println("before sIn.accept() ");
        Socket socketIn = sIn.accept();
        Socket socketOut = sOut.accept();
 		System.out.println("bind with client");
        try {
          multiJabberServer.serversList.add(multiJabberServer.new ServeOneJabber(socketIn,socketOut));
        } catch(IOException e) {
          socketIn.close();
          socketOut.close();
        }
      }
    } finally {
      sIn.close();
      sOut.close();
    }
  }
}