UnicastConnectionManager.java [plain text]
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;
private static Hashtable servers = new Hashtable();
static Hashtable clients = new Hashtable();
ArrayList connections;
private volatile Thread serverThread;
private ServerSocket ssock;
String serverName;
int serverPort;
static Thread scavenger;
Object serverobj;
private static RMISocketFactory defaultSocketFactory = RMISocketFactory.getSocketFactory();
private RMIServerSocketFactory serverFactory;
private RMIClientSocketFactory clientFactory;
private static int ncsock = 0; private static int nssock = 0; private static int ncmanager = 0; private static int nsmanager = 0;
private static final boolean debug = false;
private static final Object GLOBAL_LOCK = new Object();
static {
try {
localhost = InetAddress.getLocalHost().getHostAddress();
}
catch (UnknownHostException _) {
localhost = "localhost";
}
}
private static void startScavenger(){
scavenger = new Thread(new Runnable(){
public void run(){
if (debug) System.out.println("************* start scavenger.");
boolean liveon = true;
while (liveon){
try{
Thread.sleep(UnicastConnection.CONNECTION_TIMEOUT);
}catch(InterruptedException _ie){
break;
}
liveon = false;
Iterator iter = clients.values().iterator();
long l = System.currentTimeMillis();
try{
while(iter.hasNext()){
UnicastConnectionManager man = (UnicastConnectionManager)iter.next();
ArrayList conns = man.connections;
synchronized(conns) { 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; }
}
}
}catch(ConcurrentModificationException cme) {
liveon = true;
}
}
scavenger = null;
if (debug) System.out.println("************* exit scavenger.");
}
});
scavenger.setDaemon(true);
scavenger.start();
}
private UnicastConnectionManager(String host, int port, RMIClientSocketFactory csf) {
ssock = null;
serverName = host;
serverPort = port;
serverFactory = null;
clientFactory = csf;
connections = new ArrayList();
}
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;
}
public static synchronized UnicastConnectionManager getInstance(String host, int port, RMIClientSocketFactory csf) {
if (csf == null) {
csf = defaultSocketFactory;
}
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);
UnicastConnectionManager svrman = (UnicastConnectionManager)servers.get(key);
if(svrman != null){ man.serverobj = svrman.serverobj;
}
}
return (man);
}
public static synchronized UnicastConnectionManager getInstance(int port, RMIServerSocketFactory ssf) throws RemoteException {
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");
}
key.port = man.serverPort;
servers.put(key, man);
}
return (man);
}
public UnicastConnection getConnection() throws IOException {
if (ssock == null) {
return (getClientConnection());
}
else {
return (getServerConnection());
}
}
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");
}
return (conn);
}
private UnicastConnection getClientConnection() throws IOException {
ArrayList conns = connections;
UnicastConnection conn;
synchronized(conns) {
int nconn = conns.size() - 1;
if(nconn >= 0) {
conn = (UnicastConnection)conns.get(nconn);
conns.remove(nconn);
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);
}
public void discardConnection(UnicastConnection conn) {
if (ssock != null) conn.disconnect();
else {
UnicastConnection.resetTime(conn);
synchronized(GLOBAL_LOCK) {
connections.add(conn); if (scavenger == null)
startScavenger();
}
}
}
public void startServer() {
synchronized(this) {
if (ssock == null || serverThread != null) {
return;
}
serverThread = new Thread(this);
}
serverThread.start();
}
public void stopServer() {
synchronized(this) {
if(serverThread != null){
serverThread = null;
try{
ssock.close();
}catch(Exception _){}
}
}
}
public void run() {
for (;serverThread != null;) { try {
UnicastConnection conn = getServerConnection();
String remoteHost = null;
if (conn.sock != null) {
remoteHost = conn.sock.getInetAddress().getHostAddress();
}
(new RMIIncomingThread(conn, remoteHost)).start();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
void write(ObjectOutput out) throws IOException {
out.writeUTF(serverName);
out.writeInt(serverPort);
}
static UnicastConnectionManager read(ObjectInput in) throws IOException {
String host = in.readUTF();
int port = in.readInt();
return (getInstance(host, port, null));
}
}
class TripleKey {
String host;
int port;
Object other;
TripleKey(String host, int port, Object other) {
this.host = host;
this.port = port;
this.other = other;
}
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 )) {
return (true);
}
}
return (false);
}
}