/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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 java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.rmi.RemoteException;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.rmi.server.RMISocketFactory;
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);
}

/**
 * Get the string representation, describing the connection.
 */
public String toString()
{
  return serverName+":"+serverPort+" ("+serverobj+")";
}

/**
 * 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);
}

  /**
   * Get the string representation, describing the connection.
   */
  public String toString()
  {
    return host+":"+port+" ("+other+")";
  }

}
