/** * Reads the variables from JShell into bindings. */ private void readVariableValues(Bindings globalBindings, Bindings engineBindings) { jshell.variables().forEach(varSnippet -> { try { String name = varSnippet.name(); Object value = executionControl.getActualVarValue(varSnippet); if(globalBindings != null && !engineBindings.containsKey(name) && globalBindings.containsKey(name)) { globalBindings.put(name, value); } else { engineBindings.put(name, value); } } catch(Exception e) { e.printStackTrace(); } }); }
private static Map<String, Object> getAttributesFromInlineGroovyScript(final Map<String, Object> attributes, final Matcher matcherInline) throws ScriptException { final String script = matcherInline.group(1).trim(); final ScriptEngine engine = new ScriptEngineManager().getEngineByName("groovy"); if (engine == null) { LOGGER.warn("Script engine is not available for Groovy"); return new HashMap<>(); } final Object[] args = {attributes, LOGGER}; LOGGER.debug("Executing script, with parameters [{}]", args); final Bindings binding = new SimpleBindings(); binding.put("attributes", attributes); binding.put("logger", LOGGER); return (Map<String, Object>) engine.eval(script, binding); }
public static void appendTo(Bindings bindings) { // standard java collections bindings.put("newArrayList", ARRAY_LIST); bindings.put("newLinkedList", LINKED_LIST); bindings.put("newHashSet", HASH_SET); bindings.put("newHashMap", HASH_MAP); bindings.put("newCopyOnWriteArrayList", COPY_ON_WRITE_ARRAY_LIST); bindings.put("newConcurrentHashSet", CONCURRENT_HASH_SET); bindings.put("newConcurrentHashMap", CONCURRENT_HASH_MAP); bindings.put("listOf", LIST_OF); bindings.put("setOf", SET_OF); // guava immutables bindings.put("immutableListOf", IMMUTABLE_LIST_OF); bindings.put("immutableSetOf", IMMUTABLE_SET_OF); // misc bindings.put("parseUuid", PARSE_UUID); }
@Override public void appendTo(@Nonnull Bindings bindings) { // provide exports to access the exports registry & core server classes bindings.put("exports", exports); bindings.put("server", Bukkit.getServer()); bindings.put("plugin", plugin); bindings.put("services", Bukkit.getServicesManager()); // some util functions bindings.put("colorize", (Function<Object, String>) HelperScriptBindings::colorize); bindings.put("newMetadataKey", (Function<Object, MetadataKey>) HelperScriptBindings::newMetadataKey); bindings.put("newEmptyScheme", (Supplier<MenuScheme>) HelperScriptBindings::newScheme); bindings.put("newScheme", (Function<SchemeMapping, MenuScheme>) HelperScriptBindings::newScheme); // some general functions for working with java collections in js GeneralScriptBindings.appendTo(bindings); // provide hook into the resolvePackageWildcard method below, used by the importWildcardPackage function bindings.put("resolvePackageWildcard", (Function<String, List<String>>) HelperScriptBindings::resolvePackageWildcard); }
private IJsonType transformCombination( JsonSchemaType parent, URL enclosing, String name, Bindings jsonObj ) { IJsonType type = transformAllOf( parent, enclosing, name, jsonObj ); if( type != null ) { return type; } type = transformAnyOf( parent, enclosing, name, jsonObj ); if( type != null ) { return type; } return transformOneOf( parent, enclosing, name, jsonObj ); }
private IJsonType findReferenceTypeOrCombinationType( JsonSchemaType parent, URL enclosing, String name, Bindings jsonObj ) { IJsonType result; result = findReference( parent, enclosing, jsonObj ); if( result == null ) { result = transformCombination( parent, enclosing, name, jsonObj ); if( result == null ) { result = deriveTypeFromEnum( jsonObj ); if( result == null ) { // No type or other means of deriving a type could be found. // Default type is Dynamic (in Java this is Object) result = DynamicType.instance(); } } } return result; }
/** * Convert the Object to a String value suitable for a Json Url argument. * @param value A Json value. On of: Bindings, List, or simple value. * @return Json formatted value String. */ @Extension public static String makeValue( Object value ) { if( value instanceof Bindings ) { value = JsonUtil.toJson( (Bindings)value ); } else if( value instanceof List ) { value = JsonUtil.listToJson( (List)value ); } try { return URLEncoder.encode( value.toString(), "UTF-8" ); } catch( UnsupportedEncodingException e ) { throw new RuntimeException( e ); } }
private void transferIssuesFromErrantType( JsonSchemaType parent, IJsonType result, Bindings jsonObj ) { if( result instanceof ErrantType ) { Object value = jsonObj.get( JSCH_REF ); Token token = null; if( value instanceof Pair ) { token = ((Token[])((Pair)value).getFirst())[1]; } for( JsonIssue issue: ((ErrantType)result).getIssues() ) { parent.addIssue( new JsonIssue( issue.getKind(), token, issue.getMessage() ) ); } } }
@Override public Bindings parseJson( String jsonText, boolean withBigNumbers, boolean withTokens ) throws ScriptException { SimpleParserImpl parser = new SimpleParserImpl( new Tokenizer( new StringReader( jsonText ) ), withBigNumbers ); Object result = parser.parse( withTokens ); List<String> errors = parser.getErrors(); if( errors.size() != 0 ) { StringBuilder sb = new StringBuilder( "Found errors:\n" ); for( String err : errors ) { sb.append( err ).append( "\n" ); } throw new ScriptException( sb.toString() ); } if( result instanceof Pair ) { result = ((Pair)result).getSecond(); } if( result instanceof Bindings ) { return (Bindings)result; } return NashornJsonParser.wrapValueInBindings( result ); }
@Override public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception { final Object self = request.getReceiver(); final CallSiteDescriptor desc = request.getCallSiteDescriptor(); if (self == null || !canLinkTypeStatic(self.getClass())) { return null; } GuardedInvocation inv; if (self instanceof JSObject) { inv = lookup(desc, request, linkerServices); inv = inv.replaceMethods(linkerServices.filterInternalObjects(inv.getInvocation()), inv.getGuard()); } else if (self instanceof Map || self instanceof Bindings) { // guard to make sure the Map or Bindings does not turn into JSObject later! final GuardedInvocation beanInv = nashornBeansLinker.getGuardedInvocation(request, linkerServices); inv = new GuardedInvocation(beanInv.getInvocation(), NashornGuards.combineGuards(beanInv.getGuard(), NashornGuards.getNotJSObjectGuard())); } else { throw new AssertionError("got instanceof: " + self.getClass()); // Should never reach here. } return Bootstrap.asTypeSafeReturn(inv, linkerServices, desc); }
@Test public void createBindingsTest() { final ScriptEngineManager m = new ScriptEngineManager(); final ScriptEngine e = m.getEngineByName("nashorn"); final Bindings b = e.createBindings(); b.put("foo", 42.0); Object res = null; try { res = e.eval("foo == 42.0", b); } catch (final ScriptException | NullPointerException se) { se.printStackTrace(); fail(se.getMessage()); } assertEquals(res, Boolean.TRUE); }
@Test public void userEngineScopeBindingsRetentionTest() throws ScriptException { final ScriptEngineManager m = new ScriptEngineManager(); final ScriptEngine e = m.getEngineByName("nashorn"); final ScriptContext newContext = new SimpleScriptContext(); newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE); e.eval("function foo() {}", newContext); // definition retained with user's ENGINE_SCOPE Binding assertTrue(e.eval("typeof foo", newContext).equals("function")); final Bindings oldBindings = newContext.getBindings(ScriptContext.ENGINE_SCOPE); // but not in another ENGINE_SCOPE binding newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE); assertTrue(e.eval("typeof foo", newContext).equals("undefined")); // restore ENGINE_SCOPE and check again newContext.setBindings(oldBindings, ScriptContext.ENGINE_SCOPE); assertTrue(e.eval("typeof foo", newContext).equals("function")); }
@SuppressWarnings("unused") protected Bindings getBindings( Object value ) { if( value instanceof Pair ) { return getBindings( ((Pair)value).getSecond() ); } if( value instanceof Bindings ) { return (Bindings)value; } if( value instanceof JsonImplBase ) { return ((JsonImplBase)value)._bindings; } throw new IllegalStateException( "Unhandled type: " + value.getClass() ); }
/** * Use http POST to pass JSON bindings to this URL and get back the full content as a String. * <p> * If an argument is a javax.script.Bindings or a List, it is transformed to JSON. Otherwise, * the argument is coerced to a String. All arguments are URL encoded. * * @return The full content of this URL coerced to a String. * * @see #postForJsonContent(URL, Bindings) */ public static String postForTextContent( @This URL url, Bindings bindings ) { try { byte[] bytes = bindings.makeArguments().getBytes( "UTF-8" ); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); conn.setRequestMethod( "POST" ); conn.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded" ); conn.setRequestProperty( "Content-Length", String.valueOf( bytes.length ) ); conn.setDoOutput( true ); try( OutputStream out = conn.getOutputStream() ) { out.write( bytes ); } try( Reader in = StreamUtil.getInputStreamReader( conn.getInputStream() ) ) { return StreamUtil.getContent( in ); } } catch( Exception e ) { throw new RuntimeException( e ); } }
private Bindings buildBindings(RuleContext ctx, FromDeviceMsg msg) { Bindings bindings = NashornJsEvaluator.getAttributeBindings(ctx.getDeviceMetaData().getDeviceAttributes()); if (msg != null) { switch (msg.getMsgType()) { case POST_ATTRIBUTES_REQUEST: bindings = NashornJsEvaluator.updateBindings(bindings, (UpdateAttributesRequest) msg); break; case POST_TELEMETRY_REQUEST: TelemetryUploadRequest telemetryMsg = (TelemetryUploadRequest) msg; for (List<KvEntry> entries : telemetryMsg.getData().values()) { bindings = NashornJsEvaluator.toBindings(bindings, entries); } } } return bindings; }
@Test public void megamorphicPropertyReadTest() throws ScriptException { final NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); final ScriptEngine engine = factory.getScriptEngine(); final Bindings scope = engine.getBindings(ScriptContext.ENGINE_SCOPE); boolean ret; // Why 16 is the upper limit of this loop? The default nashorn dynalink megamorphic threshold is 16. // See jdk.nashorn.internal.runtime.linker.Bootstrap.NASHORN_DEFAULT_UNSTABLE_RELINK_THRESHOLD // We do, 'eval' of the same in this loop twice. So, 16*2 = 32 times that callsite in the script // is exercised - much beyond the default megamorphic threshold. for (int i = 0; i < 16; i++) { scope.remove(VAR_NAME); ret = lookupVar(engine, VAR_NAME); assertFalse(ret, "Expected false in iteration " + i); scope.put(VAR_NAME, "foo"); ret = lookupVar(engine, VAR_NAME); assertTrue(ret, "Expected true in iteration " + i); } }
@Test public void mapScriptObjectMirrorCallsiteTest() throws ScriptException { final ScriptEngineManager m = new ScriptEngineManager(); final ScriptEngine engine = m.getEngineByName("nashorn"); final String TEST_SCRIPT = "typeof obj.foo"; final Bindings global = engine.getContext().getBindings(ScriptContext.ENGINE_SCOPE); engine.eval("var obj = java.util.Collections.emptyMap()"); // this will drive callsite "obj.foo" of TEST_SCRIPT // to use "obj instanceof Map" as it's guard engine.eval(TEST_SCRIPT, global); // redefine 'obj' to be a script object engine.eval("obj = {}"); final Bindings newGlobal = engine.createBindings(); // transfer 'obj' from default global to new global // new global will get a ScriptObjectMirror wrapping 'obj' newGlobal.put("obj", global.get("obj")); // Every ScriptObjectMirror is a Map! If callsite "obj.foo" // does not see the new 'obj' is a ScriptObjectMirror, it'll // continue to use Map's get("obj.foo") instead of ScriptObjectMirror's // getMember("obj.foo") - thereby getting null instead of undefined assertEquals("undefined", engine.eval(TEST_SCRIPT, newGlobal)); }
private IJsonType deriveTypeFromEnum( Bindings bindings ) { List list = getJSchema_Enum( bindings ); if( list == null ) { return null; } IJsonType type = null; for( Object elem : list ) { IJsonType csr = Json.transformJsonObject( "", null, elem ); if( type == null ) { type = csr; } else if( !type.equals( csr ) ) { type = DynamicType.instance(); } } return type; }
static <E extends IJsonIO> List<E> readList( String tag, Bindings bindings ) { //noinspection unchecked List<Bindings> list = (List<Bindings>)bindings.get( tag ); if( list == null ) { return Collections.emptyList(); } List<E> objs = list.isEmpty() ? Collections.emptyList() : new ArrayList<>(); for( Bindings elem : list ) { objs.add( read( elem ) ); } return objs; }
public void testThing() { Product thing = Product.create(); thing.setPrice( 1.55 ); assertEquals( 1.55, thing.getPrice() ); Product.dimensions dims = Product.dimensions.create(); dims.setLength( 3.0 ); dims.setWidth( 4.0 ); dims.setHeight( 5.0 ); thing.setDimensions( dims ); Product.dimensions dims2 = thing.getDimensions(); assertSame( dims, dims2 ); Bindings bindings = (Bindings)thing; dims2 = (Product.dimensions)bindings.get( "dimensions" ); assertSame( dims, dims2 ); }
private static Map<String, Object> getCombinedVariables(Bindings globalBindings, Bindings engineBindings) { if(globalBindings == null) { return engineBindings; } Map<String, Object> variables = new HashMap<>(); variables.putAll(globalBindings); variables.putAll(engineBindings); return variables; }
private PacScriptEngine getScriptEngine(String pacSource) throws PacParsingException { try { String helperJSScript = getHelperJsScriptSource(); LOGGER.log(Level.FINER, "PAC Helper JavaScript :\n{0}", helperJSScript); ScriptEngine engine; if (nashornJava8u40Available) { engine = getNashornJSScriptEngine(); } else { engine = getGenericJSScriptEngine(); } LOGGER.log(Level.FINE, "PAC script evaluator using: {0}", getEngineInfo(engine)); PacHelperMethods pacHelpers = Lookup.getDefault().lookup(PacHelperMethods.class); if (pacHelpers == null) { // this should be redundant but we take no chances pacHelpers = new NbPacHelperMethods(); } Bindings b = engine.createBindings(); b.put(JS_HELPER_METHODS_INSTANCE_NAME, pacHelpers); engine.setBindings(b, ScriptContext.ENGINE_SCOPE); engine.eval(pacSource); engine.eval(helperJSScript); // Do some minimal testing of the validity of the PAC Script. final PacJsEntryFunction jsMainFunction; if (nashornJava8u40Available) { jsMainFunction = testScriptEngine(engine, true); } else { jsMainFunction = testScriptEngine(engine, false); } return new PacScriptEngine(engine, jsMainFunction); } catch (ScriptException ex) { throw new PacParsingException(ex); } }
@SuppressWarnings("unchecked") public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException { try { List<Invoker<T>> invokersCopy = new ArrayList<Invoker<T>>(invokers); Compilable compilable = (Compilable) engine; Bindings bindings = engine.createBindings(); bindings.put("invokers", invokersCopy); bindings.put("invocation", invocation); bindings.put("context", RpcContext.getContext()); CompiledScript function = compilable.compile(rule); Object obj = function.eval(bindings); if (obj instanceof Invoker[]) { invokersCopy = Arrays.asList((Invoker<T>[]) obj); } else if (obj instanceof Object[]) { invokersCopy = new ArrayList<Invoker<T>>(); for (Object inv : (Object[]) obj) { invokersCopy.add((Invoker<T>)inv); } } else { invokersCopy = (List<Invoker<T>>) obj; } return invokersCopy; } catch (ScriptException e) { //fail then ignore rule .invokers. logger.error("route error , rule has been ignored. rule: " + rule + ", method:" + invocation.getMethodName() + ", url: " + RpcContext.getContext().getUrl(), e); return invokers; } }
private Node perform(HashMap<String, java.lang.Object> a6y) throws Exception { Bindings bindings = engine.createBindings(); bindings.put("a6y", a6y); try { engine.eval(script, bindings); return jsToNode(a6y.get("response")); } catch (ScriptException e) { throw new Exception(e); } }
private void syncBindings(ScriptEngine scriptEngine, ScriptLanguage scriptLanguage) { Bindings currentBindings = scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE); this.scriptEngines.forEach((String name, ScriptEngine engine) -> { Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE); currentBindings.keySet().forEach((String key) -> { bindings.put(key, scriptLanguage.decode(currentBindings.get(key))); }); }); }
private void initBindings(Bindings bindings, ScriptEngine scriptEngine, ScriptLanguage scriptLanguage) { Bindings currentBindings = scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE); bindings.keySet().forEach((String key) -> { currentBindings.put(key, scriptLanguage.decode(bindings.get(key))); }); }
public String getInfoFor(Player player, String string) { string = string .replaceAll(Variables.statueVariable, AuthMeApi.getInstance().isRegistered(player.getName()) ? Variables.registeredStatueMessage : Variables.unregisteredStatueMessage) .replaceAll(Variables.playerVariable, player.getName()) .replaceAll(Variables.playerCustomVariable, player.getCustomName()) .replaceAll(Variables.playerDisplayVariable, player.getDisplayName()) .replaceAll(Variables.playerIpVariable, player.getAddress().getHostString()) .replaceAll(Variables.serverIpVariable, Bukkit.getIp()) .replaceAll(Variables.playerLevelVariable, player.getExpToLevel() + ""); if (Variables.script.isEmpty()) { return string; } ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName(Variables.scriptEngine); Bindings bindings = engine.createBindings(); bindings.put("line", string); bindings.put("player", player); bindings.put("plugin", plugin); try { string = engine.eval(Variables.script, bindings).toString(); } catch (ScriptException e) { e.printStackTrace(); } return string; }
public static void listToJson( StringBuilder sb, int indent, List value ) { sb.append( '[' ); if( value.size() > 0 ) { sb.append( "\n" ); int iSize = value.size(); int i = 0; while( i < iSize ) { Object comp = value.get( i ); if( comp instanceof Pair ) { comp = ((Pair)comp).getSecond(); } if( comp instanceof Bindings ) { toJson( ((Bindings)comp), sb, indent + 4 ); } else if( comp instanceof List ) { listToJson( sb, indent + 4, (List)comp ); } else { indent( sb, indent + 4 ); JsonUtil.appendValue( sb, comp ); } appendCommaNewLine( sb, i < iSize - 1 ); i++; } } indent( sb, indent + 2 ); sb.append( "]" ); }
public String resolveVariableName(Object value) { Bindings bindings = getScriptEngine().getBindings(ScriptContext.ENGINE_SCOPE); Iterator<Entry<String, Object>> iterator = bindings.entrySet().stream().filter(entry -> entry.getValue() == value).iterator(); if (!iterator.hasNext()) { throw new SpongeException("Variable for processor " + value + " not found."); } Map.Entry<String, Object> variableEntry = iterator.next(); if (iterator.hasNext()) { throw new SpongeException("Multiple variables for processor " + value + " have been found."); } return variableEntry.getKey(); }
public static boolean isSchema( Bindings bindings ) { // Ideally the "$schema" element would be required, but JSchema does not require it. return bindings.get( JsonSchemaTransformer.JSCH_SCHEMA ) != null || // As a fallback check for "$id" as this is pretty uniquely Json Schema bindings.get( JsonSchemaTransformer.JSCH_ID ) != null || // As a fallback to the fallback, check for: "type": "object" or "type": "array" bindings.get( JsonSchemaTransformer.JSCH_TYPE ) != null && (bindings.get( JsonSchemaTransformer.JSCH_TYPE ).equals( Type.Object.getName() ) || bindings.get( JsonSchemaTransformer.JSCH_TYPE ).equals( Type.Array.getName() )); }
private Object doEvaluate(String js, Object input) { Objects.requireNonNull(input); Objects.requireNonNull(engine, "No JavaScript engine available!"); Bindings bindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE); bindings.put("input", input); bindings.putAll(references); try { return engine.eval(js); } catch (ScriptException e) { throw new IllegalArgumentException("Could not evaluate JavaScript: " + e.getLocalizedMessage(), e); } }
public EngineMap() { this.map = Collections.synchronizedMap(new EnumMap<>(Engine.class)); final ScriptEngine js = Engine.JAVASCRIPT.newScriptEngine(); this.map.put(Engine.JAVASCRIPT, js); try { js.eval("engines = {}"); } catch (final ScriptException e) { throw new RuntimeException(e); // should never happen } final Bindings engines = (Bindings) js.get("engines"); engines.put("js", js); this.context = js.getContext(); engines.put("context", this.context); for (final Engine engine : Engine.values()) this.map.computeIfAbsent(engine, e -> { final ScriptEngine scriptEngine = e.newScriptEngine(this.context); ((Bindings) scriptEngine.get("engines")).put(e.getName(), scriptEngine); return scriptEngine; }); }
public Boolean execute(Bindings bindings) throws ScriptException { Object eval = engine.eval(bindings); if (eval instanceof Boolean) { return (Boolean) eval; } else { log.warn("Wrong result type: {}", eval); throw new ScriptException("Wrong result type: " + eval); } }
private void addConstructors( SrcClass srcClass ) { srcClass.addConstructor( new SrcConstructor() .body( new SrcStatementBlock() .addStatement( new SrcRawStatement() .rawText( "super();" ) ) ) ); srcClass.addConstructor( new SrcConstructor() .addParam( "bindings", Bindings.class.getSimpleName() ) .body( new SrcStatementBlock() .addStatement( new SrcRawStatement() .rawText( "super(bindings);" ) ) ) ); }
private boolean isCombination( Bindings jsonObj ) { return (jsonObj.containsKey( JSCH_ALL_OF ) || jsonObj.containsKey( JSCH_ONE_OF ) || jsonObj.containsKey( JSCH_ANY_OF )) && !isPropertiesDefined( jsonObj ); }
private static String makeValue( Object value ) throws UnsupportedEncodingException { if( value instanceof Bindings ) { value = JsonUtil.toJson( (Bindings)value ); } else if( value instanceof List ) { value = JsonUtil.listToJson( (List)value ); } return URLEncoder.encode( value.toString(), "UTF-8" ); }
static Bindings wrapValueInBindings( Object result ) throws ScriptException { if( result == null || result instanceof List || result instanceof String || result instanceof Number || result instanceof Boolean ) { Bindings wrapper = new SimpleBindings(); wrapper.put( "value", result ); return wrapper; } throw new ScriptException( "Unexpected JSON result type: " + result.getClass().getName() ); }
public static void main(String[] args) throws Exception { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine jsengine = Helper.getJsEngine(manager); if (jsengine == null) { System.out.println("Warning: No js engine found; test vacuously passes."); return; } jsengine.eval("var v = 'hello';"); // Create a new scope Bindings b = jsengine.createBindings(); // b is newly created scope. We don't expect 'v' there. // we expect b to be empty... if (b.keySet().size() != 0) { throw new RuntimeException("no variables expected in new scope"); } // verify that we can create new variable from Java jsengine.put("fromJava", "hello world"); // below should execute without problems.. jsengine.eval(" if (fromJava != 'hello world') throw 'unexpected'"); // verify that script globals are exposed to Java // we have created 'v' and 'fromJava' already. if (! jsengine.get("v").equals("hello")) { throw new RuntimeException("unexpected value of 'v'"); } if (! jsengine.get("fromJava").equals("hello world")) { throw new RuntimeException("unexpected value of 'fromJava'"); } }
/** * Test multi-threaded access to undefined global variables for shared script classes with multiple globals. */ @Test public static void multiThreadedGlobalTest() throws ScriptException, InterruptedException { final ScriptEngineManager m = new ScriptEngineManager(); final ScriptEngine e = m.getEngineByName("nashorn"); final Bindings b = e.createBindings(); final ScriptContext origContext = e.getContext(); final ScriptContext newCtxt = new SimpleScriptContext(); newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE); assertEquals(e.eval("foo = 'original context';", origContext), "original context"); assertEquals(e.eval("foo = 'new context';", newCtxt), "new context"); final String sharedScript = "foo"; final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000)); final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000)); t1.start(); t2.start(); t1.join(); t2.join(); final Object obj3 = e.eval("delete foo; foo = 'newer context';", newCtxt); assertEquals(obj3, "newer context"); final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000)); final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000)); t3.start(); t4.start(); t3.join(); t4.join(); Assert.assertEquals(e.eval(sharedScript), "original context"); Assert.assertEquals(e.eval(sharedScript, newCtxt), "newer context"); }