make inherit BrowserFrameSwing, BrowserFrameWeb(MockBrowserFrame) from BrowserFrame
2 * Created on Aug 13, 2003
4 * @author Richard Gradischnegg RG
9 * BridgeMain: main class for bridge, does initialization and provides logging
10 * delegate and utility functionality.
12 * @author Richard Gradischnegg RG
16 import isac.gui.browser.BrowserFrameSwing;
17 import isac.util.BridgeMainPaths;
18 import isac.util.FixedPortRMISocketFactory;
19 import isac.util.ObjectManagerRMISocketFactory;
20 import isac.util.ObjectManagerPaths;
22 import java.awt.BorderLayout;
23 import java.awt.Color;
25 import java.awt.event.WindowAdapter;
26 import java.awt.event.WindowEvent;
27 import java.awt.event.WindowListener;
28 import java.io.BufferedReader;
30 import java.io.FileInputStream;
31 import java.io.FileNotFoundException;
32 import java.io.IOException;
33 import java.io.InputStream;
34 import java.io.InputStreamReader;
35 import java.io.OutputStream;
36 import java.io.PrintWriter;
37 import java.io.Serializable;
38 import java.rmi.RemoteException;
39 import java.rmi.server.RMISocketFactory;
40 import java.util.Properties;
41 import java.util.Vector;
43 import javax.swing.JFrame;
44 import javax.swing.JPanel;
45 import javax.swing.JScrollPane;
46 import javax.swing.JTextArea;
48 import org.apache.log4j.Logger;
51 * Bridge main class: initializes connection to SML, starts auxillary threads,
52 * handles logging mechanism
56 class BridgeMain implements Serializable {
58 private static final long serialVersionUID = 507L;
59 private static final Logger logger = Logger.getLogger(BridgeMain.class.getName());
61 private String ini_path_;
63 private int socket_port_;
65 private JFrame log_frame_;
69 private String kernel_exec_;
71 private String kernel_args_;
73 private long wait_millis_;
75 private final static int TRANS_STRING = 1;
77 private final static int TRANS_MATHML = 2;
79 private int transport_mode_ = TRANS_STRING;
85 JScrollPane scroll_pane_;
87 private Thread thread_clients2kernel_;
89 private Thread thread_sml_;
91 private Thread thread_kernel2clients_;
93 private Thread thread_time_checker_;
95 private ClientList client_list_;
97 private BridgeLogger bridge_logger_;
99 private OutputStream sml_output_;
101 private InputStream sml_input_;
103 private PrintWriter sml_writer_;
105 private BufferedReader sml_reader_;
107 private Vector time_out_times_;
109 public int ignore_output_ = 0;
111 private BridgeRMI bridge_rmi_; // multiple RMI connections: Vector
113 private boolean restoring_; // true = bridge is in restoring_ phase
115 private boolean kernel_responding_ = true;
119 * Constructor used to set up the bridge main program
122 * path_ to initialization file
124 BridgeMain(String iniPath) {
125 // hack for suppressing warning messages
126 // (no longer nescessary with j2sdk1.4.2)
127 // System.setProperty("java.util.prefs.syncInterval", "20000000000");
129 if (logger.isDebugEnabled())
130 logger.debug("BridgeMain obj.init: ini_path_=" + iniPath);
131 this.ini_path_ = iniPath;
134 bridge_logger_ = new BridgeLogger(path_);
135 client_list_ = new ClientList();
136 time_out_times_ = new Vector();
138 startThreadsFirstTime();
141 private void setUpBridgeLog() {
142 if (BridgeMainPaths.SHOW_GUI_LOGGER) {
143 log_frame_ = new JFrame("Java<->SML");
144 log_frame_.setLocation(700, 250);
145 panel_ = new JPanel();
146 panel_.setSize(200, 300);
147 panel_.setLayout(new BorderLayout());
148 panel_.setBackground(Color.white);
150 text_area_ = new JTextArea();
151 text_area_.setFont(new Font("Monospaced", 0, 11));
152 scroll_pane_ = new JScrollPane(text_area_,
153 JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
154 JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
155 panel_.add("Center", scroll_pane_);
156 log_frame_.getContentPane().add(panel_);
158 log_frame_.setTitle("BridgeLog Java <=> SML");
159 WindowListener l = new WindowAdapter() {
161 public void windowClosing(WindowEvent e) {
165 log_frame_.addWindowListener(l);
167 log_frame_.setSize(300, 500);
168 log_frame_.setVisible(true);
172 // Read Bridge properties from Files
173 private void readProperties() {
174 Properties p = new Properties();
177 p.load(new FileInputStream(ini_path_));
178 prop = p.getProperty("transportMode");
179 if (prop.equals("string")) {
180 transport_mode_ = TRANS_STRING;
181 } else if (prop.equals("mathml")) {
182 transport_mode_ = TRANS_MATHML;
184 System.out.println("INI-File: transport_mode_ value not valid");
187 System.out.println("transport_mode_ = " + transport_mode_);
189 prop = p.getProperty("socketPort");
191 socket_port_ = Integer.valueOf(prop).intValue();
192 } catch (NumberFormatException e1) {
193 System.out.println("INI-File: socketport is not a number!");
196 Float.floatToIntBits(3.14f);
197 System.out.println("socket_port_ = " + socket_port_);
199 prop = p.getProperty("path");
200 File f = new File(prop);
201 System.out.println(prop);
202 if (f.isDirectory()) {
205 System.out.println("INI-File: path_ is not a valid directory!");
208 System.out.println("path_ = " + path_);
210 prop = p.getProperty("waitMillis");
212 wait_millis_ = Long.valueOf(prop).longValue();
213 } catch (NumberFormatException e1) {
214 System.out.println("INI-File: wait_millis_ is not a number!");
217 System.out.println("wait_millis_ = " + wait_millis_);
219 kernel_exec_ = p.getProperty("kernelExec");
220 kernel_args_ = p.getProperty("kernelArgs");
222 } catch (FileNotFoundException e) {
223 System.out.println("Couldn't open INI File");
225 } catch (IOException e) {
226 System.out.println("Couldn't read INI File");
231 // Start sml Threads and catch in- and output-streams
232 private void startSMLThread() {
233 if (logger.isDebugEnabled())
234 logger.debug("startSMLThread");
235 SMLThread smlThread = new SMLThread(this, kernel_exec_, kernel_args_);
236 thread_sml_ = new Thread(smlThread, "java_bridge_execution");
237 thread_sml_.setDaemon(true);
238 // daemon threads: discontinue running after main application is
240 log(1, "SML Execution Thread starting...");
242 log(1, "SML Execution Thread started");
243 sml_input_ = smlThread.getInputStream();
244 log(1, "SML input stream");
245 sml_output_ = smlThread.getOutputStream();
246 log(1, "SML output stream");
248 sml_writer_ = new PrintWriter(sml_output_, true);
249 // NIO (doesn't run for some reason)
252 // Channels.newWriter(Channels.newChannel(sml_output_), "ISO-8859-1"));
254 sml_reader_ = new BufferedReader(new InputStreamReader(sml_input_));
257 // new BufferedReader(
258 // Channels.newReader(Channels.newChannel(sml_input_), "ISO-8859-1"));
260 log(1, "SML in/output streams fetched");
261 // log(1, sml_writer_.toString());
262 // log(1, sml_reader_.toString());
265 private void startThreadsFirstTime() {
266 if (logger.isDebugEnabled())
267 logger.debug("startThreadsFirstTime");
270 Clients2KernelServer c2k = new Clients2KernelServer(this);
271 thread_clients2kernel_ = new Thread(c2k, "java_bridge_clients2kernel");
272 thread_clients2kernel_.setDaemon(true);
273 thread_clients2kernel_.start();
274 log(1, "Clients2Kernel Thread started");
276 Kernel2ClientsServer k2c = new Kernel2ClientsServer(this);
277 thread_kernel2clients_ = new Thread(k2c, "java_bridge_kernel2clients");
278 thread_kernel2clients_.setDaemon(true);
279 thread_kernel2clients_.start();
280 log(1, "Kernel2Clients Thread started");
282 thread_time_checker_ = new TimeCheckerThread(this, wait_millis_);
283 thread_time_checker_.setDaemon(true);
284 thread_time_checker_.start();
285 log(1, "TimeChecker Thread started");
288 public void restartSML() {
289 log(1, "No response from sml-kernel: restart");
290 time_out_times_.clear();
291 log(1, "Trying to kill sml-kernel...");
292 while (thread_sml_.isAlive()) {
293 thread_sml_.interrupt();
295 log(1, "Successfully killed sml-kernel");
298 log(1, "BridgeMain: trying to close reader/writer");
301 log(1, "BridgeMain: closed reader/writer");
302 } catch (IOException e) {
303 log(1, "BridgeMain: couldn't close reader/writer");
306 restoreStateOfKernel();
309 // This method restores the last consistent state of the kernel
310 // It will be called when the sml kernel crashes
311 private void restoreStateOfKernel() {
312 // test first if kernel is still responding:
313 // if this is the case, no further restoring_ is needed
314 // dummy call to test respondablity
315 // it could be also work to send a SIGINT (^C in terminal)
316 // to the not reacting sml-Kernel
317 // But this is not possible in Java (only with C in JNI)
319 while (!kernel_responding_) {
320 sml_writer_.println("DEconstrCalcTree 0;");
321 // if the kernel responds to this instruction, it has
322 // not crashed: no restarting nescessary
323 if (sml_reader_.ready()) {
325 sml_reader_.readLine();
326 kernel_responding_ = true;
329 } catch (Exception e) {
331 if (!kernel_responding_) {
332 log(1, "Kernel is not responding: now restarting");
333 this.restoring_ = true;
336 * Vector inputs = bridge_rmi_.getInputs();
339 * Iterator it = newInputs.iterator(); while (it.hasNext()) { int
340 * clientID = ((ClientInput)it.next()).getClientID();
341 * client_list_.getPrintWriterOfClient(clientID).println(" <FATALERROR>
344 log(1, "------ now restoring_ state of kernel");
345 this.restoring_ = true;
346 // send empty response string to blocking client
347 client_list_.getPrintWriterOfClient(bridge_rmi_.getRmiID()).println(
349 log(1, "------ restoreExistingCalcTrees()");
350 bridge_rmi_.restoreExistingCalcTrees();
351 // TODO: bridge_rmi_.deleteLastBufferInput();
352 this.restoring_ = false;
353 log(1, "------ done restoring_ state of kernel");
355 * ignore_output_ = inputs.size(); Iterator it = inputs.iterator();
356 * while (it.hasNext()) { ClientInput clientInput =
357 * (ClientInput)it.next(); String input = clientInput.getInputLine();
358 * log(1, "user "+clientInput.getClientID()+" ---> " + input); //Resend
359 * user input to sml sml_writer_.println(input); time_out_times_.add(new
360 * Long(System.currentTimeMillis())); }
364 // Here goes the future load balancing functionality
365 // public void startNewKernel() {
366 // implement load balancing
369 protected void finalize() throws Throwable {
370 super.finalize(); // gosling p.47
371 // Objects created in run method are finalized when
372 // program terminates and thread exits
373 while (thread_sml_.isAlive()) {
374 thread_sml_.interrupt();
375 log(1, "waiting for SML thread to quit..");
377 bridge_logger_.log(1, "finished");
378 bridge_logger_.close();
382 * Log a message with a specified severity level
387 * the message to be logged
389 public void log(int level, String msg) {
390 if(BridgeMainPaths.LOG_TO_FILE)
391 this.bridge_logger_.log(level, msg);
392 if(BridgeMainPaths.SHOW_GUI_LOGGER)
393 this.text_area_.append(msg + "\n");
396 public ClientList getClientList() {
400 public BufferedReader getSmlReader() {
401 //if (logger.isDebugEnabled())
402 // logger.debug("getSmlReader x");
406 public PrintWriter getSmlWriter() {
410 public Vector getTimeOutTimes() {
411 return time_out_times_;
414 public String getPath() {
418 public int getSocketPort() {
422 public void setRMI(BridgeRMI bridgeRMI) {
423 if (logger.isDebugEnabled())
424 logger.debug("setRMI: bridge_rmi_=" + bridgeRMI);
425 this.bridge_rmi_ = bridgeRMI;
426 bridgeRMI.setRmiID(1); // only one BridgeRMI used so far
429 boolean isRestoring() {
433 void setRestoring(boolean b) {
439 * commandline arguments (exactly 4 expected: _iniPath _host
443 public static void main(String[] args) {
445 String ini_load_result = BridgeMainPaths.loadFromFile(args[0]);
447 if (ini_load_result != null)
448 ini_load_result += BridgeMainPaths.loadFromResource(args[0]);
450 if (ini_load_result != null) {
451 System.err.println(ini_load_result);
455 // initialize bridge main part
456 BridgeMain bridge = new BridgeMain(BridgeMainPaths.INI_PATH);
459 // Use ObjectManagerRMISocketFactory
461 RMISocketFactory.setSocketFactory( new FixedPortRMISocketFactory(BridgeMainPaths.BRIDGE_RMI_PORT ));
463 // setup rmi connection to to the clients
464 BridgeRMI rmi = new BridgeRMI(bridge, BridgeMainPaths.HOST,
465 BridgeMainPaths.BRIDGE_MAIN_PORT, BridgeMainPaths.DTD_PATH);
467 System.out.println( rmi );
470 } catch (RemoteException e) {
471 System.out.println("Could not instantiate RMI: exiting");
474 catch (IOException e)
476 System.out.println("Exception: " + e.getMessage());