Obsah
1. Podpora skriptovacích jazyků v JDK6 a OpenJDK6
2. Skriptovací jazyky a JSR 223
3. Třídy a rozhraní používané při práci se skripty
4. První demonstrační příklad: výpis všech dostupných skriptovacích enginů
5. Druhý demonstrační příklad: získání skriptovacího engine několika způsoby
6. Třetí demonstrační příklad: několik způsobů spuštění skriptu
7. Čtvrtý demonstrační příklad: návratové hodnoty skriptů
8. Pátý demonstrační příklad: předávání parametrů a volání funkcí
1. Podpora skriptovacích jazyků v JDK6 a OpenJDK6
V předchozích částech seriálu o programovacím jazyku Java i o vlastnostech JDK a OpenJDK jsme se zabývali především tím, jakým způsobem interně pracují správci paměti a jak lze v některých případech zvýšit výkonnost aplikací napsaných v Javě (změnou GC, nastavením parametrů haldy/heapu, povolením huge/large pages, použitím alternativních knihoven nabízených v Oracle JDK), popř. snížit jejich paměťové nároky, například použitím komprimovaných ukazatelů na objekty (compressed oops), konfigurací velikostí jednotlivých oblastí na haldě atd. Dnes poněkud od těchto témat odbočíme, protože se budeme zabývat podporou skriptovacích jazyků v JDK a JRE. V minulosti bylo vyvinuto poměrně velké množství skriptovacích jazyků určených pro běh na virtuálním stroji jazyka Java (JVM), ať již se jedná o reimplementace již existujících programovacích jazyků (Basic, Cobol, Lisp, Erlang, Forth, Logo, Python, Ruby či Scheme), tak i jazyků zcela nových, mezi něž patří například BeanShell, Groovy, Scala či právě vznikající jazyk Ceylon.
Důvodů, proč pro virtuální stroj jazyka Java vznikly a stále vznikají nové skriptovací jazyky, je více. Mezi ty hlavní důvody však patří především existence mnoha knihoven pro Javu (včetně knihoven, které jsou součástí každé JVM, což mj. znamená podporu pro práci se sítěmi, tvorbu GUI atd.), dnes již relativně dobrá přenositelnost aplikací běžících nad JVM na různé platformy, včetně platforem mobilních, automatická správa paměti alokované v rámci virtuálního stroje a v některých případech taktéž to, že skripty je možné překládat do plnohodnotného javovského bajtkódu, který je poté při běhu aplikace buď interpretován nebo opět překládán just-in-time překladačem do nativního kódu mikroprocesoru použitého na počítači, kde je virtuální stroj Javy spuštěn. To, že pro platformu Javy existuje velké množství skriptovacích jazyků různé složitosti a taktéž vyjadřovacích schopností, je samozřejmě dobře, protože je možné podporu pro skripty vložit do uživatelských aplikací, což může mít velký vliv na obchodní úspěch takové aplikace (známým příkladem je například AutoCAD, pro nějž vzniklo díky podpoře AutoLISPu velké množství amatérských i profesionálních nadstaveb, což na druhou stranu rozšířilo i okruh uživatelů, kteří si AutoCAD pořídili).
2. Skriptovací jazyky a JSR 223
Zpočátku skriptovací jazyky určené pro běh na virtuálním stroji Javy vznikaly takovým způsobem, že každý jazyk nabízel programátorům odlišné programátorské rozhraní pro komunikaci mezi programy napsanými v Javě a skripty. To samozřejmě nebyl ideální stav, protože to komplikovalo práci jak vývojářům daného skriptovacího jazyka (ti museli vymyslet vhodné API a to taktéž popsat), tak i vývojářům, kteří chtěli podporu pro nějaký skriptovací jazyk implementovat ve svých programech. Z tohoto důvodu vznikl v rámci jednoho „požadavku na změnu“ (JSR – Java Specification Request) i návrh jednotného API použitelného pro různé skriptovací jazyky. Tento JSR získal pořadové číslo 223 a výsledná specifikace je známá pod celým svým názvem JSR 223: Scripting for the JavaTM Platform. Ve specifikaci JSR 223 je popsáno jak API, které by měli tvůrci jednotlivých skriptovacích jazyků (nebo spíše skriptovacích enginů, které skripty zpracovávají) dodržet, tak i způsob, jak jsou jednotlivé skriptovací enginy inicializovány v době běhu aplikace, podpora pro skripty kompilované do bajtkódu atd.
Aby to však nebylo málo, byl do JDK integrován projekt Rhino, což je skriptovací engine určený pro programovací jazyk JavaScript (resp. jeho standard ECMA-262), který je kompletně napsán v Javě a navíc byl uvolněn jako open-source. Zatímco jsou přeložené třídy tvořící skriptovací engine Rhino v Oracle JDK uloženy přímo v archivu rt.jar, můžeme tento engine v IcedTea6 najít v samostatném archivu rhino.jar, umístěném ve stejném adresáři, jako rt.jar (jre/lib). Díky tomu, že je Rhino součástí JDK, lze v javovských programech volat JavaScriptové programy, dokonce lze spustit i JavaScriptový shell. Navíc, pokud by bylo nutné použít vlastní (novější) implementaci Rhina, než nabízí používaná JDK, může se rhino*.jar umístit na classpath a samotná JDK se již postará o to, aby měl tento archiv přednost před Rhinem dodávaným spolu s JDK. Vzhledem k tomu, že je dnes Rhino součástí JDK, budou všechny dnešní demonstrační příklady počítat s jeho podporou.
3. Třídy a rozhraní používané při práci se skripty
Pro jednotnou práci s různými skriptovacími enginy, spouštění celých skriptů (příkaz po příkazu), volání vybraných funkcí či metod ve skriptech i pro provádění dalších činností je v API Javy specifikováno pouze šest rozhraní a šest tříd; z toho jedna třída představuje obecnou výjimku vzniklou při práci se skripty. Všech šest rozhraní a šest tříd je uloženo v balíčku javax.script. V praxi, zejména tehdy, pokud se nebude pracovat s kompilovanými skripty, se však počet skutečně používaných tříd a rozhraní snižuje – zpravidla se používá pouze třída ScriptEngineManager a rozhraní ScriptEngine, Invocable a ScriptException. V následující tabulce jsou vypsána všechna rozhraní definovaná v balíčku javax.script:
Jméno rozhraní | Popis |
---|---|
Bindings | Mapa obsahující klíče typu řetězec (jedná se o třídu zapouzdřující jednu z implementací rozhraní Map). |
Compilable | Rozhraní, které může být implementované skriptovacím enginem podporujícím překlad skriptů. |
Invocable | Rozhraní, které může být implementované skriptovacím enginem podporujícím volání jednotlivých funkcí nebo metod. |
ScriptContext | Třídy implementující toto rozhraní zajišťují komunikaci mezi skriptovacím enginem a ostatními objekty. |
ScriptEngine | Rozhraní implementované všemi skriptovacími enginy. |
ScriptEngineFactory | Rozhraní pro třídy používané pro získávání informací o jednotlivých skriptovacích enginech, popř. pro vytvoření (či získání) instance některého enginu. |
V další tabulce je vypsáno všech šest výše zmíněných tříd, které jsou taktéž součástí balíčku javax.script:
Jméno třídy | Popis |
---|---|
AbstractScriptEngine | Standardní implementace přetížené metody eval(). |
CompiledScript | Instance potomků této třídy reprezentují přeložený skript. |
ScriptEngineManager | Třída používaná především pro vytvoření (získání) instance vybraného skriptovacího enginu. |
SimpleBindings | Implementace rozhraní Bindings (viz předchozí tabulka) pomocí HashMapy. |
SimpleScriptContext | Implementace rozhraní ScriptContext (viz předchozí tabulka). |
ScriptException | Třída reprezentující výjimky vyvolávané při inicializaci a spouštění skriptů. Důležité je, že tato výjimka může nést i informaci o jménu souboru se skriptem i přesné lokalizaci chyby (číslo řádku i číslo sloupce). |
4. První demonstrační příklad: výpis všech dostupných skriptovacích enginů
V dnešním prvním demonstračním příkladu je ukázáno, jakým způsobem je možné získat informace o všech skriptovacích enginech, které jsou v javovském virtuálním stroji, v němž je testovací aplikace spuštěná, dostupné. Nejprve je vytvořena instance třídy StringEngineManager, po jejíž inicializaci je již možné získat informace o všech podporovaných skriptovacích enginech pomocí metody StringEngineManager.getEngineFactories(), která vrací seznam objektů implementující rozhraní StringEngineFactory. Toto rozhraní předepisuje některé metody, které je možné využít pro získání jména a verze podporovaného skriptovacího jazyka a taktéž seznam aliasů (přezdívek) daného skriptovacího enginu, což je poměrně důležitá informace použitá v následujícím demonstračním příkladu uvedeném v další kapitole. Zdrojový kód prvního demonstračního příkladu je poměrně jednoduchý:
import javax.script.ScriptEngineFactory; import javax.script.ScriptEngineManager; /** * Utilita, ktera po svem spusteni vypise vsechny dostupne skriptovaci enginy a * programovaci jazyky podporovane danym enginem. * * @author Pavel Tisnovsky */ public class ScriptingTest1 { private static void listAllScriptEngines() { // Zakladni pristupovy bod ke skriptovacim technologiim // zajistuje v JDK trida ScriptEngineManager. ScriptEngineManager engineManager = new ScriptEngineManager(); // Ziskani vsech dostupnych skriptovacich enginu a vypis // jejich vlastnosti i podporovanych jazyku. for (ScriptEngineFactory factory : engineManager.getEngineFactories()) { String engineName = factory.getEngineName(); String engineVersion = factory.getEngineVersion(); String languageName = factory.getLanguageName(); String languageVersion = factory.getLanguageVersion(); System.out.printf("Language: %s (%s)\n", languageName, languageVersion); System.out.printf("Script engine: %s (%s)\n", engineName, engineVersion); // Vypis vsech aliasu. for (String name : factory.getNames()) { System.out.printf(" Engine Alias: %s\n", name); } } } public static void main(String[] args) { listAllScriptEngines(); } }
Následuje příklad textového výstupu generovaného touto testovací aplikací při jejím překladu a spuštění pomocí IcedTea6–1.8.x (IcedTea je OpenJDK přeložené pomocí GNU nástrojů a s použitím poměrně velkého množství patchů, které nebyly z různých důvodů zařazeny přímo do OpenJDK):
Language: ECMAScript (1.6) Script engine: Mozilla Rhino (1.6 release 2) Engine Alias: js Engine Alias: rhino Engine Alias: JavaScript Engine Alias: javascript Engine Alias: ECMAScript Engine Alias: ecmascript
5. Druhý demonstrační příklad: získání skriptovacího engine několika způsoby
Ve druhém demonstračním příkladu je ukázáno několik způsobů, jakými je možné získat skriptovací engine podporující požadovaný skriptovací jazyk. V tomto příkladu se počítá s tím, že JRE, v němž je příklad spuštěn, má nainstalovánu podporu pro JavaScript, popř. jsou potřebné knihovny dostupné na CLASSPATH. Jak jsme se již dozvěděli z předchozích kapitol, je JavaScript podporován jak v Oracle JDK, tak i v OpenJDK – v obou případech je použita implementace skriptovacího enginu Rhino. V demonstračním příkladu se pro získání instance tohoto enginu používá jak výběr pomocí jména či aliasu, tak i pomocí přípony souborů se skripty, popř. pomocí MIME typu. Pokud není skriptovací engine odpovídající zadané podmínce nalezen, vrátí se pouze hodnota NULL, tj. NEdojde přímo k vyvolání výjimky; až při pokusu o přístup k neexistujícímu objektu samozřejmě dojde k NPE :-). Následuje výpis zdrojového kódu druhého demonstračního příkladu:
import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; /** * V teto utilite je ukazano nekolik zpusobu, jakymi je mozne ziskat * skriptovaci engine. * * @author Pavel Tisnovsky */ public class ScriptingTest2 { ScriptEngineManager engineManager; /** * Ziskani skriptovaciho engine podle jmena. */ private void getEngineByNameTest(String name) { System.out.print("Hledani podle jmena '" + name + "'"); printEngineInfo(this.engineManager.getEngineByName(name)); } /** * Ziskani skriptovaciho engine podle pripony. */ private void getEngineByExtensionTest(String extension) { System.out.print("Hledani podle pripony '" + extension + "'"); printEngineInfo(this.engineManager.getEngineByExtension(extension)); } /** * Ziskani skriptovaciho engine podle MIME typu. */ private void getEngineByMimeTypeTest(String mimeType) { System.out.print("Hledani podle MIME typu '" + mimeType + "'"); printEngineInfo(this.engineManager.getEngineByMimeType(mimeType)); } private void runTests() { this.engineManager = new ScriptEngineManager(); getEngineByNameTest("JavaScript"); getEngineByNameTest("javaScript"); // spatne jmeno! getEngineByNameTest("javascript"); getEngineByNameTest("EcmaScript"); // nektere verze Rhina podporuji "ECMAScript" getEngineByNameTest("ecmaScript"); // spatne jmeno! getEngineByNameTest("ecmascript"); getEngineByExtensionTest("js"); getEngineByExtensionTest("bas"); // pravdepodobne se nenalezne getEngineByMimeTypeTest("text/javascript"); getEngineByMimeTypeTest("text/ecmascript"); getEngineByMimeTypeTest("application/javascript"); getEngineByMimeTypeTest("application/ecmascript"); } /** * Vypis informace o tom, zda byl ci nebyl odpovidajici * skriptovaci engine nalezen. */ private void printEngineInfo(ScriptEngine engine) { String answer = engine == null ? "ne" : ""; System.out.println(": skriptovaci engine " + answer + "byl nalezen"); } public static void main(String[] args) { new ScriptingTest2().runTests(); } }
Pod tímto odstavcem je opět uvedena ukázka textového výstupu testovací aplikace v případě, že je pro její spuštění použito IcedTea6–1.8:
Hledani podle jmena 'JavaScript': skriptovaci engine byl nalezen Hledani podle jmena 'javaScript': skriptovaci engine nebyl nalezen Hledani podle jmena 'javascript': skriptovaci engine byl nalezen Hledani podle jmena 'EcmaScript': skriptovaci engine nebyl nalezen Hledani podle jmena 'ecmaScript': skriptovaci engine nebyl nalezen Hledani podle jmena 'ecmascript': skriptovaci engine byl nalezen Hledani podle pripony 'js': skriptovaci engine byl nalezen Hledani podle pripony 'bas': skriptovaci engine nebyl nalezen Hledani podle MIME typu 'text/javascript': skriptovaci engine byl nalezen Hledani podle MIME typu 'text/ecmascript': skriptovaci engine byl nalezen Hledani podle MIME typu 'application/javascript': skriptovaci engine byl nalezen Hledani podle MIME typu 'application/ecmascript': skriptovaci engine byl nalezen
6. Třetí demonstrační příklad: několik způsobů spuštění skriptu
Třetí demonstrační aplikace je již zaměřena poněkud praktičtěji, než předchozí dva příklady. Po vytvoření instance třídy ScriptEngineManager a získání skriptovacího enginu určeného pro programovací jazyk JavaScript se pomocí metody ScriptEngine.eval() spustí jednoduchý skript, a to třemi různými způsoby. Při použití prvního způsobu je skript uložen v řetězci, při použití způsobu druhého je získán z některé třídy implementující rozhraní Reader (může se jednat například o stažení skriptu ze sítě, jeho načtení z archivu typu ZIP atd.) a konečně v případě třetím je skript načten z běžného souboru, popř. ze souboru uloženého v javovském archivu (JAR), v němž je zabalena celá aplikace. V případě, že při spuštění skriptu dojde k nějaké chybě, je vygenerována výjimka typu ScriptException, z níž je možné v některých případech získat i informace o čísle textového řádku, popř. i sloupce, ve kterém k chybě došlo:
import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringReader; import java.io.IOException; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; /** * Demonstracni priklad, v nemz je ukazano nekolik zpusobu spusteni skriptu. * * @author Pavel Tisnovsky */ public class ScriptingTest3 { static final String script = "println('Hello world');"; ScriptEngineManager engineManager; ScriptEngine scriptEngine; /** * Spusteni skriptu, ktery je ulozen v retezci. */ private void runScriptStoredInString() { try { this.scriptEngine.eval(script); } catch (ScriptException e) { e.printStackTrace(); } } /** * Spusteni skriptu, ktery je ziskan z objektu typu Reader nebo * z nektereho potomka teto tridy. */ private void runScriptFromReader() { StringReader stringReader = new StringReader(script); try { this.scriptEngine.eval(stringReader); } catch (ScriptException e) { e.printStackTrace(); } finally { stringReader.close(); } } /** * Spusteni skriptu, ktery je ulozen v externim souboru. */ private void runScriptStoredInFile() { InputStream inputStream = this.getClass().getResourceAsStream("scripts/test1.js"); try { this.scriptEngine.eval(new InputStreamReader(inputStream)); } catch (ScriptException e) { e.printStackTrace(); } finally { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * Spusteni skriptu tremi ruznymi moznostmi. */ private void runTests() { this.engineManager = new ScriptEngineManager(); this.scriptEngine = engineManager.getEngineByName("JavaScript"); runScriptStoredInString(); runScriptFromReader(); runScriptStoredInFile(); } public static void main(String[] args) { new ScriptingTest3().runTests(); } }
Pro správnou funkci aplikace je nutné, aby byl v podadresáři scripts vytvořen soubor nazvaný test1.js, který může obsahovat například následující příkaz:
println('Hello world');
7. Čtvrtý demonstrační příklad: návratové hodnoty skriptů
Skripty naprogramované v JavaScriptu, nebo v některém dalším programovacím jazyku implementovaném skriptovacím enginem, samozřejmě musí umět nějakým způsobem komunikovat s javovským programem, který skript spouští. Nejjednodušším způsobem, jakým je možné tuto komunikaci zajistit, je načtení návratové hodnoty skriptu. Metoda ScriptEngine.eval() totiž vrací objekt, který vznikl vyhodnocením posledního příkazu skriptu (poněkud odlišná je situace při použití metody Invocable.invokeFunction() či Invocable.invokeMethod(), viz další kapitolu). Metoda ScriptEngine.eval() má sice v deklaraci jako typ návratové hodnoty specifikován Object, ve skutečnosti se však skriptovací engine snaží vytvořit javovský objekt takového typu, který se co nejvíce přibližuje návratovému typu výrazu, což ovšem není vždy úplně jednoduché a ani jednoznačné, protože skriptovací jazyky jsou většinou dynamicky typované a někdy taktéž nerozlišují například mezi celými čísly a čísly reálnými. V následujícím příkladu je ukázáno, jak lze vyhodnotit poslední příkaz skriptu na javovský objekt typu Double, String či dokonce Date. Povšimněte si, jak lze přímo ve skriptu vytvořit nový javovský objekt:
import java.util.Date; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; /** * Demonstracni priklad, v nemz je ukazano, jak muze skript vratit * Javovskemu programu navratovou hodnotu a jaky ma tato hodnota typ. * * @author Pavel Tisnovsky */ public class ScriptingTest4 { ScriptEngineManager engineManager; ScriptEngine scriptEngine; public void runSimpleScriptWhichReturnsDouble() throws ScriptException { final String script = "1.5/2;"; Double result = (Double)this.scriptEngine.eval(script); System.out.println("Navratova hodnota skriptu '" + script + "': " + result); } public void runSimpleScriptWhichReturnsString() throws ScriptException { final String script = "'Hello' + ' ' + 'world'"; String result = (String)this.scriptEngine.eval(script); System.out.println("Navratova hodnota skriptu '" + script + "': " + result); } public void createJavaObject1() throws ScriptException { final String script = "new java.util.Date()"; Object result = this.scriptEngine.eval(script); System.out.println("Navratova hodnota skriptu '" + script + "': " + result); } public void createJavaObject2() throws ScriptException { final String script = "new java.util.Date()"; Date result = (Date)this.scriptEngine.eval(script); System.out.println("Navratova hodnota skriptu '" + script + "': " + result); } /** * Spusteni skriptu tremi ruznymi moznostmi. */ private void runTests() { this.engineManager = new ScriptEngineManager(); this.scriptEngine = engineManager.getEngineByName("JavaScript"); try { runSimpleScriptWhichReturnsDouble(); runSimpleScriptWhichReturnsString(); createJavaObject1(); createJavaObject2(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { new ScriptingTest4().runTests(); } }
Příklad výstupu předchozího příkladu:
Navratova hodnota skriptu '1/2;': 0.5 Navratova hodnota skriptu ''Hello' + ' ' + 'world'': Hello world Navratova hodnota skriptu 'new java.util.Date()': Tue Apr 12 21:50:43 CEST 2011 Navratova hodnota skriptu 'new java.util.Date()': Tue Apr 12 21:50:43 CEST 2011
8. Pátý demonstrační příklad: předávání parametrů a volání funkcí
Demonstrační příklad uvedený v předchozí kapitole používal pro komunikaci mezi skriptem a Javovským programem v podstatě velmi primitivní způsob, který je možné použít pouze v těch nejjednodušších případech. V praxi se však většinou setkáme s tím, že je celý skript rozdělen do mnoha funkcí, které by bylo vhodné volat z programů napsaných v Javě, samozřejmě i s tím, že se těmto funkcím předají nějaké parametry a funkce vrátí výsledek. I toho je samozřejmě možné ve standardním „skriptovacím“ API dosáhnout a to poměrně jednoduše, ovšem pouze za předpokladu, že to daný skriptovací jazyk a skriptovací engine umožňuje. V případě použití projektu Rhino (JavaScript) implementuje jeho skriptovací engine rozhraní Invocable, které mj. obsahuje i metodu Invocable.invokeFunction(). Tato metoda má jeden povinný parametr, kterým je název volané funkce, a potom libovolný počet dalších parametrů, které jsou přímo předány volané funkci (samozřejmě po konverzi mezi datovými typy Javy a daného skriptovacího jazyka). V následujícím demonstračním příkladu je ukázáno, jak lze metodu Invocable.invokeFunction() použít. Povšimněte si, že skript musí být nejdříve „vyhodnocen“ pomocí eval():
import java.util.Date; import javax.script.Invocable; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; /** * Demonstracni priklad, v nemz je ukazano spousteni vybranych funkci, * predavani parametru skriptum a ziskavani navratovych hodnot funkci. * * @author Pavel Tisnovsky */ public class ScriptingTest5 { ScriptEngineManager engineManager; ScriptEngine scriptEngine; Invocable invocableEngine; private void testInvokeFunction() throws ScriptException, NoSuchMethodException { final String script = "function foo() {\n" + " println('Hello, world!');\n" + "}\n"; this.scriptEngine.eval(script); this.invocableEngine.invokeFunction("foo"); } private void testInvokeFunctionWithParameters() throws ScriptException, NoSuchMethodException { final String script = "function printHello(str1, str2) {\n" + " println(str1 + ' ' + str2);\n" + "}\n"; this.scriptEngine.eval(script); this.invocableEngine.invokeFunction("printHello", "hello", "world"); } private void printFunctionResult(String script, Object result) { System.out.println("Navratova hodnota funkce:\n" + script + "je: " + result); System.out.println("Typ navratove hodnoty: " + result.getClass().getName() + "\n"); } private void testInvokeFunctionWhichReturnsNumber() throws Exception { final String script = "function plus(x, y) {\n" + " return x + y;\n" + "}\n"; this.scriptEngine.eval(script); Object result = this.invocableEngine.invokeFunction("plus", 1, 2); printFunctionResult(script, result); } private void testInvokeFunctionWhichReturnsString() throws Exception { final String script = "function concatenateWords(str1, str2) {\n" + " return str1 + ' ' + str2;\n" + "}\n"; this.scriptEngine.eval(script); Object result = this.invocableEngine.invokeFunction("concatenateWords", "Hello", "world"); printFunctionResult(script, result); } private void testInvokeFunctionWhichReturnsDate() throws Exception { final String script = "function calculateDate(epochTime) {\n" + " var date = new java.util.Date(epochTime);\n" + " return date;\n" + "}\n"; this.scriptEngine.eval(script); Object result = this.invocableEngine.invokeFunction("calculateDate", 0); printFunctionResult(script, result); result = this.invocableEngine.invokeFunction("calculateDate", System.currentTimeMillis()); printFunctionResult(script, result); } /** * Spusteni skriptu tremi ruznymi moznostmi. */ private void runTests() { this.engineManager = new ScriptEngineManager(); this.scriptEngine = engineManager.getEngineByName("JavaScript"); this.invocableEngine = (Invocable)this.scriptEngine; try { testInvokeFunction(); testInvokeFunctionWithParameters(); testInvokeFunctionWhichReturnsNumber(); testInvokeFunctionWhichReturnsString(); testInvokeFunctionWhichReturnsDate(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { new ScriptingTest5().runTests(); } }
Po spuštění výše uvedeného příkladu se vypíše následující text:
Hello, world! hello world Navratova hodnota funkce: function plus(x, y) { return x + y; } je: 3.0 Typ navratove hodnoty: java.lang.Double *** někdy též java.lang.Integer *** Navratova hodnota funkce: function concatenateWords(str1, str2) { return str1 + ' ' + str2; } je: Hello world Typ navratove hodnoty: java.lang.String Navratova hodnota funkce: function calculateDate(epochTime) { var date = new java.util.Date(epochTime); return date; } je: Thu Jan 01 01:00:00 CET 1970 Typ navratove hodnoty: java.util.Date Navratova hodnota funkce: function calculateDate(epochTime) { var date = new java.util.Date(epochTime); return date; } je: Tue Apr 12 22:17:12 CEST 2011 Typ navratove hodnoty: java.util.Date
9. Odkazy na Internetu
- JSRs: Java Specification Requests – JSR 223: Scripting for the Java Platform
http://www.jcp.org/en/jsr/detail?id=223 - Scripting for the Java Platform
http://java.sun.com/developer/technicalArticles/J2SE/Desktop/scripting/ - Scripting for the Java Platform (Wikipedia)
http://en.wikipedia.org/wiki/Scripting_for_the_Java_Platform - Java Community Process
http://en.wikipedia.org/wiki/Java_Specification_Request - Package javax.script (JavaDoc)
http://download.oracle.com/javase/6/docs/api/javax/script/package-summary.html - javax.script.Bindings
http://download.oracle.com/javase/6/docs/api/javax/script/Bindings.html - javax.script.Compilable
http://download.oracle.com/javase/6/docs/api/javax/script/Compilable.html - javax.script.Invocable
http://download.oracle.com/javase/6/docs/api/javax/script/Invocable.html - javax.script.ScriptContext
http://download.oracle.com/javase/6/docs/api/javax/script/ScriptContext.html - javax.script.ScriptEngine
http://download.oracle.com/javase/6/docs/api/javax/script/ScriptEngine.html - javax.script.ScriptEngineFactory
http://download.oracle.com/javase/6/docs/api/javax/script/ScriptEngineFactory.html - javax.script.AbstractScriptEngine
http://download.oracle.com/javase/6/docs/api/javax/script/AbstractScriptEngine.html - javax.script.CompiledScript
http://download.oracle.com/javase/6/docs/api/javax/script/CompiledScript.html - javax.script.ScriptEngineManager
http://download.oracle.com/javase/6/docs/api/javax/script/ScriptEngineManager.html - javax.script.SimpleBindings
http://download.oracle.com/javase/6/docs/api/javax/script/SimpleBindings.html - javax.script.SimpleScriptContext
http://download.oracle.com/javase/6/docs/api/javax/script/SimpleScriptContext.html - javax.script.ScriptException
http://download.oracle.com/javase/6/docs/api/javax/script/ScriptException.html - The Java Compatibility Test Tools: JavaTest Harness
http://java.sun.com/developer/technicalArticles/JCPtools2/ - JavaScript engine (Wikipedia)
http://en.wikipedia.org/wiki/JavaScript_engine - Rhino (JavaScript engine)
http://en.wikipedia.org/wiki/Rhino_(JavaScript_engine) - Rhino: JavaScript for Java
http://www.mozilla.org/rhino/ - Java HotSpot VM Options
http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html - HugePages
http://linux-mm.org/HugePages - Tuning big java heap and linux huge pages
http://www.tikalk.com/alm/forums/tuning-big-java-heap-and-linux-huge-pages - How do I set up hugepages in Red Hat Enterprise Linux 4
http://magazine.redhat.com/2007/05/29/how-do-i-set-up-hugepages-in-red-hat-enterprise-linux-4/ - Java SE Tuning Tip: Large Pages on Windows and Linux
http://blogs.sun.com/dagastine/entry/java_se_tuning_tip_large - Translation lookaside buffer
http://en.wikipedia.org/wiki/Translation_lookaside_buffer - Physical Address Extension
http://en.wikipedia.org/wiki/Physical_Address_Extension - Java HotSpot VM Options
http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html - Amdahl's law
http://en.wikipedia.org/wiki/Amdahl_law - Garbage collection (computer science)
http://en.wikipedia.org/wiki/Garbage_collection_(computer_science) - Dr. Dobb's | G1: Java's Garbage First Garbage Collector
http://www.drdobbs.com/article/printableArticle.jhtml?articleId=219401061&dept_url=/java/ - Java's garbage-collected heap
http://www.javaworld.com/javaworld/jw-08–1996/jw-08-gc.html - Compressed oops in the Hotspot JVM
http://wikis.sun.com/display/HotSpotInternals/CompressedOops - 32-bit or 64-bit JVM? How about a Hybrid?
http://blog.juma.me.uk/2008/10/14/32-bit-or-64-bit-jvm-how-about-a-hybrid/ - Compressed object pointers in Hotspot VM
http://blogs.sun.com/nike/entry/compressed_object_pointers_in_hotspot - Java HotSpot™ Virtual Machine Performance Enhancements
http://download.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html - Using jconsole
http://download.oracle.com/javase/1.5.0/docs/guide/management/jconsole.html - jconsole – Java Monitoring and Management Console
http://download.oracle.com/javase/1.5.0/docs/tooldocs/share/jconsole.html - Great Computer Language Shootout
http://c2.com/cgi/wiki?GreatComputerLanguageShootout - x86–64
http://en.wikipedia.org/wiki/X86–64 - Physical Address Extension
http://en.wikipedia.org/wiki/Physical_Address_Extension - Java performance
http://en.wikipedia.org/wiki/Java_performance - 1.6.0_14 (6u14)
http://www.oracle.com/technetwork/java/javase/6u14–137039.html?ssSourceSiteId=otncn - Update Release Notes
http://www.oracle.com/technetwork/java/javase/releasenotes-136954.html - Java virtual machine: 4.10 Limitations of the Java Virtual Machine
http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#88659 - Java™ Platform, Standard Edition 7 Binary Snapshot Releases
http://dlc.sun.com.edgesuite.net/jdk7/binaries/index.html - Trying the prototype
http://mail.openjdk.java.net/pipermail/lambda-dev/2010-August/002179.html - Better closures (for Java)
http://blogs.sun.com/jrose/entry/better_closures - Lambdas in Java: An In-Depth Analysis
http://www.infoq.com/articles/lambdas-java-analysis - Class ReflectiveOperationException
http://download.java.net/jdk7/docs/api/java/lang/ReflectiveOperationException.html - Proposal: Indexing access syntax for Lists and Maps
http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001108.html - Proposal: Elvis and Other Null-Safe Operators
http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000047.html - Java 7 : Oracle pushes a first version of closures
http://www.baptiste-wicht.com/2010/05/oracle-pushes-a-first-version-of-closures/ - Groovy: An agile dynamic language for the Java Platform
http://groovy.codehaus.org/Operators - Better Strategies for Null Handling in Java
http://www.slideshare.net/Stephan.Schmidt/better-strategies-for-null-handling-in-java - Control Flow in the Java Virtual Machine
http://www.artima.com/underthehood/flowP.html - Java Virtual Machine
http://en.wikipedia.org/wiki/Java_virtual_machine - ==, .equals(), compareTo(), and compare()
http://leepoint.net/notes-java/data/expressions/22compareobjects.html - New JDK7 features
http://openjdk.java.net/projects/jdk7/features/ - Project Coin: Bringing it to a Close(able)
http://blogs.sun.com/darcy/entry/project_coin_bring_close - ClosableFinder source code
http://blogs.sun.com/darcy/resource/ProjectCoin/CloseableFinder.java - Joe Darcy blog about JDK
http://blogs.sun.com/darcy - Java 7 – more dynamics
http://www.baptiste-wicht.com/2010/04/java-7-more-dynamics/ - ArrayList (JDK 1.4)
http://download.oracle.com/javase/1.4.2/docs/api/java/util/ArrayList.html