/* UnicastConnectionManager.java --
   Copyright (c) 1996, 1997, 1998, 1999, 2002, 2004
   Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.java.rmi.server;

import gnu.java.rmi.server.RMIIncomingThread;
import gnu.java.rmi.server.UnicastConnection;

import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectInput;
import java.net.InetAddress;
import java.net.Socket;
import java.net.ServerSocket;
import java.net.UnknownHostException;
import java.rmi.RemoteException;
import java.rmi.server.RMISocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.rmi.server.RMIClientSocketFactory;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.Hashtable;
import java.util.Iterator;

public class UnicastConnectionManager
	implements Runnable, ProtocolConstants {

private static String localhost;
// use different maps for server/client type UnicastConnectionManager
private static Hashtable servers = new Hashtable();
// Package-private to avoid trampolines.
static Hashtable clients = new Hashtable();
ArrayList connections; //client connection pool

// make serverThread volatile for poll
private volatile Thread serverThread;
private ServerSocket ssock;
String serverName;
int serverPort;

// Package-private to avoid a trampoline.
static Thread scavenger;

// If client and server are in the same VM, serverobj represents server
Object serverobj;

private static RMISocketFactory defaultSocketFactory = RMISocketFactory.getSocketFactory();
private RMIServerSocketFactory serverFactory;
private RMIClientSocketFactory clientFactory;

// The following is for debug
private static int ncsock = 0;    //count of client socket
private static int nssock = 0;    //count of server socket
private static int ncmanager = 0; //count of client manager
private static int nsmanager = 0; //count of server manager

private static final boolean debug = false;

private static final Object GLOBAL_LOCK = new Object();

static {
        try {
                //Use host address instead of host name to avoid name resolving issues
                //localhost = InetAddress.getLocalHost().getHostName();
                localhost = InetAddress.getLocalHost().getHostAddress();
        }
        catch (UnknownHostException _) {
                localhost = "localhost";
        }
        
        
}

//Only one scavenger thread running globally
private static void startScavenger(){
    scavenger = new Thread(new Runnable(){
        public void run(){
            if (debug) System.out.println("************* start scavenger.");
            boolean liveon = true;
            while (liveon){
                // Sleep for the expire timeout
                try{
                    Thread.sleep(UnicastConnection.CONNECTION_TIMEOUT);
                }catch(InterruptedException _ie){
                    break;
                }
                liveon = false;
                // Scavenge all clients' connections that're expired
                Iterator iter = clients.values().iterator();
                long l = System.currentTimeMillis();
                try{
                    while(iter.hasNext()){
                        UnicastConnectionManager man = (UnicastConnectionManager)iter.next();
                        ArrayList conns = man.connections;
                        synchronized(conns) { // is the lock a little coarser?
                            for (int last = conns.size() - 1;
                                 last >= 0;
                                 --last)
                            {
                                UnicastConnection conn = (UnicastConnection)conns.get(last);
                                if (UnicastConnection.isExpired(conn, l)){
                                    conns.remove(last);
                                    conn.disconnect();
                                    conn = null;   
                                }else
                                    liveon = true; //there're still live connections
                            }
                        }
                    }
                }catch(ConcurrentModificationException cme) {
                    // handle it lazily
                    liveon = true;
                }
            }
            scavenger = null;
            if (debug) System.out.println("************* exit scavenger.");
        }
    });
    // As it is used for client connection, we may put this thread
    // in daemon state to prevent the VM from blocking when exiting.
    scavenger.setDaemon(true);
    scavenger.start();
}

/**
  * Client UnicastConnectionManager constructor
  */
private UnicastConnectionManager(String host, int port, RMIClientSocketFactory csf) {
	ssock = null;
	serverName = host;
	serverPort = port;
	serverFactory = null;
	clientFactory = csf;
    connections = new ArrayList();
}

/**
  * Server UnicastConnectionManager constructor
  */
private UnicastConnectionManager(int port, RMIServerSocketFactory ssf) throws RemoteException {

	try {
		ssock = ssf.createServerSocket(port);
		serverPort = ssock.getLocalPort();
	}
	catch (IOException ioex) {
		ssock = null;
		serverPort = 0;
		throw new java.rmi.server.ExportException("can not create Server Socket on port " + port,ioex);
	}
	serverName = localhost;
	serverFactory = ssf;
	clientFactory = null;
}

/**
 * Return a client connection manager which will connect to the given
 * host/port.
 */
public static synchronized UnicastConnectionManager getInstance(String host, int port, RMIClientSocketFactory csf) {
//System.out.println("getInstance: " + host + "," + port + "," + csf);
	if (csf == null) {
        csf = defaultSocketFactory;
	}
	// change host name to host address to avoid name resolving issues
	try{
    	host = InetAddress.getByName(host).getHostAddress();
    }catch(Exception _){}
    
	TripleKey key = new TripleKey(host, port, csf);
	UnicastConnectionManager man = (UnicastConnectionManager)clients.get(key);
	if (man == null) {
		man = new UnicastConnectionManager(host, port, csf);
        if (debug) {
            ncmanager++;
            System.out.println("\n\n ====== " + ncmanager + " client managers.\n\n");
        }
		clients.put(key, man);
        
        // Detect if client and server are in the same VM, i.e., their keys are equal
        UnicastConnectionManager svrman = (UnicastConnectionManager)servers.get(key);
        if(svrman != null){ // server and client are in the same VM
            man.serverobj = svrman.serverobj;
        }
	}
	return (man);
}

/**
 * Return a server connection manager which will accept connection on the
 * given port.
 */
public static synchronized UnicastConnectionManager getInstance(int port, RMIServerSocketFactory ssf) throws RemoteException {
//System.out.println("getInstance: " + port + "," + ssf);
	if (ssf == null) {
        ssf = defaultSocketFactory;
	}
	TripleKey key = new TripleKey(localhost, port, ssf);
	UnicastConnectionManager man = (UnicastConnectionManager)servers.get(key);
	if (man == null) {
		man = new UnicastConnectionManager(port, ssf);
        if (debug) {
            nsmanager++;
            System.out.println("\n\n ****** " + nsmanager + " server managers.\n\n");
        }
		// The provided port might not be the set port.
		key.port = man.serverPort;
		servers.put(key, man);
	}
	return (man);
}

/**
 * Get a connection from this manager.
 */
public UnicastConnection getConnection() throws IOException {
	if (ssock == null) {
		return (getClientConnection());
	}
	else {
		return (getServerConnection());
	}
}

/**
 * Accept a connection to this server.
 */
private UnicastConnection getServerConnection() throws IOException {
	Socket sock = ssock.accept();
    sock.setTcpNoDelay(true); //??
	UnicastConnection conn = new UnicastConnection(this, sock);
	conn.acceptConnection();
    if (debug){
        nssock++;
        System.out.println("\n\n ****** " + nssock + " server socks.\n\n");
    }
    //System.out.println("Server connection " + sock);
	return (conn);
}

/**
 * Make a conection from this client to the server.
 */
private UnicastConnection getClientConnection() throws IOException {
    ArrayList conns = connections;
    UnicastConnection conn;
    
    synchronized(conns) {
        int nconn = conns.size() - 1;
    
        // if there're free connections in connection pool
        if(nconn >= 0) {
            conn = (UnicastConnection)conns.get(nconn);
            //Should we check if conn is alive using Ping??
            conns.remove(nconn);
            
            // Check if the connection is already expired
            long l = System.currentTimeMillis();
            if (!UnicastConnection.isExpired(conn, l)){
                return conn;
            }else {
                conn.disconnect();
                conn = null;   
            }
        }
    }
    
	Socket sock = clientFactory.createSocket(serverName, serverPort);
    conn = new UnicastConnection(this, sock);
	conn.makeConnection(DEFAULT_PROTOCOL);
    
    if (debug) {
        ncsock++;
        System.out.println("\n\n ====== " + ncsock + " client socks.\n\n");
    }

	return (conn);
}

/**
 * Discard a connection when we're done with it - maybe it can be
 * recycled.
 */
public void discardConnection(UnicastConnection conn) {
//System.out.println("Discarding connection " + conn);
    //conn.disconnect();
    if (ssock != null) //server connection
	conn.disconnect();
    else {
        // To client connection, we'd like to return back to pool
        UnicastConnection.resetTime(conn);
        //Ensure there're only one scavenger globally
        synchronized(GLOBAL_LOCK) {
            connections.add(conn); //borrow this lock to garantee thread safety 
            if (scavenger == null)
                startScavenger();
        }
    }
}

/**
 * Start a server on this manager if it's a server socket and we've not
 * already got one running.
 */
public void startServer() {
	synchronized(this) {
		if (ssock == null || serverThread != null) {
			return;
		}
		serverThread = new Thread(this);
        // The following is not necessary when java.lang.Thread's constructor do this.
        // serverThread.setContextClassLoader(Thread.currentThread().getContextClassLoader());
	}
	serverThread.start();
}

/**
 * Stop a server on this manager
 */
public void stopServer() {
    synchronized(this) {
    	if(serverThread != null){
    	    serverThread = null;
    	    try{
    	        ssock.close();
    	    }catch(Exception _){}
    	}
    }
}

/**
 * Server thread for connection manager.
 */
public void run() {
	for (;serverThread != null;) { // if serverThread==null, then exit thread
		try {
//System.out.println("Waiting for connection on " + serverPort);
			UnicastConnection conn = getServerConnection();

			// get address of remote host for the RMIIncomingThread object
			String remoteHost = null;
			if (conn.sock != null) {
				remoteHost = conn.sock.getInetAddress().getHostAddress();			
			}

			// use a thread pool to improve performance
            //ConnectionRunnerPool.dispatchConnection(conn);
            (new RMIIncomingThread(conn, remoteHost)).start();
//	   (new Thread(conn)).start();
		}
		catch (Exception e) {
            e.printStackTrace();
		}
	}
}

/**
 * Serialization routine.
 */
void write(ObjectOutput out) throws IOException {
        out.writeUTF(serverName);
        out.writeInt(serverPort);
}

/**
 * Serialization routine.
 */
static UnicastConnectionManager read(ObjectInput in) throws IOException {
        String host = in.readUTF();
        int port = in.readInt();
        //RMIClientSocketFactory csf = ((RMIObjectInputStream)in).manager.clientFactory;
        //return (getInstance(host, port, csf));
        return (getInstance(host, port, null));
}

}

/**
 * This is use as the hashkey for the client/server connections.
 */
class TripleKey {

String host;
int port;
Object other;

TripleKey(String host, int port, Object other) {
	this.host = host;
	this.port = port;
	this.other = other;
}

/**
 * Hash code just include the host and other - we ignore the port since
 * this has unusual matching behaviour.
 */
public int hashCode() {
	return (host.hashCode() ^ other.hashCode());
}

public boolean equals(Object obj) {
	if (obj instanceof TripleKey) {
		TripleKey other = (TripleKey)obj;
		if (this.host.equals(other.host) &&
		    this.other == other.other &&
            (this.port == other.port /* || this.port == 0 || other.port == 0*/)) {
			return (true);
		}
	}
	return (false);
}

}
