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:
317: public void discardConnection(UnicastConnection conn) {
318:
319:
320: if (ssock != null)
321: conn.disconnect();
322: else {
323:
324: UnicastConnection.resetTime(conn);
325:
326: synchronized(GLOBAL_LOCK) {
327: connections.add(conn);
328: if (scavenger == null)
329: startScavenger();
330: }
331: }
332: }
333:
334:
338: public void startServer() {
339: synchronized(this) {
340: if (ssock == null || serverThread != null) {
341: return;
342: }
343: serverThread = new Thread(this);
344:
345:
346: }
347: serverThread.start();
348: }
349:
350:
353: public void stopServer() {
354: synchronized(this) {
355: if(serverThread != null){
356: serverThread = null;
357: try{
358: ssock.close();
359: }catch(Exception _){}
360: }
361: }
362: }
363:
364:
367: public void run() {
368: for (;serverThread != null;) {
369: try {
370:
371: UnicastConnection conn = getServerConnection();
372:
373:
374: String remoteHost = null;
375: if (conn.sock != null) {
376: remoteHost = conn.sock.getInetAddress().getHostAddress();
377: }
378:
379:
380:
381: (new RMIIncomingThread(conn, remoteHost)).start();
382:
383: }
384: catch (Exception e) {
385: e.printStackTrace();
386: }
387: }
388: }
389:
390:
393: void write(ObjectOutput out) throws IOException {
394: out.writeUTF(serverName);
395: out.writeInt(serverPort);
396: }
397:
398:
401: static UnicastConnectionManager read(ObjectInput in) throws IOException {
402: String host = in.readUTF();
403: int port = in.readInt();
404:
405:
406: return (getInstance(host, port, null));
407: }
408:
409: }
410:
411:
414: class TripleKey {
415:
416: String host;
417: int port;
418: Object other;
419:
420: TripleKey(String host, int port, Object other) {
421: this.host = host;
422: this.port = port;
423: this.other = other;
424: }
425:
426:
430: public int hashCode() {
431: return (host.hashCode() ^ other.hashCode());
432: }
433:
434: public boolean equals(Object obj) {
435: if (obj instanceof TripleKey) {
436: TripleKey other = (TripleKey)obj;
437: if (this.host.equals(other.host) &&
438: this.other == other.other &&
439: (this.port == other.port )) {
440: return (true);
441: }
442: }
443: return (false);
444: }
445:
446: }