src/java/isac/bridge/BridgeMain.java
author mlang
Tue, 28 Jun 2005 13:14:03 +0200
changeset 2544 631fe7f467b7
parent 2448 f6065237ac78
child 2707 6973cc026d5d
permissions -rw-r--r--
cosmetics part2
     1 /*
     2  * Created on Aug 13, 2003
     3  */
     4 package isac.bridge;
     5 
     6 /**
     7  * BridgeMain: main class for bridge, does initialization and provides logging
     8  * delegate and utility functionality.
     9  * 
    10  * @author rgradisc
    11  * @version 1.1
    12  */
    13 
    14 
    15 import java.awt.BorderLayout;
    16 import java.awt.Color;
    17 import java.awt.Font;
    18 import java.awt.event.WindowAdapter;
    19 import java.awt.event.WindowEvent;
    20 import java.awt.event.WindowListener;
    21 import java.io.BufferedReader;
    22 import java.io.File;
    23 import java.io.FileInputStream;
    24 import java.io.FileNotFoundException;
    25 import java.io.IOException;
    26 import java.io.InputStream;
    27 import java.io.InputStreamReader;
    28 import java.io.OutputStream;
    29 import java.io.PrintWriter;
    30 import java.rmi.RemoteException;
    31 import java.util.Properties;
    32 import java.util.Vector;
    33 
    34 import javax.swing.JFrame;
    35 import javax.swing.JPanel;
    36 import javax.swing.JScrollPane;
    37 import javax.swing.JTextArea;
    38 
    39 import org.apache.log4j.Logger;
    40 
    41 /**
    42  * Bridge main class: initializes connection to SML, starts auxillary threads,
    43  * handles logging mechanism
    44  * 
    45  * @author rgradisc
    46  */
    47 class BridgeMain extends JFrame {
    48 
    49     private String ini_path_;
    50 
    51     private int socket_port_;
    52 
    53     private String path_;
    54 
    55     private String kernel_exec_;
    56 
    57     private String kernel_args_;
    58 
    59     private long wait_millis_;
    60 
    61     private final static int TRANS_STRING = 1;
    62 
    63     private final static int TRANS_MATHML = 2;
    64 
    65     private int transport_mode_ = TRANS_STRING;
    66 
    67     JPanel panel_;
    68 
    69     JTextArea text_area_;
    70 
    71     JScrollPane scroll_pane_;
    72 
    73     private Thread thread_clients2kernel_;
    74 
    75     private Thread thread_sml_;
    76 
    77     private Thread thread_kernel2clients_;
    78 
    79     private Thread thread_time_checker_;
    80 
    81     private ClientList client_list_;
    82 
    83     private BridgeLogger bridge_logger_;
    84 
    85     private OutputStream sml_output_;
    86 
    87     private InputStream sml_input_;
    88 
    89     private PrintWriter sml_writer_;
    90 
    91     private BufferedReader sml_reader_;
    92 
    93     private Vector time_out_times_;
    94 
    95     public int ignore_output_ = 0;
    96 
    97     private BridgeRMI bridge_rmi_; // multiple RMI connections: Vector
    98 
    99     private boolean restoring_; // true = bridge is in restoring_ phase
   100 
   101     private boolean kernel_responding_ = true;
   102 
   103     static Logger logger_ = Logger.getLogger(BridgeMain.class.getName());
   104 
   105     /**
   106      * Constructor used to set up the bridge main program
   107      * 
   108      * @param ini_path_:
   109      *            path_ to initialization file
   110      */
   111     BridgeMain(String iniPath) {
   112         //hack for suppressing warning messages
   113         //(no longer nescessary with j2sdk1.4.2)
   114         //System.setProperty("java.util.prefs.syncInterval", "20000000000");
   115 
   116         logger_.warn("BridgeMain obj.init: ini_path_=" + iniPath);
   117         this.ini_path_ = iniPath;
   118         readProperties();
   119 
   120         bridge_logger_ = new BridgeLogger(path_);
   121         client_list_ = new ClientList();
   122         time_out_times_ = new Vector();
   123         setUpBridgeLog();
   124         startThreadsFirstTime();
   125     }
   126 
   127     private void setUpBridgeLog() {
   128         this.setLocation(700, 250);
   129         panel_ = new JPanel();
   130         panel_.setSize(200, 300);
   131         panel_.setLayout(new BorderLayout());
   132         panel_.setBackground(Color.white);
   133 
   134         text_area_ = new JTextArea();
   135         text_area_.setFont(new Font("Monospaced", 0, 11));
   136         scroll_pane_ = new JScrollPane(text_area_,
   137                 JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
   138                 JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
   139         panel_.add("Center", scroll_pane_);
   140         getContentPane().add(panel_);
   141 
   142         setTitle("BridgeLog Java <=> SML");
   143         WindowListener l = new WindowAdapter() {
   144 
   145             public void windowClosing(WindowEvent e) {
   146                 System.exit(0);
   147             }
   148         };
   149         addWindowListener(l);
   150         pack();
   151         this.setSize(300, 500);
   152         this.show();
   153     }
   154 
   155     // Read Bridge properties from Files
   156     private void readProperties() {
   157         Properties p = new Properties();
   158         String prop;
   159         try {
   160             p.load(new FileInputStream(ini_path_));
   161             prop = p.getProperty("transportMode");
   162             if (prop.equals("string")) {
   163                 transport_mode_ = TRANS_STRING;
   164             } else if (prop.equals("mathml")) {
   165                 transport_mode_ = TRANS_MATHML;
   166             } else {
   167                 System.out.println("INI-File: transport_mode_ value not valid");
   168                 System.exit(1);
   169             }
   170             System.out.println("transport_mode_ = " + transport_mode_);
   171 
   172             prop = p.getProperty("socketPort");
   173             try {
   174                 socket_port_ = Integer.valueOf(prop).intValue();
   175             } catch (NumberFormatException e1) {
   176                 System.out.println("INI-File: socketport is not a number!");
   177                 System.exit(1);
   178             }
   179             Float.floatToIntBits(3.14f);
   180             System.out.println("socket_port_ = " + socket_port_);
   181 
   182             prop = p.getProperty("path");
   183             File f = new File(prop);
   184             if (f.isDirectory()) {
   185                 path_ = prop;
   186             } else {
   187                 System.out.println("INI-File: path_ is not a valid directory!");
   188                 System.exit(1);
   189             }
   190             System.out.println("path_ = " + path_);
   191 
   192             prop = p.getProperty("waitMillis");
   193             try {
   194                 wait_millis_ = Long.valueOf(prop).longValue();
   195             } catch (NumberFormatException e1) {
   196                 System.out.println("INI-File: wait_millis_ is not a number!");
   197                 System.exit(1);
   198             }
   199             System.out.println("wait_millis_ = " + wait_millis_);
   200 
   201             kernel_exec_ = p.getProperty("kernelExec");
   202             kernel_args_ = p.getProperty("kernelArgs");
   203 
   204         } catch (FileNotFoundException e) {
   205             System.out.println("Couldn't open INI File");
   206             System.exit(1);
   207         } catch (IOException e) {
   208             System.out.println("Couldn't read INI File");
   209             System.exit(1);
   210         }
   211     }
   212 
   213     //Start sml Threads and catch in- and output-streams
   214     private void startSMLThread() {
   215         logger_.warn("startSMLThread");
   216         SMLThread smlThread = new SMLThread(this, kernel_exec_, kernel_args_);
   217         thread_sml_ = new Thread(smlThread, "java_bridge_execution");
   218         thread_sml_.setDaemon(true);
   219         // daemon threads: discontinue running after main application is
   220         // finished
   221         log(1, "SML Execution Thread starting...");
   222         thread_sml_.start();
   223         log(1, "SML Execution Thread started");
   224         sml_input_ = smlThread.getInputStream();
   225         log(1, "SML input stream");
   226         sml_output_ = smlThread.getOutputStream();
   227         log(1, "SML output stream");
   228         //old IO:
   229         sml_writer_ = new PrintWriter(sml_output_, true);
   230         //NIO (doesn't run for some reason)
   231         //    sml_writer_ =
   232         //      new PrintWriter(
   233         //        Channels.newWriter(Channels.newChannel(sml_output_), "ISO-8859-1"));
   234         //old IO:
   235         sml_reader_ = new BufferedReader(new InputStreamReader(sml_input_));
   236         //NIO:
   237         //    sml_reader_ =
   238         //      new BufferedReader(
   239         //        Channels.newReader(Channels.newChannel(sml_input_), "ISO-8859-1"));
   240 
   241         log(1, "SML in/output streams fetched");
   242         //log(1, sml_writer_.toString());
   243         //log(1, sml_reader_.toString());
   244     }
   245 
   246     private void startThreadsFirstTime() {
   247         logger_.warn("startThreadsFirstTime");
   248         startSMLThread();
   249 
   250         Clients2KernelServer c2k = new Clients2KernelServer(this);
   251         thread_clients2kernel_ = new Thread(c2k, "java_bridge_clients2kernel");
   252         thread_clients2kernel_.setDaemon(true);
   253         thread_clients2kernel_.start();
   254         log(1, "Clients2Kernel Thread started");
   255 
   256         Kernel2ClientsServer k2c = new Kernel2ClientsServer(this);
   257         thread_kernel2clients_ = new Thread(k2c, "java_bridge_kernel2clients");
   258         thread_kernel2clients_.setDaemon(true);
   259         thread_kernel2clients_.start();
   260         log(1, "Kernel2Clients Thread started");
   261 
   262         thread_time_checker_ = new TimeCheckerThread(this, wait_millis_);
   263         thread_time_checker_.setDaemon(true);
   264         thread_time_checker_.start();
   265         log(1, "TimeChecker Thread started");
   266     }
   267 
   268     public void restartSML() {
   269         log(1, "No response from sml-kernel: restart");
   270         time_out_times_.clear();
   271         log(1, "Trying to kill sml-kernel...");
   272         while (thread_sml_.isAlive()) {
   273             thread_sml_.interrupt();
   274         }
   275         log(1, "Successfully killed sml-kernel");
   276 
   277         try {
   278             log(1, "BridgeMain: trying to close reader/writer");
   279             sml_reader_.close();
   280             sml_writer_.close();
   281             log(1, "BridgeMain: closed reader/writer");
   282         } catch (IOException e) {
   283             log(1, "BridgeMain: couldn't close reader/writer");
   284         }
   285         startSMLThread();
   286         restoreStateOfKernel();
   287     }
   288 
   289     // This method restores the last consistent state of the kernel
   290     // It will be called when the sml kernel crashes
   291     private void restoreStateOfKernel() {
   292         //test first if kernel is still responding:
   293         //if this is the case, no further restoring_ is needed
   294         //dummy call to test respondablity
   295         //it could be also work to send a SIGINT (^C in terminal)
   296         //to the not reacting sml-Kernel
   297         //But this is not possible in Java (only with C in JNI)
   298         try {
   299             while (!kernel_responding_) {
   300                 sml_writer_.println("DEconstrCalcTree 0;");
   301                 // if the kernel responds to this instruction, it has
   302                 // not crashed: no restarting nescessary
   303                 if (sml_reader_.ready()) {
   304                     Thread.sleep(1000);
   305                     sml_reader_.readLine();
   306                     kernel_responding_ = true;
   307                 }
   308             }
   309         } catch (Exception e) {
   310         }
   311         if (!kernel_responding_) {
   312             log(1, "Kernel is not responding: now restarting");
   313             this.restoring_ = true;
   314         }
   315         /*
   316          * Vector inputs = bridge_rmi_.getInputs();
   317          */
   318         /*
   319          * Iterator it = newInputs.iterator(); while (it.hasNext()) { int
   320          * clientID = ((ClientInput)it.next()).getClientID();
   321          * client_list_.getPrintWriterOfClient(clientID).println(" <FATALERROR>
   322          * </FATALERROR>"); }
   323          */
   324         log(1, "------ now restoring_ state of kernel");
   325         this.restoring_ = true;
   326         //send empty response string to blocking client
   327         client_list_.getPrintWriterOfClient(bridge_rmi_.getRmiID()).println(
   328                 "<ISAC></ISAC>");
   329         log(1, "------ restoreExistingCalcTrees()");
   330         bridge_rmi_.restoreExistingCalcTrees();
   331         //TODO: bridge_rmi_.deleteLastBufferInput();
   332         this.restoring_ = false;
   333         log(1, "------ done restoring_ state of kernel");
   334         /*
   335          * ignore_output_ = inputs.size(); Iterator it = inputs.iterator();
   336          * while (it.hasNext()) { ClientInput clientInput =
   337          * (ClientInput)it.next(); String input = clientInput.getInputLine();
   338          * log(1, "user "+clientInput.getClientID()+" ---> " + input); //Resend
   339          * user input to sml sml_writer_.println(input); time_out_times_.add(new
   340          * Long(System.currentTimeMillis())); }
   341          */
   342     }
   343 
   344     //Here goes the future load balancing functionality
   345     //public void startNewKernel() {
   346     // implement load balancing
   347     //}
   348 
   349     protected void finalize() throws Throwable {
   350         super.finalize(); //gosling p.47
   351         //Objects created in run method are finalized when
   352         //program terminates and thread exits
   353         while (thread_sml_.isAlive()) {
   354             thread_sml_.interrupt();
   355             log(1, "waiting for SML thread to quit..");
   356         }
   357         bridge_logger_.log(1, "finished");
   358         bridge_logger_.close();
   359     }
   360 
   361     /**
   362      * Log a message with a specified severity level
   363      * 
   364      * @param level
   365      *            severity level
   366      * @param msg
   367      *            the message to be logged
   368      */
   369     public void log(int level, String msg) {
   370         this.bridge_logger_.log(level, msg);
   371         this.text_area_.append(msg + "\n");
   372     }
   373 
   374     public ClientList getClientList() {
   375         return client_list_;
   376     }
   377 
   378     public BufferedReader getSmlReader() {
   379         logger_.warn("getSmlReader x");
   380         return sml_reader_;
   381     }
   382 
   383     public PrintWriter getSmlWriter() {
   384         return sml_writer_;
   385     }
   386 
   387     public Vector getTimeOutTimes() {
   388         return time_out_times_;
   389     }
   390 
   391     public String getPath() {
   392         return path_;
   393     }
   394 
   395     public int getSocketPort() {
   396         return socket_port_;
   397     }
   398 
   399     public void setRMI(BridgeRMI bridgeRMI) {
   400         logger_.warn("setRMI: bridge_rmi_=" + bridgeRMI);
   401         this.bridge_rmi_ = bridgeRMI;
   402         bridgeRMI.setRmiID(1); //only one BridgeRMI used so far
   403     }
   404 
   405     boolean isRestoring() {
   406         return restoring_;
   407     }
   408 
   409     void setRestoring(boolean b) {
   410         restoring_ = b;
   411     }
   412 
   413     /**
   414      * @param args
   415      *            commandline arguments (exactly 4 expected: _iniPath _host
   416      *            _port _dtdPath)
   417      * @see BridgeMain()
   418      */
   419     public static void main(String[] args) {
   420         if (args.length != 4) {
   421             System.out
   422                     .println("Usage: java BridgeMain _iniPath _host _port _dtdPath");
   423         } else {
   424             // initialize bridge main part
   425             BridgeMain bridge = new BridgeMain(args[0]);
   426 
   427             try {
   428                 // setup rmi connection to to the clients
   429                 BridgeRMI rmi = new BridgeRMI(bridge, args[1], Integer
   430                         .parseInt(args[2]), args[3]);
   431                 bridge.setRMI(rmi);
   432             } catch (RemoteException e) {
   433                 System.out.println("Could not instantiate RMI: exiting");
   434                 e.printStackTrace();
   435             }
   436         }
   437     }
   438 }