/** * Creates a new variable scope, extending from the current scope. Allows you to create a nested * contextual scope which can override variables from higher levels. * * Should be used in a try/finally context, similar to lock-use patterns: * * <code> * interpreter.enterScope(); * try (interpreter.enterScope()) { * // ... * } * </code> */ public InterpreterScopeClosable enterScope() { return enterScope(null); }
@Override public String interpret(TagNode tagNode, JinjavaInterpreter interpreter) { String macroExpr = "{{" + tagNode.getHelpers().trim() + "}}"; try (InterpreterScopeClosable c = interpreter.enterScope()) { LinkedHashMap<String, Object> args = new LinkedHashMap<>(); MacroFunction caller = new MacroFunction(tagNode.getChildren(), "caller", args, false, false, true, interpreter.getContext()); interpreter.getContext().addGlobalMacro(caller); return interpreter.render(macroExpr); } }
@Test public void itBlocksDisabledTags() { Map<Context.Library, Set<String>> disabled = ImmutableMap.of(Context.Library.TAG, ImmutableSet.of("raw")); assertThat(interpreter.render("{% raw %}foo{% endraw %}")).isEqualTo("foo"); try (JinjavaInterpreter.InterpreterScopeClosable c = interpreter.enterScope(disabled)) { interpreter.render("{% raw %} foo {% endraw %}"); } TemplateError e = interpreter.getErrorsCopy().get(0); assertThat(e.getItem()).isEqualTo(ErrorItem.TAG); assertThat(e.getReason()).isEqualTo(ErrorReason.DISABLED); assertThat(e.getMessage()).contains("'raw' is disabled in this context"); }
@Test public void itBlocksDisabledExpTests() { Map<Context.Library, Set<String>> disabled = ImmutableMap.of(Context.Library.EXP_TEST, ImmutableSet.of("even")); assertThat(interpreter.render("{% if 2 is even %}yes{% endif %}")).isEqualTo("yes"); try (JinjavaInterpreter.InterpreterScopeClosable c = interpreter.enterScope(disabled)) { interpreter.render("{% if 2 is even %}yes{% endif %}"); TemplateError e = interpreter.getErrorsCopy().get(0); assertThat(e.getItem()).isEqualTo(ErrorItem.EXPRESSION_TEST); assertThat(e.getReason()).isEqualTo(ErrorReason.DISABLED); assertThat(e.getMessage()).contains("even' is disabled in this context"); } }
@Test public void itBlocksDisabledFilters() { Map<Context.Library, Set<String>> disabled = ImmutableMap.of(Context.Library.FILTER, ImmutableSet.of("truncate")); assertThat(interpreter.resolveELExpression("\"hey\"|truncate(2)", -1)).isEqualTo("h..."); try (JinjavaInterpreter.InterpreterScopeClosable c = interpreter.enterScope(disabled)) { interpreter.resolveELExpression("\"hey\"|truncate(2)", -1); TemplateError e = interpreter.getErrorsCopy().get(0); assertThat(e.getItem()).isEqualTo(ErrorItem.FILTER); assertThat(e.getReason()).isEqualTo(ErrorReason.DISABLED); assertThat(e.getMessage()).contains("truncate' is disabled in this context"); } }
@Test public void itBlocksDisabledExpTests() { Map<Context.Library, Set<String>> disabled = ImmutableMap.of(Context.Library.EXP_TEST, ImmutableSet.of("even")); assertThat(interpreter.render("{% if 2 is even %}yes{% endif %}")).isEqualTo("yes"); try (JinjavaInterpreter.InterpreterScopeClosable c = interpreter.enterScope(disabled)) { interpreter.render("{% if 2 is even %}yes{% endif %}"); TemplateError e = interpreter.getErrorsCopy().get(0); assertThat(e.getItem()).isEqualTo(ErrorItem.EXPRESSION_TEST); assertThat(e.getReason()).isEqualTo(ErrorReason.DISABLED); assertThat(e.getMessage()).contains("even' is disabled in this context"); } }
@Test public void itBlocksDisabledTags() { Map<Context.Library, Set<String>> disabled = ImmutableMap.of(Context.Library.TAG, ImmutableSet.of("raw")); assertThat(interpreter.render("{% raw %}foo{% endraw %}")).isEqualTo("foo"); try (JinjavaInterpreter.InterpreterScopeClosable c = interpreter.enterScope(disabled)) { interpreter.render("{% raw %} foo {% endraw %}"); } TemplateError e = interpreter.getErrorsCopy().get(0); assertThat(e.getItem()).isEqualTo(ErrorItem.TAG); assertThat(e.getReason()).isEqualTo(ErrorReason.DISABLED); assertThat(e.getMessage()).contains("'raw' is disabled in this context"); }
@Test public void itBlocksDisabledFilters() { Map<Context.Library, Set<String>> disabled = ImmutableMap.of(Context.Library.FILTER, ImmutableSet.of("truncate")); assertThat(interpreter.resolveELExpression("\"hey\"|truncate(2)", -1)).isEqualTo("h..."); try (JinjavaInterpreter.InterpreterScopeClosable c = interpreter.enterScope(disabled)) { interpreter.resolveELExpression("\"hey\"|truncate(2)", -1); TemplateError e = interpreter.getErrorsCopy().get(0); assertThat(e.getItem()).isEqualTo(ErrorItem.FILTER); assertThat(e.getReason()).isEqualTo(ErrorReason.DISABLED); assertThat(e.getMessage()).contains("truncate' is disabled in this context"); } }
@Test public void itBlocksDisabledTagsInIncludes() { final String jinja = "top {% include \"tags/includetag/raw.html\" %}"; Map<Context.Library, Set<String>> disabled = ImmutableMap.of(Context.Library.TAG, ImmutableSet.of("raw")); assertThat(interpreter.render(jinja)).isEqualTo("top before raw after\n"); try (JinjavaInterpreter.InterpreterScopeClosable c = interpreter.enterScope(disabled)) { interpreter.render(jinja); } TemplateError e = interpreter.getErrorsCopy().get(0); assertThat(e.getItem()).isEqualTo(ErrorItem.TAG); assertThat(e.getReason()).isEqualTo(ErrorReason.DISABLED); assertThat(e.getMessage()).contains("'raw' is disabled in this context"); }
@Test public void itBlocksDisabledTagsInIncludes() { final String jinja = "top {% include \"tags/includetag/raw.html\" %}"; Map<Context.Library, Set<String>> disabled = ImmutableMap.of(Context.Library.TAG, ImmutableSet.of("raw")); assertThat(interpreter.render(jinja)).isEqualTo("top before raw after\n"); try (JinjavaInterpreter.InterpreterScopeClosable c = interpreter.enterScope(disabled)) { interpreter.render(jinja); } TemplateError e = interpreter.getErrorsCopy().get(0); assertThat(e.getItem()).isEqualTo(ErrorItem.TAG); assertThat(e.getReason()).isEqualTo(ErrorReason.DISABLED); assertThat(e.getMessage()).contains("'raw' is disabled in this context"); }
@Override public Object doEvaluate(Map<String, Object> argMap, Map<String, Object> kwargMap, List<Object> varArgs) { JinjavaInterpreter interpreter = JinjavaInterpreter.getCurrent(); try (InterpreterScopeClosable c = interpreter.enterScope()) { for (Map.Entry<String, Object> scopeEntry : localContextScope.getScope().entrySet()) { if (scopeEntry.getValue() instanceof MacroFunction) { interpreter.getContext().addGlobalMacro((MacroFunction) scopeEntry.getValue()); } else { interpreter.getContext().put(scopeEntry.getKey(), scopeEntry.getValue()); } } // named parameters for (Map.Entry<String, Object> argEntry : argMap.entrySet()) { interpreter.getContext().put(argEntry.getKey(), argEntry.getValue()); } // parameter map interpreter.getContext().put("kwargs", kwargMap); // varargs list interpreter.getContext().put("varargs", varArgs); LengthLimitingStringBuilder result = new LengthLimitingStringBuilder(interpreter.getConfig().getMaxOutputSize()); for (Node node : content) { result.append(node.render(interpreter)); } return result.toString(); } }
@Override public String interpret(TagNode tagNode, JinjavaInterpreter interpreter) { try (InterpreterScopeClosable c = interpreter.enterScope()) { String boolFlagStr = StringUtils.trim(tagNode.getHelpers()); boolean escapeFlag = BooleanUtils.toBoolean(StringUtils.isNotBlank(boolFlagStr) ? boolFlagStr : "true"); interpreter.getContext().setAutoEscape(escapeFlag); LengthLimitingStringBuilder result = new LengthLimitingStringBuilder(interpreter.getConfig().getMaxOutputSize()); for (Node child : tagNode.getChildren()) { result.append(child.render(interpreter)); } return result.toString(); } }
@Test public void enterScopeTryWithResources() { interpreter.getContext().put("foo", "parent"); try (InterpreterScopeClosable c = interpreter.enterScope()) { interpreter.getContext().put("foo", "child"); assertThat(interpreter.resolveELExpression("foo", 1)).isEqualTo("child"); } assertThat(interpreter.resolveELExpression("foo", 1)).isEqualTo("parent"); }
@Test public void enterScopeTryWithResources() { interpreter.getContext().put("foo", "parent"); try (InterpreterScopeClosable c = interpreter.enterScope()) { interpreter.getContext().put("foo", "child"); assertThat(interpreter.resolveELExpression("foo", 1)).isEqualTo("child"); } assertThat(interpreter.resolveELExpression("foo", 1)).isEqualTo("parent"); }
ForLoop loop = ObjectIterator.getLoop(collection); try (InterpreterScopeClosable c = interpreter.enterScope()) {
@Test public void enterScopeTryFinally() { interpreter.getContext().put("foo", "parent"); interpreter.enterScope(); try { interpreter.getContext().put("foo", "child"); assertThat(interpreter.resolveELExpression("foo", 1)).isEqualTo("child"); } finally { interpreter.leaveScope(); } assertThat(interpreter.resolveELExpression("foo", 1)).isEqualTo("parent"); }
@Test public void enterScopeTryFinally() { interpreter.getContext().put("foo", "parent"); interpreter.enterScope(); try { interpreter.getContext().put("foo", "child"); assertThat(interpreter.resolveELExpression("foo", 1)).isEqualTo("child"); } finally { interpreter.leaveScope(); } assertThat(interpreter.resolveELExpression("foo", 1)).isEqualTo("parent"); }
@Test public void bubbleUpDependenciesFromLowerScope() { String dependencyType = "foo"; String dependencyIdentifier = "123"; interpreter.enterScope(); interpreter.getContext().addDependency(dependencyType, dependencyIdentifier); assertThat(interpreter.getContext().getDependencies().get(dependencyType)).contains(dependencyIdentifier); interpreter.leaveScope(); assertThat(interpreter.getContext().getDependencies().get(dependencyType)).contains(dependencyIdentifier); }
@Test public void bubbleUpDependenciesFromLowerScope() { String dependencyType = "foo"; String dependencyIdentifier = "123"; interpreter.enterScope(); interpreter.getContext().addDependency(dependencyType, dependencyIdentifier); assertThat(interpreter.getContext().getDependencies().get(dependencyType)).contains(dependencyIdentifier); interpreter.leaveScope(); assertThat(interpreter.getContext().getDependencies().get(dependencyType)).contains(dependencyIdentifier); }