2 * Created on Aug 13, 2003
4 * @author Richard Gradischnegg RG
9 * BridgeMain: main class for bridge, does initialization and provides logging delegate and utility functionality.
11 * @author Richard Gradischnegg RG
14 import isac.gui.browser.BrowserFrame;
15 import isac.util.BridgeMainPaths;
16 import isac.util.FixedPortRMISocketFactory;
17 import isac.util.ObjectManagerRMISocketFactory;
18 import isac.util.ObjectManagerPaths;
20 import java.awt.BorderLayout;
21 import java.awt.Color;
23 import java.awt.event.WindowAdapter;
24 import java.awt.event.WindowEvent;
25 import java.awt.event.WindowListener;
26 import java.io.BufferedReader;
28 import java.io.FileInputStream;
29 import java.io.FileNotFoundException;
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.InputStreamReader;
33 import java.io.OutputStream;
34 import java.io.PrintWriter;
35 import java.io.Serializable;
36 import java.rmi.RemoteException;
37 import java.rmi.server.RMISocketFactory;
38 import java.util.Properties;
39 import java.util.Vector;
41 import javax.swing.JFrame;
42 import javax.swing.JPanel;
43 import javax.swing.JScrollPane;
44 import javax.swing.JTextArea;
46 import org.apache.log4j.Logger;
49 * Bridge main class: initializes connection to SML, starts auxillary threads, handles logging mechanism
53 class BridgeMain implements Serializable {
55 private static final long serialVersionUID = 507L;
56 private static final Logger logger = Logger.getLogger(BridgeMain.class.getName());
57 private String ini_path_;
58 private int socket_port_;
59 private JFrame log_frame_;
61 private String kernel_exec_;
62 private String kernel_args_;
63 private long wait_millis_;
64 private final static int TRANS_STRING = 1;
65 private final static int TRANS_MATHML = 2;
66 private int transport_mode_ = TRANS_STRING;
69 JScrollPane scroll_pane_;
70 private Thread thread_clients2kernel_;
71 private Thread thread_sml_;
72 private Thread thread_kernel2clients_;
73 private Thread thread_time_checker_;
74 private ClientList client_list_;
75 private BridgeLogger bridge_logger_;
76 private OutputStream sml_output_;
77 private InputStream sml_input_;
78 private PrintWriter sml_writer_;
79 private BufferedReader sml_reader_;
80 private Vector time_out_times_;
81 public int ignore_output_ = 0;
82 private BridgeRMI bridge_rmi_; // multiple RMI connections: Vector
83 private boolean restoring_; // true = bridge is in restoring_ phase
84 private boolean kernel_responding_ = true;
87 * Constructor used to set up the bridge main program
89 * @param ini_path_: path_ to initialization file
91 BridgeMain(String iniPath) {
92 // hack for suppressing warning messages
93 // (no longer nescessary with j2sdk1.4.2)
94 // System.setProperty("java.util.prefs.syncInterval", "20000000000");
96 if (logger.isDebugEnabled()) {
97 logger.debug("BridgeMain obj.init: ini_path_=" + iniPath);
99 this.ini_path_ = iniPath;
102 bridge_logger_ = new BridgeLogger(path_);
103 client_list_ = new ClientList();
104 time_out_times_ = new Vector();
106 startThreadsFirstTime();
109 private void setUpBridgeLog() {
110 if (BridgeMainPaths.SHOW_GUI_LOGGER) {
111 log_frame_ = new JFrame("Java<->SML");
112 log_frame_.setLocation(700, 250);
113 panel_ = new JPanel();
114 panel_.setSize(200, 300);
115 panel_.setLayout(new BorderLayout());
116 panel_.setBackground(Color.white);
118 text_area_ = new JTextArea();
119 text_area_.setFont(new Font("Monospaced", 0, 11));
120 scroll_pane_ = new JScrollPane(text_area_,
121 JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
122 JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
123 panel_.add("Center", scroll_pane_);
124 log_frame_.getContentPane().add(panel_);
126 log_frame_.setTitle("BridgeLog Java <=> SML");
127 WindowListener l = new WindowAdapter() {
128 public void windowClosing(WindowEvent e) {
132 log_frame_.addWindowListener(l);
134 log_frame_.setSize(300, 500);
135 log_frame_.setVisible(true);
139 // Read Bridge properties from Files
140 private void readProperties() {
141 Properties p = new Properties();
144 p.load(new FileInputStream(ini_path_));
145 prop = p.getProperty("transportMode");
146 if (prop.equals("string")) {
147 transport_mode_ = TRANS_STRING;
148 } else if (prop.equals("mathml")) {
149 transport_mode_ = TRANS_MATHML;
151 System.out.println("INI-File: transport_mode_ (" + prop + ") value not valid");
154 System.out.println("transport_mode_ = " + transport_mode_);
156 prop = p.getProperty("socketPort");
158 socket_port_ = Integer.valueOf(prop).intValue();
159 } catch (NumberFormatException e1) {
160 System.out.println("INI-File: socketport (" + prop + ") is not a number!");
163 System.out.println("socket_port_ = " + socket_port_);
165 prop = p.getProperty("path");
166 File f = new File(prop);
167 if (f.isDirectory()) {
170 System.out.println("INI-File: path_ (" + prop + ") is not a valid directory!");
173 System.out.println("path_ = " + path_);
175 prop = p.getProperty("waitMillis");
177 wait_millis_ = Long.valueOf(prop).longValue();
178 } catch (NumberFormatException e1) {
179 System.out.println("INI-File: wait_millis_ (" + prop + ") is not a number!");
182 System.out.println("wait_millis_ = " + wait_millis_);
184 kernel_exec_ = p.getProperty("kernelExec");
185 kernel_args_ = p.getProperty("kernelArgs");
187 } catch (FileNotFoundException e) {
188 System.out.println("Couldn't open INI File: " + ini_path_);
190 } catch (IOException e) {
191 System.out.println("Couldn't read INI File: " + ini_path_);
196 // Start sml Threads and catch in- and output-streams
197 private void startSMLThread() {
198 if (logger.isDebugEnabled()) {
199 logger.debug("startSMLThread");
201 SMLThread smlThread = new SMLThread(this, kernel_exec_, kernel_args_);
202 thread_sml_ = new Thread(smlThread, "java_bridge_execution");
203 thread_sml_.setDaemon(true);
204 // daemon threads: discontinue running after main application is
206 log(1, "SML Execution Thread starting...");
208 log(1, "SML Execution Thread started");
209 sml_input_ = smlThread.getInputStream();
210 log(1, "SML input stream");
211 sml_output_ = smlThread.getOutputStream();
212 log(1, "SML output stream");
214 sml_writer_ = new PrintWriter(sml_output_, true);
215 // NIO (doesn't run for some reason)
218 // Channels.newWriter(Channels.newChannel(sml_output_), "ISO-8859-1"));
220 sml_reader_ = new BufferedReader(new InputStreamReader(sml_input_));
223 // new BufferedReader(
224 // Channels.newReader(Channels.newChannel(sml_input_), "ISO-8859-1"));
226 // WN120413 Isabelle2002 --> 2011
228 String line_tty = "theory TTY_Communication imports Isac begin ";
229 log(1, "[[to sml: " + line_tty);
230 sml_writer_.println(line_tty);
231 // log(1, sml_writer_.toString());
232 // log(1, sml_reader_.toString());
235 private void startThreadsFirstTime() {
236 if (logger.isDebugEnabled()) {
237 logger.debug("startThreadsFirstTime");
241 Clients2KernelServer c2k = new Clients2KernelServer(this);
242 thread_clients2kernel_ = new Thread(c2k, "java_bridge_clients2kernel");
243 thread_clients2kernel_.setDaemon(true);
244 thread_clients2kernel_.start();
245 log(1, "Clients2Kernel Thread started");
247 Kernel2ClientsServer k2c = new Kernel2ClientsServer(this);
248 thread_kernel2clients_ = new Thread(k2c, "java_bridge_kernel2clients");
249 thread_kernel2clients_.setDaemon(true);
250 thread_kernel2clients_.start();
251 log(1, "Kernel2Clients Thread started");
253 thread_time_checker_ = new TimeCheckerThread(this, wait_millis_);
254 thread_time_checker_.setDaemon(true);
255 thread_time_checker_.start();
256 log(1, "TimeChecker Thread started");
259 public void restartSML() {
260 log(1, "No response from sml-kernel: restart");
261 time_out_times_.clear();
262 log(1, "Trying to kill sml-kernel...");
263 while (thread_sml_.isAlive()) {
264 thread_sml_.interrupt();
266 log(1, "Successfully killed sml-kernel");
269 log(1, "BridgeMain: trying to close reader/writer");
272 log(1, "BridgeMain: closed reader/writer");
273 } catch (IOException e) {
274 log(1, "BridgeMain: couldn't close reader/writer");
277 restoreStateOfKernel();
280 // This method restores the last consistent state of the kernel
281 // It will be called when the sml kernel crashes
282 private void restoreStateOfKernel() {
283 // test first if kernel is still responding:
284 // if this is the case, no further restoring_ is needed
285 // dummy call to test respondablity
286 // it could be also work to send a SIGINT (^C in terminal)
287 // to the not reacting sml-Kernel
288 // But this is not possible in Java (only with C in JNI)
290 while (!kernel_responding_) {
291 sml_writer_.println("DEconstrCalcTree 0;");
292 // if the kernel responds to this instruction, it has
293 // not crashed: no restarting nescessary
294 if (sml_reader_.ready()) {
296 sml_reader_.readLine();
297 kernel_responding_ = true;
300 } catch (Exception e) {
302 if (!kernel_responding_) {
303 log(1, "Kernel is not responding: now restarting");
304 this.restoring_ = true;
307 * Vector inputs = bridge_rmi_.getInputs();
310 * Iterator it = newInputs.iterator(); while (it.hasNext()) { int
311 * clientID = ((ClientInput)it.next()).getClientID();
312 * client_list_.getPrintWriterOfClient(clientID).println(" <FATALERROR>
315 log(1, "------ now restoring_ state of kernel");
316 this.restoring_ = true;
317 // send empty response string to blocking client
318 client_list_.getPrintWriterOfClient(bridge_rmi_.getRmiID()).println(
320 log(1, "------ restoreExistingCalcTrees()");
321 bridge_rmi_.restoreExistingCalcTrees();
322 // TODO: bridge_rmi_.deleteLastBufferInput();
323 this.restoring_ = false;
324 log(1, "------ done restoring_ state of kernel");
326 * ignore_output_ = inputs.size(); Iterator it = inputs.iterator();
327 * while (it.hasNext()) { ClientInput clientInput =
328 * (ClientInput)it.next(); String input = clientInput.getInputLine();
329 * log(1, "user "+clientInput.getClientID()+" ---> " + input); //Resend
330 * user input to sml sml_writer_.println(input); time_out_times_.add(new
331 * Long(System.currentTimeMillis())); }
335 // Here goes the future load balancing functionality
336 // public void startNewKernel() {
337 // implement load balancing
339 protected void finalize() throws Throwable {
340 super.finalize(); // gosling p.47
341 // Objects created in run method are finalized when
342 // program terminates and thread exits
343 while (thread_sml_.isAlive()) {
344 thread_sml_.interrupt();
345 log(1, "waiting for SML thread to quit..");
347 bridge_logger_.log(1, "finished");
348 bridge_logger_.close();
352 * Log a message with a specified severity level
354 * @param level severity level
355 * @param msg the message to be logged
357 public void log(int level, String msg) {
358 if (BridgeMainPaths.LOG_TO_FILE) {
359 this.bridge_logger_.log(level, msg);
361 if (BridgeMainPaths.SHOW_GUI_LOGGER) {
362 this.text_area_.append(msg + "\n");
366 public ClientList getClientList() {
370 public BufferedReader getSmlReader() {
371 //if (logger.isDebugEnabled())
372 // logger.debug("getSmlReader x");
376 public PrintWriter getSmlWriter() {
380 public Vector getTimeOutTimes() {
381 return time_out_times_;
384 public String getPath() {
388 public int getSocketPort() {
392 public void setRMI(BridgeRMI bridgeRMI) {
393 if (logger.isDebugEnabled()) {
394 logger.debug("setRMI: bridge_rmi_=" + bridgeRMI);
396 this.bridge_rmi_ = bridgeRMI;
397 bridgeRMI.setRmiID(1); // only one BridgeRMI used so far
400 boolean isRestoring() {
404 void setRestoring(boolean b) {
409 * @param args commandline arguments (exactly 4 expected: _iniPath _host _port _dtdPath)
412 public static void main(String[] args) {
414 System.out.println("Starting Bridge...");
416 String ini_load_result = BridgeMainPaths.loadFromFile(args[0]);
418 if (ini_load_result != null) {
419 ini_load_result += BridgeMainPaths.loadFromResource(args[0]);
422 if (ini_load_result != null) {
423 System.err.println(ini_load_result);
427 // initialize bridge main part
428 BridgeMain bridge = new BridgeMain(BridgeMainPaths.INI_PATH);
431 // Use ObjectManagerRMISocketFactory
433 RMISocketFactory.setSocketFactory(new FixedPortRMISocketFactory(BridgeMainPaths.BRIDGE_RMI_PORT));
435 // setup rmi connection to to the clients
436 BridgeRMI rmi = new BridgeRMI(bridge, BridgeMainPaths.HOST,
437 BridgeMainPaths.BRIDGE_MAIN_PORT, BridgeMainPaths.DTD_PATH);
439 // System.out.println( rmi );
442 } catch (RemoteException e) {
443 System.out.println("Could not instantiate RMI: exiting");
445 } catch (IOException e) {
446 System.out.println("Exception: " + e.getMessage());