1: 
  38: 
  39: 
  40: package ;
  41: 
  42: import ;
  43: import ;
  44: import ;
  45: import ;
  46: import ;
  47: import ;
  48: import ;
  49: import ;
  50: import ;
  51: import ;
  52: import ;
  53: import ;
  54: import ;
  55: import ;
  56: import ;
  57: 
  58: public class UnicastConnectionManager
  59:         implements Runnable, ProtocolConstants {
  60: 
  61: private static String localhost;
  62: 
  63: private static Hashtable servers = new Hashtable();
  64: 
  65: static Hashtable clients = new Hashtable();
  66: ArrayList connections; 
  67: 
  68: 
  69: private volatile Thread serverThread;
  70: private ServerSocket ssock;
  71: String serverName;
  72: int serverPort;
  73: 
  74: 
  75: static Thread scavenger;
  76: 
  77: 
  78: Object serverobj;
  79: 
  80: private static RMISocketFactory defaultSocketFactory = RMISocketFactory.getSocketFactory();
  81: private RMIServerSocketFactory serverFactory;
  82: private RMIClientSocketFactory clientFactory;
  83: 
  84: 
  85: private static int ncsock = 0;    
  86: private static int nssock = 0;    
  87: private static int ncmanager = 0; 
  88: private static int nsmanager = 0; 
  89: 
  90: private static final boolean debug = false;
  91: 
  92: private static final Object GLOBAL_LOCK = new Object();
  93: 
  94: static {
  95:         try {
  96:                 
  97:                 
  98:                 localhost = InetAddress.getLocalHost().getHostAddress();
  99:         }
 100:         catch (UnknownHostException _) {
 101:                 localhost = "localhost";
 102:         }
 103: 
 104: 
 105: }
 106: 
 107: 
 108: private static void startScavenger(){
 109:     scavenger = new Thread(new Runnable(){
 110:         public void run(){
 111:             if (debug) System.out.println("************* start scavenger.");
 112:             boolean liveon = true;
 113:             while (liveon){
 114:                 
 115:                 try{
 116:                     Thread.sleep(UnicastConnection.CONNECTION_TIMEOUT);
 117:                 }catch(InterruptedException _ie){
 118:                     break;
 119:                 }
 120:                 liveon = false;
 121:                 
 122:                 Iterator iter = clients.values().iterator();
 123:                 long l = System.currentTimeMillis();
 124:                 try{
 125:                     while(iter.hasNext()){
 126:                         UnicastConnectionManager man = (UnicastConnectionManager)iter.next();
 127:                         ArrayList conns = man.connections;
 128:                         synchronized(conns) { 
 129:                             for (int last = conns.size() - 1;
 130:                                  last >= 0;
 131:                                  --last)
 132:                             {
 133:                                 UnicastConnection conn = (UnicastConnection)conns.get(last);
 134:                                 if (UnicastConnection.isExpired(conn, l)){
 135:                                     conns.remove(last);
 136:                                     conn.disconnect();
 137:                                     conn = null;
 138:                                 }else
 139:                                     liveon = true; 
 140:                             }
 141:                         }
 142:                     }
 143:                 }catch(ConcurrentModificationException cme) {
 144:                     
 145:                     liveon = true;
 146:                 }
 147:             }
 148:             scavenger = null;
 149:             if (debug) System.out.println("************* exit scavenger.");
 150:         }
 151:     });
 152:     
 153:     
 154:     scavenger.setDaemon(true);
 155:     scavenger.start();
 156: }
 157: 
 158: 
 161: private UnicastConnectionManager(String host, int port, RMIClientSocketFactory csf) {
 162:         ssock = null;
 163:         serverName = host;
 164:         serverPort = port;
 165:         serverFactory = null;
 166:         clientFactory = csf;
 167:     connections = new ArrayList();
 168: }
 169: 
 170: 
 173: private UnicastConnectionManager(int port, RMIServerSocketFactory ssf) throws RemoteException {
 174: 
 175:         try {
 176:                 ssock = ssf.createServerSocket(port);
 177:                 serverPort = ssock.getLocalPort();
 178:         }
 179:         catch (IOException ioex) {
 180:                 ssock = null;
 181:                 serverPort = 0;
 182:                 throw new java.rmi.server.ExportException("can not create Server Socket on port " + port,ioex);
 183:         }
 184:         
 185:         
 186:         
 187:         
 188:         
 189:         
 190:         serverName = "localhost";
 191:         serverFactory = ssf;
 192:         clientFactory = null;
 193: }
 194: 
 195: 
 199: public static synchronized UnicastConnectionManager getInstance(String host, int port, RMIClientSocketFactory csf) {
 200: 
 201:         if (csf == null) {
 202:         csf = defaultSocketFactory;
 203:         }
 204:         
 205:         try{
 206:         host = InetAddress.getByName(host).getHostAddress();
 207:     }catch(Exception _){}
 208: 
 209:         TripleKey key = new TripleKey(host, port, csf);
 210:         UnicastConnectionManager man = (UnicastConnectionManager)clients.get(key);
 211:         if (man == null) {
 212:                 man = new UnicastConnectionManager(host, port, csf);
 213:         if (debug) {
 214:             ncmanager++;
 215:             System.out.println("\n\n ====== " + ncmanager + " client managers.\n\n");
 216:         }
 217:                 clients.put(key, man);
 218: 
 219:         
 220:         UnicastConnectionManager svrman = (UnicastConnectionManager)servers.get(key);
 221:         if(svrman != null){ 
 222:             man.serverobj = svrman.serverobj;
 223:         }
 224:         }
 225:         return (man);
 226: }
 227: 
 228: 
 232: public static synchronized UnicastConnectionManager getInstance(int port, RMIServerSocketFactory ssf) throws RemoteException {
 233: 
 234:         if (ssf == null) {
 235:         ssf = defaultSocketFactory;
 236:         }
 237:         TripleKey key = new TripleKey(localhost, port, ssf);
 238:         UnicastConnectionManager man = (UnicastConnectionManager)servers.get(key);
 239:         if (man == null) {
 240:                 man = new UnicastConnectionManager(port, ssf);
 241:         if (debug) {
 242:             nsmanager++;
 243:             System.out.println("\n\n ****** " + nsmanager + " server managers.\n\n");
 244:         }
 245:                 
 246:                 key.port = man.serverPort;
 247:                 servers.put(key, man);
 248:         }
 249:         return (man);
 250: }
 251: 
 252: 
 255: public UnicastConnection getConnection() throws IOException {
 256:         if (ssock == null) {
 257:                 return (getClientConnection());
 258:         }
 259:         else {
 260:                 return (getServerConnection());
 261:         }
 262: }
 263: 
 264: 
 267: private UnicastConnection getServerConnection() throws IOException {
 268:         Socket sock = ssock.accept();
 269:     sock.setTcpNoDelay(true); 
 270:         UnicastConnection conn = new UnicastConnection(this, sock);
 271:         conn.acceptConnection();
 272:     if (debug){
 273:         nssock++;
 274:         System.out.println("\n\n ****** " + nssock + " server socks.\n\n");
 275:     }
 276:     
 277:         return (conn);
 278: }
 279: 
 280: 
 283: private UnicastConnection getClientConnection() throws IOException {
 284:     ArrayList conns = connections;
 285:     UnicastConnection conn;
 286: 
 287:     synchronized(conns) {
 288:         int nconn = conns.size() - 1;
 289: 
 290:         
 291:         if(nconn >= 0) {
 292:             conn = (UnicastConnection)conns.get(nconn);
 293:             
 294:             conns.remove(nconn);
 295: 
 296:             
 297:             long l = System.currentTimeMillis();
 298:             if (!UnicastConnection.isExpired(conn, l)){
 299:                 return conn;
 300:             }else {
 301:                 conn.disconnect();
 302:                 conn = null;
 303:             }
 304:         }
 305:     }
 306: 
 307:         Socket sock = clientFactory.createSocket(serverName, serverPort);
 308:     conn = new UnicastConnection(this, sock);
 309:         conn.makeConnection(DEFAULT_PROTOCOL);
 310: 
 311:     if (debug) {
 312:         ncsock++;
 313:         System.out.println("\n\n ====== " + ncsock + " client socks.\n\n");
 314:     }
 315: 
 316:         return (conn);
 317: }
 318: 
 319: 
 322: public String toString()
 323: {
 324:   return serverName+":"+serverPort+" ("+serverobj+")";
 325: }
 326: 
 327: 
 331: public void discardConnection(UnicastConnection conn) {
 332: 
 333:     
 334:     if (ssock != null) 
 335:         conn.disconnect();
 336:     else {
 337:         
 338:         UnicastConnection.resetTime(conn);
 339:         
 340:         synchronized(GLOBAL_LOCK) {
 341:             connections.add(conn); 
 342:             if (scavenger == null)
 343:                 startScavenger();
 344:         }
 345:     }
 346: }
 347: 
 348: 
 352: public void startServer() {
 353:         synchronized(this) {
 354:                 if (ssock == null || serverThread != null) {
 355:                         return;
 356:                 }
 357:                 serverThread = new Thread(this);
 358:         
 359:         
 360:         }
 361:         serverThread.start();
 362: }
 363: 
 364: 
 367: public void stopServer() {
 368:     synchronized(this) {
 369:         if(serverThread != null){
 370:             serverThread = null;
 371:             try{
 372:                 ssock.close();
 373:             }catch(Exception _){}
 374:         }
 375:     }
 376: }
 377: 
 378: 
 381: public void run() {
 382:         for (;serverThread != null;) { 
 383:                 try {
 384: 
 385:                         UnicastConnection conn = getServerConnection();
 386: 
 387:                         
 388:                         String remoteHost = null;
 389:                         if (conn.sock != null) {
 390:                                 remoteHost = conn.sock.getInetAddress().getHostAddress();
 391:                         }
 392: 
 393:                         
 394:             
 395:             (new RMIIncomingThread(conn, remoteHost)).start();
 396: 
 397:                 }
 398:                 catch (Exception e) {
 399:             e.printStackTrace();
 400:                 }
 401:         }
 402: }
 403: 
 404: 
 407: void write(ObjectOutput out) throws IOException {
 408:         out.writeUTF(serverName);
 409:         out.writeInt(serverPort);
 410: }
 411: 
 412: 
 415: static UnicastConnectionManager read(ObjectInput in) throws IOException {
 416:         String host = in.readUTF();
 417:         int port = in.readInt();
 418:         
 419:         
 420:         return (getInstance(host, port, null));
 421: }
 422: 
 423: }
 424: 
 425: 
 428: class TripleKey {
 429: 
 430: String host;
 431: int port;
 432: Object other;
 433: 
 434: TripleKey(String host, int port, Object other) {
 435:         this.host = host;
 436:         this.port = port;
 437:         this.other = other;
 438: }
 439: 
 440: 
 444: public int hashCode() {
 445:         return (host.hashCode() ^ other.hashCode());
 446: }
 447: 
 448: public boolean equals(Object obj) {
 449:         if (obj instanceof TripleKey) {
 450:                 TripleKey other = (TripleKey)obj;
 451:                 if (this.host.equals(other.host) &&
 452:                     this.other == other.other &&
 453:             (this.port == other.port )) {
 454:                         return (true);
 455:                 }
 456:         }
 457:         return (false);
 458: }
 459: 
 460:   
 463:   public String toString()
 464:   {
 465:     return host+":"+port+" ("+other+")";
 466:   }
 467: 
 468: }