/** * Perform expression compilation. This will only succeed once exit descriptors for all nodes have * been determined. If the compilation fails and has failed more than 100 times the expression is * no longer considered suitable for compilation. */ public boolean compileExpression() { if (this.failedAttempts > FAILED_ATTEMPTS_THRESHOLD) { // Don't try again return false; } if (this.compiledAst == null) { synchronized (this.expression) { // Possibly compiled by another thread before this thread got into the sync block if (this.compiledAst != null) { return true; } SpelCompiler compiler = SpelCompiler.getCompiler(this.configuration.getCompilerClassLoader()); this.compiledAst = compiler.compile(this.ast); if (this.compiledAst == null) { this.failedAttempts++; } } } return (this.compiledAst != null); }
/** * Factory method for compiler instances. The returned SpelCompiler will * attach a class loader as the child of the given class loader and this * child will be used to load compiled expressions. * @param classLoader the ClassLoader to use as the basis for compilation * @return a corresponding SpelCompiler instance */ public static SpelCompiler getCompiler(@Nullable ClassLoader classLoader) { ClassLoader clToUse = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader()); synchronized (compilers) { SpelCompiler compiler = compilers.get(clToUse); if (compiler == null) { compiler = new SpelCompiler(clToUse); compilers.put(clToUse, compiler); } return compiler; } }
/** * Attempt compilation of the supplied expression. A check is made to see * if it is compilable before compilation proceeds. The check involves * visiting all the nodes in the expression Ast and ensuring enough state * is known about them that bytecode can be generated for them. * @param expression the expression to compile * @return an instance of the class implementing the compiled expression, * or {@code null} if compilation is not possible */ @Nullable public CompiledExpression compile(SpelNodeImpl expression) { if (expression.isCompilable()) { if (logger.isDebugEnabled()) { logger.debug("SpEL: compiling " + expression.toStringAST()); } Class<? extends CompiledExpression> clazz = createExpressionClass(expression); if (clazz != null) { try { return ReflectionUtils.accessibleConstructor(clazz).newInstance(); } catch (Throwable ex) { throw new IllegalStateException("Failed to instantiate CompiledExpression", ex); } } } if (logger.isDebugEnabled()) { logger.debug("SpEL: unable to compile " + expression.toStringAST()); } return null; }
private void compile(Expression expression) { assertTrue(SpelCompiler.compile(expression)); }
private Class<? extends CompiledExpression> createExpressionClass(SpelNodeImpl expressionToCompile) { String className = "spel/Ex" + getNextSuffix(); ClassWriter cw = new ExpressionClassWriter(); cw.visit(V1_5, ACC_PUBLIC, className, null, "org/springframework/expression/spel/CompiledExpression", null); return loadClass(StringUtils.replace(className, "/", "."), data);
private void assertCantCompile(Expression expression) { assertFalse(SpelCompiler.compile(expression)); }
private Class<? extends CompiledExpression> createExpressionClass(SpelNodeImpl expressionToCompile) { String className = "spel/Ex" + getNextSuffix(); ClassWriter cw = new ExpressionClassWriter(); cw.visit(V1_5, ACC_PUBLIC, className, null, "org/springframework/expression/spel/CompiledExpression", null); return loadClass(StringUtils.replace(className, "/", "."), data);
/** * Perform expression compilation. This will only succeed once exit descriptors for all nodes have * been determined. If the compilation fails and has failed more than 100 times the expression is * no longer considered suitable for compilation. */ public boolean compileExpression() { if (this.failedAttempts > FAILED_ATTEMPTS_THRESHOLD) { // Don't try again return false; } if (this.compiledAst == null) { synchronized (this.expression) { // Possibly compiled by another thread before this thread got into the sync block if (this.compiledAst != null) { return true; } SpelCompiler compiler = SpelCompiler.getCompiler(this.configuration.getCompilerClassLoader()); this.compiledAst = compiler.compile(this.ast); if (this.compiledAst == null) { this.failedAttempts++; } } } return (this.compiledAst != null); }
private void assertCanCompile(Expression expression) { assertTrue(SpelCompiler.compile(expression)); }
private Class<? extends CompiledExpression> createExpressionClass(SpelNodeImpl expressionToCompile) { String className = "spel/Ex" + getNextSuffix(); ClassWriter cw = new ExpressionClassWriter(); cw.visit(V1_5, ACC_PUBLIC, className, null, "org/springframework/expression/spel/CompiledExpression", null); return loadClass(className.replaceAll("/", "."), data);
/** * Factory method for compiler instances. The returned SpelCompiler will * attach a class loader as the child of the given class loader and this * child will be used to load compiled expressions. * @param classLoader the ClassLoader to use as the basis for compilation * @return a corresponding SpelCompiler instance */ public static SpelCompiler getCompiler(@Nullable ClassLoader classLoader) { ClassLoader clToUse = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader()); synchronized (compilers) { SpelCompiler compiler = compilers.get(clToUse); if (compiler == null) { compiler = new SpelCompiler(clToUse); compilers.put(clToUse, compiler); } return compiler; } }
/** * Attempt compilation of the supplied expression. A check is made to see * if it is compilable before compilation proceeds. The check involves * visiting all the nodes in the expression Ast and ensuring enough state * is known about them that bytecode can be generated for them. * @param expression the expression to compile * @return an instance of the class implementing the compiled expression, * or {@code null} if compilation is not possible */ @Nullable public CompiledExpression compile(SpelNodeImpl expression) { if (expression.isCompilable()) { if (logger.isDebugEnabled()) { logger.debug("SpEL: compiling " + expression.toStringAST()); } Class<? extends CompiledExpression> clazz = createExpressionClass(expression); if (clazz != null) { try { return ReflectionUtils.accessibleConstructor(clazz).newInstance(); } catch (Throwable ex) { throw new IllegalStateException("Failed to instantiate CompiledExpression", ex); } } } if (logger.isDebugEnabled()) { logger.debug("SpEL: unable to compile " + expression.toStringAST()); } return null; }
/** * Perform expression compilation. This will only succeed once exit descriptors for all nodes have * been determined. If the compilation fails and has failed more than 100 times the expression is * no longer considered suitable for compilation. */ public boolean compileExpression() { if (this.failedAttempts > FAILED_ATTEMPTS_THRESHOLD) { // Don't try again return false; } if (this.compiledAst == null) { synchronized (this.expression) { // Possibly compiled by another thread before this thread got into the sync block if (this.compiledAst != null) { return true; } SpelCompiler compiler = SpelCompiler.getCompiler(this.configuration.getCompilerClassLoader()); this.compiledAst = compiler.compile(this.ast); if (this.compiledAst == null) { this.failedAttempts++; } } } return (this.compiledAst != null); }
@Test public void booleanLiteral() throws Exception { expression = parser.parseExpression("true"); boolean resultI = expression.getValue(1, Boolean.TYPE); assertEquals(true, resultI); assertTrue(SpelCompiler.compile(expression)); boolean resultC = expression.getValue(1, Boolean.TYPE); assertEquals(true, resultC); expression = parser.parseExpression("false"); resultI = expression.getValue(1, Boolean.TYPE); assertEquals(false, resultI); assertTrue(SpelCompiler.compile(expression)); resultC = expression.getValue(1, Boolean.TYPE); assertEquals(false, resultC); }
/** * Factory method for compiler instances. The returned SpelCompiler will * attach a class loader as the child of the given class loader and this * child will be used to load compiled expressions. * @param classLoader the ClassLoader to use as the basis for compilation * @return a corresponding SpelCompiler instance */ public static SpelCompiler getCompiler(@Nullable ClassLoader classLoader) { ClassLoader clToUse = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader()); synchronized (compilers) { SpelCompiler compiler = compilers.get(clToUse); if (compiler == null) { compiler = new SpelCompiler(clToUse); compilers.put(clToUse, compiler); } return compiler; } }
/** * Attempt compilation of the supplied expression. A check is made to see * if it is compilable before compilation proceeds. The check involves * visiting all the nodes in the expression Ast and ensuring enough state * is known about them that bytecode can be generated for them. * @param expression the expression to compile * @return an instance of the class implementing the compiled expression, * or {@code null} if compilation is not possible */ @Nullable public CompiledExpression compile(SpelNodeImpl expression) { if (expression.isCompilable()) { if (logger.isDebugEnabled()) { logger.debug("SpEL: compiling " + expression.toStringAST()); } Class<? extends CompiledExpression> clazz = createExpressionClass(expression); if (clazz != null) { try { return ReflectionUtils.accessibleConstructor(clazz).newInstance(); } catch (Throwable ex) { throw new IllegalStateException("Failed to instantiate CompiledExpression", ex); } } } if (logger.isDebugEnabled()) { logger.debug("SpEL: unable to compile " + expression.toStringAST()); } return null; }
Expression expression = parser.parseExpression("false and false"); boolean resultI = expression.getValue(1, Boolean.TYPE); SpelCompiler.compile(expression); boolean resultC = expression.getValue(1, Boolean.TYPE); assertEquals(false, resultI); SpelCompiler.compile(expression); resultC = expression.getValue(1, Boolean.TYPE); assertEquals(false, resultI); SpelCompiler.compile(expression); resultC = expression.getValue(1, Boolean.TYPE); assertEquals(false, resultI); SpelCompiler.compile(expression); resultC = expression.getValue(1, Boolean.TYPE); assertEquals(true, resultI);
@Test public void mapAccessorCompilable() { Map<String, Object> testMap = getSimpleTestMap(); StandardEvaluationContext sec = new StandardEvaluationContext(); sec.addPropertyAccessor(new MapAccessor()); SpelExpressionParser sep = new SpelExpressionParser(); // basic Expression ex = sep.parseExpression("foo"); assertEquals("bar",ex.getValue(sec,testMap)); assertTrue(SpelCompiler.compile(ex)); assertEquals("bar",ex.getValue(sec,testMap)); // compound expression ex = sep.parseExpression("foo.toUpperCase()"); assertEquals("BAR",ex.getValue(sec,testMap)); assertTrue(SpelCompiler.compile(ex)); assertEquals("BAR",ex.getValue(sec,testMap)); // nested map Map<String,Map<String,Object>> nestedMap = getNestedTestMap(); ex = sep.parseExpression("aaa.foo.toUpperCase()"); assertEquals("BAR",ex.getValue(sec,nestedMap)); assertTrue(SpelCompiler.compile(ex)); assertEquals("BAR",ex.getValue(sec,nestedMap)); // avoiding inserting checkcast because first part of expression returns a Map ex = sep.parseExpression("getMap().foo"); MapGetter mapGetter = new MapGetter(); assertEquals("bar",ex.getValue(sec,mapGetter)); assertTrue(SpelCompiler.compile(ex)); assertEquals("bar",ex.getValue(sec,mapGetter)); }
Expression expression = parser.parseExpression("false or false"); boolean resultI = expression.getValue(1, Boolean.TYPE); SpelCompiler.compile(expression); boolean resultC = expression.getValue(1, Boolean.TYPE); assertEquals(false, resultI);