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