- Direct Known Subclasses:
AbstractSplinePathBuilder
,DefaultScriptingContext
,ExtendedScriptingContext
,Simulation
Simulation
to be subclasses of ScriptingContext
while an already
configured scripting context's script engine and bindings.
There are several subclasses of ScriptingContext
in this
package. In particular, the class ExtendedScriptingContext
,
provides methods for importing Java classes into a scripting
environment (these methods were added by the author out of
frustration with the Rhino to Nashorn transition, where the default
mechanism for importing java classes suddenly changed). The class
DefaultScriptingContext
will look up a scripting language by
name, with the name provided in a constructor. The default is to
use the
ESP
scripting language (added by the author after the "powers that be"
decided to drop support for Nashorn and finding that GraalVM, the suggested
alternative, did not provide adequate support for multithreading).
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic class
Class to allow two sets of bindings associated with a ScriptingContext to be swapped. -
Constructor Summary
ConstructorsConstructorDescriptionConstructor.ScriptingContext
(boolean trusted) Deprecated.trusted scripting contexts are not applicable when the security manager has been eliminated.ScriptingContext
(ScriptingContext parent) Constructor using a parent. -
Method Summary
Modifier and TypeMethodDescriptionfinal Object
callScriptFunction
(String functionName, Object... args) Evaluate a script function.final Object
callScriptFunction
(Bindings bindings, String functionName, Object... args) Evaluate a script function given a set of bindings.final Object
callScriptMethod
(Object scriptObject, String methodName, Object... args) Evaluate a script object's method.final Object
callScriptMethod
(Bindings bindings, Object scriptObject, String methodName, Object... args) Evaluate a script object's method using specified bindings.final boolean
containsScriptObject
(String name) Determine if a script object with a given name exists (i.e., is contained the default bindings).final Bindings
Create a new set of script bindings.protected ScriptingContext.BindingSwapper
createBindingSwapper
(Bindings bindings) Create a binding swapper.static ScriptEngine
createScriptEngine
(ScriptEngineManager manager, String languageName) Create a script engine.protected Bindings
Get the default script bindings.protected ScriptEngine
Get the script engine.protected String
Get the scripting language.protected final void
Execute code, that can throw checked exceptions, in privileged mode.final Object
evalScript
(Reader reader) Evaluate a script provided via a Reader.final Object
evalScript
(String script) Evaluate a script provided in a string.final Object
evalScript
(String fileName, Reader reader) Evaluate a script provided via a Reader given the Reader's file name.final Object
evalScript
(String script, Bindings bindings) Evaluate a script provided in a string using specified bindings.final Writer
Get the write for scripting-language error output.getNames()
Get a set of object names.final Reader
Get the reader for scripting-language input.final String
Get the script language name.final Object
getScriptObject
(String name) Get a script object given a name.final Writer
Get the writer for scripting-language output.final boolean
Determine if a script engine is available.protected final Object
invokePrivateFunction
(Properties properties, String functionName, Object... args) Invoke a function from a private script.protected final Object
invokePrivateFunction
(Bindings bindings, Properties properties, String functionName, Object... args) Invoke a function defined by a private script with specified bindings.final void
putScriptObject
(String name, Object object) Assign a name to a script or java object.final void
setErrorWriter
(Writer writer) Set the writer for script error output.final void
Set the reader for script input.final void
Set the writer for script output.static boolean
Test if GraalVM is running.
-
Constructor Details
-
ScriptingContext
public ScriptingContext()Constructor. -
ScriptingContext
Deprecated.trusted scripting contexts are not applicable when the security manager has been eliminated.Constructor specifying the security mode.- Parameters:
trusted
- true if the script context is trusted; false otherwise
-
ScriptingContext
Constructor using a parent. Unless methods are overridden, the parent scripting context provides the scripting language, script engine, and bindings.- Parameters:
parent
- the parent scripting context; null if there is none.
-
-
Method Details
-
usingGraalVM
public static boolean usingGraalVM()Test if GraalVM is running. This method is provided because scripting languages don't work the same with GraalVM as with OpenJDK:- Immediately after a script engine is created, one should get the script engine's bindings and call bindings.put("polyglot.js.allowAllAccess", true) - otherwise attempts to call a Java method or construct a Java object will fail.
- If the default security manager is installed, calling engine.get(ScriptEngine.FILENAME) will throw an exception unless protected by a doPrivileged block. Seen in GraalVM CE Java11-20.1.0.
- Returns:
- true if GraalVM appears to be running; false otherwise
-
createBindingSwapper
Create a binding swapper. The use of this class is intended for the case where a script will be run in a separate thread and then suspend itself. When a scripting context runs a script, it puts its default bindings in an inherited thread-local variable. If new thread is created while that script is running, those bindings will be inherited. Then the bindings that a script will run can be passed to this method, and the binding swapper can be used to toggle between the two sets of bindings if the new thread is suspended or restored.The caller must ensure that the default bindings are in effect when threads making use of a binding swapper create additional threads that use scripting contexts to run scripts.
Most applications should not need to create binding swappers. The class was created to support classes in the package org.bzdev.devqsim. The
ScriptingContext
class does not provide a public method that returns a script engine, nor a public method to set its bindings. Some methods such as evalScript, however, allow alternate bindings to be used, and will keep the old bindings on a stack, restoring those with the method exits. A binding swapper can be used to swap those temporary bindings with the script engine's default bindings. For example, the devqsim package has a class namedTaskThread
that uses a binding swapper to temporarily change the current bindings to the default bindings when a thread is being paused because the simulation may be running in a script and needs those original bindings for instrumentation-related tasks that occur as threads are suspended and restored.- Parameters:
bindings
- the binding to initially swap with an existing binding whenScriptingContext.BindingSwapper.swap()
is called- Returns:
- the new binding swapper
-
createScriptEngine
Create a script engine. This method is provided due to a security issue discovered with Javascript in which calling a ScriptEngineManager's method getEngineByName would result in elevated privileges if called after a security manager is installed. A test indicated that one can suppress this behavior by using AccessController.doPrivilege with a context that has no permissions. A bug report was filed (this was some time ago with a much earlier version of Java).This method is now used to allow some initialization when GraalVM is used so that specific properties can be set (otherwise GraalVM's ECMAScript implementation will be severely restricted - it will not be able to call Java methods or constructors.
- Parameters:
manager
- a ScriptEngineManager used to obtain the enginelanguageName
- the name of the scripting language;- Returns:
- the script engine created; null if none matches the specified scripting-language name
-
evalScript
Evaluate a script provided via a Reader.- Parameters:
reader
- a Reader providing the script- Returns:
- the value produced by the script
- Throws:
ScriptException
- an error occurred in the scriptNullPointerException
- the script or bindings were nullUnsupportedOperationException
- the script engine is null
-
evalScript
public final Object evalScript(String fileName, Reader reader) throws ScriptException, UnsupportedOperationException Evaluate a script provided via a Reader given the Reader's file name. The file name that the script engine uses is set temporarily and then restored to its previous value after the script is read.- Parameters:
fileName
- the file name for the readerreader
- a Reader providing the script- Returns:
- the value produced by the script
- Throws:
ScriptException
- an error occurred in the scriptNullPointerException
- the script or bindings were nullUnsupportedOperationException
- the script engine is null
-
evalScript
Evaluate a script provided in a string.- Parameters:
script
- the script to evaluate- Returns:
- the value produced by the script
- Throws:
ScriptException
- an error occurred in the scriptNullPointerException
- the script or bindings were nullUnsupportedOperationException
- the script engine is null
-
evalScript
public final Object evalScript(String script, Bindings bindings) throws ScriptException, IllegalArgumentException Evaluate a script provided in a string using specified bindings.- Parameters:
script
- the script to evaluatebindings
- the script's bindings; null for the default bindings- Returns:
- the value produced by the script
- Throws:
ScriptException
- an error occurred in the scriptIllegalArgumentException
- an argument was null or the bindings were not created by this scripting context
-
callScriptFunction
public final Object callScriptFunction(String functionName, Object... args) throws ScriptException, UnsupportedOperationException, NoSuchMethodException Evaluate a script function.- Parameters:
functionName
- the script function to callargs
- the arguments- Returns:
- the value computed by the function
- Throws:
ScriptException
- the function was not defined or matching arguments could not be foundUnsupportedOperationException
- there was no script engine to useNoSuchMethodException
- the function does not exist or the arguments do not match
-
callScriptFunction
public final Object callScriptFunction(Bindings bindings, String functionName, Object... args) throws ScriptException, IllegalArgumentException, NoSuchMethodException Evaluate a script function given a set of bindings.- Parameters:
bindings
- the bindings to use when the script is evaluated; null for the default bindingsfunctionName
- the script function to callargs
- the arguments- Returns:
- the value computed by the function
- Throws:
ScriptException
- the function was not defined or matching arguments could not be foundIllegalArgumentException
- an argument was null or the bindings were not created by this scripting contextNoSuchMethodException
- the function does not exist or the arguments do not match
-
callScriptMethod
public final Object callScriptMethod(Object scriptObject, String methodName, Object... args) throws ScriptException, UnsupportedOperationException, NoSuchMethodException Evaluate a script object's method.- Parameters:
scriptObject
- the script object whose method is to be invokedmethodName
- the name of the method to invokeargs
- the arguments- Returns:
- the value computed by the method
- Throws:
ScriptException
- an exception occurred in a script object's methodNoSuchMethodException
- the method does not exist or the arguments do not matchUnsupportedOperationException
- scripting is not supportedIllegalArgumentException
- the scriptObject was null or is not an object recognized by the scripting language
-
callScriptMethod
public final Object callScriptMethod(Bindings bindings, Object scriptObject, String methodName, Object... args) throws ScriptException, UnsupportedOperationException, NoSuchMethodException Evaluate a script object's method using specified bindings.- Parameters:
bindings
- the bindingsscriptObject
- the script object whose method is to be invokedmethodName
- the name of the method to invokeargs
- the arguments- Returns:
- the value computed by the method
- Throws:
ScriptException
- an exception occurred in a script object's methodUnsupportedOperationException
- scripting is not supportedNoSuchMethodException
- the method does not exist or the arguments do not match
-
containsScriptObject
Determine if a script object with a given name exists (i.e., is contained the default bindings). The look-up uses the default bindings that were provided by the method getDefaultBindings() when it was called by a constructor. These bindings are the engine-scope bindings that will be used when the script is evaluated using the methods provided in this class.- Parameters:
name
- the name of the object- Returns:
- true if a binding for the name exists; false otherwise
-
getScriptObject
Get a script object given a name. The object is obtained using the default bindings that were provided by the method getDefaultBindings() when it was called by a constructor. These bindings are the engine-scope bindings that will be used when the script is evaluated using the methods provided in this class.- Parameters:
name
- the name of the object- Returns:
- the object; null if there is none
-
putScriptObject
Assign a name to a script or java object. The object is stored in the default bindings that were provided by the method getDefaultBindings() when it was called by a constructor. These bindings are the engine-scope bindings that will be used when the script is evaluated using the methods provided in this class.- Parameters:
name
- the name to assign to the objectobject
- the object- Throws:
UnsupportedOperationException
- the script context does not provide any bindings
-
doGetScriptEngine
Get the script engine. Subclasses providing a scripting environment must override this method. It will typically be called once, but could be called multiple times, so the method must be idempotent in case it is called multiple times. It will not be called by this class if the constructor provided a parent.- Returns:
- the script engine for this scripting context; null if there is none
-
hasScriptEngine
public final boolean hasScriptEngine()Determine if a script engine is available.- Returns:
- true if there is a script engine; false otherwise
-
createBindings
Create a new set of script bindings.- Returns:
- a new set of script bindings; null if there is no script engine
-
doGetDefaultBindings
Get the default script bindings. Subclasses providing a scripting environment must override this method. It will typically be called once, but could be called multiple times, so the method must be idempotent. It will not be called by this class if the constructor provided a parent.- Returns:
- the default bindings for this scripting context; null if there are none
-
doGetScriptLanguage
Get the scripting language. Subclasses providing a scripting environment must override this method. It will typically be called once, but could be called multiple times, so the method must be idempotent. It will not be called by this class if the constructor provided a parent.- Returns:
- the script engine for this scripting context; null if there is none
-
getScriptLanguage
Get the script language name.- Returns:
- the name of the scripting language; null if there is none
-
setWriter
Set the writer for script output.- Parameters:
writer
- the writer- Throws:
UnsupportedOperationException
- scripting was not enabled
-
getWriter
Get the writer for scripting-language output.- Returns:
- the writer
- Throws:
UnsupportedOperationException
- scripting was not enabled
-
setErrorWriter
Set the writer for script error output.- Parameters:
writer
- the writer- Throws:
UnsupportedOperationException
- scripting was not enabled
-
getErrorWriter
Get the write for scripting-language error output.- Returns:
- the writer
- Throws:
UnsupportedOperationException
- scripting was not enabled
-
setReader
Set the reader for script input.- Parameters:
reader
- the reader- Throws:
UnsupportedOperationException
- scripting was not enabled
-
getReader
Get the reader for scripting-language input.- Returns:
- the reader
- Throws:
UnsupportedOperationException
- scripting was not enabled
-
doScriptPrivileged
Execute code, that can throw checked exceptions, in privileged mode.If a subclass overrides this method, it must call super.doScriptPrivleged with the same arguments. This may be necessary in order to make the method accessible to other classes in the subclass' package. Ideally, the method would be declared to be final, but this unfortunately precludes allowing protected access in the subclass' package.
- Parameters:
c
- an ExceptionedCallable providing the code to run- Throws:
Exception
- an exception was raised
-
invokePrivateFunction
protected final Object invokePrivateFunction(Bindings bindings, Properties properties, String functionName, Object... args) throws ScriptException, UnsupportedOperationException Invoke a function defined by a private script with specified bindings. The script is stored in aProperties
list of properties under a key with the same name thatgetScriptLanguage()
returns in order to allow multiple scripting languages to be supported (EMCAScript, the official name for Javascript, is supported by the JDK, with other scripting languages available separately). The script will be evaluated once in sandbox mode, and must return an object whose methods will represent the functions that can be called (while at the implementation level, the methods of an object are called, the object is not visible to the caller). TheInvocable
interface will then be used to evaluate the appropriate method without having to evaluate the script each time this method is called. A separate object is used for each bindings/properties pair.The evaluation of the function is performed in the mode specified by the third argument.
Note: this method was added (with a change in the format of the properties for each language) because testing indicated that the Graal Javascript implementation, which a time this method was introduced, is likely to be the replacement for Nashorn, does not allow a function defined for one set of bindings to be used with objects defined in another set of bindings. To be sure this method would work with Graal's scripting languages, the object containing the methods is now placed in the same bindings used to obtain the arguments listed in the arguments that follow the function name.
- Parameters:
bindings
- the bindings to use when evaluating the functionproperties
- a properties list containing the script as an entry for a given scripting-language name (ECMAScript for Javascript)functionName
- the name of the function to invokeargs
- the function arguments- Returns:
- the object produced by the script evaluation
- Throws:
ScriptException
- an error occurred during the execution of the scriptUnsupportedOperationException
- no script engine was provided
-
invokePrivateFunction
protected final Object invokePrivateFunction(Properties properties, String functionName, Object... args) throws ScriptException, UnsupportedOperationException Invoke a function from a private script. The script is stored in aProperties
list of properties under a key with the same name thatgetScriptLanguage()
returns in order to allow multiple scripting languages to be supported (EMCAScript, the official name for Javascript, is supported by the JDK, with other scripting languages available separately). The script will be evaluated once in sandbox mode, and must return an object whose methods will represent the functions that can be called (while at the implementation level, the methods of an object are called, the object is not visible to the caller). TheInvocable
interface will then be used to evaluate the appropriate method without having to evaluate the script each time this method is called. A separate object is used for each bindings/properties pair, and the bindings are those currently in effect for this scripting context's script engine.The evaluation of the function is performed in the mode specified by the second argument.
Note: this method was added (with a change in the format of the properties for each language) because testing indicated that the Graal Javascript implementation, which a time this method was introduced, is likely to be the replacement for Nashorn, does not allow a function defined for one set of bindings to be used with objects defined in another set of bindings. To be sure this method would work with Graal's scripting languages, the object containing the methods is now placed in the same bindings used to obtain the arguments listed in the arguments that follow the function name.
- Parameters:
properties
- a properties list containing the script as an entry for a given scripting-language name (ECMAScript for Javascript)functionName
- the name of the function to invokeargs
- the function arguments- Returns:
- the object produced by the script evaluation
- Throws:
ScriptException
- an error occurred during the execution of the scriptUnsupportedOperationException
- no script engine was provided
-
getNames
Get a set of object names. These names are the names for scripting-language objects that are defined in the current engine-scope and global-scope bindings. This method is useful mainly for debugging or for obtaining data for documentation.- Returns:
- an unmodifiable set of the current object names
-