Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
titleJavaImporter
// 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());
}

$ARG (-scripting mode only)

This global object can be used to access the arguments passed to the script, similar to how the arguments object is used, for example:

Code Block
title$ARG example
>> jjs -scripting -- arg1 arg2 arg3
jjs> $ARG
arg1,arg2,arg3
jjs> $ARG[1]
arg2


$OPTIONS (-scripting mode only)

This property exposes command line options passed to nashorn "command line".

Code Block
title$OPTIONS usage
print("-scripting = " + $OPTIONS._scripting);
print("--compile-only = " + $OPTIONS._compile_only);
print("-timezone = " + $OPTIONS._timezone.ID);

$ENV (-scripting mode only)

$ENV property exposes OS environment variables to script.

Code Block
title$ENV example
// print $JAVA_HOME and $PATH from the OS shell

print($ENV["JAVA_HOME"])
print($ENV["PATH"])
print($ENV.JAVA_HOME)
print($ENV.PATH)

readLine (-scripting mode only)

This function reads one line of input from stdin and sends it to stdout, or you can assign the result to a variable. You can also pass a string to the readLine() function to get a prompt line as in the following example:

Code Block
titlereadLine example
jjs> var name = readLine("What is your name? ")
What is your name? Bob
jjs> print("Hello, ${name}!")
Hello, Bob!
jjs> 

readFully (-scripting mode only)

This function reads the entire contents of a file passed in as a string argument and sends it to stdout, or you can assign the result to a variable.

Code Block
titlereadFully example
jjs> readFully("text.txt")
This is the contents of the text.txt file located in the current working directory.

Java object

"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). Below we cover in details the properties of the type objects.

Java object

"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). Below we cover in details the properties of the type objects.

Code Block
titleJava.type
 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)
 
// 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")

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
titlenew on abstract class
var TimerTask =  
Code Block
titleJava.type
 var arrayListType = Java.type("java.util.ArrayListTimerTask")
 var intTypetask = new 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)
 
// 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 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
titleanonymous class like expression
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
titleSAM
 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
titleSAM function conversion
 var timer = new can use the dot:

 var ftype = Java.type("java.awtutil.geom.Arc2D$FloatTimer")
 
// and this works too:
  
  var ftype = Java.type("java.awt.geom.Arc2D.Float")

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.:

timer.schedule(function() { print("Hello World!") })

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
titleJava.extend examples
var ArrayList = 
Code Block
titlenew on abstract class
var TimerTask =  Java.type("java.util.TimerTask"ArrayList")
var ArrayListExtender = Java.extend(ArrayList)
var taskprintSizeInvokedArrayList = new TimerTaskArrayListExtender() {
 run   size: function() { print("Hellosize Worldinvoked!"); } })

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
titleanonymous class like expression
var task
}

var printAddInvokedArrayList = new TimerTaskArrayListExtender() {
    runadd: function(x, y) {
      if(typeof(y) === "undefined") {
          print("Hello Worldadd(e) invoked!");
      }
}
 else {
          print("add(i, e) invoked!");
      }
    }
}

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. Examplewhich 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
titleSAMJava.from examples
 var taskFile = 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
titleSAM function conversion
 var timerJava.type("java.io.File")
var listHomeDir = new Java.typeFile("java.util.Timer~")
 timer.schedule(function(listFiles()

// Java array to JavaScript array conversion by Java.from
var jsListHome = Java.from(listHomeDir)

var jpegModifiedDates = jsListHome
    .filter(function(val) { print("Hello World!return val.getName().endsWith(".jpg") })

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:

    .map(function(val) { return val.lastModified() })

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
titleJava.to example
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
  
Code Block
titleJava.extend examples
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!");
         }
    }
}

Java.from function

// 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), returns an object that can be used to invoke superclass methods on that object. E.g.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
titleJava.from examplessuper example
var File CharArray = Java.type("char[]")
var jString = Java.type("java.iolang.FileString")
var listHomeDirCharacter = new FileJava.type("~java.lang.Character").listFiles()

// Java array to JavaScript array conversion by Java.from
var jsListHome = Java.from(listHomeDir)

var jpegModifiedDates = jsListHome

function capitalize(s) {
    if(s instanceof CharArray) {
        return new jString(s).toUpperCase()
    }
    .filter(function(valif(s instanceof jString) {
        return vals.getNametoUpperCase().endsWith(".jpg")
    })
    return Character.maptoUpperCase(function(val) { return val.lastModified() })

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
titleJava.to example
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 
     s) // must be int
}

var sw = new (Java.type("java.io.StringWriter"))

var FilterWriterAdapter = Java.extend(Java.type("java.io.FilterWriter"))

var cw = new FilterWriterAdapter(sw) {
    write: function(s, off, len) {
        s = capitalize(s)
        // Must handle overloads by arity
        if(off === undefined) {
            cw_super.write(s, 0, s.length())
     // as per ECMAScript} ToNumber conversion
print(javaIntArray[2])  // prints 0, as boolean false was converted to number 0else if (typeof s === "string") {
            cw_super.write(s, off, len)
        }
  // 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), returns an object that can be used to invoke superclass methods on that object. E.g.:

}
}
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)

JSAdapter constructor

JSAdapter supports java.lang.reflect.Proxy-like proxy mechanism for script objects.

Code Block
titleJSAdapter example
// A JSAdapter object with proxy-like special hooks
var obj = new JSAdapter() {
    __get__: function(name
Code Block
titleJava.super example
var CharArray = Java.type("char[]")
var jString = Java.type("java.lang.String")
var Character = Java.type("java.lang.Character")

function capitalize(s) {
    if(s instanceof CharArray) {
        return new jString(s).toUpperCase()
    }
    if(s instanceof jString) {
        return s.toUpperCase()
    }
    return Character.toUpperCase(s) // must be int
}

var sw = new (Java.type("java.io.StringWriter"))

var FilterWriterAdapter = Java.extend(Java.type("java.io.FilterWriter"))

var cw = new FilterWriterAdapter(sw) {
    write: function(s, off, lenprint("getter called for '" + name + "'"); return name;
    },

    __put__: function(name, value) {
        print("setter called for '" + name + "' with " + value);
    },

    __call__: function(name, arg1, arg2) {
        s = capitalize(s)
        // Must handle overloads by arityprint("method '" + name + "' called with " + arg1 + ", " + arg2);
    },

    if(off === undefined__new__: function(arg1, arg2) {
        print("new with " +  cw_super.write(s, 0, s.length())arg1 + ", " + arg2);
    },

    } else if (typeof s === "string") {
__getIds__: function() {
        print("__getIds__ called");
        return [ "foo", "bar" ];
    cw_super.write(s, off, len)},

    __getValues__: function() {
        } print("__getValues__ called");
    }
}
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)

JSAdapter constructor

JSAdapter supports java.lang.reflect.Proxy-like proxy mechanism for script objects.

  return [ "fooval", "barval" ];
    },

    __has__: function(name) {
        print("__has__ called with '" + name + "'");
        return name == "js";
    },

    __delete__: function(name) {
        print("__delete__ called with '" + name + "'");
        return true;
    }
};

// calls __get__
print(obj.foo);

// calls __put__
obj.foo = 33;

// calls __call__
obj.func("hello", "world");

// calls __new__
new obj("hey!", "it works!");

for (i in obj) {
    print(i);
}

for each (i in obj) {
    print(i);
}

Scripting mode extension objects and functions

$ARG (-scripting mode only)

This global object can be used to access the arguments passed to the script, similar to how the arguments object is used, for example:

Code Block
title$ARG example
$ jjs -scripting -- arg1 arg2 arg3
jjs> $ARG
arg1,arg2,arg3
jjs> $ARG[1]
arg2


echo (-scripting mode only)

This is a synonym to "print" function -  the values passed in as arguments to be converted to strings, printed to stdout separated by spaces, and followed by a new line.

 

Code Block
titleecho example
$ jjs -scripting
jjs> echo("hello world");
hello world

$ENV (-scripting mode only)

$ENV object exposes OS process environment variables to script.

Code Block
title$ENV example
// print $JAVA_HOME and $PATH from the OS shell

print($ENV["JAVA_HOME"])
print($ENV["PATH"])
print($ENV.JAVA_HOME)
print($ENV.PATH)

$EXEC (-scripting mode only)

This global function launches processes to run commands, for example:

Code Block
title$EXEC example
jjs> $EXEC("ls -l")
total 0
drwxr-xr-x+ 1 johndoe staff 4096 Aug 18 11:03 dir
-rwxrw-r--  1 johndoe staff  168 Aug 19 17:44 file.txt

jjs> $EXEC("cat", "Send this to stdout")
Send this to stdout

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. For example, the result of $EXEC() is saved to $OUT.

$ERR (-scripting mode only)

This global object is used to store the latest standard error (stderr) of the process.

$EXIT (-scripting mode only)

This global object is used to store the exit code of the process. If the exit code is not zero, then the process failed.

$OPTIONS (-scripting mode only)

This property exposes command line options passed to nashorn "command line".

Code Block
title$OPTIONS usage
print("-scripting = " + $OPTIONS._scripting);
print("--compile-only = " + $OPTIONS._compile_only);
print("-timezone = " + $OPTIONS._timezone.ID);

readFully (-scripting mode only)

This function reads the entire contents of a file passed in as a string argument and sends it to stdout, or you can assign the result to a variable.

Code Block
titlereadFully example
jjs> readFully("text.txt")
This is the contents of the text.txt file located in the current working directory.

readLine (-scripting mode only)

This function reads one line of input from stdin and sends it to stdout, or you can assign the result to a variable. You can also pass a string to the readLine() function to get a prompt line as in the following example:

Code Block
titlereadLine example
jjs> var name = readLine("What is your name? ")
What is your name? Bob
jjs> print("Hello, ${name}!")
Hello, Bob!
jjs> 
Code Block
titleJSAdapter example
// A JSAdapter object with proxy-like special hooks
var obj = new JSAdapter() {
    __get__: function(name) {
        print("getter called for '" + name + "'"); return name;
    },

    __put__: function(name, value) {
        print("setter called for '" + name + "' with " + value);
    },

    __call__: function(name, arg1, arg2) {
        print("method '" + name + "' called with " + arg1 + ", " + arg2);
    },

    __new__: function(arg1, arg2) {
        print("new with " + arg1 + ", " + arg2);
    },

    __getIds__: function() {
        print("__getIds__ called");
        return [ "foo", "bar" ];
    },

    __getValues__: function() {
        print("__getValues__ called");
        return [ "fooval", "barval" ];
    },

    __has__: function(name) {
        print("__has__ called with '" + name + "'");
        return name == "js";
    },

    __delete__: function(name) {
        print("__delete__ called with '" + name + "'");
        return true;
    }
};

// calls __get__
print(obj.foo);

// calls __put__
obj.foo = 33;

// calls __call__
obj.func("hello", "world");

// calls __new__
new obj("hey!", "it works!");

for (i in obj) {
    print(i);
}

for each (i in obj) {
    print(i);
}