/[xulu]/trunk/src/appl/parallel/starter/server/XuluServerStarter.java
ViewVC logotype

Contents of /trunk/src/appl/parallel/starter/server/XuluServerStarter.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations)
Wed Feb 25 11:54:01 2009 UTC (15 years, 9 months ago) by mojays
File size: 18949 byte(s)
First Commit, corresponds to Revision 1008 of Wikisquare-SVN 
1 package appl.parallel.starter.server;
2
3 import java.awt.AWTException;
4 import java.awt.Image;
5 import java.awt.MenuItem;
6 import java.awt.PopupMenu;
7 import java.awt.SystemTray;
8 import java.awt.Toolkit;
9 import java.awt.TrayIcon;
10 import java.awt.event.ActionEvent;
11 import java.awt.event.ActionListener;
12 import java.awt.event.MouseAdapter;
13 import java.awt.event.MouseEvent;
14 import java.awt.event.MouseListener;
15 import java.io.BufferedReader;
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.io.InputStreamReader;
19 import java.io.SequenceInputStream;
20 import java.rmi.AccessException;
21 import java.rmi.Naming;
22 import java.rmi.NotBoundException;
23 import java.rmi.Remote;
24 import java.rmi.RemoteException;
25 import java.rmi.registry.LocateRegistry;
26 import java.rmi.registry.Registry;
27 import java.rmi.server.UnicastRemoteObject;
28
29 import javax.swing.JOptionPane;
30 import javax.swing.JTextArea;
31
32 import schmitzm.swing.TextAreaPrintStream;
33 import schmitzm.swing.event.PopupMenuListener;
34
35 import appl.ext.XuluConfig;
36 import appl.parallel.ComputingResource;
37 import appl.parallel.server.XuluServer;
38 import appl.parallel.starter.Starter;
39 import appl.parallel.util.Helper;
40 import appl.util.GeneralUtil;
41
42 /**
43 * A running instance of the XuluServerStarter waits for a signal to start a
44 * {@link XuluServer}. When {@link #start()} is called the Server is started.
45 * All output from the new Serverprocess are forwarded to the actual screen (if
46 * any). The Server can also be {@link #restart() restarted} or
47 * {@link #stop() stopped}. <br>
48 * <br>
49 * For configuration of the XuluServer the {@link XuluConfig} is used. The
50 * following configuration entries are supported <TABLE border="1"
51 * <tr>
52 * <th>Entry</th>
53 * <th>Default</th>
54 * <th>Description</th>
55 * </tr>
56 * <tr>
57 * <td>XuluServerStarter.port</td>
58 * <td>1099</td>
59 * <td> The port which is used for the registry creation (if none is running)</td>
60 * </tr>
61 * <tr>
62 * <td>XuluServerStarter.javaprogram</td>
63 * <td>java</td>
64 * <td> The path to the java program</td>
65 * </tr>
66 * <tr>
67 * <td>XuluServerStarter.codebasedir</td>
68 * <td></td>
69 * <td> The absolute path to the codebase directory (should be the path to the
70 * binaries)</td>
71 * </tr>
72 * <tr>
73 * <td>XuluServerStarter.securitypolicy</td>
74 * <td></td>
75 * <td> The path to the security policy</td>
76 * </tr>
77 * <tr>
78 * <td>XuluServerStarter.furtherjavaarguments</td>
79 * <td></td>
80 * <td> further JVM arguments</td>
81 * </tr>
82 * <tr>
83 * <td>XuluServerStarter.classpath</td>
84 * <td></td>
85 * <td> The libaries needed</td>
86 * </tr>
87 * <tr>
88 * <td>XuluServerStarter.memorymax</td>
89 * <td>64</td>
90 * <td> The maximum memory the XuluSever attempts to use (-xmx)</td>
91 * </tr>
92 * <tr>
93 * <td>XuluServerStarter.memorymin</td>
94 * <td>4</td>
95 * <td> The inital memory the XuluServer uses (-xms)</td>
96 * </tr>
97 * </TABLE>
98 *
99 * @author Dominik Appl
100 */
101 public class XuluServerStarter extends UnicastRemoteObject implements Starter,
102 ActionListener {
103
104 private enum Status {
105 /** server is not started */
106 serverOff,
107 /** * Server is started */
108 serverStarted,
109 /** A client is connected */
110 serverActive
111 }
112
113 private String bindingName = "XuluServerStarter";
114
115 private int port = 1099;
116
117 private String javaprogram = "java";
118
119 private String codebase = "";
120
121 private String securitypolicy = "";
122
123 private String furtherjavaarguments = "";
124
125 private String xuluserverarguments = "";
126
127 private String classpath = "";
128
129 private String XuluServerString = "appl.parallel.server.XuluServer";
130
131 private Process p;
132
133 // private BufferedReader input;
134
135 private SimpleConsoleOutputThread thread;
136
137 private int xms = 64;
138
139 private int xmx = 128;
140
141 private SequenceInputStream twoStreams;
142
143 private XuluStarterServerGUI starterServerGUI;
144
145 private TextAreaPrintStream textAreaOutput;
146
147 private MenuItem menu_exit;
148
149 private MenuItem menu_start;
150
151 private MenuItem menu_stop;
152
153 private MenuItem menu_showConsole;
154
155 private TrayIcon trayIcon;
156
157 private ComputingResource xuluServer;
158
159 private Image redIcon;
160
161 private Image greenIcon;
162
163 private Image yellowIcon;
164
165 private String cmd;
166
167 /**
168 * @param cmd
169 * the command to be executed by the starter. If null, the
170 * XuluConfig is used to create the commandline
171 * @param showGUI
172 * if false, no GUI/Tray is shown
173 * @throws RemoteException
174 */
175 private XuluServerStarter(String cmd, boolean showGUI)
176 throws RemoteException {
177 super();
178 this.cmd = cmd;
179 this.bind(bindingName, this, port);
180 if (showGUI) {
181 redIcon = Toolkit.getDefaultToolkit().getImage(
182 "resource/xulu_icon_red.gif");
183 greenIcon = Toolkit.getDefaultToolkit().getImage(
184 "resource/xulu_icon_green.gif");
185 yellowIcon = Toolkit.getDefaultToolkit().getImage(
186 "resource/xulu_icon_yellow.gif");
187 createGUI();
188 createTray();
189 setStatus(Status.serverOff);
190 }
191 }
192
193 /**
194 * Should be called if the status has changed (changes tray icon)
195 *
196 * @param newStatus
197 * the new status
198 */
199 private void setStatus(Status newStatus) {
200 // if tray disabled: return
201 if (trayIcon == null)
202 return;
203 switch (newStatus) {
204 case serverOff:
205 trayIcon.setImage(redIcon);
206 trayIcon.setToolTip("XuluServer is disabled");
207 break;
208 case serverStarted:
209 trayIcon.setImage(greenIcon);
210 trayIcon.setToolTip("Xulu Server is ready and waiting for tasks");
211 break;
212 case serverActive:
213 trayIcon.setImage(yellowIcon);
214 trayIcon.setToolTip("A client is connected to the XuluServer");
215 break;
216 }
217 }
218
219 /**
220 * creates and inits the tray icon.
221 */
222 private void createTray() {
223
224 if (SystemTray.isSupported()) {
225
226 SystemTray tray = SystemTray.getSystemTray();
227 Image image = Toolkit.getDefaultToolkit().getImage(
228 "temp/xulu_icon.gif");
229
230 // create menu entries
231 PopupMenu popup = new PopupMenu();
232 menu_exit = new MenuItem("Exit");
233 menu_start = new MenuItem("Start Server");
234 menu_stop = new MenuItem("Stop Server");
235 menu_showConsole = new MenuItem("Show contol window");
236 menu_exit.addActionListener(this);
237 menu_start.addActionListener(this);
238 menu_stop.addActionListener(this);
239 menu_showConsole.addActionListener(this);
240
241 popup.add(menu_start);
242 popup.add(menu_stop);
243 popup.add(menu_showConsole);
244 popup.add(menu_exit);
245 trayIcon = new TrayIcon(image, "Xulu Server", popup);
246 trayIcon.setImageAutoSize(true);
247 trayIcon.addMouseListener(new MouseAdapter() {
248 // on doubleclick popup the control-window
249 public void mouseClicked(MouseEvent e) {
250 if (e.getClickCount() > 1) {
251 starterServerGUI.setVisible(!starterServerGUI
252 .isVisible());
253 }
254 }
255 });
256
257 try {
258 tray.add(trayIcon);
259 } catch (AWTException e) {
260 System.err.println("TrayIcon could not be added.");
261 tray = null;
262 }
263
264 } else {
265 // System Tray is not supported
266 System.out.println("System Tray not supported");
267 trayIcon = null;
268 }
269
270 }
271
272 /**
273 * creates the GUI for the Starter
274 */
275 private void createGUI() {
276 // create new GUI
277 starterServerGUI = new XuluStarterServerGUI();
278 // register this instance as button listener
279 starterServerGUI.button_exit.addActionListener(this);
280 starterServerGUI.button_start.addActionListener(this);
281 starterServerGUI.button_stop.addActionListener(this);
282
283 // register TextArea as OutputStream
284 textAreaOutput = new TextAreaPrintStream(starterServerGUI.consoleArea);
285 System.setErr(textAreaOutput);
286 System.setOut(textAreaOutput);
287
288 }
289
290 /**
291 * reads the configuration out of the {@link XuluConfig}
292 */
293 private void loadConfig() {
294 XuluConfig config = XuluConfig.getXuluConfig();
295 if (config.getIntProperty("XuluServerStarter.port") != 0)
296 port = config.getIntProperty("XuluServerStarter.port");
297 if (config.getProperty("XuluServerStarter.javaprogram") != null)
298 javaprogram = config.getProperty("XuluServerStarter.javaprogram");
299 if (config.getProperty("XuluServerStarter.codebasedir") != null)
300 codebase = config.getProperty("XuluServerStarter.codebasedir");
301 if (config.getProperty("XuluServerStarter.securitypolicy") != null)
302 securitypolicy = config
303 .getProperty("XuluServerStarter.securitypolicy");
304 if (config.getProperty("XuluServerStarter.furtherjavaarguments") != null)
305 furtherjavaarguments = config
306 .getProperty("XuluServerStarter.furtherjavaarguments");
307 if (config.getProperty("XuluServerStarter.classpath") != null)
308 classpath = config.getProperty("XuluServerStarter.classpath");
309 if (config.getProperty("XuluServerStarter.memorymax") != null)
310 xmx = config.getIntProperty("XuluServerStarter.memorymax");
311 if (config.getProperty("XuluServerStarter.memorymin") != null)
312 xms = config.getIntProperty("XuluServerStarter.memorymin");
313 }
314
315 /*
316 * (non-Javadoc)
317 *
318 * @see appl.parallel.starter.Starter#restart()
319 */
320 public void restart() throws RemoteException {
321 this.stop();
322 this.start();
323 }
324
325 /**
326 * Creates the Java commandline and starts the {@link XuluServer}
327 *
328 * @see appl.parallel.starter.Starter#start()
329 */
330 public void start() throws RemoteException {
331 loadConfig();
332 try {
333 if (p != null) {
334 System.out
335 .println("Process is already running. Stop process first");
336 return;
337 }
338 String commandline = "\"" + javaprogram + "\"" + " -cp \""
339 + codebase;
340 if (!(classpath.equals("")))
341 commandline += (";" + classpath);
342 commandline += "\" ";
343 if (xms != 0)
344 commandline += (" -Xms" + xms + "M ");
345 if (xmx != 0)
346 commandline += (" -Xmx" + xmx + "M ");
347
348 commandline += (" -Djava.rmi.server.codebase=file:///" + codebase
349 + " -Djava.security.policy=" + securitypolicy + " "
350 + furtherjavaarguments + " " + XuluServerString + " " + xuluserverarguments);
351 // if there is a user commandline, use this instead
352 if (cmd != null)
353 commandline = cmd;
354 System.out.println("Executing commandline: " + commandline);
355 p = Runtime.getRuntime().exec(commandline);
356 xuluServer = null;
357 // forward the inputstream of the new process to the
358 // console/textarea
359 InputStream standardInput = p.getInputStream();
360 InputStream errorInput = p.getErrorStream();
361 thread = new SimpleConsoleOutputThread(standardInput, errorInput);
362 thread.startThread();
363 // wait until the server is bound to the registry
364 Thread.sleep(5000);
365 // lookup the new Server
366 xuluServer = (ComputingResource) Naming
367 .lookup("rmi://localhost/XuluServer");
368 setStatus(Status.serverStarted);
369 System.out
370 .println("The Starter has successfully discovered the XuluServer instance");
371
372 } catch (IOException e) {
373 // TODO Auto-generated catch block
374 e.printStackTrace();
375 } catch (NotBoundException e) {
376 System.out
377 .println("Could not find the Xulu server instance(NotBoundException).\n Creation of the XuluServer failed..please correct the commandline...");
378
379 } catch (InterruptedException e) {
380 // TODO Auto-generated catch block
381 e.printStackTrace();
382 }
383 }
384
385 /*
386 * (non-Javadoc)
387 *
388 * @see appl.parallel.starter.Starter#stop()
389 */
390 public void stop() throws RemoteException {
391 try {
392 if (twoStreams != null)
393 twoStreams.close();
394 if (thread != null)
395 thread.stopThread();
396 // if (input != null)
397 // input.close();
398 if (p != null)
399 p.destroy();
400 p = null;
401 System.out.println("Process stopped");
402 this.setStatus(Status.serverOff);
403 } catch (IOException e) {
404 e.printStackTrace();
405 }
406 }
407
408 /**
409 * Starts the XuluServerStarter <br/> The parameter -start can be used to
410 * start the Server at launch of the Starter. <br>
411 * The parameter -cmd <command> will use the given command to try to start
412 * the server. Else the XuluConfig will be used. <br>
413 * The parameter -noGUI forces the starter to not use any GUI functionality.
414 */
415 public static void main(String[] args) {
416 try {
417 System.out
418 .println("Use the parameter -help to see all available commandline options");
419 String cmd = null;
420 boolean noGUI = false;
421 boolean start = false;
422 // search for command parameter
423 for (int i = 0; i < args.length; i++) {
424 if (args[i].toLowerCase().equals("-cmd") && i < args.length)
425 cmd = args[i + 1];
426 if (args[i].toLowerCase().equals("-nogui") && i < args.length)
427 noGUI = true;
428 if (args[i].toLowerCase().equals("-start"))
429 start = true;
430 if (args[i].toLowerCase().equals("-help"))
431 printHelp();
432 }
433 XuluServerStarter starter = new XuluServerStarter(cmd, !noGUI);
434 System.out.println("XuluServerStarter initialized .... ");
435 if (start) {
436 starter.start();
437 }
438 if (!starter.isRunning()) {
439 System.out
440 .println("Hint: use parameter '-start' to start the server directly");
441 }
442 } catch (RemoteException e) {
443 // TODO Auto-generated catch block
444 e.printStackTrace();
445 }
446 }
447
448 /**
449 *
450 */
451 private static void printHelp() {
452 System.out
453 .println("The following commands can be used: \n\n"
454 + "-start can be used to start the Server at launch of the Starter.\n"
455 + "-cmd <command> will use the given command to try to start the server."
456 + " Else the XuluConfig will be used.\n"
457 + "-noGUI doesn't use any GUI functionality.\n"
458 + "-help displays this help");
459
460 }
461
462 public boolean isRunning() throws RemoteException {
463 return (p != null);
464
465 }
466
467 /**
468 * Copied from {@link Helper} and modified so that it does not depend on
469 * log4j. Binds the remote object's stub in the registry. Creates a registry
470 * if no running registry is found.
471 *
472 * @param bindingName
473 * the name to be used for binding
474 * @param bindingInstance
475 * an instance of the type to bind to the registry
476 * @param defaultPort
477 * the default registry port
478 * @throws RemoteException
479 * if something goes wrong
480 */
481 public void bind(String bindingName, Remote bindingInstance, int defaultPort)
482 throws RemoteException {
483 boolean failed = true;
484 Registry registry;
485 try {
486 registry = LocateRegistry.getRegistry();
487 registry.rebind(bindingName, bindingInstance);
488 failed = false;
489 } catch (AccessException e) {
490 System.err.println("Not enough permissions to bind" + bindingName
491 + "to the registry! Adjust your security permission file!");
492 e.printStackTrace();
493 } catch (RemoteException e) {
494 if (e instanceof java.rmi.ConnectException) {
495 System.out
496 .println("Could not connect to registry! Trying to create new one...");
497 try {
498 registry = LocateRegistry.createRegistry(defaultPort);
499 registry.rebind(bindingName, bindingInstance);
500 System.out.println("Registry successfully created at port "
501 + defaultPort);
502 failed = false;
503 } catch (RemoteException e1) {
504 // TODO Auto-generated catch block
505 e1.printStackTrace();
506 }
507 } else
508 e.printStackTrace();
509 }
510 if (failed)
511 throw new RemoteException("Could not find or create registry!");
512 }
513
514 /**
515 * The Thread is used to direct the output of the process to System.out.
516 * Notice that this stream may be redirected to a
517 * {@link TextAreaPrintStream} or any other printstream using
518 * {@link System#setOut(java.io.PrintStream)}
519 *
520 * @author appl
521 */
522 class SimpleConsoleOutputThread implements Runnable {
523 private volatile Thread outputThread;
524
525 private boolean exit;
526
527 private final InputStream standardInput;
528
529 private final InputStream errorInput;
530
531 private final BufferedReader input;
532
533 private final SequenceInputStream twoStreams;
534
535 private boolean availableLastTime = false;
536
537 /**
538 * Creates a new thread. The parmeters are the inputstreams which should
539 * be forwarded to System.out
540 *
541 * @param standardInput
542 * @param errorInput
543 */
544 public SimpleConsoleOutputThread(InputStream standardInput,
545 InputStream errorInput) {
546 this.standardInput = standardInput;
547 this.errorInput = errorInput;
548 // combine the streams
549 twoStreams = new SequenceInputStream(standardInput, errorInput);
550 input = new BufferedReader(new InputStreamReader(twoStreams));
551 }
552
553 public void startThread() {
554 exit = false;
555 if (outputThread == null)
556 outputThread = new Thread(this);
557 outputThread.start();
558 }
559
560 public void stopThread() {
561 exit = true;
562 outputThread.interrupt();
563 try {
564 input.close();
565 } catch (IOException e) {
566 System.out.println("Input closed");
567 e.printStackTrace();
568 }
569 }
570
571 public void run() {
572 String line;
573 while (exit == false) {
574 try {
575 while (input.ready()) {
576 line = input.readLine();
577 System.out.println(line);
578 }
579 Thread.sleep(1000);
580 // check if server is active for tray icon change
581 if (xuluServer != null)
582 if (availableLastTime != xuluServer.isAvailable()) {
583 if (availableLastTime)
584 setStatus(Status.serverActive);
585 else
586 setStatus(Status.serverStarted);
587 availableLastTime = (!availableLastTime);
588 }
589
590 } catch (IOException e) {
591 System.out
592 .println("Connection to server failed. Input closed");
593 e.printStackTrace();
594 exit = true;
595 } catch (InterruptedException e) {
596 if (exit == true)
597 System.out.println("Stopped output thread...");
598 }
599 }
600 }
601 }
602
603 /*
604 * (non-Javadoc)
605 *
606 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
607 */
608 public void actionPerformed(ActionEvent e) {
609 if (e.getSource() == starterServerGUI.button_stop
610 || e.getSource() == menu_stop) {
611 try {
612 this.stop();
613 } catch (Exception e1) {
614 System.out
615 .println("Could not stop the Server. Reason follows: ");
616 e1.printStackTrace();
617 }
618 } else if (e.getSource() == starterServerGUI.button_exit
619 || e.getSource() == menu_exit) {
620 // if user does not confirm: return.
621 if (JOptionPane
622 .showConfirmDialog(
623 starterServerGUI,
624 "Are you sure that you want to exit the Starter-Application?",
625 "Confirm exit", JOptionPane.OK_CANCEL_OPTION) != JOptionPane.OK_OPTION)
626 return;
627 try {
628 this.stop();
629 } catch (RemoteException e1) {
630 }
631 System.exit(1);
632
633 } else if (e.getSource() == starterServerGUI.button_start
634 || e.getSource() == menu_start) {
635 try {
636 this.start();
637 } catch (Exception e1) {
638 System.out
639 .println("Could not start the Server. Reason follows: ");
640 e1.printStackTrace();
641 }
642 } else if (e.getSource() == menu_showConsole) {
643 starterServerGUI.setVisible(true);
644 }
645
646 }
647 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26