/[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 78 - (hide 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 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.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