diff --git a/nifi-api/src/main/java/org/apache/nifi/components/ValidationContext.java b/nifi-api/src/main/java/org/apache/nifi/components/ValidationContext.java
index 95a8c09649..acaffd7c03 100644
--- a/nifi-api/src/main/java/org/apache/nifi/components/ValidationContext.java
+++ b/nifi-api/src/main/java/org/apache/nifi/components/ValidationContext.java
@@ -106,4 +106,12 @@ public interface ValidationContext extends PropertyContext {
* @return true
if a Parameter with the given name is defined in the currently selected Parameter Context
*/
boolean isParameterDefined(String parameterName);
+
+ /**
+ * Returns true
if a Parameter with the given name is defined and has a non-null value, false
if either the Parameter
+ * is not defined or the Parameter is defined but has a value of null
.
+ * @param parameterName the name of the parameter
+ * @return true
if the Parameter is defined and has a non-null value, false otherwise
+ */
+ boolean isParameterSet(String parameterName);
}
diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationValidationContext.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationValidationContext.java
index 8f7eda0e31..0075df20e4 100644
--- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationValidationContext.java
+++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationValidationContext.java
@@ -133,4 +133,9 @@ public class NotificationValidationContext implements ValidationContext {
public boolean isParameterDefined(final String parameterName) {
return false;
}
+
+ @Override
+ public boolean isParameterSet(final String parameterName) {
+ return false;
+ }
}
diff --git a/nifi-mock/src/main/java/org/apache/nifi/util/MockValidationContext.java b/nifi-mock/src/main/java/org/apache/nifi/util/MockValidationContext.java
index 87389be797..e913204c57 100644
--- a/nifi-mock/src/main/java/org/apache/nifi/util/MockValidationContext.java
+++ b/nifi-mock/src/main/java/org/apache/nifi/util/MockValidationContext.java
@@ -181,8 +181,12 @@ public class MockValidationContext extends MockControllerServiceLookup implement
@Override
public boolean isParameterDefined(final String parameterName) {
- // TODO: Implement
- return false;
+ return true;
+ }
+
+ @Override
+ public boolean isParameterSet(final String parameterName) {
+ return true;
}
}
diff --git a/nifi-nar-bundles/nifi-extension-utils/nifi-database-utils/src/test/java/org/apache/nifi/util/db/TestJdbcCommon.java b/nifi-nar-bundles/nifi-extension-utils/nifi-database-utils/src/test/java/org/apache/nifi/util/db/TestJdbcCommon.java
index b58289ba13..bbf2bdb4a9 100644
--- a/nifi-nar-bundles/nifi-extension-utils/nifi-database-utils/src/test/java/org/apache/nifi/util/db/TestJdbcCommon.java
+++ b/nifi-nar-bundles/nifi-extension-utils/nifi-database-utils/src/test/java/org/apache/nifi/util/db/TestJdbcCommon.java
@@ -16,13 +16,26 @@
*/
package org.apache.nifi.util.db;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import org.apache.avro.Conversions;
+import org.apache.avro.LogicalType;
+import org.apache.avro.LogicalTypes;
+import org.apache.avro.Schema;
+import org.apache.avro.file.DataFileStream;
+import org.apache.avro.generic.GenericData;
+import org.apache.avro.generic.GenericDatumReader;
+import org.apache.avro.generic.GenericRecord;
+import org.apache.avro.io.DatumReader;
+import org.apache.avro.util.Utf8;
+import org.apache.commons.io.input.ReaderInputStream;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.mockito.Mockito;
+import org.mockito.stubbing.Answer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -63,26 +76,13 @@ import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.stream.IntStream;
-import org.apache.avro.Conversions;
-import org.apache.avro.LogicalType;
-import org.apache.avro.LogicalTypes;
-import org.apache.avro.Schema;
-import org.apache.avro.file.DataFileStream;
-import org.apache.avro.generic.GenericData;
-import org.apache.avro.generic.GenericDatumReader;
-import org.apache.avro.generic.GenericRecord;
-import org.apache.avro.io.DatumReader;
-import org.apache.avro.util.Utf8;
-import org.apache.commons.io.input.ReaderInputStream;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.mockito.Mockito;
-import org.mockito.stubbing.Answer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class TestJdbcCommon {
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractComponentNode.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractComponentNode.java
index f5752a35cf..48e359f34e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractComponentNode.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractComponentNode.java
@@ -659,6 +659,14 @@ public abstract class AbstractComponentNode implements ComponentNode {
.explanation("Property references Parameter '" + paramName + "' but the currently selected Parameter Context does not have a Parameter with that name")
.build());
}
+
+ if (!validationContext.isParameterSet(paramName)) {
+ results.add(new ValidationResult.Builder()
+ .subject(propertyDescriptor.getDisplayName())
+ .valid(false)
+ .explanation("Property references Parameter '" + paramName + "' but the currently selected Parameter Context does not have a value set for that Parameter")
+ .build());
+ }
}
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/flow/FlowManager.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/flow/FlowManager.java
index 4d108e9c8a..d0726981bc 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/flow/FlowManager.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/flow/FlowManager.java
@@ -36,6 +36,7 @@ import org.apache.nifi.web.api.dto.FlowSnippetDTO;
import java.net.URL;
import java.util.Collection;
+import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -322,7 +323,7 @@ public interface FlowManager {
void removeRootControllerService(final ControllerServiceNode service);
- ParameterContext createParameterContext(String id, String name, Set parameters);
+ ParameterContext createParameterContext(String id, String name, Map parameters);
ParameterContextManager getParameterContextManager();
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/parameter/ParameterContext.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/parameter/ParameterContext.java
index dae4d9e22d..fcbd270e8e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/parameter/ParameterContext.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/parameter/ParameterContext.java
@@ -20,7 +20,6 @@ import org.apache.nifi.authorization.resource.Authorizable;
import java.util.Map;
import java.util.Optional;
-import java.util.Set;
public interface ParameterContext extends ParameterLookup, Authorizable {
@@ -52,19 +51,22 @@ public interface ParameterContext extends ParameterLookup, Authorizable {
void setDescription(String description);
/**
- * Updates the Parameters within this context to match the given set of Parameters.
- * @param updatedParameters the updated set of parameters
+ * Updates the Parameters within this context to match the given set of Parameters. If the Parameter Context contains any parameters that are not in
+ * the given set of updated Parameters, those parameters are unaffected. However, if the Map contains any key with a null
value, the
+ * parameter whose name is given by the key will be removed
+ *
+ * @param updatedParameters the updated set of parameters, keyed by Parameter name
* @throws IllegalStateException if any parameter is modified or removed and that parameter is being referenced by a running Processor or an enabled Controller Service, or if
* an update would result in changing the sensitivity of any parameter
*/
- void setParameters(Set updatedParameters);
+ void setParameters(Map updatedParameters);
/**
* Ensures that it is legal to update the Parameters for this Parameter Context to match the given set of Parameters
- * @param parameters the Set of Parameters that are to become the new Parameters for this Parameter Context
+ * @param parameters the updated set of parameters, keyed by Parameter name
* @throws IllegalStateException if setting the given set of Parameters is not legal
*/
- void verifyCanSetParameters(Set parameters);
+ void verifyCanSetParameters(Map parameters);
/**
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSynchronizer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSynchronizer.java
index a2c8d4cfe7..6d970db9cf 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSynchronizer.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSynchronizer.java
@@ -131,6 +131,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.zip.GZIPInputStream;
@@ -547,10 +548,10 @@ public class StandardFlowSynchronizer implements FlowSynchronizer {
}
private ParameterContext createParameterContext(final ParameterContextDTO dto, final FlowManager flowManager) {
- final Set parameters = dto.getParameters().stream()
+ final Map parameters = dto.getParameters().stream()
.map(ParameterEntity::getParameter)
.map(this::createParameter)
- .collect(Collectors.toSet());
+ .collect(Collectors.toMap(param -> param.getDescriptor().getName(), Function.identity()));
final ParameterContext context = flowManager.createParameterContext(dto.getId(), dto.getName(), parameters);
context.setDescription(dto.getDescription());
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/flow/StandardFlowManager.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/flow/StandardFlowManager.java
index 1ec226e517..f2f1bc71ba 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/flow/StandardFlowManager.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/flow/StandardFlowManager.java
@@ -736,7 +736,7 @@ public class StandardFlowManager implements FlowManager {
}
@Override
- public ParameterContext createParameterContext(final String id, final String name, final Set parameters) {
+ public ParameterContext createParameterContext(final String id, final String name, final Map parameters) {
final boolean namingConflict = parameterContextManager.getParameterContexts().stream()
.anyMatch(paramContext -> paramContext.getName().equals(name));
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/parameter/StandardParameterContext.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/parameter/StandardParameterContext.java
index e5d12a5173..04cfb8ad78 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/parameter/StandardParameterContext.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/parameter/StandardParameterContext.java
@@ -34,7 +34,6 @@ import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
-import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -97,32 +96,26 @@ public class StandardParameterContext implements ParameterContext {
return description;
}
- public void setParameters(final Set updatedParameters) {
+ public void setParameters(final Map updatedParameters) {
writeLock.lock();
try {
this.version++;
-
verifyCanSetParameters(updatedParameters);
boolean changeAffectingComponents = false;
- for (final Parameter parameter : updatedParameters) {
- if (parameter.getValue() == null && parameter.getDescriptor().getDescription() == null) {
- parameters.remove(parameter.getDescriptor());
- changeAffectingComponents = true;
- } else if (parameter.getValue() == null) {
- // Value is null but description is not. Just update the description of the existing Parameter.
- final Parameter existingParameter = parameters.get(parameter.getDescriptor());
- final ParameterDescriptor existingDescriptor = existingParameter.getDescriptor();
- final ParameterDescriptor replacementDescriptor = new ParameterDescriptor.Builder()
- .from(existingDescriptor)
- .description(parameter.getDescriptor().getDescription())
- .build();
+ for (final Map.Entry entry : updatedParameters.entrySet()) {
+ final String parameterName = entry.getKey();
+ final Parameter parameter = entry.getValue();
- final Parameter replacementParameter = new Parameter(replacementDescriptor, existingParameter.getValue());
- parameters.put(parameter.getDescriptor(), replacementParameter);
- } else {
- parameters.put(parameter.getDescriptor(), parameter);
+ if (parameter == null) {
+ final ParameterDescriptor parameterDescriptor = new ParameterDescriptor.Builder().name(parameterName).build();
+ parameters.remove(parameterDescriptor);
changeAffectingComponents = true;
+ } else {
+ final Parameter oldParameter = parameters.put(parameter.getDescriptor(), parameter);
+ if (oldParameter == null || !Objects.equals(oldParameter.getValue(), parameter.getValue())) {
+ changeAffectingComponents = true;
+ }
}
}
@@ -195,25 +188,23 @@ public class StandardParameterContext implements ParameterContext {
}
@Override
- public void verifyCanSetParameters(final Set updatedParameters) {
+ public void verifyCanSetParameters(final Map updatedParameters) {
// Ensure that the updated parameters will not result in changing the sensitivity flag of any parameter.
- for (final Parameter updatedParameter : updatedParameters) {
- validateSensitiveFlag(updatedParameter);
-
- // Parameters' names and sensitivity flags are immutable. However, the description and value are mutable. If both value and description are
- // set to `null`, this is the indication that the Parameter should be removed. If the value is `null` but the Description is supplied, the user
- // is indicating that only the description is to be changed.
- if (updatedParameter.getValue() == null && updatedParameter.getDescriptor().getDescription() == null) {
- validateReferencingComponents(updatedParameter, "remove");
- } else if (updatedParameter.getValue() != null) {
- validateReferencingComponents(updatedParameter, "update");
- } else {
- // Only parameter is changing. No value is set. This means that the Parameter must already exist.
- final Optional existing = getParameter(updatedParameter.getDescriptor());
- if (!existing.isPresent()) {
- throw new IllegalStateException("Cannot add Parameter '" + updatedParameter.getDescriptor().getName() + "' without providing a value");
- }
+ for (final Map.Entry entry : updatedParameters.entrySet()) {
+ final String parameterName = entry.getKey();
+ final Parameter parameter = entry.getValue();
+ if (parameter == null) {
+ // parameter is being deleted.
+ validateReferencingComponents(parameterName, null,"remove");
+ continue;
}
+
+ if (!Objects.equals(parameterName, parameter.getDescriptor().getName())) {
+ throw new IllegalArgumentException("Parameter '" + parameterName + "' was specified with the wrong key in the Map");
+ }
+
+ validateSensitiveFlag(parameter);
+ validateReferencingComponents(parameterName, parameter, "update");
}
}
@@ -236,25 +227,27 @@ public class StandardParameterContext implements ParameterContext {
}
- private void validateReferencingComponents(final Parameter updatedParameter, final String parameterAction) {
- final String paramName = updatedParameter.getDescriptor().getName();
-
- for (final ProcessorNode procNode : parameterReferenceManager.getProcessorsReferencing(this, paramName)) {
+ private void validateReferencingComponents(final String parameterName, final Parameter parameter, final String parameterAction) {
+ for (final ProcessorNode procNode : parameterReferenceManager.getProcessorsReferencing(this, parameterName)) {
if (procNode.isRunning()) {
- throw new IllegalStateException("Cannot " + parameterAction + " parameter '" + paramName + "' because it is referenced by " + procNode + ", which is currently running");
+ throw new IllegalStateException("Cannot " + parameterAction + " parameter '" + parameterName + "' because it is referenced by " + procNode + ", which is currently running");
}
- validateParameterSensitivity(updatedParameter, procNode);
+ if (parameter != null) {
+ validateParameterSensitivity(parameter, procNode);
+ }
}
- for (final ControllerServiceNode serviceNode : parameterReferenceManager.getControllerServicesReferencing(this, paramName)) {
+ for (final ControllerServiceNode serviceNode : parameterReferenceManager.getControllerServicesReferencing(this, parameterName)) {
final ControllerServiceState serviceState = serviceNode.getState();
if (serviceState != ControllerServiceState.DISABLED) {
- throw new IllegalStateException("Cannot " + parameterAction + " parameter '" + paramName + "' because it is referenced by "
+ throw new IllegalStateException("Cannot " + parameterAction + " parameter '" + parameterName + "' because it is referenced by "
+ serviceNode + ", which currently has a state of " + serviceState);
}
- validateParameterSensitivity(updatedParameter, serviceNode);
+ if (parameter != null) {
+ validateParameterSensitivity(parameter, serviceNode);
+ }
}
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/processor/StandardValidationContext.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/processor/StandardValidationContext.java
index b1a44e7f8d..3fc7e06d65 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/processor/StandardValidationContext.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/processor/StandardValidationContext.java
@@ -33,6 +33,7 @@ import org.apache.nifi.controller.service.ControllerServiceProvider;
import org.apache.nifi.controller.service.ControllerServiceState;
import org.apache.nifi.expression.ExpressionLanguageCompiler;
import org.apache.nifi.groups.ProcessGroup;
+import org.apache.nifi.parameter.Parameter;
import org.apache.nifi.parameter.ParameterContext;
import org.apache.nifi.parameter.ParameterReference;
import org.apache.nifi.registry.VariableRegistry;
@@ -43,6 +44,7 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
@@ -216,6 +218,21 @@ public class StandardValidationContext implements ValidationContext {
return parameterContext.getParameter(parameterName).isPresent();
}
+ @Override
+ public boolean isParameterSet(final String parameterName) {
+ if (parameterContext == null) {
+ return false;
+ }
+
+ final Optional parameterOption = parameterContext.getParameter(parameterName);
+ if (!parameterOption.isPresent()) {
+ return false;
+ }
+
+ final String value = parameterOption.get().getValue();
+ return value != null;
+ }
+
@Override
public String toString() {
return "StandardValidationContext[componentId=" + componentId + ", properties=" + properties + "]";
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/TestStandardProcessorNode.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/TestStandardProcessorNode.java
index 08dc4f3f0c..d1fb511587 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/TestStandardProcessorNode.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/TestStandardProcessorNode.java
@@ -550,6 +550,11 @@ public class TestStandardProcessorNode {
public boolean isParameterDefined(final String parameterName) {
return false;
}
+
+ @Override
+ public boolean isParameterSet(final String parameterName) {
+ return false;
+ }
};
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/auth/AlwaysAuthenticate.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/auth/AlwaysAuthenticate.java
new file mode 100644
index 0000000000..9640be5e78
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/auth/AlwaysAuthenticate.java
@@ -0,0 +1,46 @@
+/*
+ * 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.integration.auth;
+
+import org.apache.nifi.authentication.AuthenticationResponse;
+import org.apache.nifi.authentication.LoginCredentials;
+import org.apache.nifi.authentication.LoginIdentityProvider;
+import org.apache.nifi.authentication.LoginIdentityProviderConfigurationContext;
+import org.apache.nifi.authentication.LoginIdentityProviderInitializationContext;
+import org.apache.nifi.authentication.exception.IdentityAccessException;
+import org.apache.nifi.authentication.exception.InvalidLoginCredentialsException;
+import org.apache.nifi.authentication.exception.ProviderCreationException;
+import org.apache.nifi.authentication.exception.ProviderDestructionException;
+
+public class AlwaysAuthenticate implements LoginIdentityProvider {
+ @Override
+ public AuthenticationResponse authenticate(final LoginCredentials credentials) throws InvalidLoginCredentialsException, IdentityAccessException {
+ return new AuthenticationResponse(credentials.getUsername(), credentials.getUsername(), 1_000_000L, "unit-test-issuer");
+ }
+
+ @Override
+ public void initialize(final LoginIdentityProviderInitializationContext initializationContext) throws ProviderCreationException {
+ }
+
+ @Override
+ public void onConfigured(final LoginIdentityProviderConfigurationContext configurationContext) throws ProviderCreationException {
+ }
+
+ @Override
+ public void preDestruction() throws ProviderDestructionException {
+ }
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/auth/VolatileAccessPolicyProvider.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/auth/VolatileAccessPolicyProvider.java
new file mode 100644
index 0000000000..c010f0569b
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/auth/VolatileAccessPolicyProvider.java
@@ -0,0 +1,118 @@
+/*
+ * 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.integration.auth;
+
+import org.apache.nifi.authorization.AccessPolicy;
+import org.apache.nifi.authorization.AccessPolicyProvider;
+import org.apache.nifi.authorization.AccessPolicyProviderInitializationContext;
+import org.apache.nifi.authorization.AuthorizerConfigurationContext;
+import org.apache.nifi.authorization.RequestAction;
+import org.apache.nifi.authorization.exception.AuthorizationAccessException;
+import org.apache.nifi.authorization.exception.AuthorizerCreationException;
+import org.apache.nifi.authorization.exception.AuthorizerDestructionException;
+
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+public class VolatileAccessPolicyProvider implements AccessPolicyProvider {
+ private final VolatileUserGroupProvider userGroupProvider = new VolatileUserGroupProvider();
+ private Set accessPolicies = new HashSet<>();
+
+ public synchronized void grantAccess(final String user, final String resourceIdentifier, final RequestAction action) {
+ final AccessPolicy existingPolicy = getAccessPolicy(resourceIdentifier, action);
+
+ final AccessPolicy policy;
+ if (existingPolicy == null) {
+ policy = new AccessPolicy.Builder()
+ .addUser(user)
+ .action(action)
+ .identifierGenerateRandom()
+ .resource(resourceIdentifier)
+ .build();
+ } else {
+ policy = new AccessPolicy.Builder()
+ .addUsers(existingPolicy.getUsers())
+ .addUser(user)
+ .action(action)
+ .identifier(existingPolicy.getIdentifier())
+ .resource(resourceIdentifier)
+ .build();
+ }
+
+ accessPolicies.remove(existingPolicy);
+ accessPolicies.add(policy);
+ }
+
+ public synchronized void revokeAccess(final String user, final String resourceIdentifier, final RequestAction action) {
+ final AccessPolicy existingPolicy = getAccessPolicy(resourceIdentifier, action);
+
+ if (existingPolicy == null) {
+ return;
+ }
+
+ final AccessPolicy policy= new AccessPolicy.Builder()
+ .addUsers(existingPolicy.getUsers())
+ .removeUser(user)
+ .action(action)
+ .identifier(existingPolicy.getIdentifier())
+ .resource(resourceIdentifier)
+ .build();
+
+ accessPolicies.remove(existingPolicy);
+ accessPolicies.add(policy);
+ }
+
+ @Override
+ public synchronized Set getAccessPolicies() throws AuthorizationAccessException {
+ return new HashSet<>(accessPolicies);
+ }
+
+ @Override
+ public synchronized AccessPolicy getAccessPolicy(final String identifier) throws AuthorizationAccessException {
+ return accessPolicies.stream()
+ .filter(policy -> policy.getIdentifier().equals(identifier))
+ .findAny()
+ .orElse(null);
+ }
+
+ @Override
+ public synchronized AccessPolicy getAccessPolicy(final String resourceIdentifier, final RequestAction action) throws AuthorizationAccessException {
+ return accessPolicies.stream()
+ .filter(policy -> Objects.equals(policy.getResource(), resourceIdentifier))
+ .filter(policy -> Objects.equals(policy.getAction(), action))
+ .findAny()
+ .orElse(null);
+ }
+
+ @Override
+ public synchronized VolatileUserGroupProvider getUserGroupProvider() {
+ return userGroupProvider;
+ }
+
+ @Override
+ public void initialize(final AccessPolicyProviderInitializationContext initializationContext) throws AuthorizerCreationException {
+ }
+
+ @Override
+ public void onConfigured(final AuthorizerConfigurationContext configurationContext) throws AuthorizerCreationException {
+ }
+
+ @Override
+ public void preDestruction() throws AuthorizerDestructionException {
+ }
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/auth/VolatileUserGroupProvider.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/auth/VolatileUserGroupProvider.java
new file mode 100644
index 0000000000..7e4849bcbe
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/auth/VolatileUserGroupProvider.java
@@ -0,0 +1,111 @@
+/*
+ * 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.integration.auth;
+
+import org.apache.nifi.authorization.AuthorizerConfigurationContext;
+import org.apache.nifi.authorization.Group;
+import org.apache.nifi.authorization.User;
+import org.apache.nifi.authorization.UserAndGroups;
+import org.apache.nifi.authorization.UserGroupProvider;
+import org.apache.nifi.authorization.UserGroupProviderInitializationContext;
+import org.apache.nifi.authorization.exception.AuthorizationAccessException;
+import org.apache.nifi.authorization.exception.AuthorizerCreationException;
+import org.apache.nifi.authorization.exception.AuthorizerDestructionException;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+public class VolatileUserGroupProvider implements UserGroupProvider {
+ private final Map users = new HashMap<>();
+ private final Map groups = new HashMap<>();
+ private final Map> userGroupMapping = new HashMap<>();
+
+ public void addUser(final User user) {
+ this.users.put(user.getIdentifier(), user);
+ }
+
+ public void addGroup(final Group group) {
+ this.groups.put(group.getIdentifier(), group);
+ }
+
+ public void addUserToGroup(final User user, final Group group) {
+ userGroupMapping.computeIfAbsent(user, i -> new HashSet<>()).add(group);
+ }
+
+ @Override
+ public Set getUsers() throws AuthorizationAccessException {
+ return new HashSet<>(users.values());
+ }
+
+ @Override
+ public User getUser(final String identifier) throws AuthorizationAccessException {
+ return users.get(identifier);
+ }
+
+ @Override
+ public User getUserByIdentity(final String identity) throws AuthorizationAccessException {
+ return users.values().stream()
+ .filter(user -> Objects.equals(identity, user.getIdentity()))
+ .findFirst()
+ .orElse(null);
+ }
+
+ @Override
+ public Set getGroups() throws AuthorizationAccessException {
+ return new HashSet<>(groups.values());
+ }
+
+ @Override
+ public Group getGroup(final String identifier) throws AuthorizationAccessException {
+ return groups.get(identifier);
+ }
+
+ @Override
+ public UserAndGroups getUserAndGroups(final String identity) throws AuthorizationAccessException {
+ final User user = getUserByIdentity(identity);
+ final Set groups = userGroupMapping.get(user);
+ final Set groupCopy = groups == null ? Collections.emptySet() : new HashSet<>(groups);
+
+ return new UserAndGroups() {
+ @Override
+ public User getUser() {
+ return user;
+ }
+
+ @Override
+ public Set getGroups() {
+ return groupCopy;
+ }
+ };
+ }
+
+ @Override
+ public void initialize(final UserGroupProviderInitializationContext initializationContext) throws AuthorizerCreationException {
+ }
+
+ @Override
+ public void onConfigured(final AuthorizerConfigurationContext configurationContext) throws AuthorizerCreationException {
+ }
+
+ @Override
+ public void preDestruction() throws AuthorizerDestructionException {
+ }
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/parameters/ParametersIT.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/parameters/ParametersIT.java
index 7d0755da32..4a394ae518 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/parameters/ParametersIT.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/parameters/ParametersIT.java
@@ -58,7 +58,7 @@ public class ParametersIT extends FrameworkIntegrationTest {
final ParameterReferenceManager referenceManager = new StandardParameterReferenceManager(getFlowController().getFlowManager());
final ParameterContext parameterContext = new StandardParameterContext(UUID.randomUUID().toString(), "param-context", referenceManager, null);
- parameterContext.setParameters(Collections.singleton(new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
+ parameterContext.setParameters(Collections.singletonMap("test", new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
getRootGroup().setParameterContext(parameterContext);
updateAttribute.setProperties(Collections.singletonMap("test", "#{test}"));
@@ -83,7 +83,7 @@ public class ParametersIT extends FrameworkIntegrationTest {
final ParameterReferenceManager referenceManager = new StandardParameterReferenceManager(getFlowController().getFlowManager());
final ParameterContext parameterContext = new StandardParameterContext(UUID.randomUUID().toString(), "param-context", referenceManager, null);
- parameterContext.setParameters(Collections.singleton(new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
+ parameterContext.setParameters(Collections.singletonMap("test", new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
getRootGroup().setParameterContext(parameterContext);
updateAttribute.setProperties(Collections.singletonMap("test", "${#{test}:toUpper()}"));
@@ -108,7 +108,7 @@ public class ParametersIT extends FrameworkIntegrationTest {
final ParameterReferenceManager referenceManager = new StandardParameterReferenceManager(getFlowController().getFlowManager());
final ParameterContext parameterContext = new StandardParameterContext(UUID.randomUUID().toString(), "param-context", referenceManager, null);
- parameterContext.setParameters(Collections.singleton(new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
+ parameterContext.setParameters(Collections.singletonMap("test", new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
getRootGroup().setParameterContext(parameterContext);
updateAttribute.setProperties(Collections.singletonMap("test", "${#{test}:toUpper()}"));
@@ -133,7 +133,7 @@ public class ParametersIT extends FrameworkIntegrationTest {
final ParameterReferenceManager referenceManager = new StandardParameterReferenceManager(getFlowController().getFlowManager());
final ParameterContext parameterContext = new StandardParameterContext(UUID.randomUUID().toString(), "param-context", referenceManager, null);
- parameterContext.setParameters(Collections.singleton(new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
+ parameterContext.setParameters(Collections.singletonMap("test", new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
getRootGroup().setParameterContext(parameterContext);
@@ -165,7 +165,7 @@ public class ParametersIT extends FrameworkIntegrationTest {
final ParameterReferenceManager referenceManager = new StandardParameterReferenceManager(getFlowController().getFlowManager());
final ParameterContext parameterContext = new StandardParameterContext(UUID.randomUUID().toString(), "param-context", referenceManager, null);
- parameterContext.setParameters(Collections.singleton(new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
+ parameterContext.setParameters(Collections.singletonMap("test", new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
getRootGroup().setParameterContext(parameterContext);
@@ -193,7 +193,7 @@ public class ParametersIT extends FrameworkIntegrationTest {
final ParameterReferenceManager referenceManager = new StandardParameterReferenceManager(getFlowController().getFlowManager());
final ParameterContext parameterContext = new StandardParameterContext(UUID.randomUUID().toString(), "param-context", referenceManager, null);
- parameterContext.setParameters(Collections.singleton(new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
+ parameterContext.setParameters(Collections.singletonMap("test", new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
getRootGroup().setParameterContext(parameterContext);
@@ -225,7 +225,7 @@ public class ParametersIT extends FrameworkIntegrationTest {
final ParameterReferenceManager referenceManager = new StandardParameterReferenceManager(getFlowController().getFlowManager());
final ParameterContext parameterContext = new StandardParameterContext(UUID.randomUUID().toString(), "param-context", referenceManager, null);
- parameterContext.setParameters(Collections.singleton(new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
+ parameterContext.setParameters(Collections.singletonMap("test", new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
getRootGroup().setParameterContext(parameterContext);
@@ -267,7 +267,7 @@ public class ParametersIT extends FrameworkIntegrationTest {
final ParameterReferenceManager referenceManager = new StandardParameterReferenceManager(getFlowController().getFlowManager());
final ParameterContext parameterContext = new StandardParameterContext(UUID.randomUUID().toString(), "param-context", referenceManager, null);
- parameterContext.setParameters(Collections.singleton(new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
+ parameterContext.setParameters(Collections.singletonMap("test", new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
getRootGroup().setParameterContext(parameterContext);
@@ -307,7 +307,7 @@ public class ParametersIT extends FrameworkIntegrationTest {
final ParameterReferenceManager referenceManager = new StandardParameterReferenceManager(getFlowController().getFlowManager());
final ParameterContext parameterContext = new StandardParameterContext(UUID.randomUUID().toString(), "param-context", referenceManager, null);
- parameterContext.setParameters(Collections.singleton(new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
+ parameterContext.setParameters(Collections.singletonMap("test", new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
getRootGroup().setParameterContext(parameterContext);
@@ -337,7 +337,7 @@ public class ParametersIT extends FrameworkIntegrationTest {
final ParameterReferenceManager referenceManager = new StandardParameterReferenceManager(getFlowController().getFlowManager());
final ParameterContext parameterContext = new StandardParameterContext(UUID.randomUUID().toString(), "param-context", referenceManager, null);
- parameterContext.setParameters(Collections.singleton(new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
+ parameterContext.setParameters(Collections.singletonMap("test", new Parameter(new ParameterDescriptor.Builder().name("test").build(), "unit")));
getRootGroup().setParameterContext(parameterContext);
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/processor/ProcessorParameterTokenIT.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/processor/ProcessorParameterTokenIT.java
index 3843d2aea7..906b092170 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/processor/ProcessorParameterTokenIT.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/processor/ProcessorParameterTokenIT.java
@@ -40,7 +40,6 @@ import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -77,9 +76,9 @@ public class ProcessorParameterTokenIT extends FrameworkIntegrationTest {
final ParameterContext parameterContext = new StandardParameterContext(UUID.randomUUID().toString(), "testEscapedParameterReference", ParameterReferenceManager.EMPTY, null);
getRootGroup().setParameterContext(parameterContext);
- final Set parameters = new HashSet<>();
- parameters.add(new Parameter(new ParameterDescriptor.Builder().name("foo").build(), "bar"));
- parameters.add(new Parameter(new ParameterDescriptor.Builder().name("sensitive").sensitive(true).build(), "*password*"));
+ final Map parameters = new HashMap<>();
+ parameters.put("foo", new Parameter(new ParameterDescriptor.Builder().name("foo").build(), "bar"));
+ parameters.put("sensitive", new Parameter(new ParameterDescriptor.Builder().name("sensitive").sensitive(true).build(), "*password*"));
parameterContext.setParameters(parameters);
verifyText(procNode, "hello", "hello");
@@ -107,9 +106,9 @@ public class ProcessorParameterTokenIT extends FrameworkIntegrationTest {
final ParameterContext parameterContext = new StandardParameterContext(UUID.randomUUID().toString(), "testEscapedParameterReference", ParameterReferenceManager.EMPTY, null);
getRootGroup().setParameterContext(parameterContext);
- final Set parameters = new HashSet<>();
- parameters.add(new Parameter(new ParameterDescriptor.Builder().name("foo").build(), "bar"));
- parameters.add(new Parameter(new ParameterDescriptor.Builder().name("sensitive").sensitive(true).build(), "*password*"));
+ final Map parameters = new HashMap<>();
+ parameters.put("foo", new Parameter(new ParameterDescriptor.Builder().name("foo").build(), "bar"));
+ parameters.put("sensitive", new Parameter(new ParameterDescriptor.Builder().name("sensitive").sensitive(true).build(), "*password*"));
parameterContext.setParameters(parameters);
verifyCannotSetParameter(procNode, "#{sensitive}", null);
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/versioned/ImportFlowIT.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/versioned/ImportFlowIT.java
index 52063150e7..99f91b8186 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/versioned/ImportFlowIT.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/integration/versioned/ImportFlowIT.java
@@ -34,6 +34,8 @@ import org.apache.nifi.registry.flow.VersionedControllerService;
import org.apache.nifi.registry.flow.VersionedFlow;
import org.apache.nifi.registry.flow.VersionedFlowSnapshot;
import org.apache.nifi.registry.flow.VersionedFlowSnapshotMetadata;
+import org.apache.nifi.registry.flow.VersionedParameter;
+import org.apache.nifi.registry.flow.VersionedParameterContext;
import org.apache.nifi.registry.flow.VersionedProcessGroup;
import org.apache.nifi.registry.flow.VersionedProcessor;
import org.apache.nifi.registry.flow.mapping.NiFiRegistryFlowMapper;
@@ -44,6 +46,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
@@ -70,7 +73,7 @@ public class ImportFlowIT extends FrameworkIntegrationTest {
processor.setAutoTerminatedRelationships(Collections.singleton(REL_SUCCESS));
processor.setProperties(Collections.singletonMap(NopServiceReferencingProcessor.SERVICE.getName(), controllerService.getIdentifier()));
- final VersionedFlowSnapshot proposedFlow = createFlowSnapshot(Collections.singletonList(controllerService), Collections.singletonList(processor));
+ final VersionedFlowSnapshot proposedFlow = createFlowSnapshot(Collections.singletonList(controllerService), Collections.singletonList(processor), null);
// Create an Inner Process Group and update it to match the Versioned Flow.
final ProcessGroup innerGroup = getFlowController().getFlowManager().createProcessGroup("inner-group-id");
@@ -107,7 +110,7 @@ public class ImportFlowIT extends FrameworkIntegrationTest {
}
- private VersionedFlowSnapshot createFlowSnapshot(final List controllerServices, final List processors) {
+ private VersionedFlowSnapshot createFlowSnapshot(final List controllerServices, final List processors, final Map parameters) {
final VersionedFlowSnapshotMetadata snapshotMetadata = new VersionedFlowSnapshotMetadata();
snapshotMetadata.setAuthor("unit-test");
snapshotMetadata.setBucketIdentifier("unit-test-bucket");
@@ -159,6 +162,21 @@ public class ImportFlowIT extends FrameworkIntegrationTest {
versionedFlowSnapshot.setFlow(flow);
versionedFlowSnapshot.setFlowContents(flowContents);
+ if (parameters != null) {
+ final Set versionedParameters = new HashSet<>();
+ for (final Map.Entry entry : parameters.entrySet()) {
+ final VersionedParameter versionedParameter = new VersionedParameter();
+ versionedParameter.setName(entry.getKey());
+ versionedParameter.setValue(entry.getValue());
+ versionedParameters.add(versionedParameter);
+ }
+
+ final VersionedParameterContext versionedParameterContext = new VersionedParameterContext();
+ versionedParameterContext.setName("Unit Test Context");
+ versionedParameterContext.setParameters(versionedParameters);
+ versionedFlowSnapshot.setParameterContexts(Collections.singletonMap("unit-test-context", versionedParameterContext));
+ }
+
return versionedFlowSnapshot;
}
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/parameter/TestStandardParameterContext.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/parameter/TestStandardParameterContext.java
index 1b211a2d37..6008e636bc 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/parameter/TestStandardParameterContext.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/parameter/TestStandardParameterContext.java
@@ -27,7 +27,6 @@ import org.mockito.Mockito;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@@ -47,9 +46,9 @@ public class TestStandardParameterContext {
final ParameterDescriptor xyzDescriptor = new ParameterDescriptor.Builder().name("xyz").build();
final ParameterDescriptor fooDescriptor = new ParameterDescriptor.Builder().name("foo").description("bar").sensitive(true).build();
- final Set parameters = new HashSet<>();
- parameters.add(new Parameter(abcDescriptor, "123"));
- parameters.add(new Parameter(xyzDescriptor, "242526"));
+ final Map parameters = new HashMap<>();
+ parameters.put("abc", new Parameter(abcDescriptor, "123"));
+ parameters.put("xyz", new Parameter(xyzDescriptor, "242526"));
context.setParameters(parameters);
@@ -63,15 +62,15 @@ public class TestStandardParameterContext {
assertNull(xyzParam.getDescriptor().getDescription());
assertEquals("242526", xyzParam.getValue());
- final Set secondParameters = new HashSet<>();
- secondParameters.add(new Parameter(fooDescriptor, "baz"));
+ final Map secondParameters = new HashMap<>();
+ secondParameters.put("foo", new Parameter(fooDescriptor, "baz"));
context.setParameters(secondParameters);
assertTrue(context.getParameter("abc").isPresent());
assertTrue(context.getParameter("xyz").isPresent());
- secondParameters.add(new Parameter(abcParam.getDescriptor(), null));
- secondParameters.add(new Parameter(xyzParam.getDescriptor(), null));
+ secondParameters.put("abc", null);
+ secondParameters.put("xyz", null);
context.setParameters(secondParameters);
@@ -86,8 +85,8 @@ public class TestStandardParameterContext {
assertEquals(Collections.singletonMap(fooDescriptor, fooParam), context.getParameters());
- final Set thirdParameters = new HashSet<>();
- thirdParameters.add(new Parameter(fooDescriptor, "other"));
+ final Map thirdParameters = new HashMap<>();
+ thirdParameters.put("foo", new Parameter(fooDescriptor, "other"));
context.setParameters(thirdParameters);
assertEquals("other", context.getParameter("foo").get().getValue());
@@ -100,8 +99,8 @@ public class TestStandardParameterContext {
final ParameterDescriptor abcDescriptor = new ParameterDescriptor.Builder().name("abc").description("abc").build();
- final Set parameters = new HashSet<>();
- parameters.add(new Parameter(abcDescriptor, "123"));
+ final Map parameters = new HashMap<>();
+ parameters.put("abc", new Parameter(abcDescriptor, "123"));
context.setParameters(parameters);
@@ -112,7 +111,7 @@ public class TestStandardParameterContext {
ParameterDescriptor updatedDescriptor = new ParameterDescriptor.Builder().name("abc").description("Updated").build();
final Parameter newDescriptionParam = new Parameter(updatedDescriptor, "321");
- context.setParameters(Collections.singleton(newDescriptionParam));
+ context.setParameters(Collections.singletonMap("abc", newDescriptionParam));
abcParam = context.getParameter("abc").get();
assertEquals(abcDescriptor, abcParam.getDescriptor());
@@ -121,12 +120,12 @@ public class TestStandardParameterContext {
updatedDescriptor = new ParameterDescriptor.Builder().name("abc").description("Updated Again").build();
final Parameter paramWithoutValue = new Parameter(updatedDescriptor, null);
- context.setParameters(Collections.singleton(paramWithoutValue));
+ context.setParameters(Collections.singletonMap("abc", paramWithoutValue));
abcParam = context.getParameter("abc").get();
assertEquals(abcDescriptor, abcParam.getDescriptor());
assertEquals("Updated Again", abcParam.getDescriptor().getDescription());
- assertEquals("321", abcParam.getValue());
+ assertNull(abcParam.getValue());
}
@Test
@@ -139,17 +138,17 @@ public class TestStandardParameterContext {
final ParameterDescriptor xyzDescriptor = new ParameterDescriptor.Builder().name("xyz").build();
final ParameterDescriptor fooDescriptor = new ParameterDescriptor.Builder().name("foo").description("bar").sensitive(true).build();
- final Set parameters = new HashSet<>();
- parameters.add(new Parameter(abcDescriptor, "123"));
- parameters.add(new Parameter(xyzDescriptor, "242526"));
+ final Map parameters = new HashMap<>();
+ parameters.put("abc", new Parameter(abcDescriptor, "123"));
+ parameters.put("xyz", new Parameter(xyzDescriptor, "242526"));
context.setParameters(parameters);
final ParameterDescriptor sensitiveXyzDescriptor = new ParameterDescriptor.Builder().name("xyz").sensitive(true).build();
- final Set updatedParameters = new HashSet<>();
- updatedParameters.add(new Parameter(fooDescriptor, "baz"));
- updatedParameters.add(new Parameter(sensitiveXyzDescriptor, "242526"));
+ final Map updatedParameters = new HashMap<>();
+ updatedParameters.put("foo", new Parameter(fooDescriptor, "baz"));
+ updatedParameters.put("xyz", new Parameter(sensitiveXyzDescriptor, "242526"));
try {
context.setParameters(updatedParameters);
@@ -159,7 +158,7 @@ public class TestStandardParameterContext {
final ParameterDescriptor insensitiveAbcDescriptor = new ParameterDescriptor.Builder().name("abc").sensitive(false).build();
updatedParameters.clear();
- updatedParameters.add(new Parameter(insensitiveAbcDescriptor, "123"));
+ updatedParameters.put("abc", new Parameter(insensitiveAbcDescriptor, "123"));
try {
context.setParameters(updatedParameters);
@@ -179,13 +178,13 @@ public class TestStandardParameterContext {
final ParameterDescriptor abcDescriptor = new ParameterDescriptor.Builder().name("abc").sensitive(true).build();
- final Set parameters = new HashSet<>();
- parameters.add(new Parameter(abcDescriptor, "123"));
+ final Map parameters = new HashMap<>();
+ parameters.put("abc", new Parameter(abcDescriptor, "123"));
context.setParameters(parameters);
parameters.clear();
- parameters.add(new Parameter(abcDescriptor, "321"));
+ parameters.put("abc", new Parameter(abcDescriptor, "321"));
context.setParameters(parameters);
assertEquals("321", context.getParameter("abc").get().getValue());
@@ -194,7 +193,7 @@ public class TestStandardParameterContext {
Mockito.when(procNode.isRunning()).thenReturn(true);
parameters.clear();
- parameters.add(new Parameter(abcDescriptor, "123"));
+ parameters.put("abc", new Parameter(abcDescriptor, "123"));
try {
context.setParameters(parameters);
@@ -202,10 +201,10 @@ public class TestStandardParameterContext {
} catch (final IllegalStateException expected) {
}
- context.setParameters(Collections.emptySet());
+ context.setParameters(Collections.emptyMap());
parameters.clear();
- parameters.add(new Parameter(abcDescriptor, null));
+ parameters.put("abc", new Parameter(abcDescriptor, null));
try {
context.setParameters(parameters);
Assert.fail("Was able to remove parameter while referencing processor was running");
@@ -224,15 +223,15 @@ public class TestStandardParameterContext {
Mockito.when(serviceNode.getState()).thenReturn(ControllerServiceState.ENABLED);
final ParameterDescriptor abcDescriptor = new ParameterDescriptor.Builder().name("abc").sensitive(true).build();
- final Set parameters = new HashSet<>();
- parameters.add(new Parameter(abcDescriptor, "123"));
+ final Map parameters = new HashMap<>();
+ parameters.put("abc", new Parameter(abcDescriptor, "123"));
context.setParameters(parameters);
referenceManager.addControllerServiceReference("abc", serviceNode);
parameters.clear();
- parameters.add(new Parameter(abcDescriptor, "321"));
+ parameters.put("abc", new Parameter(abcDescriptor, "321"));
for (final ControllerServiceState state : EnumSet.of(ControllerServiceState.ENABLED, ControllerServiceState.ENABLING, ControllerServiceState.DISABLING)) {
Mockito.when(serviceNode.getState()).thenReturn(state);
@@ -249,7 +248,7 @@ public class TestStandardParameterContext {
parameters.clear();
context.setParameters(parameters);
- parameters.add(new Parameter(abcDescriptor, null));
+ parameters.put("abc", new Parameter(abcDescriptor, null));
try {
context.setParameters(parameters);
Assert.fail("Was able to remove parameter being referenced by Controller Service that is DISABLING");
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/resources/int-tests/clustered-nifi.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/resources/int-tests/clustered-nifi.properties
index 2516b42364..809eaf3359 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/resources/int-tests/clustered-nifi.properties
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/resources/int-tests/clustered-nifi.properties
@@ -218,7 +218,7 @@ nifi.cluster.flow.election.max.candidates=
# cluster load balancing properties #
nifi.cluster.load.balance.host=
-nifi.cluster.load.balance.port=6342
+nifi.cluster.load.balance.port=0
nifi.cluster.load.balance.connections.per.node=4
nifi.cluster.load.balance.max.thread.count=8
nifi.cluster.load.balance.comms.timeout=30 sec
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
index 34670e0681..7594fa8622 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
@@ -1046,10 +1046,11 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
final Set boundProcessGroups = parameterContext.getParameterReferenceManager().getProcessGroupsBound(parameterContext);
final ParameterContext updatedParameterContext = new StandardParameterContext(parameterContext.getIdentifier(), parameterContext.getName(), ParameterReferenceManager.EMPTY, null);
- final Set parameters = parameterContextDto.getParameters().stream()
+ final Map parameters = new HashMap<>();
+ parameterContextDto.getParameters().stream()
.map(ParameterEntity::getParameter)
.map(this::createParameter)
- .collect(Collectors.toSet());
+ .forEach(param -> parameters.put(param.getDescriptor().getName(), param));
updatedParameterContext.setParameters(parameters);
final List validationResults = new ArrayList<>();
@@ -1089,6 +1090,10 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
}
private Parameter createParameter(final ParameterDTO dto) {
+ if (dto.getDescription() == null && dto.getSensitive() == null && dto.getValue() == null) {
+ return null; // null description, sensitivity flag, and value indicates a deletion, which we want to represent as a null Parameter.
+ }
+
final ParameterDescriptor descriptor = new ParameterDescriptor.Builder()
.name(dto.getName())
.description(dto.getDescription())
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardParameterContextDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardParameterContextDAO.java
index aaab83045e..4b02b9d661 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardParameterContextDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardParameterContextDAO.java
@@ -37,10 +37,10 @@ import org.apache.nifi.web.api.entity.ParameterEntity;
import org.apache.nifi.web.dao.ParameterContextDAO;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.stream.Collectors;
public class StandardParameterContextDAO implements ParameterContextDAO {
private FlowManager flowManager;
@@ -57,7 +57,7 @@ public class StandardParameterContextDAO implements ParameterContextDAO {
@Override
public ParameterContext createParameterContext(final ParameterContextDTO parameterContextDto) {
- final Set parameters = getParameters(parameterContextDto);
+ final Map parameters = getParameters(parameterContextDto);
final ParameterContext parameterContext = flowManager.createParameterContext(parameterContextDto.getId(), parameterContextDto.getName(), parameters);
if (parameterContextDto.getDescription() != null) {
parameterContext.setDescription(parameterContextDto.getDescription());
@@ -65,16 +65,30 @@ public class StandardParameterContextDAO implements ParameterContextDAO {
return parameterContext;
}
- private Set getParameters(final ParameterContextDTO parameterContextDto) {
- final Set parameterDtos = parameterContextDto.getParameters();
- if (parameterDtos == null) {
- return Collections.emptySet();
+ private Map getParameters(final ParameterContextDTO parameterContextDto) {
+ final Set parameterEntities = parameterContextDto.getParameters();
+ if (parameterEntities == null) {
+ return Collections.emptyMap();
}
- return parameterContextDto.getParameters().stream()
- .map(ParameterEntity::getParameter)
- .map(this::createParameter)
- .collect(Collectors.toSet());
+ final Map parameterMap = new HashMap<>();
+ for (final ParameterEntity parameterEntity : parameterEntities) {
+ final ParameterDTO parameterDto = parameterEntity.getParameter();
+
+ if (parameterDto.getName() == null) {
+ throw new IllegalArgumentException("Cannot specify a Parameter without a name");
+ }
+
+ final boolean deletion = parameterDto.getDescription() == null && parameterDto.getSensitive() == null && parameterDto.getValue() == null;
+ if (deletion) {
+ parameterMap.put(parameterDto.getName(), null);
+ } else {
+ final Parameter parameter = createParameter(parameterDto);
+ parameterMap.put(parameterDto.getName(), parameter);
+ }
+ }
+
+ return parameterMap;
}
private Parameter createParameter(final ParameterDTO dto) {
@@ -118,7 +132,7 @@ public class StandardParameterContextDAO implements ParameterContextDAO {
}
if (parameterContextDto.getParameters() != null) {
- final Set parameters = getParameters(parameterContextDto);
+ final Map parameters = getParameters(parameterContextDto);
context.setParameters(parameters);
}
diff --git a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/ValidationContextAdapter.java b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/ValidationContextAdapter.java
index b983c16f5d..eee7e37370 100644
--- a/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/ValidationContextAdapter.java
+++ b/nifi-nar-bundles/nifi-scripting-bundle/nifi-scripting-processors/src/main/java/org/apache/nifi/script/impl/ValidationContextAdapter.java
@@ -100,6 +100,11 @@ public abstract class ValidationContextAdapter implements ValidationContext {
return innerValidationContext.isParameterDefined(parameterName);
}
+ @Override
+ public boolean isParameterSet(final String parameterName) {
+ return innerValidationContext.isParameterSet(parameterName);
+ }
+
@Override
public Collection getReferencedParameters(final String propertyName) {
return innerValidationContext.getReferencedParameters(propertyName);
diff --git a/nifi-stateless/nifi-stateless-core/src/main/java/org/apache/nifi/stateless/core/StatelessParameterContext.java b/nifi-stateless/nifi-stateless-core/src/main/java/org/apache/nifi/stateless/core/StatelessParameterContext.java
index e48a965274..2a9ad4fdbe 100644
--- a/nifi-stateless/nifi-stateless-core/src/main/java/org/apache/nifi/stateless/core/StatelessParameterContext.java
+++ b/nifi-stateless/nifi-stateless-core/src/main/java/org/apache/nifi/stateless/core/StatelessParameterContext.java
@@ -61,13 +61,13 @@ public class StatelessParameterContext implements ParameterContext {
}
@Override
- public void setParameters(final Set updatedParameters) {
- throw new UnsupportedOperationException();
+ public void setParameters(final Map updatedParameters) {
+ throw new UnsupportedOperationException(); // This parameter context does not support updating - all parameters are provided in the constructor.
}
@Override
- public void verifyCanSetParameters(final Set parameters) {
- throw new UnsupportedOperationException();
+ public void verifyCanSetParameters(final Map parameters) {
+ throw new UnsupportedOperationException(); // This parameter context does not support updating - all parameters are provided in the constructor.
}
@Override
diff --git a/nifi-stateless/nifi-stateless-core/src/main/java/org/apache/nifi/stateless/core/StatelessValidationContext.java b/nifi-stateless/nifi-stateless-core/src/main/java/org/apache/nifi/stateless/core/StatelessValidationContext.java
index 81f1eb0a93..9ed84344b4 100644
--- a/nifi-stateless/nifi-stateless-core/src/main/java/org/apache/nifi/stateless/core/StatelessValidationContext.java
+++ b/nifi-stateless/nifi-stateless-core/src/main/java/org/apache/nifi/stateless/core/StatelessValidationContext.java
@@ -26,6 +26,7 @@ import org.apache.nifi.controller.ControllerService;
import org.apache.nifi.controller.ControllerServiceLookup;
import org.apache.nifi.controller.PropertyConfiguration;
import org.apache.nifi.expression.ExpressionLanguageCompiler;
+import org.apache.nifi.parameter.Parameter;
import org.apache.nifi.parameter.ParameterContext;
import org.apache.nifi.parameter.ParameterReference;
import org.apache.nifi.registry.VariableRegistry;
@@ -36,6 +37,7 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.stream.Collectors;
public class StatelessValidationContext implements ValidationContext {
@@ -146,6 +148,22 @@ public class StatelessValidationContext implements ValidationContext {
return parameterContext.getParameter(parameterName).isPresent();
}
+ @Override
+ public boolean isParameterSet(final String parameterName) {
+ if (parameterContext == null) {
+ return false;
+ }
+
+ final Optional parameterOption = parameterContext.getParameter(parameterName);
+ if (!parameterOption.isPresent()) {
+ return false;
+ }
+
+ final String value = parameterOption.get().getValue();
+ return value != null;
+
+ }
+
@Override
public ControllerServiceLookup getControllerServiceLookup() {
return this.lookup;