src/java/isac/bridge/BridgeMain.java
author rgradisc
Wed, 29 Oct 2003 16:56:23 +0100
changeset 1067 36d8c3cdfe45
parent 1066 1e6bb22dbfbf
child 1072 de92eb07857e
permissions -rw-r--r--
*** empty log message ***
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
/**
rgradisc@859
     7
 * BridgeMain: main class for bridge, does initialization and 
rgradisc@859
     8
 * provides logging delegate and utility function.
rgradisc@859
     9
 * @author rgradisc
rgradisc@859
    10
 */
rgradisc@859
    11
rgradisc@859
    12
import java.awt.BorderLayout;
rgradisc@859
    13
import java.awt.Color;
rgradisc@1066
    14
import java.awt.Font;
rgradisc@859
    15
import java.awt.event.WindowAdapter;
rgradisc@859
    16
import java.awt.event.WindowEvent;
rgradisc@859
    17
import java.awt.event.WindowListener;
rgradisc@859
    18
import java.io.BufferedReader;
rgradisc@1035
    19
import java.io.File;
rgradisc@859
    20
import java.io.FileInputStream;
rgradisc@859
    21
import java.io.FileNotFoundException;
rgradisc@859
    22
import java.io.IOException;
rgradisc@859
    23
import java.io.InputStream;
rgradisc@859
    24
import java.io.InputStreamReader;
rgradisc@859
    25
import java.io.OutputStream;
rgradisc@859
    26
import java.io.PrintWriter;
rgradisc@1065
    27
import java.rmi.RemoteException;
rgradisc@859
    28
import java.util.Iterator;
rgradisc@859
    29
import java.util.Properties;
rgradisc@859
    30
import java.util.Vector;
rgradisc@859
    31
rgradisc@859
    32
import javax.swing.JFrame;
rgradisc@859
    33
import javax.swing.JPanel;
rgradisc@859
    34
import javax.swing.JScrollPane;
rgradisc@859
    35
import javax.swing.JTextArea;
rgradisc@859
    36
rgradisc@1065
    37
/**
rgradisc@1065
    38
 * Bridge main class: initializes connection to SML, 
rgradisc@1065
    39
 * starts auxillary threads 
rgradisc@1065
    40
 * @author rgradisc
rgradisc@1065
    41
 */
rgradisc@859
    42
class BridgeMain extends JFrame {
rgradisc@859
    43
  private String iniPath;
rgradisc@859
    44
  private int socketPort;
rgradisc@859
    45
  private String path;
rgradisc@859
    46
  private String kernelExec;
rgradisc@859
    47
  private String kernelArgs;
rgradisc@859
    48
  private long waitMillis;
rgradisc@859
    49
rgradisc@859
    50
  private final static int TRANS_STRING = 1;
rgradisc@859
    51
  private final static int TRANS_MATHML = 2;
rgradisc@859
    52
rgradisc@859
    53
  private int transportMode = TRANS_STRING;
rgradisc@859
    54
rgradisc@859
    55
  JPanel panel;
rgradisc@859
    56
  JTextArea textArea;
rgradisc@859
    57
  JScrollPane scrollPane;
rgradisc@859
    58
rgradisc@859
    59
  private Thread thread_clients2ki; // Load-Balancing: Vector
rgradisc@859
    60
  private Thread thread_sml; // Load-Balancing: Vector
rgradisc@859
    61
  private Thread thread_ki2clients; // Load-Balancing: Vector  
rgradisc@859
    62
  private Thread thread_timeChecker; // Load-Balancing: Vector
rgradisc@1065
    63
rgradisc@859
    64
  private ClientList clientList;
rgradisc@859
    65
  private BridgeLogger bridgeLogger;
rgradisc@859
    66
rgradisc@859
    67
  private OutputStream smlOutput; // Load-Balancing: Vector
rgradisc@859
    68
  private InputStream smlInput; // Load-Balancing: Vector  
rgradisc@859
    69
  private PrintWriter smlWriter; // Load-Balancing: Vector
rgradisc@859
    70
  private BufferedReader smlReader; // Load-Balancing: Vector 
rgradisc@859
    71
rgradisc@859
    72
  private Vector timeOutTimes;
rgradisc@859
    73
  public int ignoreOutput = 0; // Load-Balancing: Vector  
rgradisc@859
    74
rgradisc@859
    75
  private Vector newInputs;
rgradisc@859
    76
  private Vector answeredInputs;
rgradisc@1035
    77
rgradisc@989
    78
  private BridgeRMI rmi;
rgradisc@859
    79
rgradisc@859
    80
  //---------------------------------------------------------------
rgradisc@859
    81
  /**
rgradisc@859
    82
   * Constructor used to set up the bridge main program
rgradisc@864
    83
   * @param iniPath: path to initialization file
rgradisc@859
    84
   */
rgradisc@859
    85
  BridgeMain(String iniPath) {
rgradisc@1065
    86
    //FIXME: hack for suppressing warning messages  
rgradisc@1065
    87
    System.setProperty("java.util.prefs.syncInterval", "2000000");
rgradisc@1065
    88
rgradisc@859
    89
    this.iniPath = iniPath;
rgradisc@859
    90
    readProperties();
rgradisc@859
    91
rgradisc@859
    92
    bridgeLogger = new BridgeLogger(path);
rgradisc@859
    93
    clientList = new ClientList();
rgradisc@859
    94
    timeOutTimes = new Vector();
rgradisc@859
    95
    newInputs = new Vector();
rgradisc@859
    96
    answeredInputs = new Vector();
rgradisc@859
    97
    setUpGUI();
rgradisc@1065
    98
    startThreadsFirstTime();    
rgradisc@859
    99
  }
rgradisc@859
   100
rgradisc@865
   101
  //--------------------------------------------------------------- 
rgradisc@1056
   102
  private void setUpGUI() {
rgradisc@1056
   103
    this.setLocation(700, 250);
rgradisc@859
   104
    panel = new JPanel();
rgradisc@1056
   105
    panel.setSize(200, 300);
rgradisc@859
   106
    panel.setLayout(new BorderLayout());
rgradisc@859
   107
    panel.setBackground(Color.white);
rgradisc@859
   108
rgradisc@859
   109
    textArea = new JTextArea();
rgradisc@1067
   110
    textArea.setFont(new Font("Monospaced", 0, 11));
rgradisc@859
   111
    scrollPane =
rgradisc@859
   112
      new JScrollPane(
rgradisc@859
   113
        textArea,
rgradisc@859
   114
        JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
rgradisc@859
   115
        JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
rgradisc@859
   116
    panel.add("Center", scrollPane);
rgradisc@859
   117
    getContentPane().add(panel);
rgradisc@859
   118
rgradisc@859
   119
    setTitle("Bridge Server Program");
rgradisc@859
   120
    WindowListener l = new WindowAdapter() {
rgradisc@859
   121
      public void windowClosing(WindowEvent e) {
rgradisc@859
   122
        System.exit(0);
rgradisc@859
   123
      }
rgradisc@859
   124
    };
rgradisc@859
   125
    addWindowListener(l);
rgradisc@1056
   126
    pack();
rgradisc@1056
   127
    this.setSize(300, 500);
rgradisc@1035
   128
    this.show();
rgradisc@859
   129
  }
rgradisc@859
   130
rgradisc@859
   131
  //---------------------------------------------------------------
rgradisc@859
   132
  private void readProperties() {
rgradisc@859
   133
    Properties p = new Properties();
rgradisc@859
   134
    String prop;
rgradisc@859
   135
    try {
rgradisc@859
   136
      p.load(new FileInputStream(iniPath));
rgradisc@859
   137
      prop = p.getProperty("transportMode");
rgradisc@859
   138
      if (prop.equals("string")) {
rgradisc@859
   139
        transportMode = TRANS_STRING;
rgradisc@859
   140
      } else if (prop.equals("mathml")) {
rgradisc@859
   141
        transportMode = TRANS_MATHML;
rgradisc@859
   142
      } else {
rgradisc@859
   143
        System.out.println("INI-File: transportMode value not valid");
rgradisc@859
   144
        System.exit(1);
rgradisc@859
   145
      }
rgradisc@859
   146
      System.out.println("transportMode = " + transportMode);
rgradisc@859
   147
rgradisc@859
   148
      prop = p.getProperty("socketPort");
rgradisc@859
   149
      try {
rgradisc@859
   150
        socketPort = Integer.valueOf(prop).intValue();
rgradisc@859
   151
      } catch (NumberFormatException e1) {
rgradisc@859
   152
        System.out.println("INI-File: socketport is not a number!");
rgradisc@859
   153
        System.exit(1);
rgradisc@859
   154
      }
rgradisc@859
   155
      System.out.println("socketPort = " + socketPort);
rgradisc@859
   156
rgradisc@859
   157
      prop = p.getProperty("path");
rgradisc@859
   158
      File f = new File(prop);
rgradisc@859
   159
      if (f.isDirectory()) {
rgradisc@859
   160
        path = prop;
rgradisc@859
   161
      } else {
rgradisc@859
   162
        System.out.println("INI-File: path is not a valid directory!");
rgradisc@859
   163
        System.exit(1);
rgradisc@859
   164
      }
rgradisc@859
   165
      System.out.println("path = " + path);
rgradisc@859
   166
rgradisc@859
   167
      prop = p.getProperty("waitMillis");
rgradisc@859
   168
      try {
rgradisc@859
   169
        waitMillis = Long.valueOf(prop).longValue();
rgradisc@859
   170
      } catch (NumberFormatException e1) {
rgradisc@859
   171
        System.out.println("INI-File: waitMillis is not a number!");
rgradisc@859
   172
        System.exit(1);
rgradisc@859
   173
      }
rgradisc@859
   174
      System.out.println("waitMillis = " + waitMillis);
rgradisc@859
   175
rgradisc@859
   176
      kernelExec = p.getProperty("kernelExec");
rgradisc@859
   177
      kernelArgs = p.getProperty("kernelArgs");
rgradisc@859
   178
rgradisc@859
   179
    } catch (FileNotFoundException e) {
rgradisc@859
   180
      System.out.println("Couldn't open INI File");
rgradisc@859
   181
      System.exit(1);
rgradisc@859
   182
    } catch (IOException e) {
rgradisc@859
   183
      System.out.println("Couldn't read INI File");
rgradisc@859
   184
      System.exit(1);
rgradisc@859
   185
    }
rgradisc@859
   186
  }
rgradisc@859
   187
rgradisc@859
   188
  //---------------------------------------------------------------
rgradisc@859
   189
  private void startSMLThread() {
rgradisc@859
   190
    SMLThread smlThread = new SMLThread(this, kernelExec, kernelArgs);
rgradisc@859
   191
    thread_sml = new Thread(smlThread, "java_bridge_execution");
rgradisc@859
   192
    thread_sml.setDaemon(true);
rgradisc@859
   193
    // daemon threads: discontinue running after main application is finished    
rgradisc@1035
   194
    log(1, "SML Execution Thread starting...");
rgradisc@1035
   195
    thread_sml.start();
rgradisc@859
   196
    log(1, "SML Execution Thread started");
rgradisc@859
   197
    smlInput = smlThread.getInputStream();
rgradisc@1035
   198
    log(1, "SML input stream");
rgradisc@859
   199
    smlOutput = smlThread.getOutputStream();
rgradisc@1035
   200
    log(1, "SML output stream");
rgradisc@859
   201
    //old IO:
rgradisc@859
   202
    smlWriter = new PrintWriter(smlOutput, true);
rgradisc@859
   203
    //NIO:
rgradisc@859
   204
    //    smlWriter =
rgradisc@859
   205
    //      new PrintWriter(
rgradisc@859
   206
    //        Channels.newWriter(Channels.newChannel(smlOutput), "ISO-8859-1"));
rgradisc@859
   207
    //old IO:
rgradisc@859
   208
    smlReader = new BufferedReader(new InputStreamReader(smlInput));
rgradisc@859
   209
    //NIO:
rgradisc@859
   210
    //    smlReader =
rgradisc@859
   211
    //      new BufferedReader(
rgradisc@859
   212
    //        Channels.newReader(Channels.newChannel(smlInput), "ISO-8859-1"));
rgradisc@859
   213
rgradisc@859
   214
    log(1, "SML in/output streams fetched");
rgradisc@859
   215
    //log(1, smlWriter.toString());
rgradisc@859
   216
    //log(1, smlReader.toString());
rgradisc@859
   217
  }
rgradisc@859
   218
rgradisc@859
   219
  //---------------------------------------------------------------
rgradisc@1056
   220
  private void startThreadsFirstTime() {
rgradisc@1035
   221
    startSMLThread();
rgradisc@1056
   222
rgradisc@859
   223
    Clients2KIServer c2ki = new Clients2KIServer(this);
rgradisc@859
   224
    thread_clients2ki = new Thread(c2ki, "java_bridge_clients2ki");
rgradisc@859
   225
    thread_clients2ki.setDaemon(true);
rgradisc@859
   226
    thread_clients2ki.start();
rgradisc@859
   227
    log(1, "Clients2KI Thread started");
rgradisc@859
   228
rgradisc@859
   229
    KI2ClientsServer ki2c = new KI2ClientsServer(this);
rgradisc@859
   230
    thread_ki2clients = new Thread(ki2c, "java_bridge_ki2clients");
rgradisc@859
   231
    thread_ki2clients.setDaemon(true);
rgradisc@859
   232
    thread_ki2clients.start();
rgradisc@859
   233
    log(1, "KI2Clients Thread started");
rgradisc@859
   234
rgradisc@859
   235
    thread_timeChecker = new TimeCheckerThread(this, waitMillis);
rgradisc@859
   236
    thread_timeChecker.setDaemon(true);
rgradisc@859
   237
    thread_timeChecker.start();
rgradisc@1035
   238
    log(1, "TimeChecker Thread started");
rgradisc@859
   239
  }
rgradisc@859
   240
rgradisc@859
   241
  //---------------------------------------------------------------
rgradisc@859
   242
  public void restartSML() {
rgradisc@859
   243
    log(1, "No response from sml-kernel: restart");
rgradisc@859
   244
    timeOutTimes.clear();
rgradisc@859
   245
    log(1, "Trying to kill sml-kernel...");
rgradisc@859
   246
    while (thread_sml.isAlive()) {
rgradisc@859
   247
      /*       
rgradisc@859
   248
      try {
rgradisc@859
   249
        smlOutput.write(3);
rgradisc@859
   250
        smlOutput.flush();
rgradisc@859
   251
      } catch (IOException e) {        
rgradisc@859
   252
        e.printStackTrace();
rgradisc@859
   253
      }
rgradisc@859
   254
      */
rgradisc@859
   255
      thread_sml.interrupt();
rgradisc@859
   256
      //log(1, "Trying to kill sml-kernel");
rgradisc@859
   257
    }
rgradisc@859
   258
    log(1, "Successfully killed sml-kernel");
rgradisc@859
   259
rgradisc@859
   260
    try {
rgradisc@1067
   261
      log(1, "BridgeMain: trying to close reader/writer");      
rgradisc@859
   262
      smlReader.close();
rgradisc@1065
   263
      smlWriter.close();
rgradisc@859
   264
      log(1, "BridgeMain: closed reader/writer");
rgradisc@859
   265
    } catch (IOException e) {
rgradisc@859
   266
      log(1, "BridgeMain: couldn't close reader/writer");
rgradisc@859
   267
    }
rgradisc@859
   268
    startSMLThread();
rgradisc@859
   269
    restoreStateOfKI();
rgradisc@859
   270
  }
rgradisc@859
   271
rgradisc@859
   272
  //---------------------------------------------------------------
rgradisc@859
   273
  private void restoreStateOfKI() { // pass kernelID   
rgradisc@1067
   274
    newInputs.clear(); // discard unanswered inputs: they have to be resent         
rgradisc@1067
   275
    //FIXXXME: works with only one client
rgradisc@1067
   276
    clientList.getPrintWriterOfClient(1).println("Error in Kernel");    
rgradisc@859
   277
    ignoreOutput = answeredInputs.size();
rgradisc@859
   278
    Iterator it = answeredInputs.iterator();
rgradisc@859
   279
    while (it.hasNext()) {
rgradisc@859
   280
      String input = (String)it.next();
rgradisc@859
   281
      log(1, "user ---> " + input);
rgradisc@859
   282
      //Resend user input to sml
rgradisc@859
   283
      smlWriter.println(input);
rgradisc@859
   284
      timeOutTimes.add(new Long(System.currentTimeMillis()));
rgradisc@859
   285
    }
rgradisc@859
   286
  }
rgradisc@859
   287
rgradisc@859
   288
  //---------------------------------------------------------------
rgradisc@859
   289
  //public void startNewKernel() {
rgradisc@859
   290
  // load balancing	
rgradisc@859
   291
  //}
rgradisc@859
   292
rgradisc@859
   293
  //---------------------------------------------------------------
rgradisc@859
   294
  protected void finalize() {
rgradisc@859
   295
    //Objects created in run method are finalized when 
rgradisc@859
   296
    //program terminates and thread exits
rgradisc@859
   297
    while (thread_sml.isAlive()) {
rgradisc@859
   298
      thread_sml.interrupt();
rgradisc@859
   299
      log(1, "waiting for SML thread to quit..");
rgradisc@859
   300
    }
rgradisc@859
   301
    bridgeLogger.log(1, "finished");
rgradisc@859
   302
    bridgeLogger.close();
rgradisc@859
   303
  }
rgradisc@859
   304
rgradisc@859
   305
  /**
rgradisc@859
   306
   * Log a message with a specified severity level
rgradisc@859
   307
   * @param level severity level
rgradisc@859
   308
   * @param msg the message to be logged
rgradisc@859
   309
   */
rgradisc@859
   310
  //---------------------------------------------------------------
rgradisc@859
   311
  public void log(int level, String msg) {
rgradisc@859
   312
    this.bridgeLogger.log(level, msg);
rgradisc@859
   313
    this.textArea.append(msg + "\n");
rgradisc@859
   314
  }
rgradisc@859
   315
rgradisc@859
   316
  /**
rgradisc@1066
   317
   * Buffers input sent to the sml-Kernel (for later possible restart)
rgradisc@1066
   318
   * @param kernelID ID of the sml-Kernel
rgradisc@1066
   319
   * @param input input to be buffered
rgradisc@1066
   320
   */
rgradisc@859
   321
  //----------------------------------------------------------------
rgradisc@859
   322
  public void bufferInput(int kernelID, String input) {
rgradisc@859
   323
    //kernelID: For use with multiple kernels
rgradisc@859
   324
    newInputs.add(input);
rgradisc@859
   325
  }
rgradisc@859
   326
rgradisc@859
   327
  /**
rgradisc@859
   328
   * This will be called when the sml-Kernel has answered a response
rgradisc@859
   329
   * and the answer was sent back to the user.
rgradisc@859
   330
   */
rgradisc@859
   331
  //----------------------------------------------------------------
rgradisc@859
   332
  public void responseSent() {
rgradisc@1035
   333
    // Kernel works as a FIFO: first item sent to kernel is
rgradisc@1035
   334
    // always returned first.
rgradisc@859
   335
    Object firstNew = newInputs.firstElement();
rgradisc@859
   336
    answeredInputs.add(firstNew);
rgradisc@859
   337
    newInputs.remove(firstNew);
rgradisc@859
   338
  }
rgradisc@859
   339
rgradisc@862
   340
  //Setters and Getters: no JavaDoc needed
rgradisc@859
   341
  public ClientList getClientList() {
rgradisc@859
   342
    return clientList;
rgradisc@859
   343
  }
rgradisc@1035
   344
rgradisc@859
   345
  public BufferedReader getSmlReader() {
rgradisc@859
   346
    return smlReader;
rgradisc@859
   347
  }
rgradisc@1035
   348
rgradisc@859
   349
  public PrintWriter getSmlWriter() {
rgradisc@859
   350
    return smlWriter;
rgradisc@859
   351
  }
rgradisc@1035
   352
rgradisc@859
   353
  public Vector getTimeOutTimes() {
rgradisc@859
   354
    return timeOutTimes;
rgradisc@859
   355
  }
rgradisc@1035
   356
rgradisc@859
   357
  public String getPath() {
rgradisc@859
   358
    return path;
rgradisc@859
   359
  }
rgradisc@1035
   360
rgradisc@859
   361
  public int getSocketPort() {
rgradisc@859
   362
    return socketPort;
rgradisc@859
   363
  }
rgradisc@989
   364
  /**
rgradisc@989
   365
   * @param bridgeRMI
rgradisc@989
   366
   */
rgradisc@989
   367
  public void setRMI(BridgeRMI bridgeRMI) {
rgradisc@989
   368
    rmi = bridgeRMI;
rgradisc@989
   369
  }
rgradisc@989
   370
rgradisc@1035
   371
  //---------------------------------------------------------------
rgradisc@1035
   372
  /**
rgradisc@1065
   373
   * @param args commandline arguments (exactly 4 expected: _iniPath _host _port _dtdPath)
rgradisc@1035
   374
   * @see BridgeMain()
rgradisc@1035
   375
   */
rgradisc@1035
   376
  public static void main(String[] args) {
rgradisc@1065
   377
    if (args.length != 4) {
rgradisc@1065
   378
      System.out.println("Usage: java BridgeMain _iniPath _host _port _dtdPath");
rgradisc@1065
   379
    } else {
rgradisc@1065
   380
	  BridgeMain bridge = new BridgeMain(args[0]);
rgradisc@1065
   381
      try {
rgradisc@1065
   382
        BridgeRMI rmi =
rgradisc@1065
   383
          new BridgeRMI(bridge, args[1], Integer.parseInt(args[2]), args[3]);
rgradisc@1066
   384
        bridge.setRMI(rmi);        
rgradisc@1065
   385
      } catch (RemoteException e) {
rgradisc@1066
   386
        System.out.println("Could not instantiate RMI: exiting");
rgradisc@1065
   387
        e.printStackTrace();
rgradisc@1065
   388
      }
rgradisc@1065
   389
    }       
rgradisc@1035
   390
  }
rgradisc@859
   391
}