org.rexxla.bsf.engines.rexx

## Class RexxScriptEngine

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

- All Implemented Interfaces:
    javax.script.Compilable, javax.script.Invocable, javax.script.ScriptEngine

      public class RexxScriptEngine
      extends javax.script.AbstractScriptEngine
      implements javax.script.Compilable, javax.script.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 and 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 and 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 java.lang.String` | `dynamicallyRequireBSF` Rexx code to dynamically require "`BSF.CLS`".
    `static java.lang.String` | `strFormatGET` The Rexx code to inject for the Rexx script annotation `@GET`.
    `static java.lang.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 and Description
    `RexxScriptEngine()` Default constructor which creates the peer BSF Rexx engine instance.

  - ### Method Summary

    All Methods Static Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `javax.script.CompiledScript` | `compile(java.io.Reader script)` Compiles (tokenizes) the script (source read from Reader) for later execution.
    `javax.script.CompiledScript` | `compile(java.lang.String script)` Compiles (tokenizes) the script (source given as a String) for later execution.
    `javax.script.Bindings` | `createBindings()` Creates and returns a SimpleBindings instance.
    `static void` | `dumpScriptContext(javax.script.ScriptContext sc)` Utility method to dump the content of the supplied `ScriptContext`.
    `java.lang.Object` | `eval(java.io.Reader r, javax.script.ScriptContext sc)` Creates the script from the supplied `Reader` and uses `(String script, ScriptContext sc)` to carry out the operation.
    `java.lang.Object` | `eval(java.lang.String script, javax.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.
    `javax.script.ScriptEngineFactory` | `getFactory()` Returns the default RexxScriptEngineFactory instance for the Rexx scripting language.
    `static java.lang.String` | `getGMTFormattedDate4Filename()` Utility method to format a `SimpleDateFormat` such that it can be used as part of a generated filename.
    `<T> T` | `getInterface(java.lang.Class<T> clasz)` Returns an implementation of an interface using functions compiled in the interpreter.
    `<T> T` | `getInterface(java.lang.Object thiz, java.lang.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`.
    `java.lang.Object` | `getNil()` Getter method that returns the ooRexx `.nil` object.
    `java.lang.Object` | `invokeFunction(java.lang.String name, java.lang.Object... args)` Invokes (calls) a public Rexx routine defined in this compiled script.
    `java.lang.Object` | `invokeMethod(java.lang.Object thiz, java.lang.String name, java.lang.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 Detail

    - #### 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 java.lang.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 java.lang.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 java.lang.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 Detail

    - #### RexxScriptEngine

          public RexxScriptEngine()

      Default constructor which creates the peer BSF Rexx engine instance.

  - ### Method Detail

    - #### 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 java.lang.Object getNil()

      Getter method that returns the ooRexx `.nil` object.
      Returns:
        a `RexxProxy` referring to the ooRexx `.nil` object

    - #### getFactory

          public javax.script.ScriptEngineFactory getFactory()

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

    - #### createBindings

          public javax.script.Bindings createBindings()

      Creates and returns a SimpleBindings instance.
      Specified by:
        `createBindings` in interface `javax.script.ScriptEngine`
      Returns:
        a new SimpleBindings instance

    - #### eval

          public java.lang.Object eval(java.io.Reader r,
                                       javax.script.ScriptContext sc)
                                throws javax.script.ScriptException

      Creates the script from the supplied `Reader` and uses `(String script, ScriptContext sc)` to carry out the operation.
      Specified by:
        `eval` in interface `javax.script.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:
        `javax.script.ScriptException`

    - #### eval

          public java.lang.Object eval(java.lang.String script,
                                       javax.script.ScriptContext sc)
                                throws javax.script.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 `javax.script.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:
        `javax.script.ScriptException`

    - #### compile

          public javax.script.CompiledScript compile(java.io.Reader script)
                                              throws javax.script.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 `javax.script.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:
        `javax.script.ScriptException`

    - #### compile

          public javax.script.CompiledScript compile(java.lang.String script)
                                              throws javax.script.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 `javax.script.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:
        `javax.script.ScriptException`

    - #### getInterface

          public <T> T getInterface(java.lang.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 `javax.script.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(java.lang.Object thiz,
                                    java.lang.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 `javax.script.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 java.lang.Object invokeFunction(java.lang.String name,
                                                 java.lang.Object... args)
                                          throws javax.script.ScriptException,
                                                 java.lang.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 `javax.script.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:
        `javax.script.ScriptException` - depending on what went wrong in invocation
        `java.lang.NoSuchMethodException` - if method does not exist

    - #### invokeMethod

          public java.lang.Object invokeMethod(java.lang.Object thiz,
                                               java.lang.String name,
                                               java.lang.Object... args)
                                        throws javax.script.ScriptException,
                                               java.lang.NoSuchMethodException

      Sends a Rexx message to the Rexx object contained in the addressed `RexxProxy` object.
      Specified by:
        `invokeMethod` in interface `javax.script.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:
        `javax.script.ScriptException` - depending on what went wrong in invocation
        `java.lang.NoSuchMethodException` - if method does not exist

    - #### dumpScriptContext

          public static void dumpScriptContext(javax.script.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 java.lang.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