Package org.rexxla.bsf.engines.rexx

# Class RexxScriptEngine

java.lang.Object
javax.script.AbstractScriptEngine
org.rexxla.bsf.engines.rexx.RexxScriptEngine

All Implemented Interfaces:
  `Compilable`, `Invocable`, `ScriptEngine`

public class RexxScriptEngine extends AbstractScriptEngine implements Compilable, Invocable
Class that extends extends the `javax.script.ScriptEngine` class and implements the `javax.script.Compilalbe` and * the `javax.script.Invocable` interface, although the latter one would only make sense in `RexxCompiledScript` class, because of the `getInterface(Class clasz)` method. Therefore the author (Rony G. Flatscher who served on the JSR-223 specification committee) thinks that the documentation in `javax.script.Invocable` is false, as it states that `Invocable` gets implemented by a `ScriptEngine`, somehow indicating it has to operate on some "state" of the script engine.
Please note: the JSR-223 specification does not imply that ScriptEngine should implement this interface!
The [oo]Rexx implementation of JSR-223 tries to be as flexible as possible and also implements this interface in its implementation of `ScriptEngine` sharing as much code between the tow (and caching compiled scripts for invoking the aforementioned method in a sensible way.

Since:
  2015-05-11
Version:
  104.20230411
Author:
  Rony G. Flatscher

- ## Nested Class Summary

  Nested Classes
  Modifier and Type
  Class
  Description
  `static class`
  `RexxScriptEngine.RexxAnnotation`
  Inner class for determining a RexxScript annotation, if one exists, the annotation field will refer to the appropriate enum value and all fields are filled in to ease processing of the script's code by the caller.

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `static boolean`
  `bPrependDynamicRequiresStatement`
  This controls whether the supplied Rexx scripts should get a dynamic requires statement prepended that makes sure that the Java support is present.
  `static boolean`
  `bRedirectStandardFiles`
  Determines whether the ScriptContext's Reader, Writer and ErrorWriter should replace the Rexx script .input (and also .debugInput, if present), .output, .error (and also .traceOutput if present).
  `static boolean`
  `bSupplyBSFExceptionObject`
  This controls whether ScriptExceptions should supply the `RexxException` object (extends `BSFException`) or fill in the ScriptException fields (message, line and column number, if present).
  `static final String`
  `dynamicallyRequireBSF`
  Rexx code to dynamically require "`BSF.CLS`".
  `static String`
  `strFormatGET`
  The Rexx code to inject for the Rexx script annotation `@GET`.
  `static String`
  `strFormatSET`
  The Rexx code to inject for the Rexx script annotation `@SET`.

  ### Fields inherited from class javax.script.AbstractScriptEngine

  `context`

  ### Fields inherited from interface javax.script.ScriptEngine

  `ARGV, ENGINE, ENGINE_VERSION, FILENAME, LANGUAGE, LANGUAGE_VERSION, NAME`

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `RexxScriptEngine()`
  Default constructor which creates the peer BSF Rexx engine instance.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `CompiledScript`
  `compile(Reader script)`
  Compiles (tokenizes) the script (source read from Reader) for later execution.
  `CompiledScript`
  `compile(String script)`
  Compiles (tokenizes) the script (source given as a String) for later execution.
  `Bindings`
  `createBindings()`
  Creates and returns a SimpleBindings instance.
  `static void`
  `dumpScriptContext(ScriptContext sc)`
  Utility method to dump the content of the supplied `ScriptContext`.
  `Object`
  `eval(Reader r, ScriptContext sc)`
  Creates the script from the supplied `Reader` and uses `(String script, ScriptContext sc)` to carry out the operation.
  `Object`
  `eval(String script, ScriptContext sc)`
  Creates a `RexxCompiledScript` object for the supplied Rexx script and then uses `RexxCompiledScript.eval(ScriptContext sc)` to carry out the operation.
  `boolean`
  `getAddLatestPackageDynamically()`
  Returns the current setting of `bAddLatestPackageDynamically`.
  `RexxEngine`
  `getBsfRexxEngine()`
  Getter method that returns the BSF scripting engine in use.
  `RexxCompiledScript`
  `getCurrentScript()`
  Getter method for "current" (the latest evaluated) script.
  `ScriptEngineFactory`
  `getFactory()`
  Returns the default RexxScriptEngineFactory instance for the Rexx scripting language.
  `static String`
  `getGMTFormattedDate4Filename()`
  Utility method to format a `SimpleDateFormat` such that it can be used as part of a generated filename.
  `<T> T`
  `getInterface(Class<T> clasz)`
  Returns an implementation of an interface using functions compiled in the interpreter.
  `<T> T`
  `getInterface(Object thiz, Class<T> clasz)`
  Returns an implementation of a Java interface where the Java method invocations will be implemented by the methods of the supplied Rexx object (a `RexxProxy`.
  `Object`
  `getNil()`
  Getter method that returns the ooRexx `.nil` object.
  `Object`
  `invokeFunction(String name, Object... args)`
  Invokes (calls) a public Rexx routine defined in this compiled script.
  `Object`
  `invokeMethod(Object thiz, String name, Object... args)`
  Sends a Rexx message to the Rexx object contained in the addressed `RexxProxy` object.
  `void`
  `setAddLatestPackageDynamically(boolean newValue)`
  Allows to change the behaviour from adding the `latestRexxPackage` to new Rexx routines.

  ### Methods inherited from class javax.script.AbstractScriptEngine

  `eval, eval, eval, eval, get, getBindings, getContext, getScriptContext, put, setBindings, setContext`

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Field Details

  - ### bSupplyBSFExceptionObject

    public static boolean bSupplyBSFExceptionObject
    This controls whether ScriptExceptions should supply the `RexxException` object (extends `BSFException`) or fill in the ScriptException fields (message, line and column number, if present). Using `BSFException.getCause()` will return the `RexxException` object, that has a method `getRexxConditionObject` which is a `RexxProxy` for the Rexx directory (cf. the ooRexx condition object documentation for its entries).
    If set to `false`, then an attempt is made to supply as much information according to the `ScriptException` constructors, which might ease generic script editors that use JSR223 script engines.

  - ### bRedirectStandardFiles

    public static boolean bRedirectStandardFiles
    Determines whether the ScriptContext's Reader, Writer and ErrorWriter should replace the Rexx script .input (and also .debugInput, if present), .output, .error (and also .traceOutput if present). There may be situations (like a GUI based interface to run Rexx scripts) where this automatic redirection should be inhibited.

  - ### strFormatGET

    public static String strFormatGET
    The Rexx code to inject for the Rexx script annotation `@GET`. Get the last argument (a Rexx Directory, dubbed "slotDir") and fetch the entry "ScriptContext" from it.

  - ### strFormatSET

    public static String strFormatSET
    The Rexx code to inject for the Rexx script annotation `@SET`. Get the last argument (a Rexx Directory, dubbed "slotDir") and fetch the entry "ScriptContext" from it.

  - ### dynamicallyRequireBSF

    public static final String dynamicallyRequireBSF
    Rexx code to dynamically require "`BSF.CLS`". This makes sure that the native part of `BSF4ooRexx` is set to support the camouflaging support from the beginning.
    See Also:
      - Constant Field Values

  - ### bPrependDynamicRequiresStatement

    public static boolean bPrependDynamicRequiresStatement
    This controls whether the supplied Rexx scripts should get a dynamic requires statement prepended that makes sure that the Java support is present. Only honored, if the instance field `bAddLatestPackageDynamically` is set to `false`.

- ## Constructor Details

  - ### RexxScriptEngine

    public RexxScriptEngine()
    Default constructor which creates the peer BSF Rexx engine instance.

- ## Method Details

  - ### getCurrentScript

    public RexxCompiledScript getCurrentScript()
    Getter method for "current" (the latest evaluated) script. Due to the ooRexx architecture each script gets compiled (actually tokenized and its package set up) and will be stored in a field. Each script that gets evaluated will replace the `currentScript` object. Fetching this `RexxCompiledScript` allows one to execute it as many times as needed, but also use all of the implemented `Invocable` methods.
    Returns:
      the current (latest) `RexxCompiledScript` object or `null` if no script has been evaluated or compiled yet

  - ### setAddLatestPackageDynamically

    public void setAddLatestPackageDynamically(boolean newValue)
    Allows to change the behaviour from adding the `latestRexxPackage` to new Rexx routines. Default is `true`, which makes sure that any new Rexx routine will get the latest Rexx package added to it, thereby gaining access to the package `BSF.CLS` and all previously defined public routines and public classes.
    Parameters:
      `newValue` - `true` or `false`

  - ### getAddLatestPackageDynamically

    public boolean getAddLatestPackageDynamically()
    Returns the current setting of `bAddLatestPackageDynamically`.
    Returns:
      current setting of `bAddLatestPackageDynamically`.

  - ### getBsfRexxEngine

    public RexxEngine getBsfRexxEngine()
    Getter method that returns the BSF scripting engine in use.
    Returns:
      the BSF Rexx engine used for this RexxScriptEngine

  - ### getNil

    public Object getNil()
    Getter method that returns the ooRexx `.nil` object.
    Returns:
      a `RexxProxy` referring to the ooRexx `.nil` object

  - ### getFactory

    public ScriptEngineFactory getFactory()
    Returns the default RexxScriptEngineFactory instance for the Rexx scripting language.
    Specified by:
      `getFactory` in interface `ScriptEngine`
    Returns:
      the default RexxScriptEngine Factory (RexxScriptEngineFactory.DEFAULT_REXX_SCRIPT_ENGINE_FACTORY)

  - ### createBindings

    public Bindings createBindings()
    Creates and returns a SimpleBindings instance.
    Specified by:
      `createBindings` in interface `ScriptEngine`
    Returns:
      a new SimpleBindings instance

  - ### eval

    public Object eval(Reader r, ScriptContext sc) throws ScriptException
    Creates the script from the supplied `Reader` and uses `(String script, ScriptContext sc)` to carry out the operation.
    Specified by:
      `eval` in interface `ScriptEngine`
    Parameters:
      `r` - - A `Reader` supplying the Rexx code to evaluate.
      `sc` - - A `ScriptContext` to use for evaluating the script
    Returns:
      the object the Rexx routine returns. In the case that a Rexx object gets returned it will be wrapped (boxed) in a `RexxProxy`. Supplying a `RexxProxy` as an argument to a Rexx routine will cause the contained Rexx object to be used in Rexx instead.
      Hint: one can interact with the contained Rexx object of a `RexxProxy` by sending it messages from Java using its `sendMessage` methods.
    Throws:
      `ScriptException`

  - ### eval

    public Object eval(String script, ScriptContext sc) throws ScriptException
    Creates a `RexxCompiledScript` object for the supplied Rexx script and then uses `RexxCompiledScript.eval(ScriptContext sc)` to carry out the operation.
    Specified by:
      `eval` in interface `ScriptEngine`
    Parameters:
      `script` - - The Rexx script to evaluate.
      `sc` - - A `ScriptContext` object supplying information for evaluating the Rexx script
    Returns:
      the object the Rexx routine returns. In the case that a Rexx object gets returned it will be wrapped (boxed) in a `RexxProxy`. Supplying a `RexxProxy` as an argument to a Rexx routine will cause the contained Rexx object to be used in Rexx instead.
      Hint: one can interact with the contained Rexx object of a `RexxProxy` by sending it messages from Java using its `sendMessage` methods.
    Throws:
      `ScriptException`

  - ### compile

    public CompiledScript compile(Reader script) throws ScriptException
    Compiles (tokenizes) the script (source read from Reader) for later execution. The actual compilation (tokenization) will be carried out by `compile(String script)`.
    Specified by:
      `compile` in interface `Compilable`
    Parameters:
      `script` - a Reader that supplies the characters of the script
    Returns:
      a CompiledScript that can be repeatedly evaluate()'d or used to invoke functions of the script or methods in an object
    Throws:
      `ScriptException`

  - ### compile

    public CompiledScript compile(String script) throws ScriptException
    Compiles (tokenizes) the script (source given as a String) for later execution. The actual compilation (tokenization) will be carried out by `compile(String script, String filename)`.
    Specified by:
      `compile` in interface `Compilable`
    Parameters:
      `script` - - The Rexx script to be compiled (tokenized).
    Returns:
      a CompiledScript that can be repeatedly evaluate()'d or used to invoke functions of the script or methods in an object
    Throws:
      `ScriptException`

  - ### getInterface

    public <T> T getInterface(Class<T> clasz)
    Returns an implementation of an interface using functions compiled in the interpreter.

    Note: Uses the implementation in `RexxCompiledScript.getInterface(Class clasz)`.

    Specified by:
      `getInterface` in interface `Invocable`
    Parameters:
      `clasz` - - The Java interface class object `<T>`, whose methods are implemented as public Rexx routines.
    Returns:
      a Java object of type `<T>`

  - ### getInterface

    public <T> T getInterface(Object thiz, Class<T> clasz)
    Returns an implementation of a Java interface where the Java method invocations will be implemented by the methods of the supplied Rexx object (a `RexxProxy`.

    Hint #1: the external `BSF4ooRexx` external Rexx function `BSFCreateRexxProxy(...)` is much more versatile and among other things allows for implementing multiple Java interface classes in a single Rexx class.

    Hint #2: when an interface method gets invoked, the Rexx method routine gets all its arguments in the same order supplied to, plus an appended `RexxSlotArgument` "slot directory" object, which contains information about this particular method invocation. This slot directory will also contain an entry, named `"SCRIPTCONTEXT"`, which allows the Rexx routine to fully interact with the `ScriptContext` used for its invocation.
    (Hint: one can always access this object from Rexx code with the statement `scriptcontext=arg('A')~lastItem~scriptContext`).)

    Specified by:
      `getInterface` in interface `Invocable`
    Parameters:
      `thiz` - - The Java object (must be a `RexxProxy`) that implements the Java interface methods
      `clasz` - - The Java interface class object `<T>`, whose methods are implemented in the `thiz` object
    Returns:
      a Java object of type `<T>`

  - ### invokeFunction

    public Object invokeFunction(String name, Object... args) throws ScriptException, NoSuchMethodException
    Invokes (calls) a public Rexx routine defined in this compiled script.

    Note: Uses the implementation in `RexxCompiledScript` where this method belongs to.

    Specified by:
      `invokeFunction` in interface `Invocable`
    Parameters:
      `name` - - The name of the public routine to invoke.
      `args` - - The arguments (a Java array of type `Object`) for the routine.

      Note # 1: If any argument is of type `RexxProxy`, then the Rexx routine will receive the contained Rexx object instead.

      Note # 2: This method will append an additional Rexx directory object argument with an entry named `"SCRIPTCONTEXT"`, which allows the Rexx routine to fully interact with the `ScriptContext` used for its invocation.
      (Hint: one can always access this object from Rexx code with the statement `scriptcontext=arg('A')~lastItem~scriptContext`).)

    Returns:
      the object the Rexx routine returns. In the case that a Rexx object gets returned it will be wrapped (boxed) in a `RexxProxy`. Supplying a `RexxProxy` as an argument to a Rexx routine will cause the contained Rexx object to be used in Rexx instead.
      Hint: one can interact with the contained Rexx object of a `RexxProxy` by sending it messages from Java using its `sendMessage` methods or the `invokeMethod(Object thiz, String name, Object...args)` method.
    Throws:
      `ScriptException` - depending on what went wrong in invocation
      `NoSuchMethodException` - if method does not exist

  - ### invokeMethod

    public Object invokeMethod(Object thiz, String name, Object... args) throws ScriptException, NoSuchMethodException
    Sends a Rexx message to the Rexx object contained in the addressed `RexxProxy` object.
    Specified by:
      `invokeMethod` in interface `Invocable`
    Parameters:
      `thiz` - - The wrapped (as a `RexxProxy`) Rexx object to receive the message
      `name` - - The Rexx message (method) name.
      `args` - - The arguments (a Java array of type `Object`) for the Rexx method.

      Note # 1: If any argument is of type `RexxProxy`, then the Rexx routine will receive the contained Rexx object instead.

      Note # 2: This method will append an additional Rexx directory object argument with an entry named `"SCRIPTCONTEXT"`, which allows the Rexx routine to fully interact with the `ScriptContext` used for its invocation.
      (Hint: one can always access this object from Rexx code with the statement `scriptcontext=arg('A')~lastItem~scriptContext`).)

    Returns:
      the object the Rexx routine returns. In the case that a Rexx object gets returned it will be wrapped (boxed) in a `RexxProxy`. Supplying a `RexxProxy` as an argument to a Rexx routine will cause the contained Rexx object to be used in Rexx instead.
      Hint: one can interact with the contained Rexx object of a `RexxProxy` by sending it messages from Java using its `sendMessage` methods or the `invokeMethod(Object thiz, String name, Object...args)` method.
    Throws:
      `ScriptException` - depending on what went wrong in invocation
      `NoSuchMethodException` - if method does not exist

  - ### dumpScriptContext

    public static void dumpScriptContext(ScriptContext sc)
    Utility method to dump the content of the supplied `ScriptContext`.
    Parameters:
      `sc` - the ScriptContext object for which the Bindings of all scopes get dumped

  - ### getGMTFormattedDate4Filename

    public static String getGMTFormattedDate4Filename()
    Utility method to format a `SimpleDateFormat` such that it can be used as part of a generated filename.
    Returns:
      a string indicating the current date and time suitable to be used as part of a filename