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: serverName = localhost;
185: serverFactory = ssf;
186: clientFactory = null;
187: }
188:
189:
193: public static synchronized UnicastConnectionManager getInstance(String host, int port, RMIClientSocketFactory csf) {
194:
195: if (csf == null) {
196: csf = defaultSocketFactory;
197: }
198:
199: try{
200: host = InetAddress.getByName(host).getHostAddress();
201: }catch(Exception _){}
202:
203: TripleKey key = new TripleKey(host, port, csf);
204: UnicastConnectionManager man = (UnicastConnectionManager)clients.get(key);
205: if (man == null) {
206: man = new UnicastConnectionManager(host, port, csf);
207: if (debug) {
208: ncmanager++;
209: System.out.println("\n\n ====== " + ncmanager + " client managers.\n\n");
210: }
211: clients.put(key, man);
212:
213:
214: UnicastConnectionManager svrman = (UnicastConnectionManager)servers.get(key);
215: if(svrman != null){
216: man.serverobj = svrman.serverobj;
217: }
218: }
219: return (man);
220: }
221:
222:
226: public static synchronized UnicastConnectionManager getInstance(int port, RMIServerSocketFactory ssf) throws RemoteException {
227:
228: if (ssf == null) {
229: ssf = defaultSocketFactory;
230: }
231: TripleKey key = new TripleKey(localhost, port, ssf);
232: UnicastConnectionManager man = (UnicastConnectionManager)servers.get(key);
233: if (man == null) {
234: man = new UnicastConnectionManager(port, ssf);
235: if (debug) {
236: nsmanager++;
237: System.out.println("\n\n ****** " + nsmanager + " server managers.\n\n");
238: }
239:
240: key.port = man.serverPort;
241: servers.put(key, man);
242: }
243: return (man);
244: }
245:
246:
249: public UnicastConnection getConnection() throws IOException {
250: if (ssock == null) {
251: return (getClientConnection());
252: }
253: else {
254: return (getServerConnection());
255: }
256: }
257:
258:
261: private UnicastConnection getServerConnection() throws IOException {
262: Socket sock = ssock.accept();
263: sock.setTcpNoDelay(true);
264: UnicastConnection conn = new UnicastConnection(this, sock);
265: conn.acceptConnection();
266: if (debug){
267: nssock++;
268: System.out.println("\n\n ****** " + nssock + " server socks.\n\n");
269: }
270:
271: return (conn);
272: }
273:
274:
277: private UnicastConnection getClientConnection() throws IOException {
278: ArrayList conns = connections;
279: UnicastConnection conn;
280:
281: synchronized(conns) {
282: int nconn = conns.size() - 1;
283:
284:
285: if(nconn >= 0) {
286: conn = (UnicastConnection)conns.get(nconn);
287:
288: conns.remove(nconn);
289:
290:
291: long l = System.currentTimeMillis();
292: if (!UnicastConnection.isExpired(conn, l)){
293: return conn;
294: }else {
295: conn.disconnect();
296: conn = null;
297: }
298: }
299: }
300:
301: Socket sock = clientFactory.createSocket(serverName, serverPort);
302: conn = new UnicastConnection(this, sock);
303: conn.makeConnection(DEFAULT_PROTOCOL);
304:
305: if (debug) {
306: ncsock++;
307: System.out.println("\n\n ====== " + ncsock + " client socks.\n\n");
308: }
309:
310: return (conn);
311: }
312:
313:
316: public String toString()
317: {
318: return serverName+":"+serverPort+" ("+serverobj+")";
319: }
320:
321:
325: public void discardConnection(UnicastConnection conn) {
326:
327:
328: if (ssock != null)
329: conn.disconnect();
330: else {
331:
332: UnicastConnection.resetTime(conn);
333:
334: synchronized(GLOBAL_LOCK) {
335: connections.add(conn);
336: if (scavenger == null)
337: startScavenger();
338: }
339: }
340: }
341:
342:
346: public void startServer() {
347: synchronized(this) {
348: if (ssock == null || serverThread != null) {
349: return;
350: }
351: serverThread = new Thread(this);
352:
353:
354: }
355: serverThread.start();
356: }
357:
358:
361: public void stopServer() {
362: synchronized(this) {
363: if(serverThread != null){
364: serverThread = null;
365: try{
366: ssock.close();
367: }catch(Exception _){}
368: }
369: }
370: }
371:
372:
375: public void run() {
376: for (;serverThread != null;) {
377: try {
378:
379: UnicastConnection conn = getServerConnection();
380:
381:
382: String remoteHost = null;
383: if (conn.sock != null) {
384: remoteHost = conn.sock.getInetAddress().getHostAddress();
385: }
386:
387:
388:
389: (new RMIIncomingThread(conn, remoteHost)).start();
390:
391: }
392: catch (Exception e) {
393: e.printStackTrace();
394: }
395: }
396: }
397:
398:
401: void write(ObjectOutput out) throws IOException {
402: out.writeUTF(serverName);
403: out.writeInt(serverPort);
404: }
405:
406:
409: static UnicastConnectionManager read(ObjectInput in) throws IOException {
410: String host = in.readUTF();
411: int port = in.readInt();
412:
413:
414: return (getInstance(host, port, null));
415: }
416:
417: }
418:
419:
422: class TripleKey {
423:
424: String host;
425: int port;
426: Object other;
427:
428: TripleKey(String host, int port, Object other) {
429: this.host = host;
430: this.port = port;
431: this.other = other;
432: }
433:
434:
438: public int hashCode() {
439: return (host.hashCode() ^ other.hashCode());
440: }
441:
442: public boolean equals(Object obj) {
443: if (obj instanceof TripleKey) {
444: TripleKey other = (TripleKey)obj;
445: if (this.host.equals(other.host) &&
446: this.other == other.other &&
447: (this.port == other.port )) {
448: return (true);
449: }
450: }
451: return (false);
452: }
453:
454:
457: public String toString()
458: {
459: return host+":"+port+" ("+other+")";
460: }
461:
462: }