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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26