Scripting in Java Tutorial - Scripting in Java Context








A script engine executes a script in a context or environment.

An instance of the ScriptContext interface represents the context for a script.

The SimpleScriptContext class is an implementation of the ScriptContext interface.

A script context consists of four components:

  • Bindings associated with a different scope. Bindings in a context passes parameters to the script.
  • Reader to read inputs
  • Writer to write outputs
  • An error Writer to write error outputs




Example

The following code creates a ScriptContext using the SimpleScriptContext class.

An instance of the SimpleScriptContext class maintains two instances of Bindings: one for engine scope and one for global scope.

By default, the SimpleScriptContext class initializes the input reader, the output writer, and the error writer for the context to the System.in, System.out, and System.err, respectively.

getReader(), getWriter(), and getErrorWriter() methods from the ScriptContext interface returns the references of the reader, writer, and the error writer from the ScriptContext , respectively.

Setter methods can set a reader and writers.

The following code shows how to obtain the reader and writers. It also shows how to set a writer to a FileWriter to write the script output to a file:

import java.io.FileWriter;
import java.io.Reader;
import java.io.Writer;

import javax.script.ScriptContext;
import javax.script.SimpleScriptContext;

public class Main {
  public static void main(String[] args) throws Exception{
    ScriptContext ctx = new SimpleScriptContext();

    // Get the reader and writers from the script context
    Reader inputReader = ctx.getReader();
    Writer outputWriter = ctx.getWriter();
    Writer errWriter = ctx.getErrorWriter();

    // Write all script outputs to an out.txt file
    Writer fileWriter = new FileWriter("out.txt");
    ctx.setWriter(fileWriter);
  }
}





Add to Context

After you create a SimpleScriptContext, you can start storing key-value pairs in the engine scope Bindings.

The setAttribute() method is used to add a key-value pair to a Bindings.

The following code shows how to add three key-value pairs.

import javax.script.ScriptContext;
import javax.script.SimpleScriptContext;
/*from  w  ww .j a  v  a  2 s.  c o m*/
public class Main {
  public static void main(String[] args) throws Exception{
    ScriptContext ctx = new SimpleScriptContext();
        ctx.setAttribute("year", 2015, ScriptContext.ENGINE_SCOPE);
        ctx.setAttribute("month", 9, ScriptContext.ENGINE_SCOPE);
        ctx.setAttribute("day", 21, ScriptContext.ENGINE_SCOPE);

  }
}

Add bindings to GLOBAL_SCOPE

To add key-value pairs to a Bindings in global scope, create and set the Bindings first.

import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.SimpleBindings;
import javax.script.SimpleScriptContext;
/*www .  j av  a 2s.  c o  m*/
public class Main {
  public static void main(String[] args) throws Exception {
    ScriptContext ctx = new SimpleScriptContext();
    Bindings globalBindings = new SimpleBindings();
    ctx.setBindings(globalBindings, ScriptContext.GLOBAL_SCOPE);
    ctx.setAttribute("year", 2015, ScriptContext.GLOBAL_SCOPE);
    ctx.setAttribute("name", "Java", ScriptContext.GLOBAL_SCOPE);
  }
}

Resolve variable in different scope

import static javax.script.ScriptContext.ENGINE_SCOPE;
import static javax.script.ScriptContext.GLOBAL_SCOPE;
/* ww w. j av  a  2 s  .c  o m*/
import java.util.List;

import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.SimpleBindings;
import javax.script.SimpleScriptContext;

public class Main {
  public static void main(String[] args) {
    ScriptContext ctx = new SimpleScriptContext();
    List<Integer> scopes = ctx.getScopes();
    System.out.println("Supported Scopes: " + scopes);

    ctx.setAttribute("year", 2015, ENGINE_SCOPE);

    Bindings globalBindings = new SimpleBindings();
    ctx.setBindings(globalBindings, GLOBAL_SCOPE);

    ctx.setAttribute("year", 2014, GLOBAL_SCOPE);
    ctx.setAttribute("name", "Jack", GLOBAL_SCOPE);
    
    String nameValue = (String) ctx.getAttribute("name");
    System.out.println("nameValue = " + nameValue);

    int engineScopeYear = (Integer) ctx.getAttribute("year", ENGINE_SCOPE);
    int globalScopeYear = (Integer) ctx.getAttribute("year", GLOBAL_SCOPE);

    System.out.println("engineScopeYear = " + engineScopeYear);
    System.out.println("globalScopeYear = " + globalScopeYear);
  }
}

The code above generates the following result.

Example 3

Using Global and Engine Scope Bindings of Engines Created by the Same ScriptEngineManager

import static javax.script.ScriptContext.ENGINE_SCOPE;
import static javax.script.ScriptContext.GLOBAL_SCOPE;
//from  w  ww .j  av  a  2  s. c o  m
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleScriptContext;

public class Main {
  public static void main(String[] args) throws ScriptException {
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine = manager.getEngineByName("JavaScript");

    manager.put("n1", 1);
    String script = "var sum = n1 + n2;print(msg + "
        + "' n1=' + n1 + ', n2=' + n2 + " + "', sum=' + sum);";

    engine.put("n2", 2);
    engine.put("msg", "a string");
    engine.eval(script);

    Bindings bindings = engine.createBindings();
    bindings.put("n2", 3);
    bindings.put("msg", "another string");
    engine.eval(script, bindings);

    ScriptContext ctx = new SimpleScriptContext();
    Bindings ctxGlobalBindings = engine.createBindings();
    ctx.setBindings(ctxGlobalBindings, GLOBAL_SCOPE);
    ctx.setAttribute("n1", 4, GLOBAL_SCOPE);
    ctx.setAttribute("n2", 5, ENGINE_SCOPE);
    ctx.setAttribute("msg", "ScriptContext:", ENGINE_SCOPE);
    engine.eval(script, ctx);

    engine.eval(script);
  }
}

The code above generates the following result.

Changing the Default ScriptContext

To get and set the default context of a ScriptEngine using its getContext() and setContext() methods, respectively, as shown:

import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleScriptContext;
//  w w  w.  j  av  a2 s  . co m
public class Main {
  public static void main(String[] args) throws ScriptException {
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine = manager.getEngineByName("JavaScript");

        ScriptContext defaultCtx = engine.getContext();
        // Work with defaultCtx here

        // Create a new context
        ScriptContext ctx = new SimpleScriptContext();
        // Configure ctx here

        engine.setContext(ctx);
  }
}

To use the Bindings of the ScriptEngineManager in the new default context, set it explicitly as shown:

import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleScriptContext;
/* w  ww.  j av a  2 s . co m*/
public class Main {
  public static void main(String[] args) throws ScriptException {
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine = manager.getEngineByName("JavaScript");

        ScriptContext defaultCtx = engine.getContext();
        // Work with defaultCtx here

        // Create a new context
        ScriptContext ctx = new SimpleScriptContext();

        // Configure ctx here

        // Set ctx as the new default context for the engine
        engine.setContext(ctx);
        

        ctx.setBindings(manager.getBindings(), ScriptContext.GLOBAL_SCOPE);

        engine.setContext(ctx);
  }
}