NIFI-8666: Allow users to escape parameter names in Expression Language using quotes. (#5133)
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 d431a02a..de6f184 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
@@ -143,8 +143,8 @@
referenceOrFunction : DOLLAR LBRACE attributeRefOrFunctionCall (COLON functionCall)* RBRACE ->
^(EXPRESSION attributeRefOrFunctionCall functionCall*);
-parameterReference : PARAMETER_REFERENCE_START ATTRIBUTE_NAME RBRACE ->
- ^(PARAMETER_REFERENCE ATTRIBUTE_NAME);
+parameterReference : PARAMETER_REFERENCE_START singleAttrRef RBRACE ->
+ ^(PARAMETER_REFERENCE singleAttrRef);
expression : referenceOrFunction;
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 986f8f6..7e1a71e 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
@@ -345,6 +345,20 @@
}
@Test
+ public void testParameterReferenceWithSpace() {
+ final Map<String, String> attributes = Collections.emptyMap();
+ final Map<String, String> stateValues = Collections.emptyMap();
+ final Map<String, String> parameters = new HashMap<>();
+ parameters.put("test param", "unit");
+
+ final Query query = Query.compile("${'#{test param}'}");
+ verifyEquals("${#{'test param'}}", attributes, stateValues, parameters,"unit");
+ verifyEquals("${#{'test param'}:append(' - '):append(#{'test param'})}", attributes, stateValues, parameters,"unit - unit");
+
+ verifyEquals("${#{\"test param\"}}", attributes, stateValues, parameters,"unit");
+ }
+
+ @Test
public void testJsonPath() throws IOException {
Map<String,String> attributes = verifyJsonPathExpressions(
ADDRESS_BOOK_JSON_PATH_EMPTY,
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/parameter/StandardParameterContext.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/parameter/StandardParameterContext.java
index 763e0fd..1bd149f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/parameter/StandardParameterContext.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/parameter/StandardParameterContext.java
@@ -221,12 +221,32 @@
public Optional<Parameter> getParameter(final ParameterDescriptor parameterDescriptor) {
readLock.lock();
try {
- return Optional.ofNullable(parameters.get(parameterDescriptor));
+ // When Expression Language is used, the Parameter may require being escaped.
+ // This is the case, for instance, if a Parameter name has a space in it.
+ // Because of this, we may have a case where we attempt to get a Parameter by name
+ // and that Parameter name is enclosed within single tick marks, as a way of escaping
+ // the name via the Expression Language. In this case, we want to strip out those
+ // escaping tick marks and use just the raw name for looking up the Parameter.
+ final ParameterDescriptor unescaped = unescape(parameterDescriptor);
+ return Optional.ofNullable(parameters.get(unescaped));
} finally {
readLock.unlock();
}
}
+ private ParameterDescriptor unescape(final ParameterDescriptor descriptor) {
+ final String parameterName = descriptor.getName().trim();
+ if ((parameterName.startsWith("'") && parameterName.endsWith("'")) || (parameterName.startsWith("\"") && parameterName.endsWith("\""))) {
+ final String stripped = parameterName.substring(1, parameterName.length() - 1);
+ return new ParameterDescriptor.Builder()
+ .from(descriptor)
+ .name(stripped)
+ .build();
+ }
+
+ return descriptor;
+ }
+
@Override
public Map<ParameterDescriptor, Parameter> getParameters() {
readLock.lock();