diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/XmlFlowSynchronizer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/XmlFlowSynchronizer.java index 8cd0b17b65..d331f9aaff 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/XmlFlowSynchronizer.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/XmlFlowSynchronizer.java @@ -33,7 +33,6 @@ import org.apache.nifi.connectable.Port; import org.apache.nifi.connectable.Position; import org.apache.nifi.connectable.Size; import org.apache.nifi.controller.flow.FlowManager; -import org.apache.nifi.controller.flowrepository.FlowRepositoryClientInstantiationException; import org.apache.nifi.controller.inheritance.AuthorizerCheck; import org.apache.nifi.controller.inheritance.BundleCompatibilityCheck; import org.apache.nifi.controller.inheritance.ConnectionMissingCheck; @@ -42,7 +41,6 @@ import org.apache.nifi.controller.inheritance.FlowInheritability; import org.apache.nifi.controller.inheritance.FlowInheritabilityCheck; import org.apache.nifi.controller.inheritance.MissingComponentsCheck; import org.apache.nifi.controller.label.Label; -import org.apache.nifi.controller.parameter.ParameterProviderInstantiationException; import org.apache.nifi.controller.queue.LoadBalanceCompression; import org.apache.nifi.controller.queue.LoadBalanceStrategy; import org.apache.nifi.controller.reporting.ReportingTaskInstantiationException; @@ -146,6 +144,7 @@ import java.util.stream.Collectors; import java.util.zip.GZIPInputStream; /** + * XML implementation of Flow Synchronizer for reading configuration using XML Document Object Model */ public class XmlFlowSynchronizer implements FlowSynchronizer { @@ -383,7 +382,7 @@ public class XmlFlowSynchronizer implements FlowSynchronizer { } private void updateFlow(final FlowController controller, final Document configuration, final DataFlow existingFlow, final boolean existingFlowEmpty) - throws ReportingTaskInstantiationException, ParameterProviderInstantiationException, FlowRepositoryClientInstantiationException { + throws ReportingTaskInstantiationException { final boolean flowAlreadySynchronized = controller.isFlowSynchronized(); final FlowManager flowManager = controller.getFlowManager(); @@ -769,8 +768,7 @@ public class XmlFlowSynchronizer implements FlowSynchronizer { } private ParameterProviderNode getOrCreateParameterProvider(final FlowController controller, final ParameterProviderDTO dto, - final boolean controllerInitialized, final boolean existingFlowEmpty) - throws ParameterProviderInstantiationException { + final boolean controllerInitialized, final boolean existingFlowEmpty) { // create a new parameter provider node when the controller is not initialized or the flow is empty if (!controllerInitialized || existingFlowEmpty) { BundleCoordinate coordinate; @@ -818,8 +816,8 @@ public class XmlFlowSynchronizer implements FlowSynchronizer { registryClient.setName(dto.getName()); registryClient.setDescription(dto.getDescription()); registryClient.setAnnotationData(dto.getAnnotationData()); - final Set sensitiveDynamicPropertyNames = dto.getSensitiveDynamicPropertyNames(); - registryClient.setProperties(dto.getProperties(), false, sensitiveDynamicPropertyNames == null ? Collections.emptySet() : sensitiveDynamicPropertyNames); + final Set sensitiveDynamicPropertyNames = getSensitiveDynamicPropertyNames(dto.getSensitiveDynamicPropertyNames(), registryClient); + registryClient.setProperties(dto.getProperties(), false, sensitiveDynamicPropertyNames); return registryClient; } else { // otherwise return the existing flow registry client node @@ -850,8 +848,8 @@ public class XmlFlowSynchronizer implements FlowSynchronizer { reportingTask.setSchedulingStrategy(SchedulingStrategy.valueOf(dto.getSchedulingStrategy())); reportingTask.setAnnotationData(dto.getAnnotationData()); - final Set sensitiveDynamicPropertyNames = dto.getSensitiveDynamicPropertyNames(); - reportingTask.setProperties(dto.getProperties(), false, sensitiveDynamicPropertyNames == null ? Collections.emptySet() : sensitiveDynamicPropertyNames); + final Set sensitiveDynamicPropertyNames = getSensitiveDynamicPropertyNames(dto.getSensitiveDynamicPropertyNames(), reportingTask); + reportingTask.setProperties(dto.getProperties(), false, sensitiveDynamicPropertyNames); return reportingTask; } else { // otherwise return the existing reporting task node @@ -1396,8 +1394,8 @@ public class XmlFlowSynchronizer implements FlowSynchronizer { procNode.setAutoTerminatedRelationships(relationships); } - final Set sensitiveDynamicPropertyNames = config.getSensitiveDynamicPropertyNames(); - procNode.setProperties(config.getProperties(), false, sensitiveDynamicPropertyNames == null ? Collections.emptySet() : sensitiveDynamicPropertyNames); + final Set sensitiveDynamicPropertyNames = getSensitiveDynamicPropertyNames(config.getSensitiveDynamicPropertyNames(), procNode); + procNode.setProperties(config.getProperties(), false, sensitiveDynamicPropertyNames); final ScheduledState scheduledState = ScheduledState.valueOf(processorDTO.getState()); if (ScheduledState.RUNNING.equals(scheduledState)) { @@ -1413,6 +1411,16 @@ public class XmlFlowSynchronizer implements FlowSynchronizer { } } + private Set getSensitiveDynamicPropertyNames(final Set parsedSensitivePropertyNames, final ComponentNode componentNode) { + final Set sensitivePropertyNames = parsedSensitivePropertyNames == null ? Collections.emptySet() : parsedSensitivePropertyNames; + return sensitivePropertyNames.stream().filter( + propertyName -> { + final PropertyDescriptor propertyDescriptor = componentNode.getPropertyDescriptor(propertyName); + return propertyDescriptor.isDynamic(); + } + ).collect(Collectors.toSet()); + } + private void updateNonFingerprintedProcessorSettings(final ProcessorNode procNode, final ProcessorDTO processorDTO) { procNode.setName(processorDTO.getName()); procNode.setPosition(toPosition(processorDTO.getPosition())); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/ControllerServiceLoader.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/ControllerServiceLoader.java index 295d825cc3..e330f0fc6e 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/ControllerServiceLoader.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/ControllerServiceLoader.java @@ -24,25 +24,14 @@ import org.apache.nifi.controller.serialization.FlowFromDOMFactory; import org.apache.nifi.encrypt.PropertyEncryptor; import org.apache.nifi.groups.ProcessGroup; import org.apache.nifi.logging.LogLevel; -import org.apache.nifi.reporting.BulletinRepository; import org.apache.nifi.util.BundleUtils; -import org.apache.nifi.util.DomUtils; import org.apache.nifi.web.api.dto.BundleDTO; import org.apache.nifi.web.api.dto.ControllerServiceDTO; -import org.apache.nifi.xml.processing.ProcessingException; -import org.apache.nifi.xml.processing.parsers.StandardDocumentProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; import org.w3c.dom.Element; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -51,59 +40,12 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; public class ControllerServiceLoader { private static final Logger logger = LoggerFactory.getLogger(ControllerServiceLoader.class); - public static List loadControllerServices(final FlowController controller, final InputStream serializedStream, final ProcessGroup parentGroup, - final PropertyEncryptor encryptor, final BulletinRepository bulletinRepo, final boolean autoResumeState, final FlowEncodingVersion encodingVersion) throws IOException { - - try (final InputStream in = new BufferedInputStream(serializedStream)) { - final StandardDocumentProvider documentProvider = new StandardDocumentProvider(); - - documentProvider.setErrorHandler(new org.xml.sax.ErrorHandler() { - - @Override - public void fatalError(final SAXParseException err) throws SAXException { - logger.error("Config file line " + err.getLineNumber() + ", col " + err.getColumnNumber() + ", uri " + err.getSystemId() + " :message: " + err.getMessage()); - if (logger.isDebugEnabled()) { - logger.error("Error Stack Dump", err); - } - throw err; - } - - @Override - public void error(final SAXParseException err) throws SAXParseException { - logger.error("Config file line " + err.getLineNumber() + ", col " + err.getColumnNumber() + ", uri " + err.getSystemId() + " :message: " + err.getMessage()); - if (logger.isDebugEnabled()) { - logger.error("Error Stack Dump", err); - } - throw err; - } - - @Override - public void warning(final SAXParseException err) throws SAXParseException { - logger.warn(" Config file line " + err.getLineNumber() + ", uri " + err.getSystemId() + " : message : " + err.getMessage()); - if (logger.isDebugEnabled()) { - logger.warn("Warning stack dump", err); - } - throw err; - } - }); - - final Document document = documentProvider.parse(in); - final Element controllerServices = document.getDocumentElement(); - final List serviceElements = DomUtils.getChildElementsByTagName(controllerServices, "controllerService"); - - final Map controllerServiceMap = ControllerServiceLoader.loadControllerServices(serviceElements, controller, parentGroup, encryptor, encodingVersion); - enableControllerServices(controllerServiceMap, controller, encryptor, autoResumeState, encodingVersion); - return new ArrayList<>(controllerServiceMap.keySet()); - } catch (final ProcessingException e) { - throw new IOException("Parsing Controller Services failed", e); - } - } - public static Map loadControllerServices(final List serviceElements, final FlowController controller, final ProcessGroup parentGroup, final PropertyEncryptor encryptor, final FlowEncodingVersion encodingVersion) { @@ -227,11 +169,20 @@ public class ControllerServiceLoader { node.pauseValidationTrigger(); try { node.setAnnotationData(dto.getAnnotationData()); - final Set sensitiveDynamicPropertyNames = dto.getSensitiveDynamicPropertyNames(); - node.setProperties(dto.getProperties(), false, sensitiveDynamicPropertyNames == null ? Collections.emptySet() : sensitiveDynamicPropertyNames); + final Set sensitiveDynamicPropertyNames = getSensitiveDynamicPropertyNames(dto.getSensitiveDynamicPropertyNames(), node); + node.setProperties(dto.getProperties(), false, sensitiveDynamicPropertyNames); } finally { node.resumeValidationTrigger(); } } + private static Set getSensitiveDynamicPropertyNames(final Set parsedSensitivePropertyNames, final ControllerServiceNode controllerServiceNode) { + final Set sensitivePropertyNames = parsedSensitivePropertyNames == null ? Collections.emptySet() : parsedSensitivePropertyNames; + return sensitivePropertyNames.stream().filter( + propertyName -> { + final PropertyDescriptor propertyDescriptor = controllerServiceNode.getPropertyDescriptor(propertyName); + return propertyDescriptor.isDynamic(); + } + ).collect(Collectors.toSet()); + } }