|
| 1 | +package org.springframework.data.relational.core.mapping; |
| 2 | + |
| 3 | +import org.springframework.beans.factory.annotation.Autowired; |
| 4 | +import org.springframework.expression.EvaluationException; |
| 5 | +import org.springframework.expression.Expression; |
| 6 | +import org.springframework.expression.common.TemplateParserContext; |
| 7 | +import org.springframework.expression.spel.standard.SpelExpressionParser; |
| 8 | +import org.springframework.expression.spel.support.StandardEvaluationContext; |
| 9 | +import org.springframework.util.Assert; |
| 10 | + |
| 11 | +/** |
| 12 | + * Provide support for processing SpEL expressions in @Table and @Column annotations, |
| 13 | + * or anywhere we want to use SpEL expressions and sanitize the result of the evaluated |
| 14 | + * SpEL expression. |
| 15 | + * |
| 16 | + * The default sanitization allows for digits, alphabetic characters and _ characters |
| 17 | + * and strips out any other characters. |
| 18 | + * |
| 19 | + * Custom sanitization (if desired) can be achieved by creating a class that implements |
| 20 | + * the {@link SpelExpressionResultSanitizer} interface and then invoking the |
| 21 | + * {@link #setSpelExpressionResultSanitizer(SpelExpressionResultSanitizer)} method. |
| 22 | + * |
| 23 | + * @author Kurt Niemi |
| 24 | + * @see SpelExpressionResultSanitizer |
| 25 | + * @since 3.1 |
| 26 | + */ |
| 27 | +public class SpelExpressionProcessor { |
| 28 | + private SpelExpressionResultSanitizer spelExpressionResultSanitizer; |
| 29 | + private StandardEvaluationContext evalContext = new StandardEvaluationContext(); |
| 30 | + private SpelExpressionParser parser = new SpelExpressionParser(); |
| 31 | + private TemplateParserContext templateParserContext = new TemplateParserContext(); |
| 32 | + |
| 33 | + public String applySpelExpression(String expression) throws EvaluationException { |
| 34 | + |
| 35 | + Assert.notNull(expression, "Expression must not be null."); |
| 36 | + |
| 37 | + // Only apply logic if we have the prefixes/suffixes required for a SpEL expression as firstly |
| 38 | + // there is nothing to evaluate (i.e. whatever literal passed in is returned as-is) and more |
| 39 | + // importantly we do not want to perform any sanitization logic. |
| 40 | + if (!isSpellExpression(expression)) { |
| 41 | + return expression; |
| 42 | + } |
| 43 | + |
| 44 | + Expression expr = parser.parseExpression(expression, templateParserContext); |
| 45 | + String result = expr.getValue(evalContext, String.class); |
| 46 | + |
| 47 | + // Normally an exception is thrown by the Spel parser on invalid syntax/errors but this will provide |
| 48 | + // a consistent experience for any issues with Spel parsing. |
| 49 | + if (result == null) { |
| 50 | + throw new EvaluationException("Spel Parsing of expression \"" + expression + "\" failed."); |
| 51 | + } |
| 52 | + |
| 53 | + String sanitizedResult = getSpelExpressionResultSanitizer().sanitize(result); |
| 54 | + |
| 55 | + return sanitizedResult; |
| 56 | + } |
| 57 | + |
| 58 | + protected boolean isSpellExpression(String expression) { |
| 59 | + |
| 60 | + String trimmedExpression = expression.trim(); |
| 61 | + if (trimmedExpression.startsWith(templateParserContext.getExpressionPrefix()) && |
| 62 | + trimmedExpression.endsWith(templateParserContext.getExpressionSuffix())) { |
| 63 | + return true; |
| 64 | + } |
| 65 | + |
| 66 | + return false; |
| 67 | + } |
| 68 | + public SpelExpressionResultSanitizer getSpelExpressionResultSanitizer() { |
| 69 | + |
| 70 | + if (this.spelExpressionResultSanitizer == null) { |
| 71 | + this.spelExpressionResultSanitizer = new SpelExpressionResultSanitizer() { |
| 72 | + @Override |
| 73 | + public String sanitize(String result) { |
| 74 | + |
| 75 | + String cleansedResult = result.replaceAll("[^\\w]", ""); |
| 76 | + return cleansedResult; |
| 77 | + } |
| 78 | + }; |
| 79 | + } |
| 80 | + return this.spelExpressionResultSanitizer; |
| 81 | + } |
| 82 | + |
| 83 | + public void setSpelExpressionResultSanitizer(SpelExpressionResultSanitizer spelExpressionResultSanitizer) { |
| 84 | + this.spelExpressionResultSanitizer = spelExpressionResultSanitizer; |
| 85 | + } |
| 86 | + |
| 87 | +} |
0 commit comments