From 8f74241a1067b79beb31cf96b9c6fe4f1dff62ad Mon Sep 17 00:00:00 2001 From: devin fisher Date: Thu, 28 Jul 2016 05:17:39 +0200 Subject: [PATCH] added functions for escaping text to the expression language Signed-off-by: Matt Burgess --- .../language/antlr/AttributeExpressionLexer.g | 9 +++ .../antlr/AttributeExpressionParser.g | 2 +- .../attribute/expression/language/Query.java | 49 ++++++++++++- .../CharSequenceTranslatorEvaluator.java | 73 +++++++++++++++++++ .../functions/EscapeJsonEvaluator.java | 47 ------------ .../expression/language/TestQuery.java | 2 +- 6 files changed, 131 insertions(+), 51 deletions(-) create mode 100644 nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/CharSequenceTranslatorEvaluator.java delete mode 100644 nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/EscapeJsonEvaluator.java diff --git a/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionLexer.g b/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionLexer.g index 1c1171c9d0..f91e6ab281 100644 --- a/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionLexer.g +++ b/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionLexer.g @@ -118,6 +118,15 @@ NOT : 'not'; COUNT : 'count'; RANDOM : 'random'; ESCAPE_JSON : 'escapeJson'; +ESCAPE_XML : 'escapeXml'; +ESCAPE_CSV : 'escapeCsv'; +ESCAPE_HTML3 : 'escapeHtml3'; +ESCAPE_HTML4 : 'escapeHtml4'; +UNESCAPE_JSON : 'unescapeJson'; +UNESCAPE_XML : 'unescapeXml'; +UNESCAPE_CSV : 'unescapeCsv'; +UNESCAPE_HTML3 : 'unescapeHtml3'; +UNESCAPE_HTML4 : 'unescapeHtml4'; // 1 arg functions SUBSTRING_AFTER : 'substringAfter'; diff --git a/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionParser.g b/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionParser.g index 5b2040342f..3f77190c8a 100644 --- a/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionParser.g +++ b/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionParser.g @@ -73,7 +73,7 @@ tokens { } // functions that return Strings -zeroArgString : (TO_UPPER | TO_LOWER | TRIM | TO_STRING | URL_ENCODE | URL_DECODE | ESCAPE_JSON) LPAREN! RPAREN!; +zeroArgString : (TO_UPPER | TO_LOWER | TRIM | TO_STRING | URL_ENCODE | URL_DECODE | ESCAPE_JSON | ESCAPE_XML | ESCAPE_CSV | ESCAPE_HTML3 | ESCAPE_HTML4 | UNESCAPE_JSON | UNESCAPE_XML | UNESCAPE_CSV | UNESCAPE_HTML3 | UNESCAPE_HTML4 ) LPAREN! RPAREN!; oneArgString : ((SUBSTRING_BEFORE | SUBSTRING_BEFORE_LAST | SUBSTRING_AFTER | SUBSTRING_AFTER_LAST | REPLACE_NULL | REPLACE_EMPTY | PREPEND | APPEND | FORMAT | STARTS_WITH | ENDS_WITH | CONTAINS | JOIN | JSON_PATH) LPAREN! anyArg RPAREN!) | (TO_RADIX LPAREN! anyArg (COMMA! anyArg)? RPAREN!); diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/Query.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/Query.java index 0a703cd3ef..7d04f6e5ce 100644 --- a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/Query.java +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/Query.java @@ -44,6 +44,7 @@ import org.apache.nifi.attribute.expression.language.evaluation.functions.Divide import org.apache.nifi.attribute.expression.language.evaluation.functions.EndsWithEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.EqualsEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.EqualsIgnoreCaseEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.functions.CharSequenceTranslatorEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.FindEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.FormatEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.GetDelimitedFieldEvaluator; @@ -93,7 +94,6 @@ import org.apache.nifi.attribute.expression.language.evaluation.functions.ToUppe import org.apache.nifi.attribute.expression.language.evaluation.functions.TrimEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.UrlDecodeEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.UrlEncodeEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.EscapeJsonEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.UuidEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.literals.BooleanLiteralEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.literals.NumberLiteralEvaluator; @@ -193,6 +193,15 @@ import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpre import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.URL_DECODE; import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.URL_ENCODE; import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ESCAPE_JSON; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ESCAPE_CSV; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ESCAPE_HTML3; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ESCAPE_HTML4; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ESCAPE_XML; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.UNESCAPE_JSON; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.UNESCAPE_CSV; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.UNESCAPE_HTML3; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.UNESCAPE_HTML4; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.UNESCAPE_XML; import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.UUID; import org.apache.nifi.attribute.expression.language.evaluation.selection.MappingEvaluator; @@ -924,9 +933,45 @@ public class Query { verifyArgCount(argEvaluators, 0, "urlDecode"); return addToken(new UrlDecodeEvaluator(toStringEvaluator(subjectEvaluator)), "urlDecode"); } + case ESCAPE_CSV: { + verifyArgCount(argEvaluators, 0, "escapeCsv"); + return addToken(CharSequenceTranslatorEvaluator.csvEscapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); + } + case ESCAPE_HTML3: { + verifyArgCount(argEvaluators, 0, "escapeHtml3"); + return addToken(CharSequenceTranslatorEvaluator.html3EscapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); + } + case ESCAPE_HTML4: { + verifyArgCount(argEvaluators, 0, "escapeHtml4"); + return addToken(CharSequenceTranslatorEvaluator.html4EscapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); + } case ESCAPE_JSON: { verifyArgCount(argEvaluators, 0, "escapeJson"); - return addToken(new EscapeJsonEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); + return addToken(CharSequenceTranslatorEvaluator.jsonEscapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); + } + case ESCAPE_XML: { + verifyArgCount(argEvaluators, 0, "escapeXml"); + return addToken(CharSequenceTranslatorEvaluator.xmlEscapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); + } + case UNESCAPE_CSV: { + verifyArgCount(argEvaluators, 0, "unescapeCsv"); + return addToken(CharSequenceTranslatorEvaluator.csvUnescapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); + } + case UNESCAPE_HTML3: { + verifyArgCount(argEvaluators, 0, "unescapeHtml3"); + return addToken(CharSequenceTranslatorEvaluator.html3UnescapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); + } + case UNESCAPE_HTML4: { + verifyArgCount(argEvaluators, 0, "unescapeHtml4"); + return addToken(CharSequenceTranslatorEvaluator.html4UnescapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); + } + case UNESCAPE_JSON: { + verifyArgCount(argEvaluators, 0, "unescapeJson"); + return addToken(CharSequenceTranslatorEvaluator.jsonUnescapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); + } + case UNESCAPE_XML: { + verifyArgCount(argEvaluators, 0, "unescapeXml"); + return addToken(CharSequenceTranslatorEvaluator.xmlUnescapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); } case SUBSTRING_BEFORE: { verifyArgCount(argEvaluators, 1, "substringBefore"); diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/CharSequenceTranslatorEvaluator.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/CharSequenceTranslatorEvaluator.java new file mode 100644 index 0000000000..11a779e276 --- /dev/null +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/CharSequenceTranslatorEvaluator.java @@ -0,0 +1,73 @@ +package org.apache.nifi.attribute.expression.language.evaluation.functions; + +import java.util.Map; + +import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.commons.lang3.text.translate.CharSequenceTranslator; +import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; +import org.apache.nifi.attribute.expression.language.evaluation.QueryResult; +import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.StringQueryResult; + +public class CharSequenceTranslatorEvaluator extends StringEvaluator +{ + public static StringEvaluator jsonEscapeEvaluator(final Evaluator subject){ + return new CharSequenceTranslatorEvaluator(subject, StringEscapeUtils.ESCAPE_JSON); + } + + public static StringEvaluator xmlEscapeEvaluator(final Evaluator subject){ + return new CharSequenceTranslatorEvaluator(subject, StringEscapeUtils.ESCAPE_XML10); + } + + public static StringEvaluator csvEscapeEvaluator(final Evaluator subject){ + return new CharSequenceTranslatorEvaluator(subject, StringEscapeUtils.ESCAPE_CSV); + } + + public static StringEvaluator html3EscapeEvaluator(final Evaluator subject){ + return new CharSequenceTranslatorEvaluator(subject, StringEscapeUtils.ESCAPE_HTML3); + } + + public static StringEvaluator html4EscapeEvaluator(final Evaluator subject){ + return new CharSequenceTranslatorEvaluator(subject, StringEscapeUtils.ESCAPE_HTML4); + } + + public static StringEvaluator jsonUnescapeEvaluator(final Evaluator subject){ + return new CharSequenceTranslatorEvaluator(subject, StringEscapeUtils.UNESCAPE_JSON); + } + + public static StringEvaluator xmlUnescapeEvaluator(final Evaluator subject){ + return new CharSequenceTranslatorEvaluator(subject, StringEscapeUtils.UNESCAPE_XML); + } + + public static StringEvaluator csvUnescapeEvaluator(final Evaluator subject){ + return new CharSequenceTranslatorEvaluator(subject, StringEscapeUtils.UNESCAPE_CSV); + } + + public static StringEvaluator html3UnescapeEvaluator(final Evaluator subject){ + return new CharSequenceTranslatorEvaluator(subject, StringEscapeUtils.UNESCAPE_HTML3); + } + + public static StringEvaluator html4UnescapeEvaluator(final Evaluator subject){ + return new CharSequenceTranslatorEvaluator(subject, StringEscapeUtils.UNESCAPE_HTML4); + } + + + private final Evaluator subject; + private final CharSequenceTranslator method; + + public CharSequenceTranslatorEvaluator(final Evaluator subject, CharSequenceTranslator method) { + this.subject = subject; + this.method = method; + } + + @Override + public QueryResult evaluate(final Map attributes) { + final String subjectValue = subject.evaluate(attributes).getValue(); + return new StringQueryResult(subjectValue == null ? "" : method.translate(subjectValue)); + } + + @Override + public Evaluator getSubjectEvaluator() { + return subject; + } +} \ No newline at end of file diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/EscapeJsonEvaluator.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/EscapeJsonEvaluator.java deleted file mode 100644 index d8ad1b48cd..0000000000 --- a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/EscapeJsonEvaluator.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.nifi.attribute.expression.language.evaluation.functions; - -import java.util.Map; - -import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; -import org.apache.nifi.attribute.expression.language.evaluation.QueryResult; -import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.StringQueryResult; - -import org.apache.commons.lang3.StringEscapeUtils; - -public class EscapeJsonEvaluator extends StringEvaluator { - - private final Evaluator subject; - - public EscapeJsonEvaluator(final Evaluator subject) { - this.subject = subject; - } - - @Override - public QueryResult evaluate(final Map attributes) { - final String subjectValue = subject.evaluate(attributes).getValue(); - return new StringQueryResult(subjectValue == null ? "" : StringEscapeUtils.escapeJson(subjectValue)); - } - - @Override - public Evaluator getSubjectEvaluator() { - return subject; - } - -} diff --git a/nifi-commons/nifi-expression-language/src/test/java/org/apache/nifi/attribute/expression/language/TestQuery.java b/nifi-commons/nifi-expression-language/src/test/java/org/apache/nifi/attribute/expression/language/TestQuery.java index 2183cb14dd..dd81b3bede 100644 --- a/nifi-commons/nifi-expression-language/src/test/java/org/apache/nifi/attribute/expression/language/TestQuery.java +++ b/nifi-commons/nifi-expression-language/src/test/java/org/apache/nifi/attribute/expression/language/TestQuery.java @@ -1315,7 +1315,7 @@ public class TestQuery { } @Test - public void testEscapeJson() { + public void testEscapeFunctions() { final Map attributes = new HashMap<>(); attributes.put("string", "making air \"QUOTES\".");