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: }