|
Den jedem Administrator geläufigen Befehl "ping" gibt es unter Java leider nicht. Er ist aber auf vielen OS verfügbar, unter anderem unter Linux und Windows. Die folgende Beispiel Applikation zeigt auf, wie schnell eine Recht geringe Anforderung an eine Applikation die Anwendung diverser Techniken notwendig macht. Einige der hier angewendeten Techniken sind allerdings durch elegantere und/oder einfachere Methoden zu ersetzen. Umgekehrt läßt sich aber an Beispielen wie diesem das Zusammenspiel diverser Techniken auszeigen. Folgendes soll die Applikation tun: a) Eingaben eines Hostnamens oder einer Host-IP-Adresse in einem JTextField. b) Überprüfung des lokalen OS b) Dem OS angepaßter Aufruf eines externen Prozesses, in diesem Fall der "ping"-Befehl. c) Umlenken der Ausgabe dieses Prozesses in ein JTextArea. Das ganze könnte dann so aussehen: 
1. Überprüfung des OS: Java verfügt über zwei Möglichkeiten, das OS festzustellen, unter dem die VM läuft. Hier soll die Methode System.getProperty("os.name");genutzt werden, die einen String zurückliefert, der im Falle eines Windows OS den Substring "Windows" enthält. Diesen Substring wollen wir mit Hilfe von regular expressions ermitteln, da dies für spätere Erweiterungen nützlich sein könnte. Momentan gehen wir aber davon aus, dass alles was im zurückgegebenen String nicht das Wort "Windows" enthält, Linux ist, Mac-Besitzer mögen dies verzeihen. Hier der Code: import java.util.regex.Pattern; import java.util.regex.Matcher; [...] private boolean winOS = false; // Ist es Windows? Erstmal "nein" antworten [...] Pattern pattern = Pattern.compile("Windows?"); // Das zu suchende Pattern setzenMatcher matcher = pattern.matcher(System.getProperty("os.name")); // Den Pattern Matcher setzenwhile (matcher.find()) winOS = true; // Ja, es ist Windows
2. Erstellen eines Frames mit JTextArea, JTextField, JButton Zugegeben: Der Mensch ist faul. Auch ich. Und dies ist kein Swing Tutorial. Als Anregung gebe ich hier deswegen nur ausschnittsweise den Code wieder, den Netbeans lieferte. private javax.swing.JButton jButton1; private javax.swing.JTextArea jTextArea1; private javax.swing.JTextField jTextField1; [...] jTextArea1 = new javax.swing.JTextArea(); jTextField1 = new javax.swing.JTextField(); jButton1 = new javax.swing.JButton() [...] jTextArea1.setColumns(20); jTextArea1.setRows(5); jButton1.setText("Ping!");jButton1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt){ jButton1ActionPerformed(evt); } }); Es folgt setzen des Layout, hinzufügen der oben erzeugten Komponenten usw. 3. Umlenkung des Standard Outputs auf ein JTextArea Zur Erinnerung: Jedem PrintStream wird ein OutputStream übergeben. Letzteren erzeugen wir mit dieser Klasse: class TextAreaOutStream extends OutputStream { private JTextArea area = null; TextAreaOutStream (JTextArea out) { this.area = out; } public void write(final int b) { SwingUtilities.invokeLater(new Runnable() { public void run() { area.append(String.valueOf((char)b)); area.setCaretPosition(area.getText().length()); } }); } Der Reihe nach: Es wird ein JTextArea deklariert, danach der Konstruktor erzeugt. Dieser erfordert die Übergabe des JTextArea, das dem JTextArea Feld der Klasse übergeben wird. Und dann... oops: Die Methode write(), die von OutputStream geerbet wurde, wird überschrieben. Die Originalmethode schreibt genau ein Byte in den OutputStream. Die überschreibene, neue Methode erzeugt eine Thread, der an das übergebene TextArea einen Character anhängt (via der Methode append des TextArea). Weiterhin wird der Textzeiger ("Caret") an das Ende des Inhaltes des Textes des TextArea setzt. Nun fehlt uns noch der PrintStream: Genau wie TextAreaOutStream ist dieser als Inner Class realisiert, und zwar in folgender abgeleiteter Klasse: class TextAreaStream extends PrintStream { TextAreaStream (JTextArea area) { super(new TextAreaOutStream(area)); } } In alt bekannter Manier wird hier einem PrintStream (über den Konstruktor) ein OutputStream (bzw. von OutputStream abgeitete Klasse) zugewiesen. Diese abgeleitete Klasse beinhaltet nun aber die entscheidende Änderung: die write()-Methode wie oben beschrieben. Am Anfang des Programs wird eine Instanz von TextAreaStream erzeugt und dem Konstruktor die Referenz auf das JTextArea übergeben und der TextAreaStream als Standardausgabe gesetzt.
out = new TextAreaStream(jTextArea1); System.setOut(out); 4. Erzeugen des externen Prozesses Im Folgenden erzeugen wir einen neuen Prozess. d.h. wir rufen den ping-Befehl auf und unterscheiden dabei zwischen Windows und Nicht-Windows. Unter Windows werden als Standard 4 Packete gesendet, unter Linux setzen wir die Anzahl explizit auf 4. Achtung: Unter Linux sind für den ping-Befehl ggf. Rechte zu ändern, bzw. erweiterte Rechte notwendig!) private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { if (winOS) // Windows? -> Ja processBuilder = new ProcessBuilder("ping", jTextField1.getText() ); else // Nein, ist Linux processBuilder = new ProcessBuilder("ping", "-c", "4", jTextField1.getText() ); try{ process = processBuilder.start(); [...] 4. Entgegennahme der Ausgabe des externen Prozesses Bisher zeigt das Programm nur die Konsolenausgaben im JTextArea an, die (direkt oder indirekt) mit System.out.println o.ä. ausgegeben wurden. Es sollen nun aber die Ausgaben des ping-Befehls entgegengenommen und in JTextArea sichtbar gemacht werden: BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(process.getInputStream())); // Ausgabestream lesen
String line; while ((line = bufferedReader.readLine()) != null) { // Und wieder ausgeben
System.out.print(line+"\n"); } bufferedReader.close(); Soweit ist nun alles implementiert, was das Programm machen sollte. Als letztes noch der Hinweis, dass eine einfache Abfrage, ob derPing erfolgreich war, durch das Statement if (process.exitValue() == 0) erfolgen kann.
|