- Loading...
...
The bound object need not be a script object. It could be a Java object as well - usual Java bean style getter/setter properties will be bound. Also a property only with getter will be bound as read-only property.
Nashorn extends ECMAScript Error (or subtype) objects with the following properties.
In addition to this Error.prototype has the following extension functions as well.
Error constructor includes dumpStack() function property
| Code Block | ||
|---|---|---|
| ||
function func() {
throw new Error()
}
function f() {
func()
}
try {
f()
} catch (e) {
print(e.stack)
print(e.lineNumber)
print(e.columnNumber)
print(e.fileName)
} |
String.prototype.trimLeft - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/TrimLeft
String.prototype.trimRight - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/TrimRight
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/toSource
__FILE__ , __LINE__, __DIR__
Current executing script file, line, directory of the script can be accessed by these global (read-only) properties. This is useful in debug/tracing scripts. __DIR__ can be used like Unix 'dirname' command. Script can load script-file relative path resources using __DIR__.
| Code Block | ||
|---|---|---|
| ||
print(__FILE__, __LINE__, __DIR__) |
print function
print function prints it's arguments (after converting those to Strings) on standard output
| Code Block | ||
|---|---|---|
| ||
print("hello", "world") |
...
The source object bound can be a ScriptObject or a ScriptOjectMirror. null or undefined source object results in TypeError being thrown.
Limitations of property binding:
* Only enumerable, immediate (not proto inherited) properties of the source object are bound. * If the target object already contains a property called "foo", the source's "foo" is skipped (not bound). * Properties added to the source object after binding to the target are not bound. * Property configuration changes on the source object (or on the target) is not propagated.
* Delete of property on the target (or the source) is not propagated - only the property value is set to 'undefined' if the property happens to be a data property.
It is recommended that the bound properties be treated as non-configurable properties to avoid surprises.
Nashorn extends ECMAScript Error (or subtype) objects with the following properties.
In addition to this Error.prototype has the following extension functions as well.
Error constructor includes dumpStack() function property
| Code Block | ||
|---|---|---|
| ||
function func() {
throw new Error()
}
function f() {
func()
}
try {
f()
} catch (e) {
print(e.stack)
print(e.lineNumber)
print(e.columnNumber)
print(e.fileName)
} |
String.prototype.trimLeft - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/TrimLeft
String.prototype.trimRight - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/TrimRight
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/toSource
__FILE__ , __LINE__, __DIR__
Current executing script file, line, directory of the script can be accessed by these global (read-only) properties. This is useful in debug/tracing scripts. __DIR__ can be used like Unix 'dirname' command. Script can load script-file relative path resources using __DIR__.
| Code Block | ||
|---|---|---|
| ||
print(__FILE__, __LINE__, __DIR__) |
print function
print function prints it's arguments (after converting those to Strings) on standard output
| Code Block | ||
|---|---|---|
| ||
print("hello", "world") |
Anchor load load
load function
Loads and evaluates script from a file or a URL or a script object. Examples:
| Code Block | ||
|---|---|---|
| ||
// can load script from files, URLs
load("foo.js"); // loads script from file "foo.js" from current directory
load("http://www.example.com/t.js"); // loads script file from given URL
// loads script from an object's properties.
// Object should have "script" and "name" properties.
// "script" property contains string code of the script.
// "name" property specifies name to be used while reporting errors from script
// This is almost like the standard "eval" except that it associates a name with
// the script string for debugging purpose.
load({ script: "print('hello')", name: "myscript.js"})
// load can also load from pseudo URLs like "nashorn:", "fx:", "classpath:"
// "nashorn:" pseudo URL scheme
// for nashorn's built-in scripts.
// load nashorn's parser support script - defines 'parse'
// function in global scope
load("nashorn:parser.js");
// load Mozilla compatibility script - which defines global functions
// like importPackage, importClass for rhino compatibility.
load("nashorn:mozilla_compat.js");
// "fx:" pseudo URL scheme for JavaFX support scripts
// "classpath:" pseudo URL scheme to load scripts from jjs classpath jars and directories
load("classpath:foo.js"); // load the first foo.js found in jjs -classpath dir |
Anchor loadWithNewGlobal loadWithNewGlobal
loadWithNewGlobal function
loadWithNewGlobal is almost like the function "load" in that it loads script from a file or a URL or a script object. But unlike 'load', loadWithNewGlobal creates a fresh ECMAScript global scope object and loads the script into it. The loaded script's global definitions go into the fresh global scope. Also, the loaded script's modifications of builtin objects (like String.prototype.indexOf) is not reflected in the caller's global scope – these are affected in the newly created global scope.
| Code Block | ||
|---|---|---|
| ||
loadWithNewGlobal({
script: "foo = 333; print(foo)",
name: "test"
});
// prints undefined as "foo" is defined in the new global and not here
print(typeof foo); |
exit and quit functions
These synonymous functions exit the current process with specified (optional) exit code.
| Code Block | ||
|---|---|---|
| ||
exit(1); // exit with given exit code
exit(); // exit 0
quit(2); // exit with given exit code
quit(); // exit 0 |
Packages, java, javax, javafx, com, edu, org
Packages and related objects are there to support java package, class access from script. The properties of the Packages variable are all the top-level Java packages, such as java and javax etc.
| Code Block | ||
|---|---|---|
| ||
var Vector = Packages.java.util.Vector;
// but short-cuts defined for important package prefixes like
// Packages.java, Packages.javax, Packages.com
// Packages.edu, Packages.javafx, Packages.org
var JFrame = javax.swing.JFrame; // javax == Packages.javax
var List = java.util.List; // java == Packages.java |
| Code Block | ||
|---|---|---|
| ||
jjs> Packages.java
[JavaPackage java]
jjs> java
[JavaPackage java]
jjs> java.util.Vector
[JavaClass java.util.Vector]
jjs> javax
[JavaPackage javax]
jjs> javax.swing.JFrame
[JavaClass javax.swing.JFrame] |
JavaImporter constructor
Many times you may want to import many Java packages – but without having to "pollute" global scope. JavaImporter helps in such situations.
| Code Block | ||
|---|---|---|
| ||
// JavaImporter constructor accepts one or more Java Package objects
var imports = new JavaImporter(java.util, java.io);
// a JavaImporter can be used as a "with" expression object
with(imports) {
// classes from java.util and java.io packages can
// can be accessed by unqualified names
var map = new HashMap(); // refers to java.util.HashMap
map.put("js", "javascript");
map.put("java", "java");
map.put("cpp", "c++");
print(map);
var f = new File("."); // refers to java.io.File
print(f.getAbsolutePath());
} |
| Code Block | ||
|---|---|---|
| ||
// read text content from the given URL
function readText(url) {
// Using JavaImporter to resolve classes
// from specified java packages within the
// 'with' statement below
with (new JavaImporter(java.io, java.net)) {
// more or less regular java code except for static types
var is = new URL(url).openStream();
try {
var reader = new BufferedReader(
new InputStreamReader(is));
var buf = '', line = null;
while ((line = reader.readLine()) != null) {
buf += line;
}
} finally {
reader.close();
}
return buf;
}
}
print(readText("http://google.com?q=jdk8")) |
"Java" global property is a script object that defines useful functions for script-to-Java interface.
Java.type function
Given a name of a Java type, returns an object representing that type in Nashorn. The Java class of the objects used to represent Java types in Nashorn is not Class but rather StaticClass. They are the objects that you can use with the new operator to create new instances of the class as well as to access static members of the class. In Nashorn, Class objects are just regular Java objects that aren't treated specially. Instead of them, StaticClass instances - which we sometimes refer to as "Java type objects" are used as constructors with the new operator, and they expose static fields, properties, and methods. While this might seem confusing at first, it actually closely matches the Java language: you use a different expression (e.g. java.io.File) as an argument in "new" and to address statics, and it is distinct from the Class object (e.g. java.io.File.class). To get StaticClass object corresponding to a Java Class object, you can use "static" property. Below we cover in details the properties of the type objects.
| Code Block | ||
|---|---|---|
| ||
var arrayListType = Java.type("java.util.ArrayList")
var intType = Java.type("int")
var stringArrayType = Java.type("java.lang.String[]")
var int2DArrayType = Java.type("int[][]")
// Note that the name of the type is always a string for a fully
// qualified name. You can use any of these types to create
// new instances, e.g.:
var anArrayList = new Java.type("java.util.ArrayList")
// or
var ArrayList = Java.type("java.util.ArrayList")
var anArrayList = new ArrayList
var anArrayListWithSize = new ArrayList(16)
var BoolArray = Java.type("boolean[]");
var arr = new BoolArray(10);
arr[0] = true;
// In the special case of inner classes, you can either use the JVM fully
// qualified name, meaning using $ sign in the class name, or you can
// use the dot:
var ftype = Java.type("java.awt.geom.Arc2D$Float")
// and this works too:
var ftype = Java.type("java.awt.geom.Arc2D.Float")
// Java Class object to type:
// similar to Java.type("java.util.Vector")
var Class = Java.type("java.lang.Class")
var VectorClass = Class.forName("java.util.Vector")
var Vector = VectorClass.static; |
If the type is abstract, you can instantiate an anonymous subclass of it using an argument list that is applicable to any of its public or protected constructors, but inserting a JavaScript object with functions properties that provide JavaScript implementations of the abstract methods. If method names are overloaded, the JavaScript function will provide implementation for all overloads. E.g.:
| Code Block | ||
|---|---|---|
| ||
var TimerTask = Java.type("java.util.TimerTask")
var task = new TimerTask({ run: function() { print("Hello World!") } }) |
Nashorn supports a syntactic extension where a "new" expression followed by an argument is identical to invoking the constructor and passing the argument to it, so you can write the above example also as:
| Code Block | ||
|---|---|---|
| ||
var task = new TimerTask {
run: function() {
print("Hello World!")
}
}
|
which is very similar to Java anonymous inner class definition. On the other hand, if the type is an abstract type with a single abstract method (commonly referred to as a "SAM type") or all abstract methods it has share the same overloaded name), then instead of an object, you can just pass a function, so the above example can become even more simplified to:
| Code Block | ||
|---|---|---|
| ||
var task = new TimerTask(function() { print("Hello World!") }) |
The use of functions can be taken even further; if you are invoking a Java method that takes a SAM type, you can just pass in a function object, and Nashorn will know what you meant:
| Code Block | ||
|---|---|---|
| ||
var Timer |
...
load function
Loads and evaluates script from a file or a URL or a script object. Examples:
| Code Block | ||
|---|---|---|
| ||
// can load script from files, URLs
load("foo.js"); // loads script from file "foo.js" from current directory
load("http://www.example.com/t.js"); // loads script file from given URL
// loads script from an object's properties.
// Object should have "script" and "name" properties.
// "script" property contains string code of the script.
// "name" property specifies name to be used while reporting errors from script
// This is almost like the standard "eval" except that it associates a name with
// the script string for debugging purpose.
load({ script: "print('hello')", name: "myscript.js"})
// load can also load from pseudo URLs like "nashorn:", "fx:". "nashorn:" pseudo URL scheme
// for nashorn's built-in scripts. "fx:" pseudo URL scheme for JavaFX support scripts
// load nashorn's parser support script - defines 'parse'
// function in global scope
load("nashorn:parser.js");
// load Mozilla compatibility script - which defines global functions
// like importPackage, importClass for rhino compatibility.
load("nashorn:mozilla_compat.js"); |
...
loadWithNewGlobal function
loadWithNewGlobal is almost like the function "load" in that it loads script from a file or a URL or a script object. But unlike 'load', loadWithNewGlobal creates a fresh ECMAScript global scope object and loads the script into it. The loaded script's global definitions go into the fresh global scope. Also, the loaded script's modifications of builtin objects (like String.prototype.indexOf) is not reflected in the caller's global scope – these are affected in the newly created global scope.
| Code Block | ||
|---|---|---|
| ||
loadWithNewGlobal({
script: "foo = 333; print(foo)",
name: "test"
});
// prints undefined as "foo" is defined in the new global and not here
print(typeof foo); |
exit and quit functions
These synonymous functions exit the current process with specified (optional) exit code.
| Code Block | ||
|---|---|---|
| ||
exit(1); // exit with given exit code
exit(); // exit 0
quit(2); // exit with given exit code
quit(); // exit 0 |
Packages, java, javax, javafx, com, edu, org
Packages and related objects are there to support java package, class access from script. The properties of the Packages variable are all the top-level Java packages, such as java and javax etc.
| Code Block | ||
|---|---|---|
| ||
var Vector = Packages.java.util.Vector;
// but short-cuts defined for important package prefixes like
// Packages.java, Packages.javax, Packages.com
// Packages.edu, Packages.javafx, Packages.org
var JFrame = javax.swing.JFrame; // javax == Packages.javax
var List = java.util.List; // java == Packages.java |
| Code Block | ||
|---|---|---|
| ||
jjs> Packages.java
[JavaPackage java]
jjs> java
[JavaPackage java]
jjs> java.util.Vector
[JavaClass java.util.Vector]
jjs> javax
[JavaPackage javax]
jjs> javax.swing.JFrame
[JavaClass javax.swing.JFrame] |
JavaImporter constructor
Many times you may want to import many Java packages – but without having to "pollute" global scope. JavaImporter helps in such situations.
| Code Block | ||
|---|---|---|
| ||
// JavaImporter constructor accepts one or more Java Package objects
var imports = new JavaImporter(java.util, java.io);
// a JavaImporter can be used as a "with" expression object
with(imports) {
// classes from java.util and java.io packages can
// can be accessed by unqualified names
var map = new HashMap(); // refers to java.util.HashMap
map.put("js", "javascript");
map.put("java", "java");
map.put("cpp", "c++");
print(map);
var f = new File("."); // refers to java.io.File
print(f.getAbsolutePath());
} |
| Code Block | ||
|---|---|---|
| ||
// read text content from the given URL
function readText(url) {
// Using JavaImporter to resolve classes
// from specified java packages within the
// 'with' statement below
with (new JavaImporter(java.io, java.net)) {
// more or less regular java code except for static types
var is = new URL(url).openStream();
try {
var reader = new BufferedReader(
new InputStreamReader(is));
var buf = '', line = null;
while ((line = reader.readLine()) != null) {
buf += line;
}
} finally {
reader.close();
}
return buf;
}
}
print(readText("http://google.com?q=jdk8")) |
"Java" global property is a script object that defines useful functions for script-to-Java interface.
Java.type function
Given a name of a Java type, returns an object representing that type in Nashorn. The Java class of the objects used to represent Java types in Nashorn is not Class but rather StaticClass. They are the objects that you can use with the new operator to create new instances of the class as well as to access static members of the class. In Nashorn, Class objects are just regular Java objects that aren't treated specially. Instead of them, StaticClass instances - which we sometimes refer to as "Java type objects" are used as constructors with the new operator, and they expose static fields, properties, and methods. While this might seem confusing at first, it actually closely matches the Java language: you use a different expression (e.g. java.io.File) as an argument in "new" and to address statics, and it is distinct from the Class object (e.g. java.io.File.class). To get StaticClass object corresponding to a Java Class object, you can use "static" property. Below we cover in details the properties of the type objects.
| Code Block | ||
|---|---|---|
| ||
var arrayListType = Java.type("java.util.ArrayListTimer") var intTypetimer = Java.type("int") var stringArrayType = Java.type("java.lang.String[]") var int2DArrayType = Java.type("int[][]") // Note that the name of the type is always a string for a fully // qualified name. You can use any of these types to create // new instances, e.g.: new Timer() timer.schedule(function() { print("Hello World!") }, 1000) java.lang.System.in.read() |
Here, Timer.schedule() expects a TimerTask as its argument, so Nashorn creates an instance of a TimerTask subclass and uses the passed function to implement its only abstract method, run(). In this usage though, you can't use non-default constructors; the type must be either an interface, or must have a protected or public no-arg constructor.
Anchor java_extend java_extend
Java.extend function
Java.extend function returns a type object for a subclass of the specified Java class (or implementation of the specified interface) that acts as a script-to-Java adapter for it. Note that you can also implement interfaces and subclass abstract classes using new operator on a type object for an interface or abstract class. However, to extend a non-abstract class, you will have to use this method. Example:
| Code Block | ||
|---|---|---|
| ||
var ArrayList = var anArrayList = new Java.type("java.util.ArrayList") // or var ArrayListvar ArrayListExtender = Java.typeextend("java.util.ArrayList") var anArrayListprintSizeInvokedArrayList = new ArrayListExtender() ArrayList{ var anArrayListWithSize = newsize: ArrayListfunction(16) var BoolArray = Java.type("boolean[]{ print("size invoked!"); } } var arrprintAddInvokedArrayList = new BoolArrayArrayListExtender(10); arr[0] = true; // In the special case of inner classes, you can either use the JVM fully // qualified name, meaning using $ sign in the class name, or you can // use the dot: var ftype = Java.type("java.awt.geom.Arc2D$Float") // and this works too: var ftype = Java.type("java.awt.geom.Arc2D.Float") // Java Class object to type: // similar to Java.type("java.util.Vector") var Class = Java.type("java.lang.Class") var VectorClass = Class.forName("java.util.Vector") var Vector = VectorClass.static; |
If the type is abstract, you can instantiate an anonymous subclass of it using an argument list that is applicable to any of its public or protected constructors, but inserting a JavaScript object with functions properties that provide JavaScript implementations of the abstract methods. If method names are overloaded, the JavaScript function will provide implementation for all overloads. E.g.:
| Code Block | ||
|---|---|---|
| ||
var TimerTask = Java.type("java.util.TimerTask")
var task = new TimerTask({ run: function() { print("Hello World!") } }) |
Nashorn supports a syntactic extension where a "new" expression followed by an argument is identical to invoking the constructor and passing the argument to it, so you can write the above example also as:
| Code Block | ||
|---|---|---|
| ||
var task = new TimerTask {
run: function() {
print("Hello World!")
}
}
|
which is very similar to Java anonymous inner class definition. On the other hand, if the type is an abstract type with a single abstract method (commonly referred to as a "SAM type") or all abstract methods it has share the same overloaded name), then instead of an object, you can just pass a function, so the above example can become even more simplified to:
| Code Block | ||
|---|---|---|
| ||
var task = new TimerTask(function() { print("Hello World!") }) |
The use of functions can be taken even further; if you are invoking a Java method that takes a SAM type, you can just pass in a function object, and Nashorn will know what you meant:
{
add: function(x, y) {
if(typeof(y) === "undefined") {
print("add(e) invoked!");
} else {
print("add(i, e) invoked!");
}
}
} |
| Anchor | ||||
|---|---|---|---|---|
|
| Code Block | ||
|---|---|---|
| ||
#// Usage: jjs javafoovars.js -- <directory>
// This example demonstrates Java subclassing by Java.extend
// and javac Compiler and Tree API. This example counts number
// of variables called "foo" in the given java source files!
if (arguments.length == 0) {
print("Usage: jjs javafoovars.js -- <directory>");
exit(1);
}
// Java types used
var File = Java.type("java.io.File");
var Files = Java.type("java.nio.file.Files");
var FileVisitOption = Java.type("java.nio.file.FileVisitOption");
var StringArray = Java.type("java.lang.String[]");
var ToolProvider | ||
| Code Block | ||
| ||
var Timer = Java.type("javajavax.utiltools.TimerToolProvider"); var timerTree = new Timer() timer.schedule(function() { print("Hello World!") }, 1000) java.lang.System.in.read() |
Here, Timer.schedule() expects a TimerTask as its argument, so Nashorn creates an instance of a TimerTask subclass and uses the passed function to implement its only abstract method, run(). In this usage though, you can't use non-default constructors; the type must be either an interface, or must have a protected or public no-arg constructor.
...
Java.extend function
Java.extend function returns a type object for a subclass of the specified Java class (or implementation of the specified interface) that acts as a script-to-Java adapter for it. Note that you can also implement interfaces and subclass abstract classes using new operator on a type object for an interface or abstract class. However, to extend a non-abstract class, you will have to use this method. Example:
| Code Block | ||
|---|---|---|
| ||
var ArrayList = Java.type("java.util.ArrayList")
var ArrayListExtender = Java.extend(ArrayList)
var printSizeInvokedArrayList = new ArrayListExtender() {
size: function() { print("size invoked!"); }
}
var printAddInvokedArrayList = new ArrayListExtender() {
add: function(x, y) {
if(typeof(y) === "undefined") {
print("add(e) invoked!");
} else {
print("add(i, e) invoked!");
}
}
} |
...
| Code Block | ||
|---|---|---|
| ||
#// Usage: jjs javafoovars.js -- <directory> // This example demonstrates Java subclassing by Java.extend // and javac Compiler and Tree API. This example counts number // of variables called "foo" in the given java source files! if (arguments.length == 0) { print("Usage: jjs javafoovars.js -- <directory>"); exit(1); } // Java types used var File = Java.type("java.io.File"); var Files = Java.type("java.nio.file.Files"); var FileVisitOption = Java.type("java.nio.file.FileVisitOption"); var StringArray = Java.type("java.lang.String[]"); var ToolProvider = Java.type("javax.tools.ToolProvider"); var Tree = Java.type("com.sun.source.tree.Tree"); var TreeScanner = Java.type("com.sun.source.util.TreeScanner"); var VariableTree = Java.type("com.sun.source.tree.VariableTree"); // count "foo"-s in the given .java files function countFoo() { // get the system compiler tool var compiler = ToolProvider.systemJavaCompiler; // get standard file manager var fileMgr = compiler.getStandardFileManager(null, null, null); // Using Java.to convert script array (arguments) to a Java String[] var compUnits = fileMgr.getJavaFileObjects( Java.to(arguments, StringArray)); // create a new compilation task var task = compiler.getTask(null, fileMgr, null, null, null, compUnits); // subclass SimpleTreeVisitor - to count variables called "foo" var FooCounterVisitor = Java.extend(TreeScanner); var fooCount = 0; var visitor = new FooCounterVisitor() { visitVariable: function (node, p) { Java.type("com.sun.source.tree.Tree"); var TreeScanner = Java.type("com.sun.source.util.TreeScanner"); var VariableTree = Java.type("com.sun.source.tree.VariableTree"); // count "foo"-s in the given .java files function countFoo() { // get the system compiler tool var compiler = ToolProvider.systemJavaCompiler; // get standard file manager var fileMgr = compiler.getStandardFileManager(null, null, null); // Using Java.to convert script array (arguments) to a Java String[] var compUnits = fileMgr.getJavaFileObjects( Java.to(arguments, StringArray)); // create a new compilation task var task = compiler.getTask(null, fileMgr, null, null, null, compUnits); // subclass SimpleTreeVisitor - to count variables called "foo" var FooCounterVisitor = Java.extend(TreeScanner); var fooCount = 0; var visitor = new FooCounterVisitor() { visitVariable: function (node, p) { if (node.name.toString() == "foo") { fooCount++; } } } for each (var cu in task.parse()) { cu.accept(visitor, null); } return fooCount; } // for each ".java" file in directory (recursively) count "foo". function main(dir) { var totalCount = 0; Files.walk(dir.toPath(), FileVisitOption.FOLLOW_LINKS). forEach(function(p) { var name = p.toFile().absolutePath; if (name.endsWith(".java")) { var count = 0; try { count = countFoo(p.toFile().getAbsolutePath()); } catch (e) { print(e); } if (count != 0) { print(name + ": " + count); } if (node.name.toString() == "foo") { totalCount += count; } fooCount++}); print("Total foo count: " + } } } for each (var cu in task.parse()) { cu.accept(visitor, null); } return fooCount; } // for each ".java" file in directory (recursively) count "foo". function main(dir) { var totalCount = 0; Files.walk(dir.toPath(), FileVisitOption.FOLLOW_LINKS). forEach(function(p) { var name = p.toFile().absolutePath; if (name.endsWith(".java")) { totalCount); } main(new File(arguments[0])); |
Java.from function
Given a Java array or Collection, this function returns a JavaScript array with a shallow copy of its contents. Note that in most cases, you can use Java arrays and lists natively in Nashorn; in cases where for some reason you need to have an actual JavaScript native array (e.g. to work with the array comprehensions functions), you will want to use this method. Example:
| Code Block | ||
|---|---|---|
| ||
var File = Java.type("java.io.File")
var listHomeDir = new File("~").listFiles()
// Java array to JavaScript array conversion by Java.from
var jsListHome = Java.from(listHomeDir)
var jpegModifiedDates = jsListHome
.filter(function(val) { return val.getName().endsWith(".jpg") })
.map(function(val) { return val.lastModified() }) |
Anchor java_to java_to
Java.to function
Given a script object and a Java type, converts the script object into the desired Java type. Currently it performs shallow creation of Java arrays, as well as wrapping of objects in Lists and Dequeues. Example:
| Code Block | ||
|---|---|---|
| ||
var anArray = [1, "13", false] // Java.to used to convert script array to a Java int array var javaIntArray = Java.to(anArray, "int[]") print(javaIntArray[0]) // prints 1 print(javaIntArray[1]) // prints 13, as string "13" was converted to number 13 var count = 0; // tryas { per ECMAScript ToNumber conversion print(javaIntArray[2]) // prints 0, as boolean false was converted to number 0 count = countFoo(p.toFile().getAbsolutePath()); } catch (e) { // as per ECMAScript ToNumber conversion |
| Anchor | ||||
|---|---|---|---|---|
|
Java.super function
When given an object created using Java.extend() or equivalent mechanism (that is, any JavaScript-to-Java adapter), Java.super returns an object that can be used to invoke superclass methods on that object. E.g.:
| Code Block | ||
|---|---|---|
| ||
var CharArray print(e); } = Java.type("char[]") var jString = Java.type("java.lang.String") var Character = Java.type("java.lang.Character") function capitalize(s) { if (counts !=instanceof 0CharArray) { return print(name + ": " + count); new jString(s).toUpperCase() } if(s instanceof totalCount += count; jString) { } return s.toUpperCase() }); return print("Total foo count: " + totalCount);Character.toUpperCase(s) // must be int } main(new File(arguments[0])); |
Java.from function
Given a Java array or Collection, this function returns a JavaScript array with a shallow copy of its contents. Note that in most cases, you can use Java arrays and lists natively in Nashorn; in cases where for some reason you need to have an actual JavaScript native array (e.g. to work with the array comprehensions functions), you will want to use this method. Example:
| Code Block | ||
|---|---|---|
| ||
var File = var sw = new (Java.type("java.io.StringWriter")) var FilterWriterAdapter = Java.extend(Java.type("java.io.FileFilterWriter")) var listHomeDircw = new FileFilterWriterAdapter("~").listFiles() // Java array to JavaScript array conversion by Java.from var jsListHome = Java.from(listHomeDir) var jpegModifiedDates = jsListHome .filter(function(val) { return val.getName().endsWith(".jpg") }sw) { write: function(s, off, len) { s = capitalize(s) // Must handle overloads by arity if(off === undefined) { cw_super.write(s, 0, s.length()) .map(function(val) { return val.lastModified() }) |
...
} else if (typeof s === "string") {
cw_super.write(s, off, len)
}
}
}
var cw_super = Java.super(cw)
cw.write("abcd")
cw.write("e".charAt(0))
cw.write("fgh".toCharArray())
cw.write("**ijk**", 2, 3)
cw.write("***lmno**".toCharArray(), 3, 4)
cw.flush()
print(sw)
|
| Anchor | ||||
|---|---|---|---|---|
|
Java subclassing - Java.extend and Java.super - a larger example:
| Code Block | ||
|---|---|---|
| ||
#// Usage: jjs -fx filebrowser.js -- <start_dir>
// Uses -fx and javafx TreeView to visualize directories
if (!$OPTIONS._fx) {
print("Usage: jjs -fx filebrowser.js -- <start_dir>");
exit(1);
}
// Java classes used
var File = Java.type("java.io.File");
var Files = Java.type("java.nio.file.Files");
// check directory argument, if passed
var dir = arguments.length > 0? new File(arguments[0]) : new File(".");
if (! dir.isDirectory()) {
print(dir + " is not a directory!");
exit(2);
}
// JavaFX classes used
var FXCollections = Java.type("javafx.collections.FXCollections");
var Scene = Java.type("javafx.scene.Scene");
var TreeItem = Java.type("javafx.scene.control.TreeItem");
var TreeView |
...
Java.to function
Given a script object and a Java type, converts the script object into the desired Java type. Currently it performs shallow creation of Java arrays, as well as wrapping of objects in Lists and Dequeues. Example:
| Code Block | ||
|---|---|---|
| ||
var anArray = [1, "13", false]
// Java.to used to convert script array to a Java int array
var javaIntArray = Java.to(anArray, "int[]")
print(javaIntArray[0]) // prints 1
print(javaIntArray[1]) // prints 13, as string "13" was converted to number 13
// as per ECMAScript ToNumber conversion
print(javaIntArray[2]) // prints 0, as boolean false was converted to number 0
// as per ECMAScript ToNumber conversion |
...
Java.super function
When given an object created using Java.extend() or equivalent mechanism (that is, any JavaScript-to-Java adapter), Java.super returns an object that can be used to invoke superclass methods on that object. E.g.:
| Code Block | ||
|---|---|---|
| ||
var CharArray = Java.type("char[]") var jString = Java.type("javajavafx.scene.langcontrol.StringTreeView"); // create a subclass of JavaFX TreeItem class var CharacterLazyTreeItem = Java.type("java.lang.Character") function capitalize(s Java.extend(TreeItem); // lazily filling children of a directory LazyTreeItem function buildChildren(dir) { var if(schildren instanceof CharArray) { = FXCollections.observableArrayList(); var stream = Files.list(dir.toPath()); return new jString(s).toUpperCase() stream.forEach(function(path) { } var if(sfile instanceof jString) { = path.toFile(); var item return= sfile.toUpperCaseisDirectory()? } return Character.toUpperCase(s) // must be int } var sw = makeLazyTreeItem(file) : new (Java.type("java.io.StringWriter")) var FilterWriterAdapter = Java.extend(Java.type("java.io.FilterWriter")) var cw = new FilterWriterAdapter(sw) {TreeItem(file.name); children.add(item); }); write: function(s, off, len) { s = capitalize(s)stream.close(); return children; } // create an instance LazyTreeItem with override methods function makeLazyTreeItem(dir) { var item = // Must handle overloads by arity new LazyTreeItem(dir.name) { expanded: false, if(off === undefined) { isLeaf: function() false, cw_super.write(s, 0, s.length()) getChildren: function() { } else if (typeof s === "string"! this.expanded) { cw_super.write(s, off, len) // call super class (TreeItem) method } } } var cw_super = Java.super(cw) cw.write("abcd") cw.write("e".charAt(0)) cw.write("fgh".toCharArray()) cw.write("**ijk**", 2, 3) cw.write("***lmno**".toCharArray(), 3, 4) cw.flush() print(sw) |
...
Java.super(item).getChildren().setAll(buildChildren(dir));
this.expanded = true;
}
// call super class (TreeItem) method
return Java.super(item).getChildren();
}
}
return item;
}
// JavaFX start method
function start(stage) {
stage.title = dir.absolutePath;
var rootItem = makeLazyTreeItem(dir);
rootItem.expanded = true;
var tree = new TreeView(rootItem);
stage.scene = new Scene(tree, 300, 450);
stage.show();
} |
Anchor Java_synchronized Java_synchronized
Java.synchronized function
Returns synchronized wrapper version of the given ECMAScript function.
| Code Block | ||||
|---|---|---|---|---|
| ||||
var Thread |
...
Java subclassing - Java.extend and Java.super - a larger example:
| Code Block | ||
|---|---|---|
| ||
#// Usage: jjs -fx filebrowser.js -- <start_dir> // Uses -fx and javafx TreeView to visualize directories if (!$OPTIONS._fx) { print("Usage: jjs -fx filebrowser.js -- <start_dir>"); exit(1); } // Java classes used var File = Java.type("java.io.File"); var Files = Java.type("java.nio.file.Files"); // check directory argument, if passed var dir = arguments.length > 0? new File(arguments[0]) : new File("."); if (! dir.isDirectory()) { print(dir + " is not a directory!"); exit(2); } // JavaFX classes used var FXCollections = Java.type("javafxjava.collectionslang.FXCollectionsThread"); var Scene sum = Java.type("javafx.scene.Scene")0; var TreeItemlock = Java.type("javafx.scene.control.TreeItem"); var TreeView = Java.type("javafx.scene.control.TreeView"); = {}; function run() { Thread.sleep(Math.floor(Math.random()*700) + 300); // create asynchronized subclasswrapper of JavaFXgiven TreeItemfunction class var LazyTreeItem = Java.extend(TreeItem); // lazilyand fillinguse childrenthe ofsecond aparam directoryas LazyTreeItem function buildChildren(dir) {the synchronization lock var children = FXCollections.observableArrayListJava.synchronized(function() sum++, lock)(); } var threads = []; for (var streami = Files.list(dir.toPath()); stream.forEach(function(path0; i < 4; i++) { var filet = new path.toFileThread(run); var item = filethreads.isDirectorypush(t)?; t.start(); } for (var i in threads) { makeLazyTreeItem(file) : new TreeItem(file.name); children.add(item); }); stream.close(); return children; } // create an instance LazyTreeItem with override methods function makeLazyTreeItem(dir) { var item = new LazyTreeItem(dir.name) { expanded: false, isLeaf: function() false, getChildren: function() { if (! this.expanded) { // call super class (TreeItem) method threads[i].join(); } // always prints 4 print(sum); |
Anchor Java.asJSONCompatible Java.asJSONCompatible
Java.asJSONCompatible function
This function accepts a script object and returns an object that is compatible with Java JSON libraries expectations; namely, that if it itself, or any object transitively reachable through it is a JavaScript array,then such objects will be exposed as JSObject that also implements the List interface for exposing the array elements.
An explicit API is required as otherwise Nashorn exposes all objects externally as JSObjects that also implement the Map interface instead. By using this method, arrays will be exposed as Lists and all other objects as Maps.
This API is since jdk 8u60+ and jdk 9. A simple example that uses Java.asJSONCompatible function:
| Code Block | ||||
|---|---|---|---|---|
| ||||
import javax.script.*; import java.util.*; public class JSONTest { public static void main(String[] args) throws Exception { ScriptEngineManager m = Java.super(item).getChildren().setAll(buildChildren(dir)new ScriptEngineManager(); ScriptEngine e this.expanded = true= m.getEngineByName("nashorn"); Object obj = } // call super class (TreeItem) methode.eval("Java.asJSONCompatible({ x: 343, y: 'hello', z: [2,4, 5] })"); Map<String, Object> map = return Java.super(item).getChildren()(Map<String, Object>)obj; }System.out.println(map.get("x")); } return item; } // JavaFX start method function start(stage) {List<Object> array = (List<Object>)map.get("z"); stage.title = dir.absolutePath; for (Object varelem rootItem: = makeLazyTreeItem(dir);array) { rootItem.expanded = true; var tree = new TreeView(rootItem System.out.println(elem); stage.scene = new Scene(tree, 300, 450);} stage.show();} } |
| Anchor | ||||
|---|---|---|---|---|
|
...
| Code Block | ||
|---|---|---|
| ||
var HashMap = Java.type("java.util.HashMap")
var map = new HashMap()
// map key-value access by java get/put method calls
map.put('js', 'nashorn')
print(map.get('js'))
// access keys of map as properties
print(map['js'])
print(map.js)
// also assign new key-value pair
// as 'property-value'
map['language'] = 'java'
print(map.get("language"))
print(map.language)
print(map['language'])
map.answer = 42
print(map.get("answer"))
print(map.answer)
print(map['answer']) |
| Anchor | ||||
|---|---|---|---|---|
|
Elements of java.util.List objects can be access as though those are array elements - array like indexed element access and update is supported. "length" property can be used on List objects to get size of the list.
| Code Block | ||
|---|---|---|
| ||
// Java List elements accessed/modified via
// array element access/update syntax
var ArrayList = Java.type("java.util.ArrayList")
var list = new ArrayList()
// add elements to list by List's add method calls
list.add("js")
list.add("ecmascript")
list.add("nashorn")
// get by List's get(int) method
print(list[0])
print(list[1])
print(list[2])
// access list elements by indexed access as well
print(list[0])
print(list[1])
print(list[2])
// assign to list elements by index as well
list[0] = list[0].toUpperCase()
list[1] = list[1].toUpperCase()
list[2] = list[2].toUpperCase()
print(list.get(0))
print(list.get(1))
print(list.get(2))
print(list[0])
print(list[1])
print(list[2])
print(list.length); // prints list.size() |
...
Explicit constructor selection (jdk9, jdk8u65)
With jdk9 and jdk8u65, explicit constructor overload selection is also supported. See Index selection of overloaded java new constructors and Explicit constructor overload selection should work with StaticClass as well
| Code Block | ||
|---|---|---|
| ||
// With jdk9, you can select a specific constructor as well.
var C = java.awt["Color(int,int,int)"];
print(new C(255, 0, 0);
var F = Java.type("java.io.File")["(String)"];
print(new F("foo.txt"));
|
...
If the command does not require any input, you can launch a process using the backtick string notation. For example, instead of $EXEC("ls -l"), you can use `ls -l`.
$OUT (-scripting mode only)
This global object is used to store the latest standard output (stdout) of the process spawned by $EXEC. For example, the result of $EXEC() is saved to $OUT.
use `ls -l`.
$OUT $ERR (-scripting mode only)
This global object is used to store the latest standard error output (stderrstdout) of the process spawned by $EXEC.
$EXIT (-scripting mode only)
This global object is used to store the exit code of the process spawned by $EXEC. If the exit code is not zero, then the process failedFor example, the result of $EXEC() is saved to $OUT.
| Code Block | ||
|---|---|---|
| ||
var Arrays = Java.type("java.util.Arrays") // use curl to download JSON weather data from the net var str = `curl http://api.openweathermap.org/data/2.5/forecast/daily?q=Chennai&mode=json&units=metric&cnt=7` // parse JSON var weather = JSON.parse($OUT) // pull out humidity as array var humidity = weather.list.map(function(curVal) { return curVal.humidity }) // Stream API to print stat print("Humidity") print(Arrays["stream(int[])"](humidity).summaryStatistics()) // pull maximum day time temperature var temp = weather.list.map(function(curVal) { return curVal.temp.max }) // Stream API to print stat print("Max Temperature") print(Arrays["stream(double[])"](temp).summaryStatistics()) |
$ERR (-scripting mode only)
This global object is used to store the latest standard error (stderr) of the process spawned by $EXEC.
$EXIT (-scripting mode only)
This global object is used to store the exit code of the process spawned by $EXEC. If the exit code is not zero, then the process failed
$OPTIONS (-scripting mode only)
...
profiling is enabled per script or per function only rather than globally. These nashorn directives are enabled only in nashorn debug mode. So, these are effective only when jjs is run -J-Dnashorn.debug option set or script engine is initialized after "nashorn.debug" system property is set to true. Also, this feature is available only on jdk 8u40 + and jdk 9 only.