Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 3. Auflage |
<< | < | > | >> | API | Kapitel 13 - Strukturierung von Java-Programmen |
Die Ausführungen in diesem Abschnitt können beim ersten Lesen übersprungen werden. Sie setzen ein grundsätzliches Verständnis für Applets voraus und verwenden Beispielcode aus den Abschnitten 38.3 und 45.3.3. Aus systematischen Gründen soll das Thema jedoch an dieser Stelle behandelt werden. |
|
Applets werden ab Kapitel 39 erklärt. Sie waren es, die mit der Möglichkeit, eigenständige Programme mit grafischer Oberfläche in Webseiten einzubinden, einen großen Teil der anfänglichen Begeisterung für Java auslösten. Später erkannte man noch einen zweiten, strategischen Vorteil: diese Programme mußten nicht installiert werden, sondern wurden einfach aufgerufen und waren immer up-to-date. Das brachte »gute alte Zeiten« in Erinnerung, bei denen die Anwender an einfachen Terminals saßen, die - wenn sie wirklich einmal defekt waren - ohne großen Aufwand ausgetauscht werden konnten.
Schnell war die Idee geboren, dies mit aktueller (Java-)Technologie nachzuahmen. Warum nicht alle benötigten Programme als Applets implementieren, die bei Bedarf von einem zentralen Server geladen werden? Man hatte nämlich erkannt, daß in den Unternehmen ein Großteil der durch Computerarbeitsplätze verursachten Kosten gar nicht bei deren Kauf entstand, sondern erst danach. Etwa durch Updates, Reparaturen und Wartungen; aber auch durch Probleme, die durch nicht verfügbare, fehlerhafte oder inkonsistente Programmversionen entstand. Die aus dieser Idee entstandenen Java Workstations konnten sich allerdings nicht durchsetzen. Trotz vielversprechender Anfänge wurden die durch langsame Netzwerkverbindungen oder unzulängliche Java-Implementierungen in den Browsern verursachten Probleme nicht gelöst. Die Java-Stations verschwanden ebenso schnell von der Bildfläche, wie sie zuvor aufgetaucht waren.
Während der Entwicklung des JDK 1.3 brachte SUN eine Technologie auf den Markt, mit der die Vorteile von Applets und Applikationen kombiniert werden sollten. Sie wird als Java Web Start (kurz WebStart) bezeichnet und ist seit dem JDK 1.4 fester Bestandteil jedes JDKs und JREs. Java Web Start bietet die Möglichkeit, Applikationen über einen Web-Server automatisch zu laden und zu aktualisieren, ohne daß dazu eine lokale Installation oder das manuelle Einspielen eines Softwareupdates erforderlich wäre. Sie kombiniert so die Installationsfreiheit von Applets mit der Geschwindigkeit und Flexibilität von Java-Applikationen. |
|
Wir wollen uns einmal ansehen, wie das Ganze funktioniert:
Die hier skizzierte Vorgehensweise beschreibt die Nutzungsmöglichkeiten von Java Web Start nur in Ansätzen. Tatsächlich bietet diese Technologie weit mehr Möglichkeiten, als hier erläutert werden könnte. So ist es beispielsweise möglich, die Anwendung in separate Teile zu zerlegen, die erst bei Bedarf geladen werden. Teile von Anwendungen lassen sich versionieren und werden nur dann aktualisiert, wenn eine neuere Version zur Verfügung steht. Man kann Applikationen auch signieren, um ihnen den Zugriff auf den kompletten Arbeitsplatz zu ermöglichen. Ohne Signatur laufen sie - ähnlich wie Applets - lediglich in einer »Sandbox« ab, in der sie nur beschränkte Zugriffsmöglichkeiten auf lokale Ressourcen haben. Weitere Informationen dazu werden in Abschnitt 13.5.3 gegeben. Ein Großteil dieser Möglichkeiten wird im Java Network Launching Protocol beschrieben, das über die Download-Seite der WebStart-Homepage heruntergeladen werden kann. Es findet sich wie alle anderen WebStart-Ressourcen und -Dokumentationen auf http://java.sun.com/products/javawebstart/index.html. |
|
Wir wollen uns in diesem Abschnitt die Aufgabe stellen, das Beispielprogramm JTree 3 aus Listing 38.13 in eine WebStart-Applikation zu verwandeln. Der Übersichtlichkeit halber erstellen wir dazu ein Unterverzeichnis wstest, in dem wir alle benötigten Dateien sammeln. Auf der CD-ROM zum Buch befindet sich dieses unterhalb der Beispieldateien, also direkt im Verzeichnis examples. Da es auf der CD-ROM bereits mit allen benötigten Dateien gefüllt ist, sind die nachfolgend beschriebenen Schritte (bei Verwendung dieses Verzeichnisses) redundant. Zum Lernen sollten sie aber dennoch nachvollzogen werden.
Zunächst kopieren wir die Dateien Listing3813.java
und WindowClosingAdapter.java in das
Verzeichnis und kompilieren sie:
javac *.java
Nach dem Kompilieren befinden sich die .class-Dateien
Listing3813.class und WindowClosingAdapter.class
in diesem Verzeichnis. Sie werden nun in ein jar-Archiv wstest.jar
verpackt:
jar cvf wstest.jar Listing3813.class WindowClosingAdapter.class
Der nächste Schritt besteht darin, die Deskriptordatei zu unserem WebStart-Projekt anzulegen. Hierbei handelt es sich um eine XML-Datei mit der Erweiterung .jnlp, in der alle Informationen untergebracht sind, die der WebStart-Anwendungsmanager für das Laden, Ausführen und Darstellen der Applikation benötigt. Sie heißt in unserem Beispiel wstest.jnlp und hat folgenden Inhalt:
001 <?xml version="1.0" encoding="utf-8"?> 002 003 <!-- JNLP File fuer HJP3 WebStart Demo-Applikation --> 004 <jnlp codebase="http://localhost:7777/" href="wstest.jnlp"> 005 006 <information> 007 <title>HJP3 WebStart Demo Application</title> 008 <vendor>Guido Krueger</vendor> 009 <homepage href="http://www.javabuch.de"/> 010 <description>HJP3 WebStart Demo Application</description> 011 <icon href="wstest.gif"/> 012 <offline-allowed/> 013 </information> 014 015 <information locale="de"> 016 <description>HJP3 WebStart Demo-Applikation</description> 017 <offline-allowed/> 018 </information> 019 020 <security> 021 <!-- <all-permissions/> --> 022 </security> 023 024 <resources> 025 <j2se version="1.3+"/> 026 <jar href="wstest.jar"/> 027 </resources> 028 029 <application-desc main-class="Listing3813"/> 030 031 </jnlp> |
Die Datei besteht aus dem jnlp-Element und vier Deskriptoren. Das jnlp-Element enthält die Attribute codebase und href. In codebase wird das Basisverzeichnis für alle relativen URLs angegeben, href ist die Lokation der jnlp-Datei selbst. localhost:7777 bedeutet, daß auf dem eigenen Rechner ein Web-Server auf TCP-Port 7777 läuft. Wir werden später noch zeigen, wie der in Abschnitt 45.3.3 vorgestellte ExperimentalWebServer für diesen Zweck verwendet werden kann. Alle URLs innerhalb der Datei können entweder absolut oder relativ zur codebase angegeben werden.
Die vier Deskriptoren haben folgende Bedeutung:
Das information-Element kann ein optionales locale-Argument haben und mehrfach vorhanden sein. So lassen sich Angaben machen, die nur für eine bestimmte Sprachversion gelten. In unserem Beispiel gibt es ein zweites information-Element, in dem die description in deutscher Sprache angegeben wird. Als mögliche Werte für das locale-Argument können die in Abschnitt 17.4 erläuterten Sprachen-/Länderstrings der Locale-Klasse verwendet werden.
Anmerkung: das offline-allowed-Element wird hier nur deshalb dupliziert, weil es auf Grund eines Bugs in der zum JDK 1.4 gehörenden WebStart-Version 1.0.1 nicht vererbt wurde. Laut BugParade sollte dieser Fehler ab WebStart 1.2 behoben sein. |
|
Zunächst benötigen wir für unsere Beispielapplikation
einen Web-Server. Der Einfachheit halber wollen wir dazu den in Abschnitt 45.3.3
vorgestellten ExperimentalWebServer
verwenden. Wir kopieren dazu die Datei ExperimentalWebServer.java
aus dem Verzeichnis examples
ebenfalls in unser Beispielverzeichnis und übersetzen sie:
javac ExperimentalWebServer.java
Soll ein anderer Web-Server verwendet werden, ist es wichtig, den Mime-Typ für jnlp-Dateien korrekt zu konfigurieren. Der Server muß eine Datei mit der Erweiterung .jnlp stets mit dem Mime-Typ application/x-java-jnlp-file an den Client übertragen. Andernfalls könnte es sein, daß der WebStart-Applikationsmanager nicht korrekt aufgerufen wird. In unserem ExperimentalWebServer ist dieser Typ bereits vorkonfiguriert, zusätzliche Anpassungen sind daher nicht nötig. |
|
Wir wollen nun noch eine einfache HTML-Datei wstest.html zum Starten der WebStart-Applikation erstellen. Sie enthält im wesentlichen einen Link auf die jnlp-Datei:
001 <html> 002 003 <head> 004 <title>HJP3 WebStart Demo Application</title> 005 </head> 006 007 <body> 008 009 <h2>HJP3 WebStart Demo Application</h2> 010 011 <a href="wstest.jnlp">Anwendung laden/starten</a> 012 013 </body> 014 015 </html> |
Zusätzlich müssen wir die in der jnlp-Datei angegebene Icon-Datei
wstest.gif in unser Beispielverzeichnis
kopieren. Anschließend können wir den Web-Server starten:
java ExperimentalWebServer 7777
Zum erstmaligen Starten der Anwendung wird die Web-Seite mit dem Link auf die jnlp-Datei aufgerufen:
Abbildung 13.3: Die Startdatei der WebStart-Anwendung im Browser
Wird nun der Link »Anwendung laden/starten« angeklickt, lädt der Browser die jnlp-Datei und ruft als zugehörige Applikation den WebStart-Applikationsmanager auf. Dieser liest die Datei ein und lädt alle darin beschriebenen Ressourcen. Anschließend wird die Applikation gestartet, und wir sehen das in Abbildung 38.10 gezeigte Programm.
Beim Herunterladen hat der WebStart-Applikationsmanager alle Dateien der Anwendung in seinen lokalen Cache kopiert. Die HTML-Datei wird nun zum Starten nicht mehr unbedingt benötigt. Stattdessen kann der WebStart-Applikationsmanager direkt aufgerufen werden. Nach einem Klick auf den Menüpunkt »Ansicht.Heruntergeladene Anwendungen« stellt er sich wie folgt dar:
Abbildung 13.4: Der WebStart-Applikationsmanager
Durch Drücken des »Starten«-Buttons wird unsere Anwendung gestartet. Die internen Abläufe unterscheiden sich dabei nicht von denen beim Starten über den Link im Browser. Zunächst wird stets die jnlp-Datei geladen und alle darin beschriebenen Ressourcen überprüft bzw. aktualisiert. Sind alle Dateien verfügbar, wird die Anwendung gestartet. Taucht ein Problem auf, bricht WebStart den Startvorgang ab und gibt eine Fehlermeldung aus. Wir wollen hier nicht weiter auf Details eingehen; der WebStart-Applikationsmanager ist einfach aufgebaut, und seine Funktionen sind weitgehend selbsterklärend.
Wird eine WebStart-Anwendung das zweite Mal gestartet, fragt der Anwendungsmanager, ob die Anwendung auf dem Desktop bzw. im Startmenü verankert werden soll. Stimmt der Anwender zu, kann sie anschließend auch auf diesem Weg gestartet werden.
Nachdem die Anwendung im lokalen Cache gespeichert wurde, kann sie auch offline betrieben werden, d.h. ohne den auf Port 7777 laufenden Webserver. Sie kann dann zwar nicht mehr über den Link im Browser gestartet werden, aber die drei anderen Wege stehen ihr noch offen. Stellt WebStart beim Aufruf einer Applikation fest, daß die in der jnlp-Datei genannten Ressourcen nicht erreichbar sind, verwendet er die lokalen Kopien und startet die Anwendung aus dem Cache. Das ist allerdings nur möglich, wenn in der jnlp-Datei das Element offline-allowed gesetzt wurde. War das nicht der Fall, kann die Anwendung nicht offline gestartet werden. |
|
Eingangs wurde schon erwähnt, daß unsignierte WebStart-Applikationen nur eingeschränkten Zugriff auf lokale Systemressourcen haben. Zwar ist - anders als bei Applets - der Aufruf von System.exit erlaubt. Dennoch gibt es einige Einschränkungen:
Damit unsignierte WebStart-Anwendungen dennoch ein gewisses Maß an praxisrelevanter Funktionalität anbieten können, stellt die WebStart-Laufzeitumgebung einige Services zur Verfügung, über die Anwendungen in kontrollierter Weise auf Systemressourcen zugreifen können:
All diese Services sind insofern als relativ sicher anzusehen, als sie dem Programm entweder nur sehr beschränkten Zugriff auf Systemressourcen erlauben (z.B. ClipboardService, PersistenceService) oder der Anwender per GUI-Dialog ihrer Benutzung zustimmen muß und somit selbst entscheiden kann, welche konkreten Ressourcen verwendet werden (z.B. FileOpenService, FileSaveService, PrintService). Dennoch sollten unsignierte WebStart-Applikationen aus potentiell unsicheren Quellen mit der nötigen Vorsicht verwendet werden. Einerseits ist nicht auszuschließen, daß man als Anwender im Eifer des Gefechts einmal unbeabsichtigt einer Service-Nutzung zustimmt, die später Schaden anrichtet. Andererseits sind Denial-of-Service-Attacken nicht auszuschließen. Hierbei verwendet eine bösartige Anwendung eine Ressource in so hohem Maße, daß sie für den ordnungsgemäßen Betrieb anderer Anwendungen nicht mehr ausreichend zur Verfügung steht. Beispiele sind etwa Programme, die 100 Prozent CPU-Last verursachen oder solche, die das Dateisystem durch Erzeugen riesiger Dateien zum Überlauf bringen. Gegen derartige Programme bieten auch die Service-Einschränkungen der WebStart-Applikationen keinen Schutz. |
|
In diesem Abschnitt wollen wir uns ein einfaches Beispiel für die Verwendung des jnlp-APIs ansehen. Ein Programm soll dem Anwender einen DateiÖffnen-Dialog präsentieren und den Inhalt der darin ausgewählten Datei auf der Konsole ausgeben (sie läßt sich im WebStart-Applikationsmanager im Dialog »Datei.Einstellungen.Erweitert« sichtbar machen). Auf die übrigen Services wollen wir nicht weiter eingehen, denn ihre Anwendung ähnelt der hier beschriebenen. Weitere Details zu den Services sind in der jnlp-API-Dokumentation zu finden.
Soll ein WebStart-Programm auf einen jnlp-Service zugreifen, muß dieser zunächst mit Hilfe der Klasse ServiceManager aus dem Paket javax.jnlp angefordert werden:
public static java.lang.Object lookup(java.lang.String name) throws UnavailableServiceException |
javax.jnlp.ServiceManager |
Die Methode lookup erwartet einen String mit dem Servicenamen als Argument. Dies muß ein qualifizierter Klassenname sein, etwa "javax.jnlp.FileOpenService" oder "javax.jnlp.PrintService". Kann der Service nicht zur Verfügung gestellt werden (die meisten Services sind optional und müssen nicht von allen WebStart-Clients implementiert werden), wird eine Ausnahme des Typs UnavailableServiceException ausgelöst. Andernfalls wird der Rückgabewert auf den gewünschten Typ konvertiert und kann dann verwendet werden.
Alle Klassen aus dem jnlp-API befinden sich im Paket javax.jnlp. Dieses ist - auch in der Version 1.4 - nicht Bestandteil des JDKs, sondern muß separat heruntergeladen werden. Es ist wie alle anderen WebStart-Ressourcen im Download-Bereich von http://java.sun.com/products/javawebstart/index.html zu finden. Benötigt wird meist lediglich die Datei jnlp.jar, die zum Kompilieren in den Klassenpfad einzubinden ist. Zur Laufzeit muß sie nicht explizit angegeben werden, sondern wird vom WebStart-Applikationsmanager zur Verfügung gestellt. |
|
Die nun folgenden Schritte sind Service-spezifisch. Der FileOpenService stellt beispielsweise folgende Methode zur Verfügung, um einen DateiÖffnen-Dialog zu erzeugen:
public FileContents openFileDialog( java.lang.String pathHint, java.lang.String[] extensions ) throws java.io.IOException |
javax.jnlp.FileOpenService |
Das erste Argument pathhint ist ein Vorgabewert der Anwendung für das Verzeichnis, aus dem die Datei geladen werden soll. Das zweite Argument enthält eine Liste von Datei-Erweiterungen, die standardmäßig angezeigt werden. Der Rückgabewert ist entweder null, falls der Dialog abgebrochen wurde, oder er enthält ein FileContents-Objekt für die vom Anwender ausgewählte Datei. Dieses kann verwendet werden, um Informationen über die Datei abzufragen sowie um Eingabe- oder Ausgabestreams zum Lesen und Schreiben der Datei zu beschaffen.
Wichtige Methoden der Klasse FileContents sind:
public java.lang.String getName() throws java.io.IOException public long getLength() throws java.io.IOException public boolean canRead() throws java.io.IOException public boolean canWrite() throws java.io.IOException public InputStream getInputStream() throws java.io.IOException public OutputStream getOutputStream(boolean overwrite) throws java.io.IOException |
javax.jnlp.FileContents |
getName liefert den Namen der Datei, und mit getLength kann ihre Länge bestimmt werden. Mit canRead und canWrite kann festgestellt werden, ob Lese- bzw. Schreibzugriffe erlaubt sind. getInputStream beschafft einen InputStream, mit dem die Datei gelesen werden kann, und getOutputStream stellt einen OutputStream zum Schreiben der Datei zur Verfügung. Das Argument overwrite gibt dabei an, ob der bestehende Inhalt überschrieben oder die neuen Daten an das Ende der bestehenden Datei angehängt werden sollen.
Nach diesen Vorbemerkungen können wir uns nun das Beispielprogramm ansehen:
001 /* WebStartTest2.java */ 002 003 import java.io.*; 004 import javax.jnlp.*; 005 006 public class WebStartTest2 007 { 008 public static void main(String[] args) 009 { 010 try { 011 //FileOpenService anfordern 012 FileOpenService fos = (FileOpenService)ServiceManager.lookup( 013 "javax.jnlp.FileOpenService" 014 ); 015 //DateiÖffnen-Dialog aufrufen 016 FileContents fc = fos.openFileDialog(null, null); 017 if (fc == null) { 018 System.err.println("openFileDialog fehlgeschlagen"); 019 } else { 020 //Dateiinhalt auf der Konsole ausgeben 021 InputStream is = fc.getInputStream(); 022 int c; 023 while ((c = is.read()) != -1) { 024 System.out.print((char)c); 025 } 026 is.close(); 027 } 028 } catch (UnavailableServiceException e) { 029 System.err.println("***" + e + "***"); 030 } catch (IOException e) { 031 System.err.println("***" + e + "***"); 032 } 033 //10 Sekunden warten, dann Programm beenden 034 try { 035 Thread.sleep(10000); 036 } catch (InterruptedException e) { 037 } 038 System.exit(0); 039 } 040 } |
WebStartTest2.java |
Das Programm kann wie im vorigen Abschnitt gezeigt übersetzt, in eine WebStart-Applikation verpackt und ausgeführt werden. Wenn die Konsole im WebStart-Applikationsmanager aktiviert wurde, kann mit dem Programm jede beliebige Datei gelesen werden - vorausgesetzt, der Anwender stimmt im DateiÖffnen-Dialog zu.
Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 3. Auflage, Addison Wesley, Version 3.0.1 |
<< | < | > | >> | API | © 1998-2003 Guido Krüger, http://www.javabuch.de |