19.3 Ausführen von Skripten
Seit Java 6 bietet die Standardbibliothek über das Paket javax.script eine API, um Skriptsprachen wie JavaScript, Groovy oder Jython anzusprechen. Diese API wurde im JSR-223, »Scripting for the Java Platform«, definiert, und das Standard-JDK und JRE bringt mit Rhino (http://www.mozilla.org/rhino/ScriptingJava.html) einen Interpreter für JavaScript mit. (Bei anderen Java SE-Implementierungen muss das nicht zwingend gegeben sein.)
Das in Java 6 neu ins bin-Verzeichnis aufgenommene Kommandozeilenprogramm jrunscript ermöglicht das Setzen von Variablen, das Ausführen von Skript-Code und das Auswerten von Ergebnissen. Eine Skript-Sprache kann auf den vollen Umfang der Java-API zurückgreifen, definiert aber üblicherweise auch eigene Bibliotheken.
Beispiel |
Führe ein simples Skript über das Kommandozeilenprogramm aus: $ jrunscript -e "print('Hallo JavaScript')" |
Eine Skript-Engine führt die Skripte aus, indem sie das Parsen, Interpretieren und Verwalten der Objekte übernimmt. Rhino übernimmt JavaScript, doch die Webseite https://scripting.dev.java.net/ führt mehr als 10 weitere Skriptsprachen auf, die sich über die neue API integrieren lassen.
19.3.1 JavaScript-Programme ausführen
Bevor wir uns mit der Java-Seite beschäftigen, wollen wir ein kleines JavaScript-Programm schreiben. Es liest aus einer Variablen im Kontext, gibt etwas auf der Konsole aus und deklariert und initialisiert eine neue Variable.
Listing 19.12: com/tutego/insel/script/tutego.js
f = new javax.swing.JFrame()
f.setSize( 500, 100 )
f.defaultCloseOperation = javax.swing.JFrame.EXIT_ON_CLOSE
f.title = "Hallo " + name + "."
f.visible = true
today = new Date()
println( today )
month = today.getMonth() + 1
Damit ein Java-Programm das Skript laden und ausführen kann, sind nur zwei Klassen nötig. Der ScriptEngineManager verschafft uns Zugang zu einer gewünschten Skript-Engine. Erfragt wird eine Skript-Engine über einen Namen (wie »JavaScript«) oder über einer Dateiendung, die die Skript-Dateien üblicherweise haben (wie »js«).
Listing 19.13: com/tutego/insel/script/JavaScriptDemo.java, Teil 1
package com.tutego.insel.script;
import java.io.InputStreamReader;
import javax.script.*;
public class ScriptDemo
{
public static void main( String[] args ) throws ScriptException
{
ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
Die Methode getEngineByName() liefert ein ScriptEngine-Objekt, dessen eval()-Methoden die Interpretation starten.
Listing 19.14: com/tutego/insel/script/JavaScriptDemo.java, Teil 2
engine.put( "name", "Christian Ullenboom" );
engine.eval( new InputStreamReader(
ScriptDemo.class.getResourceAsStream( "tutego.js" ) ) );
System.out.println( engine.get( "month" ) );
}
}
Ausgeführt stellt das Programm ein Swing-Fenster dar und gibt Folgendes auf der Konsole aus:
Hallo Christian Ullenboom.
Sun Jul 08 2007 15:25:12 GMT+0200 (CEST)
7.0
19.3.2 Groovy
Groovy (http://groovy.codehaus.org/) ist eine objektorientierte Skriptsprache, die auf einer JVM läuft und vollen Zugriff auf alle Java-Bibliotheken bietet. Die Sprache hat viele interessante Eigenschaften, die sie zu Java 2.0 machen – wenn wir die jetzige Version Java 1.7 nennen wollen. Groovy setzt auf der Standard-Java-Syntax auf und erweitert diese.[112](Bis auf sehr kleine Ausnahmen ist jedes Java-Programm ein Groovy-Programm.) Einige Höhepunkte:
Groovy-Feature | Beispiel |
Statt System.out.print()/println() reicht ein print bzw. println, und dann muss das Argument auch nicht in runden Klammern stehen. |
println 1 + 2 |
Anweisungen müssen nicht immer mit einem Semikolon abgeschlossen werden, sondern nur dann, wenn mehrere Anweisungen in einer Zeile stehen. |
print "Wow" |
Variablen müssen nicht mit einem Typ deklariert werden, das gilt auch bei catch oder Methoden/Konstruktoren. |
def age = 40 |
Zeichenketten lassen sich mit einfachen oder doppelten Anführungszeichen angeben. Einzelne Zeichen (char/Character) müssen besonders aufgebaut werden. |
print "Ja" == 'Ja' // true |
Strings in doppelten Anführungszeichen sind besondere GStrings: Enthalten sie $variable bzw. ${ausdruck}, so wird der Inhalt der Variablen bzw. der ausgewertete Ausdruck eingesetzt. |
def one = 1 |
Strings können über mehrere Zeilen laufen, wenn sie in """ oder ''' eingeschlossen sind – folgt ein Backslash am Ende der Zeile, wird kein Zeilenumbruchzeichen eingefügt. |
print """ |
Alles ungleich 0 und null ist true. |
if ( 1 ) print 'Zweig wird genommen' |
Groovy definiert einen neuen Datentyp für Bereiche (engl. ranges). |
def numbes = 0..9 |
Erweiterte Zählschleife unter Berücksichtigung von Bereichen, bzw. rechts von in steht ein Iterable wie beim erweiterten for. |
for ( i in 0..<10 ) |
== bei Referenzen bedeutet equals()-gleich; ein Identitätsvergleich realisiert is(). |
def heinz = 'Heinz' |
Operatoren können überladen werden, und die Anwendung von Operatoren entspricht Methodenaufrufen, etwa + von plus(), ++ von next() oder [] von getAt(). |
println 1 + 2 * 3 // 7 |
Alle Comparable-Objekte (und damit etwa String, BigInteger, BigDecimal) können mit ==, !=, <, >, <= und >= verglichen werden. Die Ordnung liefert compareTo(). |
def heinz = 'Heinz' |
Ist in Java nur java.lang standardmäßig importiert, ist es bei Groovy viel mehr, etwa noch java.io, java.util, java.net und noch einige. |
print new File('file.txt').exists() |
Statt explizit auf Datenstrukturklassen für Listen und Mengen zurückzugreifen, bietet Groovy eine spezielle Syntax. |
def primes = [ 2, 3, 5, 7] |
Die Operatoren ?. und ?: (Elvis-Operator) verhindern null-Zugriffe. |
def name = 'Chris' |
Der Zugriff auf Zeichen über []ist bei den Zeichenkettenklassen String, StringBuffer, StringBuilder möglich. |
def s = 'Ooog' |
Der Zugriff über [] lässt auch Bereiche zu. |
def s = "tutego" |
Der Operator << hängt Dinge an Strings (Rückgabe ist dann StringBuffer), Listen oder Dateien an. |
def s = 'oger' |
Reguläre Ausdrücke werden mit einer eigenen Syntax direkt von der Sprache unterstützt; =~ ist ein find, ==~ ein match. |
print '2010' ==~ /\d+/ |
Erweitertes switch-case etwa |
switch ( 42 ) { |
Datentyp für Dauer und spezielle Eigenschaften für Datumswerte und überladene Operatoren zum leichten Rechnen mit dem Paket groovy.time |
use ( groovy.time.TimeCategory ) { |
Closures als Codeblöcke werden unterstützt und finden überall in der Groovy-API Anwendung. |
new File( "file.txt" ).eachLine { |
Setter/Getter müssen nicht aufgerufen werden; beim Zugriff ref.property wird automatisch der Setter/Getter aufgerufen. |
def p = new Point( 10, 20 ) |
In Methoden mit Rückgabe kann das Schlüsselwort return entfallen. |
def add( a, b ) { a + b } |
Default-Parameter bei Methodendeklarationen |
static tax( cost, taxRate = 19 ) { |
Methoden und Klassen sind standardmäßig public, nicht paketsichtbar wir bei Java. Groovy erstellt automatisch Setter/Getter. |
class Person { def name } |
Mit der Klassenannotation @Immutable wird ein Typ unveränderbar, mit @Singleton ein Singleton mit einem privaten Konstruktor und öffentlichen Attribut instance für die eine Instanz. |
@Immutable class Pair { String val1, val2 } |
Diverse Builder-Klassen erleichtern den Aufbau von hierarchischen XML- oder Swing-Bäumen ebenso wie Ant-Buildskripten. |
import groovy.xml.MarkupBuilder |
Groovy-Skripte in Eclipse ausführen
Um Groovy-Skripte und Programme auszuführen, bieten sich drei Wege an:
- über eine spezielle Kommandozeile, die Groovy-Shell
- über das Eclipse-Plugin
- über die javax.script-API
Das Eclipse-Plugin unter http://groovy.codehaus.org/Eclipse+Plugin leistet gute Arbeit und wird ständig weiterentwickelt. Auf der Webseite ist der Update-Link genannt, sodass Groovy-Eclipse über den Update-Manager installiert werden kann.
- Wähle dazu Eclipse Help • Install New Software...
- In der Dialogbox fülle das Textfeld bei Work with mit dem Link http://dist.codehaus.org/groovy/distributions/greclipse/snapshot/e3.7/ (bzw. anderen Versionen je nach Eclipse-Version) und aktivieren Add...
- Aktiviere anschließend Groovy-Eclipse, und führe die Installation mit Next usw. zu Ende.
Ist Eclipse neu gestartet und das Plugin installiert, kann jedes Java-Projekt um Groovy-Unterstützung erweitert werden. Bei einem Java-Projekt aktiviert die Aktion Configure • Convert to Groovy Project im Kontextmenü genau diese Groovy-Unterstützung, sodass im Projektbaum die Groovy-Bibliotheken auftauchen.
File • New • Other... ermöglicht zum einen im Zweig Groovy das Erstellen eines neuen Groovy-Projekts (durch die Konvertierung eines existierenden Java-Projekts ist das nicht mehr nötig) und zum anderen mit Groovy Class das Erstellen einer Groovy-Klasse. Bei dieser Option lässt sich ein Paket- und Klassenname eingeben (etwa com.tutego.insel.script und GroovyBabe), und dann öffnet Eclipse den Groovy-Editor.
Löschen wir die Klassendeklaration und setzen nur die zwei Zeilen in die Datei:
Listing 19.15: com/tutego/insel/script/GroovyBabe.groovy
package com.tutego.insel.script
print "Hallo Groovy"
Ausgeführt wird das Groovy-Skript im Kontextmenü (oder Run-Menü) mit Run As • Groovy Skript.
Groovy über die Skript-API ausführen
Um Groovy als Skriptsprache aus einem Java-Programm heraus zu nutzen, können wir wieder auf die Skript-API zurückgreifen. Wenn es sich bei Eclipse schon um ein Groovy-Projekt handelt, ist ein Jar wie groovy-all-1.x.y.jar schon im Klassenpfad eingebunden, und es ist nichts ist zu tun. Andernfalls bekommen wir es von der Webseite http://groovy.codehaus.org/Download aus einem Zip-Archiv wie groovy-binary-1.8.1.zip, wo es im Ordner embeddable liegt.
Ein kleines Beispiel:
Listing 19.16: com/tutego/insel/script/GroovyDemo.java, main()
ScriptEngine engine = new ScriptEngineManager().getEngineByName( "groovy" );
System.out.println( engine.eval( "(1g..42g.gcd(56g)).sum()" ) ); // 105
Ihr Kommentar
Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.