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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (hide 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 mojays 2 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