KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > quikj > client > framework > ServerCommunications


1 package com.quikj.client.framework;
2
3 import java.net.*;
4 import java.util.*;
5 import java.io.*;
6
7 public class ServerCommunications
8 extends Thread JavaDoc
9 {
10     public static final String JavaDoc METHOD_PLUGIN = "SERVICE";
11     public static final String JavaDoc METHOD_PING = "PING";
12     public static final String JavaDoc PLUGIN_APP_ID = "Plugin-Id";
13     public static final String JavaDoc CORRELATION_ID = "Correlation-Id";
14     public static final String JavaDoc CONTENT_TYPE = "Content-Type";
15     public static final String JavaDoc CONTENT_LENGTH = "Content-Length";
16     public static final String JavaDoc CODE = "X-Encoding";
17     
18     public static final String JavaDoc PLAIN_TEXT = "text/plain";
19     
20     public static final int IOEXCEPTION = 1;
21     public static final int WRITE_ERROR = 2;
22     
23     private Random random = new Random((new Date()).getTime());
24     
25     private boolean quit = false;
26     private HTTPConnectionClosedInterface closedListener = null;
27     private HTTPMessageListenerInterface requestListener = null;
28     private Socket socket;
29     private BufferedWriter ostream;
30     private int errorNumber = 0;
31     private InetAddress address;
32     private int port;
33     private int applicationId;
34     
35     private Hashtable pendingRequests = new Hashtable();
36     private Object JavaDoc pendingRequestsLock = new Object JavaDoc();
37     private TimeoutHandler timeoutHandler;
38     private PingTimer pingTimerThread;
39     
40     private static int correlationId = 1;
41     private static Object JavaDoc correlationLock = new Object JavaDoc();
42     
43     private HTTPParser parser = null;
44     
45     // main class
46
public ServerCommunications(String JavaDoc host, int port, int app_id)
47     throws UnknownHostException
48     {
49         address = InetAddress.getByName(host);
50         this.port = port;
51         applicationId = app_id;
52     }
53     
54     public String JavaDoc getHost()
55     {
56         return address.getHostName();
57     }
58     
59     public int getPort()
60     {
61         return port;
62     }
63     
64     public int getApplicationId()
65     {
66         return applicationId;
67     }
68     
69     public boolean connect()
70     {
71         // connect to the server
72
try
73         {
74             socket = new Socket(address, port);
75             try
76             {
77                 socket.setTcpNoDelay(true);
78             }
79             catch (SocketException ex)
80             {
81                 ; // ignore
82
}
83             
84             ostream = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
85         }
86         catch (IOException ex)
87         {
88             disconnect();
89             errorNumber = IOEXCEPTION;
90             return false;
91         }
92         
93         timeoutHandler = new TimeoutHandler();
94         timeoutHandler.start();
95         
96         pingTimerThread = new ServerCommunications.PingTimer();
97         pingTimerThread.start();
98         
99         return true;
100     }
101     
102     public boolean isConnected()
103     {
104         if (socket != null)
105         {
106             return true;
107         }
108         else
109         {
110             return false;
111         }
112     }
113     
114     public void disconnect()
115     {
116         quit = true;
117         
118         if (timeoutHandler != null)
119         {
120             if (timeoutHandler.isAlive() == true)
121             {
122                 timeoutHandler.interrupt();
123             }
124             timeoutHandler = null;
125         }
126         
127         if (pingTimerThread != null)
128         {
129             if (pingTimerThread.isAlive() == true)
130             {
131                 pingTimerThread.interrupt();
132             }
133             pingTimerThread = null;
134         }
135         
136         // interrupt this thread
137
if (isAlive() == true)
138         {
139             this.interrupt();
140         }
141         
142         // netscape workaround
143
if (parser != null)
144         {
145             parser.setInterrupted(true);
146         }
147     }
148     
149     public void setRequestListener(HTTPMessageListenerInterface obj)
150     {
151         requestListener = obj;
152     }
153     
154     public void setClosedListener(HTTPConnectionClosedInterface obj)
155     {
156         closedListener = obj;
157     }
158     
159     private void restartPingTimer()
160     {
161         // re-start the ping timer
162
if (pingTimerThread != null)
163         {
164             if (pingTimerThread.isAlive() == true)
165             {
166                 pingTimerThread.interrupt();
167                 pingTimerThread.dispose();
168             }
169         }
170         
171         pingTimerThread = new ServerCommunications.PingTimer();
172         pingTimerThread.start();
173     }
174     
175     public synchronized int sendRequestMessage(String JavaDoc content_type,
176     String JavaDoc method,
177     String JavaDoc body,
178     HTTPMessageListenerInterface obj,
179     int timeout,
180     boolean multiple_responses)
181     {
182         HTTPReqMessage message = new HTTPReqMessage();
183         
184         if (method == null)
185         {
186             method = METHOD_PLUGIN;
187         }
188         
189         message.setMethod(method);
190         message.setURL("/");
191         message.setVersion("1.1");
192         
193         if (content_type.length() == 0) // not specified
194
{
195             content_type = PLAIN_TEXT;
196         }
197         
198         message.addHeader(CONTENT_TYPE, content_type);
199         message.addHeader(PLUGIN_APP_ID, (new Integer JavaDoc(applicationId)).toString());
200         
201         int crl_id = 0;
202         synchronized (correlationLock)
203         {
204             crl_id = correlationId++;
205         }
206         message.addHeader(CORRELATION_ID, (new Integer JavaDoc(crl_id)).toString());
207
208         
209         if (body != null)
210         {
211             if (body.length() > 0)
212             {
213                 String JavaDoc code = generateRandomString();
214                 
215                 message.addHeader (CODE,
216                 (new DESEncryption()).encrypt(code,
217                 SysParam.getAuth2(getClass())));
218                 
219                 // encode the body with the code
220
String JavaDoc encoded = (new DESEncryption()).encrypt(body, code);
221                 
222                 message.setBody(encoded.toCharArray());
223             }
224         }
225         
226         if (obj != null) // a response is expected
227
{
228             long timeout_date = 0L;
229             if (timeout > 0) // a timeout is specified
230
{
231                 timeout_date = (new Date()).getTime() + timeout;
232             }
233             
234             // place it in the list
235
synchronized (pendingRequestsLock)
236             {
237                 pendingRequests.put(new Integer JavaDoc(crl_id),
238                 new PendingResponseInfo(crl_id, obj, timeout_date,
239                 multiple_responses));
240                 //System.out.println ("Adding send request to the queue " + crl_id);
241
}
242         }
243         
244         // send the message to the server
245
try
246         {
247             String JavaDoc formatted_message = message.format();
248             
249             ostream.write(formatted_message, 0, formatted_message.length());
250             ostream.flush();
251         }
252         catch (IOException ex)
253         {
254             // there was an error in sending
255
errorNumber = WRITE_ERROR;
256             
257             if (obj != null) // if we had put something in the pending requests queue
258
{
259                 // remove it from the queue
260
synchronized (pendingRequestsLock)
261                 {
262                     pendingRequests.remove(new Integer JavaDoc(crl_id));
263                 }
264             }
265             
266             return -1;
267         }
268         
269         // the message has been sent
270

271         restartPingTimer();
272         return crl_id;
273     }
274     
275     // standard request message
276
public int sendRequestMessage(String JavaDoc content_type,
277     String JavaDoc body,
278     HTTPMessageListenerInterface obj,
279     int timeout,
280     boolean multiple_responses)
281     {
282         return sendRequestMessage(content_type, null, body, obj, timeout,
283         multiple_responses);
284     }
285     
286     // req- response message with no timeout, no multiple responses
287
public int sendRequestMessage(String JavaDoc content_type,
288     String JavaDoc body,
289     HTTPMessageListenerInterface obj)
290     {
291         return sendRequestMessage(content_type, null, body, obj, 0, false);
292     }
293     
294     // req - response message with no timeout
295
public int sendRequestMessage(String JavaDoc content_type,
296     String JavaDoc body,
297     HTTPMessageListenerInterface obj,
298     boolean multiple_responses)
299     {
300         return sendRequestMessage(content_type, null, body, obj, 0, multiple_responses);
301     }
302     
303     // req-response message with a timeout, no multiple responses
304
public int sendRequestMessage(String JavaDoc content_type,
305     String JavaDoc body,
306     HTTPMessageListenerInterface obj,
307     int timeout)
308     {
309         return sendRequestMessage(content_type, null, body, obj, timeout, false);
310     }
311     
312     // unidirectional message
313
public int sendRequestMessage(String JavaDoc content_type, String JavaDoc body)
314     {
315         return sendRequestMessage(content_type, null, body, null, 0, false);
316     }
317     
318     // ping message
319
public int sendPing()
320     {
321         // System.out.println ("Sending a ping message");
322
return sendRequestMessage("", METHOD_PING, null, null, 0, false);
323     }
324     
325     public void cancelRequest(int id)
326     {
327         synchronized (pendingRequestsLock)
328         {
329             //System.out.println ("Canceling request " + id);
330
pendingRequests.remove(new Integer JavaDoc(id));
331         }
332     }
333     
334     
335     public void cancelTimeout(int id)
336     {
337         changeTimeout(id, 0L);
338     }
339     
340     public void changeTimeout(int id, long timeout)
341     {
342         PendingResponseInfo info = (PendingResponseInfo)pendingRequests.get(new Integer JavaDoc(id));
343         if (info != null)
344         {
345             info.setTimeout(timeout);
346         }
347     }
348     
349     public boolean sendResponse(int req_id, int status, String JavaDoc reason,
350     String JavaDoc content_type, String JavaDoc body)
351     {
352         HTTPRspMessage message = new HTTPRspMessage();
353         
354         message.setVersion("1.1");
355         message.setStatus((new Integer JavaDoc(status)).toString());
356         
357         if (reason.length() > 0)
358         {
359             message.setReason(reason);
360         }
361         
362         message.addHeader(PLUGIN_APP_ID, (new Integer JavaDoc(applicationId)).toString());
363         message.addHeader(CORRELATION_ID, (new Integer JavaDoc(req_id)).toString());
364         
365         if (body != null)
366         {
367             if (body.length() > 0)
368             {
369                 if (content_type.length() == 0) // not specified
370
{
371                     content_type = PLAIN_TEXT;
372                 }
373                 message.addHeader(CONTENT_TYPE, content_type);
374
375                 String JavaDoc code = generateRandomString();
376                 
377                 message.addHeader (CODE,
378                 (new DESEncryption()).encrypt(code,
379                 SysParam.getAuth2(getClass())));
380                 
381                 // encode the body with the code
382
String JavaDoc encoded = (new DESEncryption()).encrypt(body, code);
383                 
384                 message.setBody(encoded.toCharArray());
385              }
386         }
387         
388         // send the message to the server
389
try
390         {
391             String JavaDoc rmessage = message.format();
392             ostream.write(rmessage, 0, rmessage.length());
393             ostream.flush();
394         }
395         catch (IOException ex)
396         {
397             // there was an error in sending
398
errorNumber = WRITE_ERROR;
399             return false;
400         }
401         
402         return true;
403     }
404     
405     private String JavaDoc generateRandomString()
406     {
407         char[] c = new char[10];
408         
409         for (int i = 0; i < 10; i++)
410         {
411             int x = random.nextInt() % 26;
412             c[i] = Integer.toString(Character.getNumericValue('a') + x, 10).charAt(0);
413         }
414         
415         return new String JavaDoc(c);
416     }
417     
418     public void run()
419     {
420         parser = null;
421         try
422         {
423              parser = new HTTPParser(socket);
424         }
425         catch (SocketException ex1)
426         {
427             return;
428         }
429         catch (IOException ex2)
430         {
431             return;
432         }
433         
434         while (true)
435         {
436             HTTPMessage message = parser.read();
437             
438             if (message == null)
439             {
440                 if ((parser.getErrorNumber() == HTTPParser.EOF) ||
441                 (parser.getErrorNumber() == HTTPParser.INTERRUPTED) ||
442                 (parser.getErrorNumber() == HTTPParser.IO_ERROR))
443                 {
444                     if (quit == false)
445                     {
446                         disconnect();
447                         if (closedListener != null)
448                         {
449                             // notify the listener
450
closedListener.connectionClosed(address.getHostName(),
451                             port,
452                             applicationId);
453                         }
454                     }
455                                         
456                     try
457                     {
458                         // System.out.println("Closing socket and getting out of here");
459
socket.close();
460                     }
461                     catch (IOException ex1)
462                     {
463                         ;
464                     }
465                     return;
466                 }
467                 // else, ignore badly formatted message
468
}
469             else // a message is received
470
{
471                 restartPingTimer();
472                 
473                 if ((message instanceof HTTPReqMessage) == true)
474                 {
475                     // do some error checking
476
HTTPReqMessage req_message = (HTTPReqMessage)message;
477                     
478                     if (req_message.getMethod().equalsIgnoreCase(METHOD_PLUGIN) == false)
479                     {
480                         // unknown method type, ignore
481
continue;
482                     }
483                     
484                     String JavaDoc appl_s = req_message.findHeader(PLUGIN_APP_ID);
485                     if (appl_s == null) // application id not specified
486
{
487                         continue; // ignore
488
}
489                     
490                     try
491                     {
492                         int appl_id = Integer.parseInt(appl_s);
493                         
494                         if (appl_id != applicationId)
495                         {
496                             // application id mismatch
497
continue; // ignore
498
}
499                     }
500                     catch (NumberFormatException JavaDoc ex)
501                     {
502                         // bad synatax for application id
503
continue; // ignore
504
}
505                     
506                     String JavaDoc crl_id_s = req_message.findHeader(CORRELATION_ID);
507                     if (crl_id_s == null) // not specified
508
{
509                         continue; // ignore
510
}
511                     
512                     int crl_id = 0;
513                     try
514                     {
515                         crl_id = Integer.parseInt(crl_id_s);
516                     }
517                     catch (NumberFormatException JavaDoc ex)
518                     {
519                         // bad synatax for correlation id
520
continue; // ignore
521
}
522                     
523                     String JavaDoc content_type = req_message.findHeader(CONTENT_TYPE);
524                     if (content_type == null) // not specified
525
{
526                         content_type = PLAIN_TEXT;
527                     }
528                     
529                     String JavaDoc body = null;
530                     if (message.getBodyLength() > 0)
531                     {
532                         body = new String JavaDoc(message.getBody());
533                     }
534                     
535                     if (body != null)
536                     {
537                         // decode the body
538
String JavaDoc code = req_message.findHeader(CODE);
539                         if (code != null)
540                         {
541                             String JavaDoc dec = (new DESEncryption()).decrypt(code,
542                             SysParam.getAuth2(getClass()));
543                             
544                             if (dec != null)
545                             {
546                                 // use the code to decrypt the content
547
String JavaDoc dec_body = (new DESEncryption()).decrypt(body, dec);
548                                 if (dec_body != null)
549                                 {
550                                     body = dec_body;
551                                 }
552                             }
553                         }
554                     }
555                     
556                     if (requestListener != null)
557                     {
558                         try
559                         {
560                             requestListener.messageReceived(crl_id,
561                             HTTPMessageListenerInterface.RECEIVED,
562                             content_type,
563                             0,
564                             null,
565                             body);
566                         }
567                         catch (Exception JavaDoc ex)
568                         {
569                             // catch any exception thrown by the application code.
570
// print it on the Java console and throw it away
571
ex.printStackTrace();
572                         }
573                     }
574                 }
575                 else // response message
576
{
577                     // do some error checking
578
HTTPRspMessage rsp_message = (HTTPRspMessage)message;
579                     
580                     String JavaDoc appl_s = rsp_message.findHeader(PLUGIN_APP_ID);
581                     if (appl_s == null) // application id not specified
582
{
583                         continue; // ignore
584
}
585                     
586                     try
587                     {
588                         int appl_id = Integer.parseInt(appl_s);
589                         
590                         if (appl_id != applicationId)
591                         {
592                             // application id mismatch
593
continue; // ignore
594
}
595                     }
596                     catch (NumberFormatException JavaDoc ex)
597                     {
598                         // bad syntax for application id
599
continue; // ignore
600
}
601                     
602                     String JavaDoc crl_id_s = rsp_message.findHeader(CORRELATION_ID);
603                     if (crl_id_s == null) // not specified
604
{
605                         continue; // ignore
606
}
607                     
608                     int crl_id = 0;
609                     try
610                     {
611                         crl_id = Integer.parseInt(crl_id_s);
612                     }
613                     catch (NumberFormatException JavaDoc ex)
614                     {
615                         // bad syntax for correlation id
616
continue; // ignore
617
}
618                     
619                     String JavaDoc status_s = rsp_message.getStatus();
620                     int status = 0;
621                     try
622                     {
623                         status = Integer.parseInt(status_s);
624                     }
625                     catch (NumberFormatException JavaDoc ex)
626                     {
627                         // bad syntax for status
628
continue; // ignore
629
}
630                     
631                     String JavaDoc reason = rsp_message.getReason();
632                     
633                     String JavaDoc content_type = rsp_message.findHeader(CONTENT_TYPE);
634                     if (content_type == null) // not specified
635
{
636                         content_type = PLAIN_TEXT;
637                     }
638                     
639                     String JavaDoc body = null;
640                     if (message.getBodyLength() > 0)
641                     {
642                         body = new String JavaDoc(message.getBody());
643                     }
644                     
645                     if (body != null)
646                     {
647                         // decode the body
648
String JavaDoc code = rsp_message.findHeader(CODE);
649                         if (code != null)
650                         {
651                             String JavaDoc dec = (new DESEncryption()).decrypt(code,
652                             SysParam.getAuth2(getClass()));
653                             
654                             if (dec != null)
655                             {
656                                 // use the code to decrypt the content
657
String JavaDoc dec_body = (new DESEncryption()).decrypt(body, dec);
658                                 if (dec_body != null)
659                                 {
660                                     body = dec_body;
661                                 }
662                             }
663                         }
664                     }
665                     
666                     
667                     PendingResponseInfo info = null;
668                     // check if the correlation id exists
669
synchronized (pendingRequestsLock)
670                     {
671                         info = (PendingResponseInfo)pendingRequests.get(new Integer JavaDoc(crl_id));
672                         if (info == null) // the response was not found in the list
673
{
674                             //System.out.println ("Throwing away response " + crl_id);
675
continue;
676                         }
677                         
678                         if (info.multipleResponse() == false)
679                         {
680                             // get it out of the queue
681
pendingRequests.remove(new Integer JavaDoc(crl_id));
682                         }
683                     }
684                     
685                     // finally send the message to the listener
686
HTTPMessageListenerInterface listener = info.getListener();
687                     if (listener != null)
688                     {
689                         try
690                         {
691                             listener.messageReceived(crl_id,
692                             HTTPMessageListenerInterface.RECEIVED,
693                             content_type,
694                             status,
695                             reason,
696                             body);
697                         }
698                         catch (Exception JavaDoc ex)
699                         {
700                             // catch all exceptions thrown by the application code.
701
// print the message to the java console and throw it away
702
ex.printStackTrace();
703                         }
704                     }
705                 }
706             }
707         }
708     }
709     
710     public int getErrorNumber()
711     {
712         return errorNumber;
713     }
714     
715     // inner classes
716
class TimeoutHandler extends Thread JavaDoc
717     {
718         public TimeoutHandler()
719         {
720         }
721         
722         public void run()
723         {
724             try
725             {
726                 while (true)
727                 {
728                     // sleep for 100ms
729
Thread.sleep(100);
730                     
731                     if (quit == true)
732                     {
733                         return;
734                     }
735                     
736                     Vector expired_timers = new Vector();
737                     
738                     long cur_time = (new Date()).getTime();
739                     
740                     synchronized (pendingRequestsLock)
741                     {
742                         Enumeration values = pendingRequests.elements();
743                         while (values.hasMoreElements() == true)
744                         {
745                             PendingResponseInfo info = (PendingResponseInfo)values.nextElement();
746                             int crl_id = info.getRequestId();
747                             
748                             long timeout = info.getTimeout();
749                             if (timeout > 0)
750                             {
751                                 if (cur_time >= timeout) // timer expired
752
{
753                                     // remove the item from the queue
754
//System.out.println ("Removing from queue (TO) " + crl_id);
755
pendingRequests.remove(new Integer JavaDoc(crl_id));
756                                     
757                                     HTTPMessageListenerInterface listener = info.getListener();
758                                     if (listener != null)
759                                     {
760                                         expired_timers.addElement(info);
761                                     }
762                                 }
763                             }
764                         }
765                     }
766                     
767                     
768                     int size = expired_timers.size();
769                     for (int i = 0; i < size; i++)
770                     {
771                         // notify the listener
772
PendingResponseInfo element = (PendingResponseInfo)expired_timers.elementAt(i);
773                         
774                         element.getListener().messageReceived(element.getRequestId(),
775                         HTTPMessageListenerInterface.TIMEOUT,
776                         "",
777                         0,
778                         null,
779                         null);
780                     }
781                     
782                     if (quit == true)
783                     {
784                         break;
785                     }
786                 }
787             }
788             catch (InterruptedException JavaDoc ex)
789             {
790                 if (quit == true)
791                 {
792                     return;
793                 }
794             }
795         }
796     }
797     
798     class PingTimer extends Thread JavaDoc
799     {
800         private boolean go = true;
801         
802         public PingTimer()
803         {
804         }
805         
806         private void dispose()
807         {
808             go = false;
809         }
810         
811         public void run()
812         {
813             try
814             {
815                 int count = 0;
816                 while (true)
817                 {
818                     sleep(1000L);
819                     
820                     if (quit == true)
821                     {
822                         return;
823                     }
824                     
825                     if (go == false)
826                     {
827                         return;
828                     }
829                     
830                     count++;
831                     if (count >= PING_TIMER)
832                     {
833                         // send a PING message to the server
834
sendPing();
835                         count = 0;
836                     }
837                 }
838             }
839             catch (InterruptedException JavaDoc ex)
840             {
841                 ; // timer cancelled, nothing to do
842
}
843         }
844         
845         private long PING_TIMER = 15 * 60; // 15 minutes
846

847     }
848
849 }
850
851
Popular Tags