http://git-wip-us.apache.org/repos/asf/nifi/blob/3a7ddc6a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/NotificationServiceManager.java ---------------------------------------------------------------------- diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/NotificationServiceManager.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/NotificationServiceManager.java index 6aebe62..2fda022 100644 --- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/NotificationServiceManager.java +++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/NotificationServiceManager.java @@ -1,430 +1,430 @@ -/* - * 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.bootstrap; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import org.apache.nifi.bootstrap.notification.NotificationContext; -import org.apache.nifi.bootstrap.notification.NotificationInitializationContext; -import org.apache.nifi.bootstrap.notification.NotificationService; -import org.apache.nifi.bootstrap.notification.NotificationType; -import org.apache.nifi.bootstrap.notification.NotificationValidationContext; -import org.apache.nifi.components.PropertyDescriptor; -import org.apache.nifi.components.PropertyValue; -import org.apache.nifi.components.ValidationContext; -import org.apache.nifi.components.ValidationResult; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -public class NotificationServiceManager { - private static final Logger logger = LoggerFactory.getLogger(NotificationServiceManager.class); - private final Map<String, ConfiguredNotificationService> servicesById = new HashMap<>(); - private final Map<NotificationType, List<ConfiguredNotificationService>> servicesByNotificationType = new HashMap<>(); - - private final ScheduledExecutorService notificationExecutor; - private int maxAttempts = 5; - - public NotificationServiceManager() { - notificationExecutor = Executors.newScheduledThreadPool(1, new ThreadFactory() { - @Override - public Thread newThread(final Runnable r) { - final Thread t = Executors.defaultThreadFactory().newThread(r); - t.setName("Notification Service Dispatcher"); - t.setDaemon(true); - return t; - } - }); - } - - public void setMaxNotificationAttempts(final int maxAttempts) { - this.maxAttempts = maxAttempts; - } - - /** - * Loads the Notification Services from the given XML configuration file. - * - * File is expected to have the following format: - * - * <pre> - * <services> - * <service> - * <id>service-identifier</id> - * <class>org.apache.nifi.MyNotificationService</class> - * <property name="My First Property">Property Value</property> - * </service> - * <service> - * <id>other-service</id> - * <class>org.apache.nifi.MyOtherNotificationService</class> - * <property name="Another Property">Property Value 2</property> - * </service> - * ... - * <service> - * <id>service-identifier-2</id> - * <class>org.apache.nifi.FinalNotificationService</class> - * <property name="Yet Another Property">3rd Prop Value</property> - * </service> - * </services> - * </pre> - * - * Note that as long as the file can be interpreted properly, a misconfigured service will result in a warning - * or error being logged and the service will be unavailable but will not prevent the rest of the services from loading. - * - * @param servicesFile the XML file to load services from. - * @throws IOException if unable to read from the given file - * @throws ParserConfigurationException if unable to parse the given file as XML properly - * @throws SAXException if unable to parse the given file properly - */ - public void loadNotificationServices(final File servicesFile) throws IOException, ParserConfigurationException, SAXException { - final DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); - docBuilderFactory.setNamespaceAware(false); - final DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); - - final Map<String, ConfiguredNotificationService> serviceMap = new HashMap<>(); - try (final InputStream fis = new FileInputStream(servicesFile); - final InputStream in = new BufferedInputStream(fis)) { - - final Document doc = docBuilder.parse(new InputSource(in)); - final List<Element> serviceElements = getChildElementsByTagName(doc.getDocumentElement(), "service"); - logger.debug("Found {} service elements", serviceElements.size()); - - for (final Element serviceElement : serviceElements) { - final ConfiguredNotificationService config = createService(serviceElement); - final NotificationService service = config.getService(); - - if (service == null) { - continue; // reason will have already been logged, so just move on. - } - - final String id = service.getIdentifier(); - if (serviceMap.containsKey(id)) { - logger.error("Found two different Notification Services configured with the same ID: '{}'. Loaded the first service.", id); - continue; - } - - // Check if the service is valid; if not, warn now so that users know this before they fail to receive notifications - final ValidationContext validationContext = new NotificationValidationContext(buildNotificationContext(config)); - final Collection<ValidationResult> validationResults = service.validate(validationContext); - final List<String> invalidReasons = new ArrayList<>(); - - for (final ValidationResult result : validationResults) { - if (!result.isValid()) { - invalidReasons.add(result.toString()); - } - } - - if (!invalidReasons.isEmpty()) { - logger.warn("Configured Notification Service {} is not valid for the following reasons: {}", service, invalidReasons); - } - - serviceMap.put(id, config); - } - } - - logger.info("Successfully loaded the following {} services: {}", serviceMap.size(), serviceMap.keySet()); - - servicesById.clear(); - servicesById.putAll(serviceMap); - } - - public void notify(final NotificationType type, final String subject, final String message) { - final List<ConfiguredNotificationService> configs = servicesByNotificationType.get(type); - if (configs == null || configs.isEmpty()) { - return; - } - - for (final ConfiguredNotificationService config : configs) { - final NotificationService service = config.getService(); - final AtomicInteger attemptCount = new AtomicInteger(0); - - notificationExecutor.submit(new Runnable() { - @Override - public void run() { - // Check if the service is valid; if not, warn now so that users know this before they fail to receive notifications - final ValidationContext validationContext = new NotificationValidationContext(buildNotificationContext(config)); - final Collection<ValidationResult> validationResults = service.validate(validationContext); - final List<String> invalidReasons = new ArrayList<>(); - - for (final ValidationResult result : validationResults) { - if (!result.isValid()) { - invalidReasons.add(result.toString()); - } - } - - // If the service is valid, attempt to send the notification - boolean failure = false; - if (invalidReasons.isEmpty()) { - final NotificationContext context = buildNotificationContext(config); - try { - service.notify(context, subject, message); - logger.info("Successfully sent notification of type {} to {}", type, service); - } catch (final Throwable t) { // keep running even if a Throwable is caught because we need to ensure that we are able to restart NiFi - logger.error("Failed to send notification of type {} to {} with Subject {} due to {}. Will ", - type, service == null ? "Unknown Notification Service" : service.toString(), subject, t.toString()); - logger.error("", t); - failure = true; - } - } else { - logger.warn("Notification Service {} is not valid for the following reasons: {}", service, invalidReasons); - failure = true; - } - - final int attempts = attemptCount.incrementAndGet(); - if (failure) { - if (attempts < maxAttempts) { - logger.info("After failing to send notification to {} {} times, will attempt again in 1 minute", service, attempts); - notificationExecutor.schedule(this, 1, TimeUnit.MINUTES); - } else { - logger.info("After failing to send notification of type {} to {} {} times, will no longer attempt to send notification", type, service, attempts); - } - } - } - }); - - if (NotificationType.NIFI_STOPPED.equals(type)) { - // If we are stopping NiFi, we want to block until we've tried to send the notification at least once before - // we return. We do this because the executor used to run the task marks the threads as daemon, and on shutdown - // we don't want to return before the notifier has had a chance to perform its task. - while (attemptCount.get() == 0) { - try { - Thread.sleep(1000L); - } catch (final InterruptedException ie) { - } - } - } - } - } - - private NotificationContext buildNotificationContext(final ConfiguredNotificationService config) { - return new NotificationContext() { - @Override - public PropertyValue getProperty(final PropertyDescriptor descriptor) { - final PropertyDescriptor fullPropDescriptor = config.getService().getPropertyDescriptor(descriptor.getName()); - if (fullPropDescriptor == null) { - return null; - } - - String configuredValue = config.getProperties().get(fullPropDescriptor.getName()); - if (configuredValue == null) { - configuredValue = fullPropDescriptor.getDefaultValue(); - } - - return new NotificationServicePropertyValue(configuredValue); - } - - @Override - public Map<PropertyDescriptor, String> getProperties() { - final Map<PropertyDescriptor, String> props = new HashMap<>(); - final Map<String, String> configuredProps = config.getProperties(); - - final NotificationService service = config.getService(); - for (final PropertyDescriptor descriptor : service.getPropertyDescriptors()) { - final String configuredValue = configuredProps.get(descriptor.getName()); - if (configuredValue == null) { - props.put(descriptor, descriptor.getDefaultValue()); - } else { - props.put(descriptor, configuredValue); - } - } - - return props; - } - - }; - } - - /** - * Registers the service that has the given identifier to respond to notifications of the given type - * - * @param type the type of notification to register the service for - * @param serviceId the identifier of the service - */ - public void registerNotificationService(final NotificationType type, final String serviceId) { - final ConfiguredNotificationService service = servicesById.get(serviceId); - if (service == null) { - throw new IllegalArgumentException("No Notification Service exists with ID " + serviceId); - } - - List<ConfiguredNotificationService> services = servicesByNotificationType.get(type); - if (services == null) { - services = new ArrayList<>(); - servicesByNotificationType.put(type, services); - } - - services.add(service); - } - - /** - * Creates a Notification Service and initializes it. Then returns the service and its configured properties - * - * @param serviceElement the XML element from which to build the Notification Service - * @return a Tuple with the NotificationService as the key and the configured properties as the value, or <code>null</code> if - * unable to create the service - */ - private ConfiguredNotificationService createService(final Element serviceElement) { - final Element idElement = getChild(serviceElement, "id"); - if (idElement == null) { - logger.error("Found configuration for Notification Service with no 'id' element; this service cannot be referenced so it will not be loaded"); - return null; - } - - final String serviceId = idElement.getTextContent().trim(); - logger.debug("Loading Notification Service with ID {}", serviceId); - - final Element classElement = getChild(serviceElement, "class"); - if (classElement == null) { - logger.error("Found configuration for Notification Service with no 'class' element; Service ID is '{}'. This service annot be loaded", serviceId); - return null; - } - - final String className = classElement.getTextContent().trim(); - final Class<?> clazz; - try { - clazz = Class.forName(className); - } catch (final Exception e) { - logger.error("Found configuration for Notification Service with ID '{}' and Class '{}' but could not load class.", serviceId, className); - logger.error("", e); - return null; - } - - if (!NotificationService.class.isAssignableFrom(clazz)) { - logger.error("Found configuration for Notification Service with ID '{}' and Class '{}' but class is not a Notification Service.", serviceId, className); - return null; - } - - final Object serviceObject; - try { - serviceObject = clazz.newInstance(); - } catch (final Exception e) { - logger.error("Found configuration for Notification Service with ID '{}' and Class '{}' but could not instantiate Notification Service.", serviceId, className); - logger.error("", e); - return null; - } - - final Map<String, String> propertyValues = new HashMap<>(); - final List<Element> propertyElements = getChildElementsByTagName(serviceElement, "property"); - for (final Element propertyElement : propertyElements) { - final String propName = propertyElement.getAttribute("name"); - if (propName == null || propName.trim().isEmpty()) { - logger.warn("Found configuration for Notification Service with ID '{}' that has property value configured but no name for the property.", serviceId); - continue; - } - - final String propValue = propertyElement.getTextContent().trim(); - propertyValues.put(propName, propValue); - } - - final NotificationService service = (NotificationService) serviceObject; - - try { - service.initialize(new NotificationInitializationContext() { - @Override - public PropertyValue getProperty(final PropertyDescriptor descriptor) { - final String propName = descriptor.getName(); - String value = propertyValues.get(propName); - if (value == null) { - value = descriptor.getDefaultValue(); - } - - return new NotificationServicePropertyValue(value); - } - - @Override - public String getIdentifier() { - return serviceId; - } - }); - } catch (final Exception e) { - logger.error("Failed to load Notification Service with ID '{}'", serviceId); - logger.error("", e); - } - - return new ConfiguredNotificationService(service, propertyValues); - } - - public static Element getChild(final Element element, final String tagName) { - final List<Element> children = getChildElementsByTagName(element, tagName); - if (children.isEmpty()) { - return null; - } - - if (children.size() > 1) { - return null; - } - - return children.get(0); - } - - public static List<Element> getChildElementsByTagName(final Element element, final String tagName) { - final List<Element> matches = new ArrayList<>(); - final NodeList nodeList = element.getChildNodes(); - for (int i = 0; i < nodeList.getLength(); i++) { - final Node node = nodeList.item(i); - if (!(node instanceof Element)) { - continue; - } - - final Element child = (Element) nodeList.item(i); - if (child.getNodeName().equals(tagName)) { - matches.add(child); - } - } - - return matches; - } - - private static class ConfiguredNotificationService { - private final NotificationService service; - private final Map<String, String> properties; - - public ConfiguredNotificationService(final NotificationService service, final Map<String, String> properties) { - this.service = service; - this.properties = properties; - } - - public NotificationService getService() { - return service; - } - - public Map<String, String> getProperties() { - return properties; - } - } -} +/* + * 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.bootstrap; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.nifi.bootstrap.notification.NotificationContext; +import org.apache.nifi.bootstrap.notification.NotificationInitializationContext; +import org.apache.nifi.bootstrap.notification.NotificationService; +import org.apache.nifi.bootstrap.notification.NotificationType; +import org.apache.nifi.bootstrap.notification.NotificationValidationContext; +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.components.PropertyValue; +import org.apache.nifi.components.ValidationContext; +import org.apache.nifi.components.ValidationResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +public class NotificationServiceManager { + private static final Logger logger = LoggerFactory.getLogger(NotificationServiceManager.class); + private final Map<String, ConfiguredNotificationService> servicesById = new HashMap<>(); + private final Map<NotificationType, List<ConfiguredNotificationService>> servicesByNotificationType = new HashMap<>(); + + private final ScheduledExecutorService notificationExecutor; + private int maxAttempts = 5; + + public NotificationServiceManager() { + notificationExecutor = Executors.newScheduledThreadPool(1, new ThreadFactory() { + @Override + public Thread newThread(final Runnable r) { + final Thread t = Executors.defaultThreadFactory().newThread(r); + t.setName("Notification Service Dispatcher"); + t.setDaemon(true); + return t; + } + }); + } + + public void setMaxNotificationAttempts(final int maxAttempts) { + this.maxAttempts = maxAttempts; + } + + /** + * Loads the Notification Services from the given XML configuration file. + * + * File is expected to have the following format: + * + * <pre> + * <services> + * <service> + * <id>service-identifier</id> + * <class>org.apache.nifi.MyNotificationService</class> + * <property name="My First Property">Property Value</property> + * </service> + * <service> + * <id>other-service</id> + * <class>org.apache.nifi.MyOtherNotificationService</class> + * <property name="Another Property">Property Value 2</property> + * </service> + * ... + * <service> + * <id>service-identifier-2</id> + * <class>org.apache.nifi.FinalNotificationService</class> + * <property name="Yet Another Property">3rd Prop Value</property> + * </service> + * </services> + * </pre> + * + * Note that as long as the file can be interpreted properly, a misconfigured service will result in a warning + * or error being logged and the service will be unavailable but will not prevent the rest of the services from loading. + * + * @param servicesFile the XML file to load services from. + * @throws IOException if unable to read from the given file + * @throws ParserConfigurationException if unable to parse the given file as XML properly + * @throws SAXException if unable to parse the given file properly + */ + public void loadNotificationServices(final File servicesFile) throws IOException, ParserConfigurationException, SAXException { + final DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); + docBuilderFactory.setNamespaceAware(false); + final DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); + + final Map<String, ConfiguredNotificationService> serviceMap = new HashMap<>(); + try (final InputStream fis = new FileInputStream(servicesFile); + final InputStream in = new BufferedInputStream(fis)) { + + final Document doc = docBuilder.parse(new InputSource(in)); + final List<Element> serviceElements = getChildElementsByTagName(doc.getDocumentElement(), "service"); + logger.debug("Found {} service elements", serviceElements.size()); + + for (final Element serviceElement : serviceElements) { + final ConfiguredNotificationService config = createService(serviceElement); + final NotificationService service = config.getService(); + + if (service == null) { + continue; // reason will have already been logged, so just move on. + } + + final String id = service.getIdentifier(); + if (serviceMap.containsKey(id)) { + logger.error("Found two different Notification Services configured with the same ID: '{}'. Loaded the first service.", id); + continue; + } + + // Check if the service is valid; if not, warn now so that users know this before they fail to receive notifications + final ValidationContext validationContext = new NotificationValidationContext(buildNotificationContext(config)); + final Collection<ValidationResult> validationResults = service.validate(validationContext); + final List<String> invalidReasons = new ArrayList<>(); + + for (final ValidationResult result : validationResults) { + if (!result.isValid()) { + invalidReasons.add(result.toString()); + } + } + + if (!invalidReasons.isEmpty()) { + logger.warn("Configured Notification Service {} is not valid for the following reasons: {}", service, invalidReasons); + } + + serviceMap.put(id, config); + } + } + + logger.info("Successfully loaded the following {} services: {}", serviceMap.size(), serviceMap.keySet()); + + servicesById.clear(); + servicesById.putAll(serviceMap); + } + + public void notify(final NotificationType type, final String subject, final String message) { + final List<ConfiguredNotificationService> configs = servicesByNotificationType.get(type); + if (configs == null || configs.isEmpty()) { + return; + } + + for (final ConfiguredNotificationService config : configs) { + final NotificationService service = config.getService(); + final AtomicInteger attemptCount = new AtomicInteger(0); + + notificationExecutor.submit(new Runnable() { + @Override + public void run() { + // Check if the service is valid; if not, warn now so that users know this before they fail to receive notifications + final ValidationContext validationContext = new NotificationValidationContext(buildNotificationContext(config)); + final Collection<ValidationResult> validationResults = service.validate(validationContext); + final List<String> invalidReasons = new ArrayList<>(); + + for (final ValidationResult result : validationResults) { + if (!result.isValid()) { + invalidReasons.add(result.toString()); + } + } + + // If the service is valid, attempt to send the notification + boolean failure = false; + if (invalidReasons.isEmpty()) { + final NotificationContext context = buildNotificationContext(config); + try { + service.notify(context, subject, message); + logger.info("Successfully sent notification of type {} to {}", type, service); + } catch (final Throwable t) { // keep running even if a Throwable is caught because we need to ensure that we are able to restart NiFi + logger.error("Failed to send notification of type {} to {} with Subject {} due to {}. Will ", + type, service == null ? "Unknown Notification Service" : service.toString(), subject, t.toString()); + logger.error("", t); + failure = true; + } + } else { + logger.warn("Notification Service {} is not valid for the following reasons: {}", service, invalidReasons); + failure = true; + } + + final int attempts = attemptCount.incrementAndGet(); + if (failure) { + if (attempts < maxAttempts) { + logger.info("After failing to send notification to {} {} times, will attempt again in 1 minute", service, attempts); + notificationExecutor.schedule(this, 1, TimeUnit.MINUTES); + } else { + logger.info("After failing to send notification of type {} to {} {} times, will no longer attempt to send notification", type, service, attempts); + } + } + } + }); + + if (NotificationType.NIFI_STOPPED.equals(type)) { + // If we are stopping NiFi, we want to block until we've tried to send the notification at least once before + // we return. We do this because the executor used to run the task marks the threads as daemon, and on shutdown + // we don't want to return before the notifier has had a chance to perform its task. + while (attemptCount.get() == 0) { + try { + Thread.sleep(1000L); + } catch (final InterruptedException ie) { + } + } + } + } + } + + private NotificationContext buildNotificationContext(final ConfiguredNotificationService config) { + return new NotificationContext() { + @Override + public PropertyValue getProperty(final PropertyDescriptor descriptor) { + final PropertyDescriptor fullPropDescriptor = config.getService().getPropertyDescriptor(descriptor.getName()); + if (fullPropDescriptor == null) { + return null; + } + + String configuredValue = config.getProperties().get(fullPropDescriptor.getName()); + if (configuredValue == null) { + configuredValue = fullPropDescriptor.getDefaultValue(); + } + + return new NotificationServicePropertyValue(configuredValue); + } + + @Override + public Map<PropertyDescriptor, String> getProperties() { + final Map<PropertyDescriptor, String> props = new HashMap<>(); + final Map<String, String> configuredProps = config.getProperties(); + + final NotificationService service = config.getService(); + for (final PropertyDescriptor descriptor : service.getPropertyDescriptors()) { + final String configuredValue = configuredProps.get(descriptor.getName()); + if (configuredValue == null) { + props.put(descriptor, descriptor.getDefaultValue()); + } else { + props.put(descriptor, configuredValue); + } + } + + return props; + } + + }; + } + + /** + * Registers the service that has the given identifier to respond to notifications of the given type + * + * @param type the type of notification to register the service for + * @param serviceId the identifier of the service + */ + public void registerNotificationService(final NotificationType type, final String serviceId) { + final ConfiguredNotificationService service = servicesById.get(serviceId); + if (service == null) { + throw new IllegalArgumentException("No Notification Service exists with ID " + serviceId); + } + + List<ConfiguredNotificationService> services = servicesByNotificationType.get(type); + if (services == null) { + services = new ArrayList<>(); + servicesByNotificationType.put(type, services); + } + + services.add(service); + } + + /** + * Creates a Notification Service and initializes it. Then returns the service and its configured properties + * + * @param serviceElement the XML element from which to build the Notification Service + * @return a Tuple with the NotificationService as the key and the configured properties as the value, or <code>null</code> if + * unable to create the service + */ + private ConfiguredNotificationService createService(final Element serviceElement) { + final Element idElement = getChild(serviceElement, "id"); + if (idElement == null) { + logger.error("Found configuration for Notification Service with no 'id' element; this service cannot be referenced so it will not be loaded"); + return null; + } + + final String serviceId = idElement.getTextContent().trim(); + logger.debug("Loading Notification Service with ID {}", serviceId); + + final Element classElement = getChild(serviceElement, "class"); + if (classElement == null) { + logger.error("Found configuration for Notification Service with no 'class' element; Service ID is '{}'. This service annot be loaded", serviceId); + return null; + } + + final String className = classElement.getTextContent().trim(); + final Class<?> clazz; + try { + clazz = Class.forName(className); + } catch (final Exception e) { + logger.error("Found configuration for Notification Service with ID '{}' and Class '{}' but could not load class.", serviceId, className); + logger.error("", e); + return null; + } + + if (!NotificationService.class.isAssignableFrom(clazz)) { + logger.error("Found configuration for Notification Service with ID '{}' and Class '{}' but class is not a Notification Service.", serviceId, className); + return null; + } + + final Object serviceObject; + try { + serviceObject = clazz.newInstance(); + } catch (final Exception e) { + logger.error("Found configuration for Notification Service with ID '{}' and Class '{}' but could not instantiate Notification Service.", serviceId, className); + logger.error("", e); + return null; + } + + final Map<String, String> propertyValues = new HashMap<>(); + final List<Element> propertyElements = getChildElementsByTagName(serviceElement, "property"); + for (final Element propertyElement : propertyElements) { + final String propName = propertyElement.getAttribute("name"); + if (propName == null || propName.trim().isEmpty()) { + logger.warn("Found configuration for Notification Service with ID '{}' that has property value configured but no name for the property.", serviceId); + continue; + } + + final String propValue = propertyElement.getTextContent().trim(); + propertyValues.put(propName, propValue); + } + + final NotificationService service = (NotificationService) serviceObject; + + try { + service.initialize(new NotificationInitializationContext() { + @Override + public PropertyValue getProperty(final PropertyDescriptor descriptor) { + final String propName = descriptor.getName(); + String value = propertyValues.get(propName); + if (value == null) { + value = descriptor.getDefaultValue(); + } + + return new NotificationServicePropertyValue(value); + } + + @Override + public String getIdentifier() { + return serviceId; + } + }); + } catch (final Exception e) { + logger.error("Failed to load Notification Service with ID '{}'", serviceId); + logger.error("", e); + } + + return new ConfiguredNotificationService(service, propertyValues); + } + + public static Element getChild(final Element element, final String tagName) { + final List<Element> children = getChildElementsByTagName(element, tagName); + if (children.isEmpty()) { + return null; + } + + if (children.size() > 1) { + return null; + } + + return children.get(0); + } + + public static List<Element> getChildElementsByTagName(final Element element, final String tagName) { + final List<Element> matches = new ArrayList<>(); + final NodeList nodeList = element.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + final Node node = nodeList.item(i); + if (!(node instanceof Element)) { + continue; + } + + final Element child = (Element) nodeList.item(i); + if (child.getNodeName().equals(tagName)) { + matches.add(child); + } + } + + return matches; + } + + private static class ConfiguredNotificationService { + private final NotificationService service; + private final Map<String, String> properties; + + public ConfiguredNotificationService(final NotificationService service, final Map<String, String> properties) { + this.service = service; + this.properties = properties; + } + + public NotificationService getService() { + return service; + } + + public Map<String, String> getProperties() { + return properties; + } + } +}
http://git-wip-us.apache.org/repos/asf/nifi/blob/3a7ddc6a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/NotificationServicePropertyValue.java ---------------------------------------------------------------------- diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/NotificationServicePropertyValue.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/NotificationServicePropertyValue.java index 944dff6..582b342 100644 --- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/NotificationServicePropertyValue.java +++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/NotificationServicePropertyValue.java @@ -1,120 +1,120 @@ -/* - * 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.bootstrap; - -import java.util.concurrent.TimeUnit; - -import org.apache.nifi.attribute.expression.language.PreparedQuery; -import org.apache.nifi.attribute.expression.language.Query; -import org.apache.nifi.components.PropertyValue; -import org.apache.nifi.controller.ControllerService; -import org.apache.nifi.expression.AttributeValueDecorator; -import org.apache.nifi.flowfile.FlowFile; -import org.apache.nifi.processor.DataUnit; -import org.apache.nifi.processor.exception.ProcessException; -import org.apache.nifi.util.FormatUtils; - -public class NotificationServicePropertyValue implements PropertyValue { - private final String rawValue; - private final PreparedQuery preparedQuery; - - public NotificationServicePropertyValue(final String rawValue) { - this.rawValue = rawValue; - this.preparedQuery = Query.prepare(rawValue); - } - - @Override - public String getValue() { - return rawValue; - } - - @Override - public Integer asInteger() { - return (rawValue == null) ? null : Integer.parseInt(rawValue.trim()); - } - - @Override - public Long asLong() { - return (rawValue == null) ? null : Long.parseLong(rawValue.trim()); - } - - @Override - public Boolean asBoolean() { - return (rawValue == null) ? null : Boolean.parseBoolean(rawValue.trim()); - } - - @Override - public Float asFloat() { - return (rawValue == null) ? null : Float.parseFloat(rawValue.trim()); - } - - @Override - public Double asDouble() { - return (rawValue == null) ? null : Double.parseDouble(rawValue.trim()); - } - - @Override - public Long asTimePeriod(final TimeUnit timeUnit) { - return (rawValue == null) ? null : FormatUtils.getTimeDuration(rawValue.trim(), timeUnit); - } - - @Override - public Double asDataSize(final DataUnit dataUnit) { - return rawValue == null ? null : DataUnit.parseDataSize(rawValue.trim(), dataUnit); - } - - @Override - public PropertyValue evaluateAttributeExpressions() throws ProcessException { - return evaluateAttributeExpressions((AttributeValueDecorator) null); - } - - @Override - public PropertyValue evaluateAttributeExpressions(final AttributeValueDecorator decorator) throws ProcessException { - return new NotificationServicePropertyValue(preparedQuery.evaluateExpressions((FlowFile) null, decorator)); - } - - @Override - public PropertyValue evaluateAttributeExpressions(final FlowFile flowFile) throws ProcessException { - throw new UnsupportedOperationException(); - } - - @Override - public PropertyValue evaluateAttributeExpressions(final FlowFile flowFile, final AttributeValueDecorator decorator) throws ProcessException { - throw new UnsupportedOperationException(); - } - - @Override - public String toString() { - return rawValue; - } - - @Override - public ControllerService asControllerService() { - throw new UnsupportedOperationException(); - } - - @Override - public <T extends ControllerService> T asControllerService(final Class<T> serviceType) throws IllegalArgumentException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isSet() { - return rawValue != null; - } - -} +/* + * 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.bootstrap; + +import java.util.concurrent.TimeUnit; + +import org.apache.nifi.attribute.expression.language.PreparedQuery; +import org.apache.nifi.attribute.expression.language.Query; +import org.apache.nifi.components.PropertyValue; +import org.apache.nifi.controller.ControllerService; +import org.apache.nifi.expression.AttributeValueDecorator; +import org.apache.nifi.flowfile.FlowFile; +import org.apache.nifi.processor.DataUnit; +import org.apache.nifi.processor.exception.ProcessException; +import org.apache.nifi.util.FormatUtils; + +public class NotificationServicePropertyValue implements PropertyValue { + private final String rawValue; + private final PreparedQuery preparedQuery; + + public NotificationServicePropertyValue(final String rawValue) { + this.rawValue = rawValue; + this.preparedQuery = Query.prepare(rawValue); + } + + @Override + public String getValue() { + return rawValue; + } + + @Override + public Integer asInteger() { + return (rawValue == null) ? null : Integer.parseInt(rawValue.trim()); + } + + @Override + public Long asLong() { + return (rawValue == null) ? null : Long.parseLong(rawValue.trim()); + } + + @Override + public Boolean asBoolean() { + return (rawValue == null) ? null : Boolean.parseBoolean(rawValue.trim()); + } + + @Override + public Float asFloat() { + return (rawValue == null) ? null : Float.parseFloat(rawValue.trim()); + } + + @Override + public Double asDouble() { + return (rawValue == null) ? null : Double.parseDouble(rawValue.trim()); + } + + @Override + public Long asTimePeriod(final TimeUnit timeUnit) { + return (rawValue == null) ? null : FormatUtils.getTimeDuration(rawValue.trim(), timeUnit); + } + + @Override + public Double asDataSize(final DataUnit dataUnit) { + return rawValue == null ? null : DataUnit.parseDataSize(rawValue.trim(), dataUnit); + } + + @Override + public PropertyValue evaluateAttributeExpressions() throws ProcessException { + return evaluateAttributeExpressions((AttributeValueDecorator) null); + } + + @Override + public PropertyValue evaluateAttributeExpressions(final AttributeValueDecorator decorator) throws ProcessException { + return new NotificationServicePropertyValue(preparedQuery.evaluateExpressions((FlowFile) null, decorator)); + } + + @Override + public PropertyValue evaluateAttributeExpressions(final FlowFile flowFile) throws ProcessException { + throw new UnsupportedOperationException(); + } + + @Override + public PropertyValue evaluateAttributeExpressions(final FlowFile flowFile, final AttributeValueDecorator decorator) throws ProcessException { + throw new UnsupportedOperationException(); + } + + @Override + public String toString() { + return rawValue; + } + + @Override + public ControllerService asControllerService() { + throw new UnsupportedOperationException(); + } + + @Override + public <T extends ControllerService> T asControllerService(final Class<T> serviceType) throws IllegalArgumentException { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isSet() { + return rawValue != null; + } + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/3a7ddc6a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/AbstractNotificationService.java ---------------------------------------------------------------------- diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/AbstractNotificationService.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/AbstractNotificationService.java index a91a377..109b1bc 100644 --- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/AbstractNotificationService.java +++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/AbstractNotificationService.java @@ -1,37 +1,37 @@ -/* - * 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.bootstrap.notification; - -import org.apache.nifi.components.AbstractConfigurableComponent; - -public abstract class AbstractNotificationService extends AbstractConfigurableComponent implements NotificationService { - private String identifier; // effectively final - - @Override - public final void initialize(final NotificationInitializationContext context) { - this.identifier = context.getIdentifier(); - init(context); - } - - protected void init(final NotificationInitializationContext context) { - } - - @Override - public String getIdentifier() { - return identifier; - } -} +/* + * 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.bootstrap.notification; + +import org.apache.nifi.components.AbstractConfigurableComponent; + +public abstract class AbstractNotificationService extends AbstractConfigurableComponent implements NotificationService { + private String identifier; // effectively final + + @Override + public final void initialize(final NotificationInitializationContext context) { + this.identifier = context.getIdentifier(); + init(context); + } + + protected void init(final NotificationInitializationContext context) { + } + + @Override + public String getIdentifier() { + return identifier; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/3a7ddc6a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationContext.java ---------------------------------------------------------------------- diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationContext.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationContext.java index 2c030a1..ba4ba93 100644 --- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationContext.java +++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationContext.java @@ -1,44 +1,44 @@ -/* - * 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.bootstrap.notification; - -import java.util.Map; - -import org.apache.nifi.components.PropertyDescriptor; -import org.apache.nifi.components.PropertyValue; - -public interface NotificationContext { - - /** - * Returns the configured value for the given PropertyDescriptor. Note that the implementation - * of PropertyValue will throw an Exception if calling {@link PropertyValue#asControllerService()} or - * {@link PropertyValue#asControllerService(Class)}, as Controller Services are not allowed to be - * referenced by Notification Services - * - * @param descriptor the property whose value should be returned - * @return the configured value for the given PropertyDescriptor, or the default - * value for the PropertyDescriptor if no value has been configured - */ - PropertyValue getProperty(PropertyDescriptor descriptor); - - /** - * @return a Map of all PropertyDescriptors to their configured values. This - * Map may or may not be modifiable, but modifying its values will not - * change the values of the processor's properties - */ - Map<PropertyDescriptor, String> getProperties(); -} +/* + * 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.bootstrap.notification; + +import java.util.Map; + +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.components.PropertyValue; + +public interface NotificationContext { + + /** + * Returns the configured value for the given PropertyDescriptor. Note that the implementation + * of PropertyValue will throw an Exception if calling {@link PropertyValue#asControllerService()} or + * {@link PropertyValue#asControllerService(Class)}, as Controller Services are not allowed to be + * referenced by Notification Services + * + * @param descriptor the property whose value should be returned + * @return the configured value for the given PropertyDescriptor, or the default + * value for the PropertyDescriptor if no value has been configured + */ + PropertyValue getProperty(PropertyDescriptor descriptor); + + /** + * @return a Map of all PropertyDescriptors to their configured values. This + * Map may or may not be modifiable, but modifying its values will not + * change the values of the processor's properties + */ + Map<PropertyDescriptor, String> getProperties(); +} http://git-wip-us.apache.org/repos/asf/nifi/blob/3a7ddc6a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationFailedException.java ---------------------------------------------------------------------- diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationFailedException.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationFailedException.java index fcab95b..93c3459 100644 --- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationFailedException.java +++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationFailedException.java @@ -1,33 +1,33 @@ -/* - * 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.bootstrap.notification; - -public class NotificationFailedException extends Exception { - private static final long serialVersionUID = 1L; - - public NotificationFailedException(final String message) { - super(message); - } - - public NotificationFailedException(final String message, final Throwable t) { - super(message, t); - } - - public NotificationFailedException(final Throwable t) { - super(t); - } -} +/* + * 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.bootstrap.notification; + +public class NotificationFailedException extends Exception { + private static final long serialVersionUID = 1L; + + public NotificationFailedException(final String message) { + super(message); + } + + public NotificationFailedException(final String message, final Throwable t) { + super(message, t); + } + + public NotificationFailedException(final Throwable t) { + super(t); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/3a7ddc6a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationInitializationContext.java ---------------------------------------------------------------------- diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationInitializationContext.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationInitializationContext.java index c75c8f4..88e0445 100644 --- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationInitializationContext.java +++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationInitializationContext.java @@ -1,39 +1,39 @@ -/* - * 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.bootstrap.notification; - - -import org.apache.nifi.components.PropertyDescriptor; -import org.apache.nifi.components.PropertyValue; - -public interface NotificationInitializationContext { - - /** - * Returns the configured value for the given PropertyDescriptor - * - * @param descriptor the property to fetch the value for - * @return the configured value for the given PropertyDescriptor, or the default value for the PropertyDescriptor - * if no value has been configured. - */ - PropertyValue getProperty(PropertyDescriptor descriptor); - - /** - * @return the identifier for the NotificationService - */ - String getIdentifier(); - -} +/* + * 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.bootstrap.notification; + + +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.components.PropertyValue; + +public interface NotificationInitializationContext { + + /** + * Returns the configured value for the given PropertyDescriptor + * + * @param descriptor the property to fetch the value for + * @return the configured value for the given PropertyDescriptor, or the default value for the PropertyDescriptor + * if no value has been configured. + */ + PropertyValue getProperty(PropertyDescriptor descriptor); + + /** + * @return the identifier for the NotificationService + */ + String getIdentifier(); + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/3a7ddc6a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationService.java ---------------------------------------------------------------------- diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationService.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationService.java index 044d906..abf9e80 100644 --- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationService.java +++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationService.java @@ -1,56 +1,56 @@ -/* - * 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.bootstrap.notification; - -import org.apache.nifi.components.ConfigurableComponent; - -/** - * <p> - * A NotificationService is simple mechanism that the Bootstrap can use to notify - * interested parties when some event takes place, such as NiFi being started, stopped, - * or restarted because the process died. - * </p> - * - * <p> - * <b>Note:</b> This feature was introduced in version 0.3.0 of NiFi and is likely to undergo - * significant refactorings. As such, at this time it is NOT considered a public API and may well - * change from version to version until the API has stabilized. At that point, it will become a public - * API. - * </p> - * - * @since 0.3.0 - */ -public interface NotificationService extends ConfigurableComponent { - - /** - * Provides the NotificatoinService with access to objects that may be of use - * throughout the life of the service - * - * @param context of initialization - */ - void initialize(NotificationInitializationContext context); - - /** - * Notifies the configured recipients of some event - * - * @param context the context that is relevant for this notification - * @param subject the subject of the message - * @param message the message to be provided to recipients - */ - void notify(NotificationContext context, String subject, String message) throws NotificationFailedException; - -} +/* + * 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.bootstrap.notification; + +import org.apache.nifi.components.ConfigurableComponent; + +/** + * <p> + * A NotificationService is simple mechanism that the Bootstrap can use to notify + * interested parties when some event takes place, such as NiFi being started, stopped, + * or restarted because the process died. + * </p> + * + * <p> + * <b>Note:</b> This feature was introduced in version 0.3.0 of NiFi and is likely to undergo + * significant refactorings. As such, at this time it is NOT considered a public API and may well + * change from version to version until the API has stabilized. At that point, it will become a public + * API. + * </p> + * + * @since 0.3.0 + */ +public interface NotificationService extends ConfigurableComponent { + + /** + * Provides the NotificatoinService with access to objects that may be of use + * throughout the life of the service + * + * @param context of initialization + */ + void initialize(NotificationInitializationContext context); + + /** + * Notifies the configured recipients of some event + * + * @param context the context that is relevant for this notification + * @param subject the subject of the message + * @param message the message to be provided to recipients + */ + void notify(NotificationContext context, String subject, String message) throws NotificationFailedException; + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/3a7ddc6a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationType.java ---------------------------------------------------------------------- diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationType.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationType.java index 26d90da..a2645ec 100644 --- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationType.java +++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationType.java @@ -1,23 +1,23 @@ -/* - * 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.bootstrap.notification; - -public enum NotificationType { - NIFI_STARTED, - NIFI_STOPPED, - NIFI_DIED; -} +/* + * 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.bootstrap.notification; + +public enum NotificationType { + NIFI_STARTED, + NIFI_STOPPED, + NIFI_DIED; +} http://git-wip-us.apache.org/repos/asf/nifi/blob/3a7ddc6a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/NotificationValidationContext.java ---------------------------------------------------------------------- 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 8f556da..a02b108 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 @@ -1,105 +1,105 @@ -/* - * 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.bootstrap.notification; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.nifi.attribute.expression.language.Query; -import org.apache.nifi.attribute.expression.language.Query.Range; -import org.apache.nifi.attribute.expression.language.StandardExpressionLanguageCompiler; -import org.apache.nifi.bootstrap.NotificationServicePropertyValue; -import org.apache.nifi.components.PropertyDescriptor; -import org.apache.nifi.components.PropertyValue; -import org.apache.nifi.components.ValidationContext; -import org.apache.nifi.controller.ControllerService; -import org.apache.nifi.controller.ControllerServiceLookup; -import org.apache.nifi.expression.ExpressionLanguageCompiler; - -public class NotificationValidationContext implements ValidationContext { - private final NotificationContext context; - private final Map<String, Boolean> expressionLanguageSupported; - - public NotificationValidationContext(final NotificationContext processContext) { - this.context = processContext; - - final Map<PropertyDescriptor, String> properties = processContext.getProperties(); - expressionLanguageSupported = new HashMap<>(properties.size()); - for (final PropertyDescriptor descriptor : properties.keySet()) { - expressionLanguageSupported.put(descriptor.getName(), descriptor.isExpressionLanguageSupported()); - } - } - - - @Override - public PropertyValue newPropertyValue(final String rawValue) { - return new NotificationServicePropertyValue(rawValue); - } - - @Override - public ExpressionLanguageCompiler newExpressionLanguageCompiler() { - return new StandardExpressionLanguageCompiler(); - } - - @Override - public ValidationContext getControllerServiceValidationContext(final ControllerService controllerService) { - throw new UnsupportedOperationException(); - } - - @Override - public PropertyValue getProperty(final PropertyDescriptor property) { - return context.getProperty(property); - } - - @Override - public Map<PropertyDescriptor, String> getProperties() { - return context.getProperties(); - } - - @Override - public String getAnnotationData() { - throw new UnsupportedOperationException(); - } - - @Override - public ControllerServiceLookup getControllerServiceLookup() { - return null; - } - - @Override - public boolean isValidationRequired(final ControllerService service) { - return true; - } - - @Override - public boolean isExpressionLanguagePresent(final String value) { - if (value == null) { - return false; - } - - final List<Range> elRanges = Query.extractExpressionRanges(value); - return (elRanges != null && !elRanges.isEmpty()); - } - - @Override - public boolean isExpressionLanguageSupported(final String propertyName) { - final Boolean supported = expressionLanguageSupported.get(propertyName); - return Boolean.TRUE.equals(supported); - } - -} +/* + * 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.bootstrap.notification; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.nifi.attribute.expression.language.Query; +import org.apache.nifi.attribute.expression.language.Query.Range; +import org.apache.nifi.attribute.expression.language.StandardExpressionLanguageCompiler; +import org.apache.nifi.bootstrap.NotificationServicePropertyValue; +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.components.PropertyValue; +import org.apache.nifi.components.ValidationContext; +import org.apache.nifi.controller.ControllerService; +import org.apache.nifi.controller.ControllerServiceLookup; +import org.apache.nifi.expression.ExpressionLanguageCompiler; + +public class NotificationValidationContext implements ValidationContext { + private final NotificationContext context; + private final Map<String, Boolean> expressionLanguageSupported; + + public NotificationValidationContext(final NotificationContext processContext) { + this.context = processContext; + + final Map<PropertyDescriptor, String> properties = processContext.getProperties(); + expressionLanguageSupported = new HashMap<>(properties.size()); + for (final PropertyDescriptor descriptor : properties.keySet()) { + expressionLanguageSupported.put(descriptor.getName(), descriptor.isExpressionLanguageSupported()); + } + } + + + @Override + public PropertyValue newPropertyValue(final String rawValue) { + return new NotificationServicePropertyValue(rawValue); + } + + @Override + public ExpressionLanguageCompiler newExpressionLanguageCompiler() { + return new StandardExpressionLanguageCompiler(); + } + + @Override + public ValidationContext getControllerServiceValidationContext(final ControllerService controllerService) { + throw new UnsupportedOperationException(); + } + + @Override + public PropertyValue getProperty(final PropertyDescriptor property) { + return context.getProperty(property); + } + + @Override + public Map<PropertyDescriptor, String> getProperties() { + return context.getProperties(); + } + + @Override + public String getAnnotationData() { + throw new UnsupportedOperationException(); + } + + @Override + public ControllerServiceLookup getControllerServiceLookup() { + return null; + } + + @Override + public boolean isValidationRequired(final ControllerService service) { + return true; + } + + @Override + public boolean isExpressionLanguagePresent(final String value) { + if (value == null) { + return false; + } + + final List<Range> elRanges = Query.extractExpressionRanges(value); + return (elRanges != null && !elRanges.isEmpty()); + } + + @Override + public boolean isExpressionLanguageSupported(final String propertyName) { + final Boolean supported = expressionLanguageSupported.get(propertyName); + return Boolean.TRUE.equals(supported); + } + +}
