Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: rcs/nml/NMLConnection.java


1   package rcs.nml;
2   
3   
4   import java.net.*;
5   import java.io.*;
6   import java.util.*;
7   import rcs.utils.*;
8   import rcs.nml.NMLFormatConverter;
9   import rcs.nml.NMLFormatConverterBase;
10  import rcs.nml.XDRFormatConverter;
11  import rcs.nml.DISPFormatConverter;
12  import rcs.utils.jcrypt;
13  import rcs.utils.URL_and_FileLoader;
14  import rcs.nml.NMLException;
15  
16  class NMLBufferConfigInfo
17  {
18    String buffer_name = null;
19    String buffer_line = null;
20    Hashtable process_lines = new Hashtable();
21  };
22  
23  class NMLConfigInfo
24  {
25    String file_name = null;
26    Hashtable buffer_configurations = new Hashtable();
27    //Vector lines_vector;
28    URL_and_FileLoader loader = null;
29  //  int lines_read = 0;
30  }
31  
32  /**
33  * Class for connecting to NML buffers, ussually via network sockets.<br>
34  * <pre>
35  * Related Documentation: 
36  * <A HREF="http://isd.cme.nist.gov/proj/rcs_lib">RCS Library</a>, <A HREF="http://isd.cme.nist.gov/proj/rcs_lib/NMLjava.html">NML Programmers Guide (Java Version)</a>
37  *
38  * Source Code:
39  * <A HREF="NMLConnection.java">NMLConnection.java</a>
40  * 
41  * </pre>
42  *
43  * @author  Will Shackleford -- <A HREF="mailto:shackle@cme.nist.gov">shackle@cme.nist.gov</a>
44  *
45  */
46  public class NMLConnection
47  {
48    static protected Hashtable previously_read_nml_configurations = null;
49  
50    /** 
51     * This variable can be set to true by some other thread to 
52     * stop the login.
53     *
54     * @see rcs.nml.NMLConnection#login(java.lang.String,java.lang.String)
55     */
56    public static boolean interrupt_login = false;
57  
58    protected NMLFormatConverterBase format_converter = null;
59    protected NMLMessageDictionary message_dictionary = null;
60    public String BufferLine = null;
61  
62    // Protocol Options
63    protected static final int NML_STCP_PROTOCOL_TYPE = 1;
64    protected static final int NML_TCP_PROTOCOL_TYPE = 2;
65    protected static final int NML_UDP_PROTOCOL_TYPE = 3;
66    public int protocol_option = NML_STCP_PROTOCOL_TYPE;
67    
68    // Data format Options
69    protected static final int NML_ASCII_ENCODING_TYPE = 4;
70    protected static final int NML_DISP_ENCODING_TYPE = 5;
71    protected static final int NML_XDR_ENCODING_TYPE = 6;
72    private int data_format_option =NML_DISP_ENCODING_TYPE;
73    
74  
75    private int serial_number = 0;
76    private int last_id_read = 0;
77    private int max_tries = 20;
78    
79    // REMOTE_CMS_REQUEST_TYPE's
80    protected static final int REMOTE_CMS_READ_REQUEST_TYPE = 1;
81    protected static final int REMOTE_CMS_WRITE_REQUEST_TYPE = 2;
82    protected static final int REMOTE_CMS_GET_KEYS_REQUEST_TYPE = 7;
83    protected static final int REMOTE_CMS_LOGIN_REQUEST_TYPE = 8;
84    protected static final int REMOTE_CMS_SET_SUBSCRIPTION_REQUEST_TYPE = 9;
85    protected static final int REMOTE_CMS_READ_COMBINED_REQUEST_TYPE =10;
86    protected static final int REMOTE_CMS_BLOCKING_READ_REQUEST_TYPE =11;
87    protected static final int REMOTE_CMS_GET_BUF_NAME_REQUEST_TYPE=12;
88    protected static final int REMOTE_CMS_CANCEL_SUBSCRIPTION_REQUEST_TYPE=13;
89    protected static final int REMOTE_CMS_SET_DIAG_INFO_REQUEST_TYPE=14;
90    protected static final int REMOTE_CMS_GET_DIAG_INFO_REQUEST_TYPE=15;
91    protected static final int REMOTE_CMS_GET_MSG_COUNT_REQUEST_TYPE=16;
92  
93    private int request_type = REMOTE_CMS_READ_REQUEST_TYPE;
94  
95    // CMS_REMOTE_SUBSCRIPTION_REQUEST_TYPE's
96    public static final int CMS_POLLED_SUBSCRIPTION = 1;
97    public static final int CMS_NO_SUBSCRIPTION =2;
98    public static final int CMS_VARIABLE_SUBSCRIPTION =3;
99  
100   // CMS_INTERNAL_ACCESS_TYPE's
101   protected static final int CMS_READ_ACCESS = 1;
102   protected static final int CMS_CHECK_IF_READ_ACCESS = 2;
103   protected static final int CMS_PEEK_ACCESS = 3;
104   protected static final int CMS_WRITE_ACCESS = 4;
105   protected static final int CMS_WRITE_IF_READ_ACCESS = 5;
106   private int access_type = CMS_READ_ACCESS;
107   private int remote_status = 0;
108   private int message_size = 0;
109   private int was_read = 0;
110   private int input_bytes_read = 0;
111   private boolean reply_header_received = false;
112   private boolean write_reply_received = true;
113   private boolean input_buffer_ready = false;
114   protected int output_data_size = 0;
115   public double min_compatible_version = 0.0;
116   public boolean confirm_write = false;
117   public boolean use_subscription=false;
118   public int subscription_id = 0;
119   public double subscription_period = 0.0;
120   public boolean poll = false;
121   public static boolean default_poll_state = false;
122   public boolean diag_enabled=false;
123   public int connection_number=0;
124 
125   protected NMLmsg last_msg_read = null;
126   /**
127    * Set config_debug_on to true to print out additional information
128    * while reading the NML Congiguration file.
129    */
130   static public boolean config_debug_on = false;
131   /**
132    * Set read_debug_on to true to print out additional information
133    * while reading.
134    */
135   static public boolean read_debug_on = false;
136   /**
137    * Set write_debug_on to true to print out additional information
138    * while writing.
139    */
140   static public boolean write_debug_on = false;
141   private String input_string = "";
142     
143   /**
144    * Name of buffer to connect to. (used in configuration file)
145    */
146   public String buffer_name = null;
147   
148   /**
149    * Name of this process as used in configuration file.
150    */
151   public String process_name = null;
152   
153     
154   /**
155    * Name/URL the configuration file to read.
156    */
157   public  String configuration_file = null;
158   private int input_buffer_offset = 0;
159   private int input_bytes_ready = 0;
160   private byte input_buffer[];
161   private byte output_buffer[];
162 
163   private static final int NML_DEFAULT_BUFFER_SIZE=2048;
164   private int buffer_size;
165   /** 
166    * TCP port of NML server.
167    */
168   public int port = 0;
169   /**
170    * buffer_number from NML configuration file.
171    */
172   public int buffer_number = 0;
173 
174   /**
175    * name of the computer the NML server runs on.
176    */
177   public String host = "";
178   protected boolean read_request_sent = false;
179   private boolean null_error_reported = false;
180   private DataInputStream m_InputStream = null;
181   private DataOutputStream m_OutputStream = null;
182   private Socket m_Socket = null;
183   private NonBlockingDatagramSocket udpSocket = null;
184   private InetAddress udpServerAddress = null;
185   private ByteArrayOutputStream baOutputStream = null;
186   private ByteArrayInputStream baInputStream = null;
187   private DatagramPacket udpInputPacket = null;
188   private long udpRetryTimeoutMillis = 30;
189   private long lastUdpRequestTime = 0;
190   private int broadcast_port = 0;
191   
192   
193   /**
194    * True when this object is connected to the NML server.
195    * All reads and writes will fail when this is false.
196    */
197   public boolean connected = false;
198 
199 
200   /**
201    * This constructs an NMLConnection which will not work until
202    * the host and port are set manually or 
203    * by reading the NML configuration file with   ReadNMLConfigurationFile().
204    * Most users should use the other constructor with several parameters.
205    *
206    * @see rcs.nml.NMLConnection#NMLConnection(rcs.nml.NMLMessageDictionary, java.lang.String, java.lang.String, java.lang.String)
207    * @see rcs.nml.NMLConnection#ReadNMLConfigurationFile(java.lang.String, java.lang.String, java.lang.String)
208    *
209    */
210   public NMLConnection()
211   {
212     //  System.out.print("\r\nconstructing NMLConnection\r\n");
213     try
214       {
215   input_buffer = new byte[NML_DEFAULT_BUFFER_SIZE];
216   output_buffer = new byte[NML_DEFAULT_BUFFER_SIZE];
217   buffer_size = NML_DEFAULT_BUFFER_SIZE;
218   interrupt_login = false;
219   poll = default_poll_state;
220   SetFormatConverter(new XDRFormatConverter());
221       }
222     catch(Exception e)
223       {
224   e.printStackTrace();
225       }
226   }
227 
228   /** 
229    * This functions sets the NMLMessageDictionary for this connection.
230    * The purpose of the NMLMessageDictionary is to provide a means
231    * for the NMLConnection to determine the structure of messages being
232    * sent or received using a message type. (An integer passed within
233    * all NML messages.)
234    *
235    * @param new_dict the NMLMessageDictionary for this NMLConnection to use.
236    * @see rcs.nml.NMLMessageDictionary
237    */
238   public void SetMessageDictionary(NMLMessageDictionary new_dict) throws NMLException
239   {
240     message_dictionary = new_dict;
241     if(null != format_converter)
242       {
243   format_converter.SetMessageDictionary(new_dict);
244       }
245   }
246   
247   /**
248    * This functions gets the NMLMessageDictionary for this connection.
249    *
250    * @return the implementation of NMLMessageDictionary used by this 
251    * NMLConnection
252    *
253    * @see rcs.nml.NMLConnection#SetMessageDictionary(rcs.nml.NMLMessageDictionary)
254    * @see rcs.nml.NMLMessageDictionary
255    */
256   public NMLMessageDictionary GetMessageDictionary() throws NMLException
257   {
258     if(null != format_converter)
259       {
260   message_dictionary = format_converter.GetMessageDictionary();
261       }
262     return message_dictionary;
263   }
264 
265   
266   /**
267    * This functions sets the NMLFormatConverter for this connection.
268    * The NMLFormatConverter is resposible for converting each of 
269    * the basic data types to some neutral format that can be 
270    * used on many different platforms. Most users should either accept
271    * the default (XDRFormatConverter) or allow the format to be specified
272    * in the NML configuration file rather than calling this function 
273    * directly.
274    *
275    * @param new_fc the NMLFormatConverter for this Connection to use.
276    *
277    * @see rcs.nml.NMLFormatConverter
278    */
279   public void SetFormatConverter(NMLFormatConverter new_fc) throws NMLException
280   {
281     try
282       {
283   format_converter = (NMLFormatConverterBase) new_fc;
284       }
285     catch(ClassCastException e)
286       {
287   System.err.println("This NMLFormatConverter is not a subclass of NMLFormatConverterBase.");
288   e.printStackTrace();
289   throw new NMLException("This NMLFormatConverter is not a subclass of NMLFormatConverterBase.",buffer_name, configuration_file,e);
290       }
291     if(null != message_dictionary && null != format_converter)
292       {
293   format_converter.SetMessageDictionary(message_dictionary);
294       }
295   }
296     
297   /**
298    * This functions gets the NMLFormatConverter for this connection.
299    *
300    * @return the NMLFormatConverter for this connection
301    *
302    * @see rcs.nml.NMLConnection#SetFormatConverter(rcs.nml.NMLFormatConverter)
303    */
304   public NMLFormatConverter GetFormatConverter() throws NMLException
305   {
306     return format_converter;
307   }
308     
309 
310   /**
311    * This constuctor creates a fully functional NML Connection 
312    * using the application defined NMLMessageDictionary,  read
313    * the NML configuration file,  and connects immediately.
314    * This is the constructor most users should use.
315    * 
316    * @param msg_dict the NMLMessageDictionary for this connection to use (the NMLMessageDictionary allows this Connection to determine the message structure from the message type)
317    * @param BufferName the name of the buffer to connect to, (must match one of the buffers in the configuration file.)
318    * @param ProcessName the name of the process that will use this connection (must match one of the process names in the configuration file)
319    * @param ConfigurationFile the file name or URL of an NML configuration file (URL's should either be complete, or they can be relative to 
320    rcs.utils.URL_and_FileLoader.current_directory)
321    * @exception  rcs.nml.NMLException 
322    *    If the configuration file can not be read, the file is improperly formatted or the buffer or process can
323    *    can not be found in it.
324    *
325    */
326   public NMLConnection(NMLMessageDictionary msg_dict, String BufferName, String ProcessName, String ConfigurationFile)  throws NMLException
327   {
328     this();
329     ReadNMLConfigurationFile(BufferName, ProcessName, ConfigurationFile);
330     SetMessageDictionary(msg_dict);
331   }
332 
333 
334   /**
335    * This function reads configuration information from the NML configuration file.
336    * 
337    * @param BufferName the name of the buffer to connect to, (must match one of the buffers in the configuration file.)
338    * @param ProcessName the name of the process that will use this connection (must match one of the process names in the configuration file)
339    * @param ConfigurationFile the file name or URL of an NML configuration file (URL's should either be complete, or they can be relative to 
340    rcs.utils.URL_and_FileLoader.current_directory)
341    * @exception  rcs.nml.NMLException 
342    *    If the configuration file can not be read, the file is improperly formatted or the buffer or process can
343    *    can not be found in it.
344    *
345    */
346   public void ReadNMLConfigurationFile(String BufferName, String ProcessName, String ConfigurationFile)  throws NMLException
347   {
348     buffer_name = BufferName;
349     process_name = ProcessName;
350     configuration_file = ConfigurationFile;
351     ReadNMLConfigurationFile();
352     connect();
353   }
354   
355   /**
356    * Clear any data saved from previously read configuration files.
357    */
358   public static void ClearStaticData()
359   {
360     previously_read_nml_configurations = null;
361   }
362 
363   protected void LoadConfigurationFileData(String configuration_file) throws Exception
364   {
365     NMLConfigInfo config_info = new NMLConfigInfo();
366     NMLBufferConfigInfo bufferConfigInfo = null;
367     config_info.file_name= configuration_file;
368     URL_and_FileLoader loader = null;
369     String current_line = null;
370     String buffer_name = null;
371     String process_name = null;
372     loader = new URL_and_FileLoader(configuration_file);
373     while(true)
374       {
375   current_line = loader.readLine();
376   if(current_line == null)
377     {
378       break;
379     }
380   if(config_debug_on)
381     {
382       System.out.println(current_line);
383     }
384   if(current_line.length() < 3)
385     {
386       continue;
387     }
388   if(current_line.startsWith("#"))
389     {
390       continue;
391     }
392   if(current_line.startsWith("B"))
393     {
394       StringTokenizer tokenizer = new StringTokenizer(current_line," \t");
395       if(null == tokenizer)
396         {
397     continue;
398         }
399       int token_number = 0;
400       while(tokenizer.hasMoreTokens())
401         {
402     String token = tokenizer.nextToken();
403     if(null == token)
404       {
405         break;
406       }
407     if(config_debug_on)
408       {
409         System.out.println("token "+token_number+" = "+token);
410       }
411     if(token_number == 1)
412       {
413         buffer_name = token;
414         bufferConfigInfo = (NMLBufferConfigInfo) config_info.buffer_configurations.get(buffer_name);
415         if(bufferConfigInfo == null)
416           {
417       bufferConfigInfo = new NMLBufferConfigInfo();
418       bufferConfigInfo.buffer_name = buffer_name;
419       bufferConfigInfo.buffer_line = current_line;
420       config_info.buffer_configurations.put(buffer_name,bufferConfigInfo);
421           }
422         else
423           {
424       if(null == bufferConfigInfo.buffer_line)
425         {
426           bufferConfigInfo.buffer_line = current_line;
427         }
428           }
429         break;
430       }
431     token_number++;
432         }
433     }
434   if(current_line.startsWith("P"))
435     {
436       StringTokenizer tokenizer = new StringTokenizer(current_line," \t");
437       if(null == tokenizer)
438         {
439     continue;
440         }
441       int token_number = 0;
442       while(tokenizer.hasMoreTokens())
443         {
444     String token = tokenizer.nextToken();
445     if(null == token)
446       {
447         break;
448       }
449     if(config_debug_on)
450       {
451         System.out.println("token "+token_number+" = "+token);
452       }
453     if(token_number == 1)
454       {
455         process_name = token;
456       }
457     if(token_number == 2)
458       {
459         buffer_name = token;
460         bufferConfigInfo = (NMLBufferConfigInfo) config_info.buffer_configurations.get(buffer_name);
461         if(bufferConfigInfo == null)
462           {
463       bufferConfigInfo = new NMLBufferConfigInfo();
464       bufferConfigInfo.buffer_name = buffer_name;
465       config_info.buffer_configurations.put(buffer_name,bufferConfigInfo);
466           }
467         bufferConfigInfo.process_lines.put(process_name, current_line);
468         break;
469       }
470     token_number++;
471         }
472     }
473       }
474     previously_read_nml_configurations.put(configuration_file,config_info);
475   }
476 
477   /** 
478    * Read preset configuration file.
479    * @exception  rcs.nml.NMLException 
480    *    If the configuration file can not be read, the file is improperly formatted or the buffer or process can
481    *    can not be found in it.
482    */
483   public void ReadNMLConfigurationFile() throws NMLException
484   {    
485     String current_line = null;
486     boolean BufferLineFound = false;
487     boolean ProcessLineFound = false;
488     boolean ConfigurationFileRead = false;
489     NMLConfigInfo config_info = null;
490     int lines_parsed = 0;
491     try
492       {
493   if(config_debug_on)
494     {
495       System.out.println("ReadNMLConfigurationFile(): buffer_name = "+buffer_name+", process_name = "+process_name+", configuration_file = "+configuration_file+",");
496     }
497       
498       
499   if(null == previously_read_nml_configurations)
500     {
501       previously_read_nml_configurations = new Hashtable();
502     }
503   else
504     {
505       config_info = (NMLConfigInfo) previously_read_nml_configurations.get(configuration_file);
506     }
507       
508   boolean buffer_line_in_hashtable = false;
509   if(null == config_info)
510     {
511       LoadConfigurationFileData(configuration_file);
512       config_info = (NMLConfigInfo) previously_read_nml_configurations.get(configuration_file);
513     }
514   
515   NMLBufferConfigInfo buf_info = (NMLBufferConfigInfo) config_info.buffer_configurations.get(buffer_name);
516   if(null == buf_info)
517     {
518       throw new NMLException("Can't find buffer line.", buffer_name, configuration_file);
519     }
520   String buffer_line = buf_info.buffer_line;
521   String process_line = (String) buf_info.process_lines.get(process_name);
522 
523   data_format_option =NML_XDR_ENCODING_TYPE;
524   ConfigurationFileRead = true;
525   if(config_debug_on)
526     {
527       System.out.println("buffer_line="+buffer_line);
528       System.out.println("process_line="+process_line);
529     }
530   if(null != process_line)
531     {
532       current_line = process_line;
533       if(current_line.startsWith("P"))
534         {
535     StringTokenizer tokenizer = new StringTokenizer(current_line," \t");
536     int token_number = 0;
537     while(tokenizer.hasMoreTokens() && token_number < 10)
538       {
539         String token = tokenizer.nextToken();
540         if(config_debug_on)
541           {
542       System.out.println("token "+token_number+" = "+token);
543           }
544         if(token_number == 1 && !token.equals(process_name))
545           {
546       break;
547           }
548         if(token_number == 2 && token.equals(buffer_name))
549           {
550       ProcessLineFound = true;
551           }
552         if(token_number == 7 && ProcessLineFound)
553           {
554       try
555         {
556           double timeout_d = Double.valueOf(token).doubleValue();
557           if(timeout_d > 0.01)
558             {
559         max_tries = (int) (timeout_d * 100.0);
560             }
561           else
562             {
563         max_tries = 1;
564         poll = true;
565             }
566         }
567       catch(Exception e)
568         {
569         }
570       if(token.toUpperCase().startsWith("INF"))
571         {
572           max_tries = -1;
573         }
574       if(config_debug_on)
575         {
576           System.out.println("max_tries="+max_tries+", token = "+token);
577         }
578           }
579         if(token_number == 9 && ProcessLineFound)
580           {
581       connection_number = Integer.valueOf(token).intValue();
582       if(config_debug_on)
583         {
584           System.out.println("connection_number="+connection_number+", token = "+token);
585         }
586           }
587         token_number++;
588       }
589     int poll_index = current_line.toUpperCase().indexOf("POLL");
590     if(poll_index >= 0)
591       {
592         poll = true;
593       }
594     int sub_index = current_line.toUpperCase().indexOf("SUB=");
595     if(sub_index >= 0)
596       {
597         poll = true;
598         String sub_period_string = current_line.substring(sub_index+4);
599         if(config_debug_on)
600           {
601       System.out.println("sub_period_string ="+sub_period_string );
602           }
603         StringTokenizer t2 = new StringTokenizer(sub_period_string,"\r\n \t");
604         String token2 = t2.nextToken();
605         subscription_period = Double.valueOf(token2).doubleValue();
606         if(config_debug_on)
607           {
608       System.out.println("subscription_period ="+subscription_period );
609           }
610       }
611         } // current_line.startsWith("P")
612     } // process_line != null
613 
614   current_line = buffer_line;
615   StringTokenizer tokenizer = new StringTokenizer(current_line," \t");
616   BufferLine = current_line;
617   int token_number = 0;
618   while(tokenizer.hasMoreTokens())
619     {
620       String token = tokenizer.nextToken();
621       if(null == token)
622         {
623     break;
624         }
625       if(config_debug_on)
626         {
627     System.out.println("token "+token_number+" = "+token);
628         }
629       if(token_number == 1)
630         {
631     if(token.equals(buffer_name))
632       {
633         BufferLineFound = true;
634       }
635     else
636       {
637         break;
638       }
639         }
640       if(token_number == 3)
641         {
642     host = token;
643     if(config_debug_on)
644       {
645         System.out.println("host = "+host);
646       }
647         }
648       if(token_number == 4)
649         {
650     try
651       {
652         buffer_size = (int) (StrToLong.convert(token))*4;
653       }
654     catch(Exception e)
655       {
656         System.err.println("Invalid buffer size token ("+token+") in "+configuration_file+" for "+buffer_name);
657         System.err.println("Using default buffer size.");
658         e.printStackTrace();
659         buffer_size = NML_DEFAULT_BUFFER_SIZE;
660       }
661     if(buffer_size <= 0)
662       {
663         buffer_size = NML_DEFAULT_BUFFER_SIZE;
664       }
665     if(config_debug_on)
666       {
667         System.out.println("buffer_size = "+buffer_size);
668       }
669         }
670       if(token_number == 7)
671         {
672     try
673       {
674         buffer_number = (((new Integer(0)).valueOf(token)).intValue());
675       }
676     catch(Exception e)
677       {
678         System.err.println("Invalid buffer number token ("+token+") in "+configuration_file+" for "+buffer_name);
679         e.printStackTrace();
680       }
681     if(config_debug_on)
682       {
683         System.out.println("buffer_number = "+buffer_number);
684       }
685         }
686       int port_index = -1;
687       if(-1 != (port_index = token.indexOf("TCP=")))
688         {
689     protocol_option = NML_TCP_PROTOCOL_TYPE;
690     String port_string = token.substring(port_index+4);
691     if(config_debug_on)
692       {
693         System.out.println("Setting port number: port_string = "+port_string);
694       }
695     try
696       {
697         port = (((new Integer(0)).valueOf(port_string)).intValue());
698       }
699     catch(Exception e)
700       {
701         System.err.println("Invalid port token ("+token+") in "+configuration_file+" for "+buffer_name);
702         e.printStackTrace();
703       }
704     if(config_debug_on)
705       {
706         System.out.println("port = "+port);
707       }
708         }
709       if(-1 != (port_index = token.indexOf("diag")))
710         {
711     diag_enabled = true;
712         }
713       if(-1 != (port_index = token.indexOf("DIAG")))
714         {
715     diag_enabled = true;
716         }
717       if(-1 != (port_index = token.indexOf("STCP=")))
718         {
719     protocol_option = NML_STCP_PROTOCOL_TYPE;
720         }
721       if(-1 != (port_index = token.indexOf("UDP=")))
722         {
723     protocol_option = NML_UDP_PROTOCOL_TYPE;
724     String port_string = token.substring(port_index+4);
725     if(config_debug_on)
726       {
727         System.out.println("Setting port number: port_string = "+port_string);
728       }
729     try
730       {
731         port = (((new Integer(0)).valueOf(port_string)).intValue());
732       }
733     catch(Exception e)
734       {
735         System.err.println("Invalid port token ("+token+") in "+configuration_file+" for "+buffer_name);
736         e.printStackTrace();
737       }
738     if(config_debug_on)
739       {
740         System.out.println("port = "+port);
741       }
742         }
743       if(-1 != (port_index = token.indexOf("ascii")))
744         {
745     data_format_option = NML_ASCII_ENCODING_TYPE;
746         }
747       if(-1 != (port_index = token.indexOf("disp")))
748         {
749     data_format_option = NML_DISP_ENCODING_TYPE;
750         }
751       int version_index = token.toUpperCase().indexOf("VERSION=");
752       if(version_index >= 0)
753         {
754     try
755       {
756         String version_string = token.substring(version_index+8);
757         min_compatible_version = Double.valueOf(version_string).doubleValue();
758       }
759     catch(Exception e)
760       {
761         e.printStackTrace();
762       }
763         }
764       int confirm_write_index = token.toUpperCase().indexOf("CONFIRM_WRITE");
765       if(confirm_write_index >= 0)
766         {
767     confirm_write = true;
768         }
769       token_number++;
770           
771     } 
772   int broadcast_port_index = current_line.toUpperCase().indexOf("BROADCAST_PORT=");
773   if(broadcast_port_index >= 0)
774     {
775       String broadcast_port_string = current_line.substring(broadcast_port_index+15);
776       if(config_debug_on)
777         {
778     System.out.println("broadcast_port_string ="+broadcast_port_string );
779         }
780       StringTokenizer t2 = new StringTokenizer(broadcast_port_string,"\r\n \t");
781       String token2 = t2.nextToken();
782       broadcast_port = Integer.valueOf(token2).intValue();
783       if(config_debug_on)
784         {
785     System.out.println(" ="+broadcast_port);
786         }
787     }// end while loop parsing tokens on on line  
788   if(BufferLineFound)
789     {
790       if(buffer_size > 0)
791         {
792     input_buffer = new byte[buffer_size];
793     output_buffer = new byte[buffer_size];
794         }
795       switch(data_format_option)
796         {
797         case NML_XDR_ENCODING_TYPE:
798     SetFormatConverter(new XDRFormatConverter());
799     break;
800 
801         case NML_DISP_ENCODING_TYPE:
802     SetFormatConverter(new DISPFormatConverter());
803     break;
804 
805         default:
806     System.err.println("Invalid data_format_option.");
807     SetFormatConverter(new XDRFormatConverter());
808     break;
809         }
810     }
811   else
812     {
813       if(!ConfigurationFileRead)
814         {
815     System.err.println("Can not read configuration file "+configuration_file);
816         }
817       else
818         {
819     System.err.println("Can not find line for "+buffer_name+" in "+configuration_file);
820         }
821     }
822       }
823     catch(NMLException nml_e)
824       {
825   throw nml_e;
826       }
827     catch(Exception e)
828       {
829   System.err.println("Error reading NML configuration file "+configuration_file);
830   System.err.println("BufferName = "+buffer_name);
831   System.err.println("ProcessName = "+process_name);
832   if(null != current_line)
833     {
834       System.err.println("last line read = "+current_line);
835     }
836   e.printStackTrace();
837   throw new NMLException("Misc. Error",buffer_name,configuration_file,e);
838       }
839     if(!ConfigurationFileRead)
840       {
841   throw new NMLException("Can not open configuration file.", buffer_name,configuration_file);
842       }
843     if(!BufferLineFound)
844       {
845   throw new NMLException("Can not find buffer line.", buffer_name,configuration_file);
846       }
847     if(!ProcessLineFound)
848       {
849   System.err.println("NMLConnection : Can not find process line for "+process_name+" connecting to "+buffer_name+" in "+configuration_file);
850       }
851   }
852 
853   protected void finalize()
854   {
855     disconnect();
856   }
857 
858   
859 
860   /** 
861    * This function connects this NMLConnection object to a server.
862    * All attempts to read or write will fail while the object is 
863    * disconnected.
864    *
865    * Since the NMLConnection(NMLMessageDictionary, String, String,String)
866    * 
867    */
868   public int connect() throws NMLException 
869   {
870     try {
871       
872       /* 
873    FIXME: Netscape classes incompatible with newest JDK java.lang
874    try
875    {
876    if(rcs.utils.BrowserInfo.IsNetscapeFourOrLater())
877    {
878    try
879    {
880    netscape.security.PrivilegeManager.enablePrivilege("UniversalConnect");
881    }
882    catch(Exception e) 
883    {
884    System.err.println("Netscape denied this applet permission for  connecting to other computers. ("+e.getMessage()+")");
885    }
886    catch(LinkageError le)
887    {
888    le.printStackTrace();
889    }
890    }
891    } catch(Exception e)
892    {
893    }
894    */
895 
896       read_request_sent = false;
897       if(port <= 0)
898   {
899     return -1;
900   }
901       if(connected)
902   {
903     disconnect();
904   }
905       if(config_debug_on)
906   {
907     System.out.println("");
908     System.out.println("Connecting (port="+port+", protocol_option="+protocol_option+", host = "+host+") . . .");
909     System.out.println("");
910   }
911 
912       /* ****************************************************************** */
913       // javac now gives a warning if this Socket constructor is used,
914       // saying the method has been deprecated.
915       //m_Socket = new Socket(host,port,true);
916       /* ******************************************************************* */
917 
918       switch(protocol_option)
919   {
920   case NML_TCP_PROTOCOL_TYPE:
921   case NML_STCP_PROTOCOL_TYPE:
922     m_Socket = new Socket(host,port);
923     m_OutputStream = new DataOutputStream(m_Socket.getOutputStream());
924     m_InputStream = new DataInputStream(m_Socket.getInputStream());
925     break;
926     
927   case NML_UDP_PROTOCOL_TYPE:
928     if(broadcast_port > 0 && subscription_period > 1E-4 && subscription_period < 600.0)
929       {
930         udpSocket  = new NonBlockingDatagramSocket(broadcast_port);
931       }
932     else
933       {
934         udpSocket  = new NonBlockingDatagramSocket();
935       }
936     udpServerAddress = InetAddress.getByName(host);
937     baOutputStream = new ByteArrayOutputStream();
938     baInputStream = new ByteArrayInputStream(input_buffer);
939     m_OutputStream = new DataOutputStream(baOutputStream);
940     m_InputStream = new DataInputStream(baInputStream);
941     udpInputPacket = new DatagramPacket(input_buffer, buffer_size);
942     break;
943 
944   default:
945     return -1;
946   }
947       write_reply_received = true;
948       read_request_sent = false;
949       input_buffer_ready = false;
950       input_bytes_read = 0;
951       last_msg_read = null;
952       interrupt_login = false;
953       message_size = 0;
954       serial_number = 0;
955 
956       /*set = new SocketSet();
957   set.port = port;
958   set.m_Socket = m_Socket;
959   set.m_OutputStream = m_OutputStream;
960   set.m_InputStream = m_InputStream;
961   set.count = 1;
962   m_socketSetHashtable.put(portInteger, set); */
963       connected = true;
964       if(read_debug_on || write_debug_on || config_debug_on)
965   {
966     System.out.print("Socket openned to "+host+":"+port+".\r\n");
967   }
968       if(diag_enabled)
969   {
970     if(setDiagInfo() < 0)
971       {
972         throw new NMLException("Couldn't send diagnostics info",buffer_name, configuration_file);
973       }
974   }
975       if(subscription_period > 1E-4 && subscription_period < 600.0)
976   {
977     if(setSubscriptionPeriod(subscription_period) < 0)
978       {
979         throw new NMLException("Subscription error",buffer_name, configuration_file);
980       }
981   }
982       
983     } 
984     catch(NMLException nml_e)
985       {
986   throw nml_e;
987       } 
988     catch(Exception e)
989       {
990   System.err.println("\r\nCan't connect to port "+port+" on host "+host+"\r\n");
991   throw new NMLException("Connect error",buffer_name, configuration_file, e);
992       } 
993     return 0;
994   }
995 
996   /** 
997    * Disconnect this object from the NML server. This
998    * allows the NML server to shutdown and come back up 
999    * while preserving the configuration information in this
1000   * object.  
1001   *
1002   * All reads and writes will fail while the object is disconnected.
1003   */
1004  public void disconnect()
1005  {
1006    try{
1007      read_request_sent = false;
1008      /* SocketSet set;
1009   Integer portInteger = new Integer(port);
1010   set = (SocketSet) m_socketSetHashtable.get(portInteger);
1011   if(null != set)
1012   {
1013   set.count--;
1014   if(set.count <= 0)
1015   { 
1016   if(set.m_OutputStream != null)
1017   {
1018   set.m_OutputStream.close();
1019   set.m_OutputStream = null;
1020   }
1021   if(set.m_InputStream != null);
1022   {
1023   set.m_InputStream.close();
1024   set.m_InputStream = null;
1025   }
1026   if(set.m_Socket != null)
1027   {
1028   set.m_Socket.close();
1029   set.m_Socket = null;
1030   }
1031   m_socketSetHashtable.remove(portInteger);
1032   m_OutputStream = null;
1033   m_InputStream = null;
1034   m_Socket = null;
1035   System.out.print("\r\n Socket "+set.port+" closed. \r\n");
1036   return;
1037   }
1038         
1039   System.out.print("\r\n Socket "+port+" closed.\r\n");  
1040   return;
1041   }
1042   */
1043        
1044      if(protocol_option == NML_UDP_PROTOCOL_TYPE &&
1045   use_subscription && subscription_id > 0)
1046  {
1047    cancelUDPSubscription();
1048  }
1049
1050      if(connected)
1051  {
1052    if(m_OutputStream != null)
1053      {
1054        m_OutputStream.close();
1055        m_OutputStream = null;
1056      }
1057    if(m_InputStream != null);
1058    {
1059      m_InputStream.close();
1060      m_InputStream = null;
1061    }
1062    if(m_Socket != null)
1063      {
1064        m_Socket.close();
1065        m_Socket = null;
1066      }
1067    if(udpSocket != null)
1068      {
1069        udpSocket.close();
1070        udpSocket = null;
1071      }
1072    if(null != baOutputStream)
1073      {
1074        baOutputStream.reset();
1075      }
1076    baOutputStream = null;
1077    baInputStream = null;
1078    if(read_debug_on || write_debug_on || config_debug_on)
1079      {
1080        System.out.print("Socket "+port+" closed.\r\n");  
1081      }
1082  }
1083      connected = false;
1084    }
1085    catch(Exception e)
1086      {
1087  if(null != e.getMessage())
1088    {
1089      System.err.print("\r\n"+e.getMessage()+"\r\n");
1090    }
1091  e.printStackTrace();
1092      } 
1093  }
1094
1095  /**
1096   * This function allows the application to gain access to 
1097   * NML servers with security enabled.
1098   *
1099   * @param name the login name of the user running the client program
1100   * @param passwd the passwd of the user to login as.
1101   * @exception  rcs.nml.NMLException 
1102   *    If the login could not be attempted because the connection to the 
1103   *    NML server failed. (If the passwd is wrong it returns false.)
1104   *
1105   * @return true if login was successful
1106   */
1107  public boolean login(String name, String passwd)   throws NMLException
1108  {
1109    switch(protocol_option)
1110      {
1111      case NML_TCP_PROTOCOL_TYPE:
1112  return loginTCP(name, passwd);  
1113
1114      case NML_UDP_PROTOCOL_TYPE:
1115  return true;
1116      
1117      case NML_STCP_PROTOCOL_TYPE:
1118  return true;
1119  
1120      default:
1121  System.err.println("NMLConnection.read(): Invalid protocol_option = "+protocol_option+" -- buffer_name = "+buffer_name);
1122  return false;
1123      }  
1124      
1125  }
1126
1127  /** 
1128   * Read a NMLmsg.
1129   *
1130   * @return null if the message in the
1131   * buffer has already been read by this NMLConnection, otherwise it
1132   * returns the NMLmsg read.
1133   *
1134   * @exception  rcs.nml.NMLException 
1135   *    The read failed (ussually because of some network error).
1136   *    
1137   */
1138  public NMLmsg read()  throws NMLException
1139  {
1140    if(read_debug_on)
1141      {
1142  System.out.println("NMLConnection.peek() called for buffer ("+buffer_name+")");
1143      }
1144    switch(protocol_option)
1145      {
1146      case NML_TCP_PROTOCOL_TYPE:
1147  return readTCP();  
1148
1149      case NML_UDP_PROTOCOL_TYPE:
1150  return readUDP();
1151      
1152      case NML_STCP_PROTOCOL_TYPE:
1153  if(null == format_converter)
1154    {  
1155      return null;
1156    }
1157  NMLmsg temp = format_converter.convertStringToMsg(readSTCPDataString());
1158  if(format_converter.error_in_update)
1159    {
1160      throw new NMLException("Format Error",buffer_name, configuration_file);
1161    }
1162  return temp;
1163
1164      default:
1165  System.err.println("NMLConnection.read(): Invalid protocol_option = "+protocol_option+" -- buffer_name = "+buffer_name);
1166  return null;
1167      }  
1168    //    return null;
1169  }
1170   
1171  public int setDiagInfo()
1172  {
1173    switch(protocol_option)
1174      {
1175      case NML_TCP_PROTOCOL_TYPE:
1176  return setTCPDiagInfo();  
1177
1178      default:
1179  break;
1180      }
1181    return -1;
1182  }
1183
1184  protected int setTCPDiagInfo()
1185  {
1186    try
1187      {
1188  if(null == m_OutputStream || null == m_InputStream)
1189    {
1190      return -1;
1191    }
1192  m_OutputStream.writeInt(serial_number);
1193  serial_number++;
1194  request_type = REMOTE_CMS_SET_DIAG_INFO_REQUEST_TYPE;
1195  m_OutputStream.writeInt(request_type);
1196  m_OutputStream.writeInt(buffer_number);
1197  int pad=0;
1198  m_OutputStream.writeInt(pad);
1199  m_OutputStream.writeInt(pad);
1200  byte bname[] = new byte[32];
1201  String temp_process_name = process_name;
1202  if(temp_process_name.length() > 15)
1203    {
1204      temp_process_name = temp_process_name.substring(0,15);
1205    }
1206  m_OutputStream.writeBytes(temp_process_name);
1207  
1208  int extra_bytes = 16-temp_process_name.length();
1209  if(config_debug_on)
1210    {
1211      System.out.println("setTCPDiagInfo(): temp_process_name="+temp_process_name+", extra_bytes="+extra_bytes);
1212    }
1213  if(extra_bytes > 0)
1214    {
1215      m_OutputStream.write(bname,0,extra_bytes);
1216    }
1217  String host_sysinfo = "";
1218  try
1219    {
1220      InetAddress local_host = InetAddress.getLocalHost();
1221      if(null != local_host)
1222        {
1223    String host_name = local_host.getHostName();
1224    if(null != host_name)
1225      {
1226        host_sysinfo += host_name+", ";
1227      }
1228        }
1229    }
1230  catch(Exception e)
1231    {
1232      e.printStackTrace();
1233    }
1234  try
1235    {
1236      String java_version = System.getProperty("java.version");
1237      if(null != java_version)
1238        {
1239    if(Character.isDigit(java_version.charAt(0)))
1240      {
1241        java_version = "Java "+java_version;
1242      }
1243    host_sysinfo += java_version+", ";
1244        }
1245      String os_name = System.getProperty("os.name");
1246      if(null != os_name)
1247        {
1248    host_sysinfo += os_name+" ";
1249        }
1250      String os_version = System.getProperty("os.version");
1251      if(null != os_version)
1252        {
1253    host_sysinfo += os_version+", ";
1254        }
1255      String os_arch = System.getProperty("os.arch");
1256      if(null != os_arch)
1257        {
1258    host_sysinfo += os_arch;
1259        }
1260    }
1261  catch(Exception e)
1262  {
1263    e.printStackTrace();
1264  }
1265  if(host_sysinfo.length() > 31)
1266    {
1267      host_sysinfo = host_sysinfo.substring(0,31);
1268    }
1269  m_OutputStream.writeBytes(host_sysinfo);
1270  if(host_sysinfo.length() < 32)
1271    {
1272      m_OutputStream.write(bname,host_sysinfo.length(),32-host_sysinfo.length());
1273    }
1274
1275  int pid = 0;
1276  m_OutputStream.writeInt(pid);
1277  m_OutputStream.writeInt(connection_number);
1278  double rcslib_ver = 0.0;
1279  try 
1280    {
1281      rcslib_ver = Double.valueOf(rcs.RCS_VERSION.version_string).doubleValue();
1282    }
1283  catch(Exception e)
1284    {
1285      e.printStackTrace();
1286    }
1287  m_OutputStream.writeDouble(rcslib_ver);
1288  int reverse_flag = 0x01020304;
1289  m_OutputStream.writeInt(reverse_flag);
1290  m_OutputStream.flush();
1291  return 0;
1292      }
1293    catch(Exception e)
1294      {
1295  e.printStackTrace();
1296  return -1;
1297      }
1298  }
1299
1300
1301  public int setSubscriptionPeriod( double period)
1302  {
1303
1304    switch(protocol_option)
1305      {
1306      case NML_TCP_PROTOCOL_TYPE:
1307  return setTCPSubscriptionPeriod(period);  
1308
1309      case NML_UDP_PROTOCOL_TYPE:
1310  return setUDPSubscriptionPeriod(period);
1311  
1312      default:
1313  System.err.println("No subscriptions allowed for protocol_option "+protocol_option);
1314  break;
1315      }
1316    return -1;
1317  }
1318
1319  protected int setUDPSubscriptionPeriod(double period)
1320  {
1321    if(min_compatible_version < 3.13 && min_compatible_version >  1e-6)
1322      {
1323  return 0;
1324      }
1325    boolean subscription_set = false;
1326    int subscription_interval_millis = (int) (period*1000);
1327    long start_set_subscription_interval = System.currentTimeMillis();
1328    reply_header_received = false;
1329    try
1330      {
1331  while(!subscription_set)
1332    {
1333      if(!udpSocket.ready((int) udpRetryTimeoutMillis))
1334        {
1335    input_buffer_ready = false;
1336    m_OutputStream.flush();
1337    baOutputStream.reset();
1338    request_type = REMOTE_CMS_SET_SUBSCRIPTION_REQUEST_TYPE;
1339    m_OutputStream.writeInt(request_type);
1340    m_OutputStream.writeInt(buffer_number);
1341    if(reply_header_received)
1342      {
1343        serial_number++;
1344      }
1345    m_OutputStream.writeInt(serial_number);
1346    m_OutputStream.writeInt(CMS_POLLED_SUBSCRIPTION);
1347    m_OutputStream.writeInt(subscription_interval_millis);
1348    m_OutputStream.writeInt(last_id_read);
1349    read_request_sent = true;
1350    reply_header_received = false;
1351    if(read_debug_on)
1352      {
1353        System.out.println("UDP setSubscription request sent.");
1354        System.out.println("serial_number = "+serial_number+", request_type = "+request_type+", buffer_number = "+buffer_number);
1355        System.out.println("access_type = "+access_type+", last_id_read = "+last_id_read+" -- buffer_name = "+buffer_name);
1356        System.out.println("lastUdpRequestTime = "+lastUdpRequestTime);
1357      }   
1358    m_OutputStream.flush();
1359    byte ba[] = baOutputStream.toByteArray();
1360    int request_length = 24;
1361    if(ba.length < request_length)
1362      {
1363        throw new NMLException("Insufficient output byte array size.",buffer_name, configuration_file);
1364      }
1365    DatagramPacket dp = new DatagramPacket(ba,request_length,udpServerAddress, port);
1366    udpSocket.send(dp);
1367    if(null == udpSocket.currentPacket)
1368      {
1369        udpInputPacket = new DatagramPacket(input_buffer, buffer_size);
1370        udpSocket.receive(udpInputPacket);
1371      }
1372    lastUdpRequestTime = System.currentTimeMillis();
1373        }
1374      else
1375        {
1376    baInputStream.reset();
1377    int returned_serial_number = m_InputStream.readInt();
1378    if(read_debug_on)
1379      {
1380        System.out.println("UDP setSubscription reply received.");
1381        System.out.println("returned_serial_number = "+returned_serial_number);
1382      }
1383    if(returned_serial_number != serial_number)
1384      {
1385        serial_number_repeats++;
1386        if(read_debug_on)
1387          {
1388      System.out.println("serial_number="+serial_number+", returned_serial_number="+returned_serial_number+",serial_number_repeats ="+serial_number_repeats);
1389          }
1390        udpInputPacket = new DatagramPacket(input_buffer, buffer_size);
1391        udpSocket.receive(udpInputPacket);
1392        continue;
1393      }
1394    reply_header_received = true;
1395    remote_status = m_InputStream.readInt();
1396    subscription_id =  m_InputStream.readInt();
1397    if(read_debug_on)
1398      {
1399        System.out.println("remote_status = "+remote_status+", buffer_number = "+buffer_number);
1400        System.out.println(" -- buffer_name = "+buffer_name);
1401      }   
1402    udpSocket.lastPacket = null;
1403    subscription_set = true;
1404    use_subscription = true;
1405    continue;
1406        }
1407    }
1408  Thread.sleep(10);
1409  if(start_set_subscription_interval - System.currentTimeMillis() > 3000)
1410    {
1411      System.err.println("Timed out trying to setup the subscription.");
1412      return -1;
1413    }
1414      }
1415    catch(Exception e)
1416      {
1417  e.printStackTrace();
1418  return -1;
1419      }
1420    return 0;
1421  }
1422
1423 protected int cancelUDPSubscription()
1424  {
1425    if(min_compatible_version < 3.13 && min_compatible_version >  1e-6)
1426      {
1427  return 0;
1428      }
1429    boolean subscription_set = false;
1430    long start_set_subscription_interval = System.currentTimeMillis();
1431    reply_header_received = false;
1432    try
1433      {
1434  while(!subscription_set)
1435    {
1436      if(!udpSocket.ready((int) udpRetryTimeoutMillis))
1437        {
1438    input_buffer_ready = false;
1439    m_OutputStream.flush();
1440    baOutputStream.reset();
1441    request_type = REMOTE_CMS_CANCEL_SUBSCRIPTION_REQUEST_TYPE;
1442    m_OutputStream.writeInt(request_type);
1443    m_OutputStream.writeInt(buffer_number);
1444    if(reply_header_received)
1445      {
1446        serial_number++;
1447      }
1448    m_OutputStream.writeInt(serial_number);
1449    m_OutputStream.writeInt(subscription_id);
1450    m_OutputStream.writeInt(0);
1451    m_OutputStream.writeInt(0);
1452    read_request_sent = true;
1453    reply_header_received = <