Nachdem bisher die grundlegende Funktionalität der Sprache Java erläutert wurde, ist eine Abgrenzung zur Sprache JavaScript sinnvoll. Häufig findet man das Missverständnis, dass JavaScript eine Art vereinfachtes Java wäre. Dies ist ein grundlegender Irrtum. JavaScript ist eine Entwicklung der Firma Netscape Corporation, die der Schließung der Lücke zwischen Designern von Webseiten und Programmierern dient. Im Gegensatz zu Java handelt es sich bei JavaScript bezüglich der Syntax um eine Untermenge von Java. Im Gegensatz zur Erstellung von Java-Applets muss ein Entwickler hierbei nur eingeschränkte Programmiererfahrung aufweisen. JavaScript ist eine Makroprogrammiersprache. Ein JavaScript-Programm wird daher nicht übersetzt, sondern im Klartext in ein HTML-Dokument eingefügt. Der Quellcode eines JavaScript-Programms ist somit für den Benutzer einsehbar. Ein Beispiel hierfür ist in Abb. 1-7 angegeben. Man erkennt, dass das JavaScript zwischen den Anweisungen <SCRIPT> und </SCRIPT> angegeben wird. Die Anweisung <BR> erzeugt eine neue Zeile. Zweck des obigen Scripts ist die Ausgabe der Zeichenkette Hallo, die in Anführungszeichen steht. Abb. 1.7: Beispiel für JavaScript Ist ein Java-Applet mit der dazugehörigen Laufzeitumgebung einmal gestartet, so laufen JavaScript-Anwendungen langsamer ab als Java-Applets. Dies ist darin begründet, dass zur Ausführung eines JavaScripts der Interpreter den Code Anweisung für Anweisung übersetzen muss. Dies wiederholt sich bei jeder Ausführung eines derartigen Programms. Java-Applets hingegen werden einmal in Bytecode übersetzt (compiliert) und sind daher in der Ausführung erheblich schneller. Man sollte jedoch bedenken, dass das Laden der Laufzeitumgebung von Java eine erhebliche Zeit benötigt, wodurch in der Regel JavaScript-Programme insgesamt schneller arbeiten als Java-Applets. Als Scriptsprache ist JavaScript weiterhin objektbasiert, jedoch nicht objektorientiert wie Java. JavaScript verwendet weder Vererbungsstrukturen, noch findet eine strenge Typenkontrolle bzw. eine Deklaration von Typen statt. Sicherheitsprobleme in JavaScript JavaScript weist einige weit ernstere Sicherheitsproblematiken auf als Java: JavaScript-Programme können die History-Datei des Browsers und Cookies lesen. In der History-Datei stehen die zuletzt vom Benutzer aufgerufenen Webseiten. Unter Ausnutzung dieser Information ist es eventuell möglich, den Benutzer zu kompromittieren. URL-Caches können gelesen werden. Ein URL-Cache wird verwendet, um die letzten aufgerufenen Webseiten entweder im Speicher oder in einem schnell zugänglichen Festplattenbereich vorzuhalten, um die Zugriffszeiten bei einem erneuten Zugriff zu verringern. Analog zum ersten Beispiel können diese Daten kompromittierend sein. In JavaScript kann ein Fenster geöffnet werden, das lediglich ein Quadratpixel groß ist. Dadurch hat der Benutzer den Eindruck, das Script hätte längst terminiert, während dieses immer noch läuft und z. B. alle Web-Zugriffe protokolliert. Schlimmer ist sogar, dass das Script auch Daten überwachen kann, die in Formulare eingegeben werden. Zu diesen zählen z. B. auch Login-Namen und Passwörter. JavaScript-Programme können in heute erhältlichen Browsern nicht abgebrochen werden. Belegt ein möglicherweise feindliches Programm die Ressourcen eines Rechners zu einem großen Teil, so kann die Ausführung nur durch Beenden des Browsers bzw. durch Ausschalten des Rechners abgebrochen werden. Einige der angesprochenen Mängel wurden mittlerweile von den Browser-Herstellern beseitigt, längst aber nicht alle. Ein weiteres sehr ernstes Problem ist, dass JavaScript im Gegensatz zu Java im regulären Betrieb Daten auf die Festplatte schreiben darf. Dies ist allerdings nicht transparent, der Benutzer muss also um Erlaubnis gefragt werden. Koppelt man dies aber mit einer harmlosen Anfrage, so steht einem Missbrauch nichts mehr im Wege. Beispielsweise könnte ein Benutzer darauf aufmerksam gemacht werden, dass zum Herunterladen einer Seite ein Plug-In nötig ist, das auf der Festplatte gespeichert werden muss. Plug-Ins dienen dazu, die Ausführung spezieller Programme auf Anwenderseite zu ermöglichen. Ein Beispiel hierfür ist ein Plug-In, das das Abspielen eines speziellen Videoformats ermöglicht. Gibt der Benutzer seine Zustimmung zu einem derartigen Plattenzugriff, so wird die Festplatte freigegeben und das Script kann nicht daran gehindert werden, nach dem Herunterladen einer Datei sämtliche vorhandene Daten im Zugriff dieses Benutzers auszuspähen, diese zu modifizieren oder gar zu löschen. Anwendungsfelder JavaScript dient maßgeblich der grafischen Aufwertung und der Steuerung von HTML-Seiten. Für umfangreiche Projekte ist JavaScript dagegen aufgrund der mäßigen Modularisierbarkeit ungeeignet. Ein großer Vorteil der JavaScript-Programme ist, dass sie bereits auf 16-Bit-Betriebssystemen eingesetzt und mit einem 16-Bit-Browser angezeigt werden können. Kombinationen von Java und JavaScript Zur Kommunikation von Java und JavaScript kann das von der Firma Netscape Corporation entwickelte LiveConnect verwendet werden. LiveConnect ermöglicht unter anderem den Zugriff auf Java-Variablen, -Methoden, -Klassen und -Packages aus JavaScript heraus, die Kontrolle von Plug-Ins und Java-Applets durch JavaScript und den Zugriff auf JavaScript-Methoden und -Eigenschaften durch Java. Zur Darstellung von LiveConnect ist es unumgänglich, einige Code-Beispiele anzuführen, auch wenn die Sprache Java erst später erläutert wird. Der insbesondere an JavaScript interessierte Leser sollte daher zunächst versuchen, das hinter LiveConnect stehende Konzept zu verstehen. Zum Verständnis der Code-Beispiele sollte anschließend das Kapitel 3 gelesen werden, in dem die Sprache Java erläutert wird. Kontrolle von Java durch JavaScript In LiveConnect stehen drei Möglichkeiten zu Verfügung, um mit Java-Anwendungen zu kommunizieren: der direkte Aufruf von Java-Methoden, die Kontrolle von Java-Applets und die Kontrolle von Java-Plug-Ins. Wenn LiveConnect verwendet wird, kann JavaScript dazu verwendet werden, um Java-Methoden aufzurufen. Sowohl in Java als auch in JavaScript werden sog. Packages verwendet, die die verschiedenen Teile der jeweiligen Sprache in inhaltlich zusammengehörige Gruppen unterteilen. In der Java-Klasse java.lang.system sind bspw. unter anderem Ausgaberoutinen von Text zusammengefasst (eine ausführliche Darstellung der Java-Packages findet sich in Kapitel 3.2). In JavaScript sind die Java-Packages und -Klassen Eigenschaften des Objektes Packages. Die Java-Syntax kann nun verwendet werden, um Java-Objekte in JavaScript zu referenzieren, wobei der Name des Packages-Objekts folgendermaßen vorangestellt wird: [Packages.]packageName.Klassenname.Methodenname Der Name Packages steht optional für java, sun oder auch netscape-Packages. Im eigentlichen Programm-Code sind java, sun und auch netscape Stellvertreter für Packages.java, Packages.sun bzw. Packages.netscape. Betrachtet man die bereits angesprochene Java-Klasse java.lang.System, so kann diese im Code entweder als Packages.java.lang.System oder als java.lang.System angesprochen werden. Angenehmerweise erfolgt der Zugriff auf Felder und Methoden einer Klasse in JavaScript in derselben Syntax wie Java. Der folgende JavaScript-Code kann bspw. dazu verwendet werden, eine Nachricht auf der Java-Konsole auszugeben: `var System = java.lang.System; System.err.println("Aufruf von JavaScript");` In der ersten Zeile des Beispiels wird der Bezug der JavaScript-Variablen System zur Java-Klasse java.lang.System hergestellt. In der zweiten Zeile wird die println-Methode der statischen Variablen err der Java-Systemklasse aufgerufen, die die Ausgabe einer Zeichenkette vornimmt. Es ist hierbei zu beachten, dass println als Java-Methode als Argument eine Zeichenkette der Form java.lang.String erwartet. Hierzu wird die JavaScript-Zeichenkette automatisch in einen String der Form java.lang.String umgewandelt. Mittels JavaScript kann weiterhin das Verhalten eines Java-Applets kontrolliert werden, ohne ein explizites Wissen über die interne Struktur des jeweiligen Applets verwenden zu müssen. JavaScript kann auf alle öffentlichen Variablen, Methoden und Eigenschaften eines Applets zugreifen. In JavaScript wird ein in einem Dokument verankertes Applet mittels dokument.appletName angesprochen, wobei appletName den Wert des NAME-Attributs bezeichnet, der in einem HTML-Dokument innerhalb des Ausdrucks <APPLET>...</APPLET> gesetzt wird. Kommen in einem Dokument mehrere Applets vor, so können diese mittels document.applets[i] angesprochen werden (i steht hier als Platzhalter für die Nummer des Applets im Dokument). document.applets[0] würde bspw. das erste auf einer Seite vorkommende Applet bezeichnen. Abb. 1.8: „Hello World"-Applet Ein häufig verwendetes Beispiel, mit dem einfache Vorgänge in Programmiersprachen verdeutlicht werden können, sind die „Hello World"-Anwendungen, in denen jeweils die Ausgabe „Hello World" erzeugt wird. Ein Java-Applet, das eine derartige Ausgabe vornimmt, ist in Abb. 1-8 dargestellt. In den ersten zwei Zeilen werden zuerst die notwendigen Packages java.applet.Applet und java.awt.Graphics importiert, mit deren Hilfe unter anderem die notwendige Funktionalität zur Erzeugung eines Fensters zur Verfügung gestellt wird. In der dritten Zeile wird die öffentliche Klasse HelloWorld von der Applet-Klasse abgeleitet, in der in Zeile vier die Ausgabe mittels g.drawString einschließlich der notwendigen Anzeigekoordinaten realisiert wird. Zur Ausführung dieses Applets und damit zur Anzeige der Zeichenkette kann die folgende HTML-Zeile verwendet werden: `<APPLET CODE="HelloWorld.class" NAME="HelloWorld" WIDTH=150 HEIGHT=25></APPLET>` Mittels des NAME-Attributs wird hier das Applet als „HelloWorld" bezeichnet. Eine Referenzierung dieses Applets kann in einem JavaScript-Programm mittels der Anweisungen document.HelloWorld oder auch document.applets["HelloWorld"] erfolgen. Kennt man zusätzlich die Anzahl der Applets in einer HTML-Seite, so kann das Applet auch mittels document.applets[0] referenziert werden, wenn es das erste ist, das in einer HTML-Seite enthalten ist. Die Anzahl der in einer HTML-Seite enthaltenen Applets kann zudem leicht mit der Variablen document.applets.length festgestellt werden. Ein großer Vorteil von LiveConnect ist, dass alle als öffentlich (public) deklarierten Variablen eines Applets, die Elternklassen und -Packages in JavaScript verwendet werden können. Statische Methoden und Eigenschaften sind in JavaScript als Methoden und Eigenschaften des Applet-Objekts verfügbar. Plug-Ins eines Dokuments können in JavaScript als Element des embeds-Arrays angesprochen werden. Die folgende HTML-Zeile beinhaltet bspw. eine Audiodatei: `<EMBED SRC=audiodatei.wav NAME="audiodatei" WIDTH=100 HEIGHT=100>` Analog zur Referenzierung von Java-Applets kann dieses Plug-In aus JavaScript mittels der Anweisungen document.embeds[0], document.embeds["audiodatei"] oder document.audiodatei angesprochen werden, wenn wiederum audiodatei das erste Plug-In ist, das in einer Webseite vorkommt. Wie auch bei Applets existiert eine Variable document.embeds.length, die die Anzahl der Plug-Ins einer Webseite reflektiert. Kontrolle von Java durch JavaScript Um aus einem Java-Applet heraus JavaScript-Methoden, -Eigenschaften und -Datenstrukturen anzusprechen, muss in einem Applet das von der Firma Netscape entwickelte Package javascript folgendermaßen importiert werden: `import netscape.javascript.*;` In netscape.javascript werden die Klasse JSObject (JavaScript Objekt) bzw. das JSException exception-Objekt definiert. Mittels des Objekts JSException exception wird hierbei eine Ausnahmebehandlung angeboten, auf die im Fehlerfall zurückgegriffen werden kann. Um die Kommunikation von Java-Applets mit JavaScript zu ermöglichen, muss in einer HTML-Seite innerhalb des APPLET-Tags das MAYSCRIPT-Attribut gesetzt werden. MAYSCRIPT verhindert, dass ein Applet ein JavaScript-Programm aufruft, ohne dass der Autor der jeweiligen Seite bekannt ist. Die Kenntnis des Autors ist aber aufgrund der Sicherheitsrestriktionen von Java zwingend erforderlich, da sonst ein Fehler ausgelöst werden würde. Es ist daher selbsterklärend, dass das MAYSCRIPT-Tag nur verwendet werden muss, wenn von Java-Applets aus JavaScript-Code aufgerufen wird. Die umgekehrte Kommunikationsrichtung verlangt diesen Mechanismus hingegen nicht. Bevor auf JavaScript zugegriffen werden kann, muss ein sog. Handle eingerichtet werden, mit Hilfe dessen auf ein Browser-Fenster zugegriffen werden kann. Hierzu wird die getWindow-Methode verwendet, die Bestandteil der Klasse netscape.javascript.JSObject ist. Das folgende Beispiel illustriert, wie Java-Code einer Variablen fenster, die bereits als Variable vom Typ JSObject vereinbart wurde, ein Handle zugewiesen wird: `public class fensterBeispiel extends Applet {` public void init() { JSObject fenster = JSObject.getWindow(this); } } In der Initialisierungsroutine init() wird hierzu der Variablen fenster ein Handle zugewiesen. Zum Zugriff auf Objekte und Eigenschaften von JavaScript steht die getMember-Methode der Klasse netscape.javascript.JSObject zur Verfügung. Nachdem man mit der getWindow-Methode ein Handle für ein JavaScript-Fenster erhalten hat, verwendet man getMember, um auf JavaScript-Objekte zuzugreifen. Der folgende Java-Code erlaubt es bspw., mittels der Variablen formular auf ein JavaScript-Objekt document.testFormular zuzugreifen: `public void init() {` JSObject fenster = JSObject.getWindow(this); formular=fenster.eval("document.testFormular"); } Hierzu kann die Methode eval verwendet werden, die Teil der Klasse fenster ist. eval dient an dieser Stelle lediglich als Abkürzung. Eine äquivalente Funktionalität erreicht man mit den folgenden zwei Zeilen, die dann die Zeile `formular=fenster.eval("document.testFormular");` ersetzen: `JSObject doc = (JSObject) fenster.getMember("document"); JSObject formular = (JSObject) doc.getMember("testFormular");` Die eval-Methode der Klasse netscape.javascript.JSObject dient also dazu, einen JavaScript-Ausdruck aufzurufen. Die allgemeine Notation dieses Aufrufs ist JSObject.getWindow().eval("ausdruck"), wobei ausdruck einen JavaScript-Ausdruck bezeichnet, der hinsichtlich eines JavaScript-Methodenaufrufs ausgewertet wird. Zur Veranschaulichung dieser Funktionalität dient das folgende Beispiel, mit Hilfe dessen ein JavaScript-Alarm ausgelöst wird, wenn eine Mausbewegung in Aufwärtsrichtung festgestellt wird: `public void init() {` JSObject fenster = JSObject.getWindow(this); } public boolean mouseUp(Event e, int x, int y) { win.eval("alert(\"Hello world!\");"); return true; } Hierzu wird zunächst ein Fenster-Handle erzeugt und anschließend die JavaScript-Methode alert mit dem Parameter „Hello World!" aufgerufen, wenn eine derartige Mausbewegung in Java festgestellt wird. Abb. 1.9: Mögliches Zusammenspiel von Java und JavaScript Eine andere Möglichkeit, JavaScript-Methoden aufzurufen, steht durch die call-Methode des JSObject-Objekts zur Verfügung. Das folgende Kommando ruft eine JavaScript-Methode aus Java auf und übergibt zusätzlich Java-Objekte als Argumente: `JSObject.call(methodenName, argumentArray);` Hierbei bezeichnet methodenName die aufzurufende JavaScript-Methode und argumentArray eine Liste von Java-Objekten, die an die JavaScript-Methode übergeben werden. Sollen lediglich einfache Werte (bspw. Ganzzahlen) übergeben werden, so muss eine Liste dieser Werte in Java erzeugt werden, die anschließend mittels argumentArray an JavaScript übergeben wird. Ein Beispiel hierzu ist in Abb. 1-9 angegeben. Hierzu wird das „Hello World"-Beispiel derart modifiziert, dass in JavaScript die Ausgabe Male erzeugt wird, wenn in Java eine Zeichenkette in einem Fenster angezeigt wird. In diesem Beispiel sollte nicht vergessen werden, das MAYSCRIPT-Attribut innerhalb des <APPLET>-Tags der HTML-Seite zu setzen. Jedes Mal, wenn das Applet initialisiert und damit aufgerufen wird, wird nun eine JavaScript-Box angezeigt, in der der Text Male erscheint. Dieselbe Funktionalität kann mit der eval-Methode erzielt werden (siehe Abb. 1-10). Abb. 1.10: Mögliches Zusammenspiel von Java und JavaScript (2) Die bisher verwendete JavaScript-Funktion alert, mittels derer Mitteilungen in Fenstern angezeigt werden, steht als Standardfunktion zur Verfügung, wenn mit JavaScript programmiert wird. Aus einem Applet heraus können aber auch benutzerdefinierte JavaScript-Funktionen aufgerufen werden. Mittels der in Abb. 1-11 dargestellten JavaScript-Funktion kann bspw. angezeigt werden, welche Software in welcher Version gerade verwendet wird. Hierbei ist darauf zu achten, dass das in Abb. 1-11 angegebene Script innerhalb des <HEAD>-Tags einer HTML-Seite definiert wird. In Abb. 1-12 ist das modifizierte Java-Applet angegeben, das das JavaScript-Programm aus Abb. 1-11 anzeigt. Abb. 1.11: Benutzerdefinierte JavaScript-Funktion Abb. 1.12: Java-Programm zum Aufruf der Script-Funktion aus Abb. 1-11 Es ist zu beachten, dass die Variable arguments als leere Liste definiert wurde. Obwohl die JavaScript-Funktion keine Argumente verwertet, muss dennoch die Syntax in der angegebenen Form verwendet werden, in diesem Fall also als leere Liste. Nachdem im ersten Teil dieses Kapitels die Geschichte und die Konzepte von Java vorgestellt wurden bzw. die Abgrenzung und das Zusammenspiel mit JavaScript eingeführt wurden, beschäftigen sich die folgenden Teilkapitel mit dem Aufbau des Buches.