NIFI-632 calling annotations as part of initialization(@OnRemoved, @OnShutdown)


Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/53b86d7a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/53b86d7a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/53b86d7a

Branch: refs/heads/develop
Commit: 53b86d7a6cdde754d34a9eb2745f270a4b57d5a9
Parents: 56d369e
Author: danbress <[email protected]>
Authored: Tue Jun 9 21:08:55 2015 -0400
Committer: danbress <[email protected]>
Committed: Tue Jun 9 21:34:28 2015 -0400

----------------------------------------------------------------------
 .../init/ControllerServiceInitializer.java      |  14 +-
 .../init/ProcessorInitializer.java              |  12 +-
 .../init/ReportingTaskingInitializer.java       |   9 ++
 .../mock/MockConfigurationContext.java          |  38 +++++
 .../documentation/mock/MockProcessContext.java  |  85 ++++++++++++
 .../documentation/util/ReflectionUtils.java     | 139 +++++++++++++++++++
 .../FullyDocumentedControllerService.java       |  63 +++++++--
 .../example/FullyDocumentedProcessor.java       |  49 ++++++-
 .../example/FullyDocumentedReportingTask.java   |  46 +++++-
 .../html/HtmlDocumentationWriterTest.java       |  33 ++++-
 .../html/ProcessorDocumentationWriterTest.java  |  19 ++-
 11 files changed, 478 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53b86d7a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/init/ControllerServiceInitializer.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/init/ControllerServiceInitializer.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/init/ControllerServiceInitializer.java
index 0f654ec..976c7a5 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/init/ControllerServiceInitializer.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/init/ControllerServiceInitializer.java
@@ -16,16 +16,21 @@
  */
 package org.apache.nifi.documentation.init;
 
+import org.apache.nifi.annotation.lifecycle.OnRemoved;
+import org.apache.nifi.annotation.lifecycle.OnShutdown;
 import org.apache.nifi.components.ConfigurableComponent;
 import org.apache.nifi.controller.ControllerService;
 import org.apache.nifi.documentation.ConfigurableComponentInitializer;
+import org.apache.nifi.documentation.mock.MockConfigurationContext;
 import 
org.apache.nifi.documentation.mock.MockControllerServiceInitializationContext;
+import org.apache.nifi.documentation.mock.MockProcessorLogger;
+import org.apache.nifi.documentation.util.ReflectionUtils;
+import org.apache.nifi.logging.ProcessorLog;
 import org.apache.nifi.nar.NarCloseable;
 import org.apache.nifi.reporting.InitializationException;
 
 /**
- * Initializes a ControllerService using a
- * MockControllerServiceInitializationContext
+ * Initializes a ControllerService using a 
MockControllerServiceInitializationContext
  *
  *
  */
@@ -37,6 +42,11 @@ public class ControllerServiceInitializer implements 
ConfigurableComponentInitia
 
         try (NarCloseable narCloseable = NarCloseable.withNarLoader()) {
             controllerService.initialize(new 
MockControllerServiceInitializationContext());
+
+            final ProcessorLog logger = new MockProcessorLogger();
+            final MockConfigurationContext context = new 
MockConfigurationContext();
+            
ReflectionUtils.quietlyInvokeMethodsWithAnnotations(OnRemoved.class, null, 
controllerService, logger, context);
+            
ReflectionUtils.quietlyInvokeMethodsWithAnnotations(OnShutdown.class, null, 
controllerService, logger, context);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53b86d7a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/init/ProcessorInitializer.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/init/ProcessorInitializer.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/init/ProcessorInitializer.java
index 331db71..7f3357c 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/init/ProcessorInitializer.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/init/ProcessorInitializer.java
@@ -16,9 +16,15 @@
  */
 package org.apache.nifi.documentation.init;
 
+import org.apache.nifi.annotation.lifecycle.OnRemoved;
+import org.apache.nifi.annotation.lifecycle.OnShutdown;
 import org.apache.nifi.components.ConfigurableComponent;
 import org.apache.nifi.documentation.ConfigurableComponentInitializer;
+import org.apache.nifi.documentation.mock.MockProcessContext;
 import org.apache.nifi.documentation.mock.MockProcessorInitializationContext;
+import org.apache.nifi.documentation.mock.MockProcessorLogger;
+import org.apache.nifi.documentation.util.ReflectionUtils;
+import org.apache.nifi.logging.ProcessorLog;
 import org.apache.nifi.nar.NarCloseable;
 import org.apache.nifi.processor.Processor;
 
@@ -34,7 +40,11 @@ public class ProcessorInitializer implements 
ConfigurableComponentInitializer {
         Processor processor = (Processor) component;
         try (NarCloseable narCloseable = NarCloseable.withNarLoader()) {
             processor.initialize(new MockProcessorInitializationContext());
+
+            final ProcessorLog logger = new MockProcessorLogger();
+            final MockProcessContext context = new MockProcessContext();
+            
ReflectionUtils.quietlyInvokeMethodsWithAnnotations(OnRemoved.class, null, 
processor, logger, context);
+            
ReflectionUtils.quietlyInvokeMethodsWithAnnotations(OnShutdown.class, null, 
processor, logger, context);
         }
     }
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53b86d7a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/init/ReportingTaskingInitializer.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/init/ReportingTaskingInitializer.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/init/ReportingTaskingInitializer.java
index 49291a7..90642e4 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/init/ReportingTaskingInitializer.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/init/ReportingTaskingInitializer.java
@@ -16,9 +16,14 @@
  */
 package org.apache.nifi.documentation.init;
 
+import org.apache.nifi.annotation.lifecycle.OnRemoved;
+import org.apache.nifi.annotation.lifecycle.OnShutdown;
 import org.apache.nifi.components.ConfigurableComponent;
 import org.apache.nifi.documentation.ConfigurableComponentInitializer;
+import org.apache.nifi.documentation.mock.MockConfigurationContext;
+import org.apache.nifi.documentation.mock.MockProcessorLogger;
 import org.apache.nifi.documentation.mock.MockReportingInitializationContext;
+import org.apache.nifi.documentation.util.ReflectionUtils;
 import org.apache.nifi.nar.NarCloseable;
 import org.apache.nifi.reporting.InitializationException;
 import org.apache.nifi.reporting.ReportingTask;
@@ -35,6 +40,10 @@ public class ReportingTaskingInitializer implements 
ConfigurableComponentInitial
         ReportingTask reportingTask = (ReportingTask) component;
         try (NarCloseable narCloseable = NarCloseable.withNarLoader()) {
             reportingTask.initialize(new MockReportingInitializationContext());
+
+            final MockConfigurationContext context = new 
MockConfigurationContext();
+            
ReflectionUtils.quietlyInvokeMethodsWithAnnotations(OnRemoved.class, null, 
reportingTask, new MockProcessorLogger(), context);
+            
ReflectionUtils.quietlyInvokeMethodsWithAnnotations(OnShutdown.class, null, 
reportingTask, new MockProcessorLogger(), context);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53b86d7a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/mock/MockConfigurationContext.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/mock/MockConfigurationContext.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/mock/MockConfigurationContext.java
new file mode 100644
index 0000000..1ba5499
--- /dev/null
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/mock/MockConfigurationContext.java
@@ -0,0 +1,38 @@
+/*
+ * 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.documentation.mock;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.PropertyValue;
+import org.apache.nifi.controller.ConfigurationContext;
+
+public class MockConfigurationContext implements ConfigurationContext {
+
+    @Override
+    public PropertyValue getProperty(PropertyDescriptor property) {
+        return null;
+    }
+
+    @Override
+    public Map<PropertyDescriptor, String> getProperties() {
+        return Collections.emptyMap();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53b86d7a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/mock/MockProcessContext.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/mock/MockProcessContext.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/mock/MockProcessContext.java
new file mode 100644
index 0000000..76d7d3d
--- /dev/null
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/mock/MockProcessContext.java
@@ -0,0 +1,85 @@
+/*
+ * 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.documentation.mock;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.PropertyValue;
+import org.apache.nifi.controller.ControllerServiceLookup;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.Relationship;
+
+public class MockProcessContext implements ProcessContext {
+
+    @Override
+    public PropertyValue getProperty(PropertyDescriptor descriptor) {
+        return null;
+    }
+
+    @Override
+    public PropertyValue getProperty(String propertyName) {
+        return null;
+    }
+
+    @Override
+    public PropertyValue newPropertyValue(String rawValue) {
+        return null;
+    }
+
+    @Override
+    public void yield() {
+
+    }
+
+    @Override
+    public int getMaxConcurrentTasks() {
+        return 0;
+    }
+
+    @Override
+    public String getAnnotationData() {
+        return "";
+    }
+
+    @Override
+    public Map<PropertyDescriptor, String> getProperties() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public String encrypt(String unencrypted) {
+        return unencrypted;
+    }
+
+    @Override
+    public String decrypt(String encrypted) {
+        return encrypted;
+    }
+
+    @Override
+    public ControllerServiceLookup getControllerServiceLookup() {
+        return new MockControllerServiceLookup();
+    }
+
+    @Override
+    public Set<Relationship> getAvailableRelationships() {
+        return Collections.emptySet();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53b86d7a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/util/ReflectionUtils.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/util/ReflectionUtils.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/util/ReflectionUtils.java
new file mode 100644
index 0000000..449bd07
--- /dev/null
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/main/java/org/apache/nifi/documentation/util/ReflectionUtils.java
@@ -0,0 +1,139 @@
+/*
+ * 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.documentation.util;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.nifi.logging.ProcessorLog;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class is a copy of org.apache.nifi.util.ReflectionUtils.  Ultimately 
the documentation generation
+ * component should be moved to a place where it can depend on this directly 
instead of copying it in.
+ *
+ *
+ */
+public class ReflectionUtils {
+
+    private final static Logger LOG = 
LoggerFactory.getLogger(ReflectionUtils.class);
+    /**
+     * Invokes all methods on the given instance that have been annotated with 
the given preferredAnnotation and if no such method exists will invoke all 
methods on the given instance that have been
+     * annotated with the given alternateAnnotation, if any exists. If the 
signature of the method that is defined in <code>instance</code> uses 1 or more 
parameters, those parameters must be
+     * specified by the <code>args</code> parameter. However, if more 
arguments are supplied by the <code>args</code> parameter than needed, the 
extra arguments will be ignored.
+     *
+     * @param preferredAnnotation preferred
+     * @param alternateAnnotation alternate
+     * @param instance instance
+     * @param logger the ProcessorLog to use for logging any errors. If null, 
will use own logger, but that will not generate bulletins or easily tie to the 
Processor's log messages.
+     * @param args args
+     * @return <code>true</code> if all appropriate methods were invoked and 
returned without throwing an Exception, <code>false</code> if one of the 
methods threw an Exception or could not be
+     * invoked; if <code>false</code> is returned, an error will have been 
logged.
+     */
+    public static boolean quietlyInvokeMethodsWithAnnotations(
+            final Class<? extends Annotation> preferredAnnotation, final 
Class<? extends Annotation> alternateAnnotation, final Object instance, final 
ProcessorLog logger, final Object... args) {
+        final List<Class<? extends Annotation>> annotationClasses = new 
ArrayList<>(alternateAnnotation == null ? 1 : 2);
+        annotationClasses.add(preferredAnnotation);
+        if (alternateAnnotation != null) {
+            annotationClasses.add(alternateAnnotation);
+        }
+
+        boolean annotationFound = false;
+        for (final Class<? extends Annotation> annotationClass : 
annotationClasses) {
+            if (annotationFound) {
+                break;
+            }
+
+            for (final Method method : instance.getClass().getMethods()) {
+                if (method.isAnnotationPresent(annotationClass)) {
+                    annotationFound = true;
+
+                    final boolean isAccessible = method.isAccessible();
+                    method.setAccessible(true);
+
+                    try {
+                        final Class<?>[] argumentTypes = 
method.getParameterTypes();
+                        if (argumentTypes.length > args.length) {
+                            if (logger == null) {
+                                LOG.error("Unable to invoke method {} on {} 
because method expects {} parameters but only {} were given",
+                                        new Object[]{method.getName(), 
instance, argumentTypes.length, args.length});
+                            } else {
+                                logger.error("Unable to invoke method {} on {} 
because method expects {} parameters but only {} were given",
+                                        new Object[]{method.getName(), 
instance, argumentTypes.length, args.length});
+                            }
+
+                            return false;
+                        }
+
+                        for (int i = 0; i < argumentTypes.length; i++) {
+                            final Class<?> argType = argumentTypes[i];
+                            if (!argType.isAssignableFrom(args[i].getClass())) 
{
+                                if (logger == null) {
+                                    LOG.error("Unable to invoke method {} on 
{} because method parameter {} is expected to be of type {} but argument passed 
was of type {}",
+                                            new Object[]{method.getName(), 
instance, i, argType, args[i].getClass()});
+                                } else {
+                                    logger.error("Unable to invoke method {} 
on {} because method parameter {} is expected to be of type {} but argument 
passed was of type {}",
+                                            new Object[]{method.getName(), 
instance, i, argType, args[i].getClass()});
+                                }
+
+                                return false;
+                            }
+                        }
+
+                        try {
+                            if (argumentTypes.length == args.length) {
+                                method.invoke(instance, args);
+                            } else {
+                                final Object[] argsToPass = new 
Object[argumentTypes.length];
+                                for (int i = 0; i < argsToPass.length; i++) {
+                                    argsToPass[i] = args[i];
+                                }
+
+                                method.invoke(instance, argsToPass);
+                            }
+                        } catch (final InvocationTargetException ite) {
+                            if (logger == null) {
+                                LOG.error("Unable to invoke method {} on {} 
due to {}", new Object[]{method.getName(), instance, ite.getCause()});
+                                LOG.error("", ite.getCause());
+                            } else {
+                                logger.error("Unable to invoke method {} on {} 
due to {}", new Object[]{method.getName(), instance, ite.getCause()});
+                            }
+                        } catch (final IllegalAccessException | 
IllegalArgumentException t) {
+                            if (logger == null) {
+                                LOG.error("Unable to invoke method {} on {} 
due to {}", new Object[]{method.getName(), instance, t});
+                                LOG.error("", t);
+                            } else {
+                                logger.error("Unable to invoke method {} on {} 
due to {}", new Object[]{method.getName(), instance, t});
+                            }
+
+                            return false;
+                        }
+                    } finally {
+                        if (!isAccessible) {
+                            method.setAccessible(false);
+                        }
+                    }
+                }
+            }
+        }
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53b86d7a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedControllerService.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedControllerService.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedControllerService.java
index cd68267..ea5f622 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedControllerService.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedControllerService.java
@@ -22,26 +22,32 @@ import java.util.List;
 
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnRemoved;
+import org.apache.nifi.annotation.lifecycle.OnShutdown;
 import org.apache.nifi.components.PropertyDescriptor;
 import org.apache.nifi.controller.AbstractControllerService;
+import org.apache.nifi.controller.ConfigurationContext;
 import org.apache.nifi.processor.util.StandardValidators;
 
-@CapabilityDescription("A documented controller service that can help you do 
things")
-@Tags({"one", "two", "three"})
-public class FullyDocumentedControllerService extends 
AbstractControllerService implements SampleService{
+@CapabilityDescription("A documented controller service that can help you do 
things")
+@Tags({ "one", "two", "three" })
+public class FullyDocumentedControllerService extends 
AbstractControllerService implements SampleService {
 
-    public static final PropertyDescriptor KEYSTORE = new 
PropertyDescriptor.Builder().name("Keystore Filename")
-            .description("The fully-qualified filename of the 
Keystore").defaultValue(null)
+    public static final PropertyDescriptor KEYSTORE = new 
PropertyDescriptor.Builder().name("Keystore Filename").description("The 
fully-qualified filename of the Keystore").defaultValue(null)
             
.addValidator(StandardValidators.FILE_EXISTS_VALIDATOR).sensitive(false).build();
-    public static final PropertyDescriptor KEYSTORE_TYPE = new 
PropertyDescriptor.Builder().name("Keystore Type")
-            .description("The Type of the Keystore").allowableValues("JKS", 
"PKCS12")
+    public static final PropertyDescriptor KEYSTORE_TYPE = new 
PropertyDescriptor.Builder().name("Keystore Type").description("The Type of the 
Keystore").allowableValues("JKS", "PKCS12")
             
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR).defaultValue("JKS").sensitive(false).build();
-    public static final PropertyDescriptor KEYSTORE_PASSWORD = new 
PropertyDescriptor.Builder()
-            .name("Keystore Password").defaultValue(null).description("The 
password for the Keystore")
+    public static final PropertyDescriptor KEYSTORE_PASSWORD = new 
PropertyDescriptor.Builder().name("Keystore 
Password").defaultValue(null).description("The password for the Keystore")
             
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR).sensitive(true).build();
 
     private static final List<PropertyDescriptor> properties;
 
+    private int onRemovedNoArgs = 0;
+    private int onRemovedArgs = 0;
+
+    private int onShutdownNoArgs = 0;
+    private int onShutdownArgs = 0;
+
     static {
         List<PropertyDescriptor> props = new ArrayList<>();
         props.add(KEYSTORE);
@@ -53,10 +59,45 @@ public class FullyDocumentedControllerService extends 
AbstractControllerService
     @Override
     protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
         return properties;
-    }
+    }
 
     @Override
     public void doSomething() {
-        // TODO Auto-generated method stub
+    }
+
+    @OnRemoved
+    public void onRemovedNoArgs() {
+        onRemovedNoArgs++;
+    }
+
+    @OnRemoved
+    public void onRemovedArgs(ConfigurationContext context) {
+        onRemovedArgs++;
+    }
+
+    @OnShutdown
+    public void onShutdownNoArgs() {
+        onShutdownNoArgs++;
+    }
+
+    @OnShutdown
+    public void onShutdownArgs(ConfigurationContext context) {
+        onShutdownArgs++;
+    }
+
+    public int getOnRemovedNoArgs() {
+        return onRemovedNoArgs;
+    }
+
+    public int getOnRemovedArgs() {
+        return onRemovedArgs;
+    }
+
+    public int getOnShutdownNoArgs() {
+        return onShutdownNoArgs;
+    }
+
+    public int getOnShutdownArgs() {
+        return onShutdownArgs;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53b86d7a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedProcessor.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedProcessor.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedProcessor.java
index 178a144..379c10b 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedProcessor.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedProcessor.java
@@ -23,13 +23,15 @@ import java.util.List;
 import java.util.Set;
 
 import org.apache.nifi.annotation.behavior.DynamicProperty;
-import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.annotation.behavior.DynamicRelationship;
 import org.apache.nifi.annotation.behavior.ReadsAttribute;
-import org.apache.nifi.annotation.documentation.SeeAlso;
-import org.apache.nifi.annotation.documentation.Tags;
 import org.apache.nifi.annotation.behavior.WritesAttribute;
 import org.apache.nifi.annotation.behavior.WritesAttributes;
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.SeeAlso;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnRemoved;
+import org.apache.nifi.annotation.lifecycle.OnShutdown;
 import org.apache.nifi.components.AllowableValue;
 import org.apache.nifi.components.PropertyDescriptor;
 import org.apache.nifi.processor.AbstractProcessor;
@@ -88,6 +90,12 @@ public class FullyDocumentedProcessor extends 
AbstractProcessor {
     private List<PropertyDescriptor> properties;
     private Set<Relationship> relationships;
 
+    private int onRemovedNoArgs = 0;
+    private int onRemovedArgs = 0;
+
+    private int onShutdownNoArgs = 0;
+    private int onShutdownArgs = 0;
+
     @Override
     protected void init(ProcessorInitializationContext context) {
         final List<PropertyDescriptor> properties = new ArrayList<>();
@@ -126,4 +134,39 @@ public class FullyDocumentedProcessor extends 
AbstractProcessor {
                 .description("This is a property you can use or 
not").dynamic(true).build();
     }
 
+    @OnRemoved
+    public void onRemovedNoArgs() {
+        onRemovedNoArgs++;
+    }
+
+    @OnRemoved
+    public void onRemovedArgs(ProcessContext context) {
+        onRemovedArgs++;
+    }
+
+    @OnShutdown
+    public void onShutdownNoArgs() {
+        onShutdownNoArgs++;
+    }
+
+    @OnShutdown
+    public void onShutdownArgs(ProcessContext context) {
+        onShutdownArgs++;
+    }
+
+    public int getOnRemovedNoArgs() {
+        return onRemovedNoArgs;
+    }
+
+    public int getOnRemovedArgs() {
+        return onRemovedArgs;
+    }
+
+    public int getOnShutdownNoArgs() {
+        return onShutdownNoArgs;
+    }
+
+    public int getOnShutdownArgs() {
+        return onShutdownArgs;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53b86d7a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedReportingTask.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedReportingTask.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedReportingTask.java
index 17e446a..43929be 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedReportingTask.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/example/FullyDocumentedReportingTask.java
@@ -20,8 +20,11 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.controller.ConfigurationContext;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnRemoved;
+import org.apache.nifi.annotation.lifecycle.OnShutdown;
 import org.apache.nifi.reporting.AbstractReportingTask;
 import org.apache.nifi.reporting.ReportingContext;
 
@@ -35,6 +38,12 @@ public class FullyDocumentedReportingTask extends 
AbstractReportingTask {
                     "Specifies whether or not to show the difference in values 
between the current status and the previous status")
             .required(true).allowableValues("true", 
"false").defaultValue("true").build();
 
+    private int onRemovedNoArgs = 0;
+    private int onRemovedArgs = 0;
+
+    private int onShutdownNoArgs = 0;
+    private int onShutdownArgs = 0;
+
     @Override
     public final List<PropertyDescriptor> getSupportedPropertyDescriptors() {
         final List<PropertyDescriptor> descriptors = new ArrayList<>();
@@ -44,7 +53,42 @@ public class FullyDocumentedReportingTask extends 
AbstractReportingTask {
 
     @Override
     public void onTrigger(ReportingContext context) {
-        // TODO Auto-generated method stub
 
     }
+
+    @OnRemoved
+    public void onRemovedNoArgs() {
+        onRemovedNoArgs++;
+    }
+
+    @OnRemoved
+    public void onRemovedArgs(ConfigurationContext context) {
+        onRemovedArgs++;
+    }
+
+    @OnShutdown
+    public void onShutdownNoArgs() {
+        onShutdownNoArgs++;
+    }
+
+    @OnShutdown
+    public void onShutdownArgs(ConfigurationContext context) {
+        onShutdownArgs++;
+    }
+
+    public int getOnRemovedNoArgs() {
+        return onRemovedNoArgs;
+    }
+
+    public int getOnRemovedArgs() {
+        return onRemovedArgs;
+    }
+
+    public int getOnShutdownNoArgs() {
+        return onShutdownNoArgs;
+    }
+
+    public int getOnShutdownArgs() {
+        return onShutdownArgs;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53b86d7a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/HtmlDocumentationWriterTest.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/HtmlDocumentationWriterTest.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/HtmlDocumentationWriterTest.java
index 9179ed2..d85e19b 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/HtmlDocumentationWriterTest.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/HtmlDocumentationWriterTest.java
@@ -28,26 +28,30 @@ import 
org.apache.nifi.documentation.example.ControllerServiceWithLogger;
 import org.apache.nifi.documentation.example.FullyDocumentedControllerService;
 import org.apache.nifi.documentation.example.FullyDocumentedReportingTask;
 import org.apache.nifi.documentation.example.ReportingTaskWithLogger;
+import org.apache.nifi.documentation.init.ControllerServiceInitializer;
+import org.apache.nifi.documentation.init.ReportingTaskingInitializer;
 import 
org.apache.nifi.documentation.mock.MockControllerServiceInitializationContext;
 import org.apache.nifi.documentation.mock.MockReportingInitializationContext;
 import org.apache.nifi.reporting.InitializationException;
 import org.apache.nifi.reporting.ReportingTask;
+import org.junit.Assert;
 import org.junit.Test;
 
 public class HtmlDocumentationWriterTest {
 
     @Test
     public void testJoin() {
-        assertEquals("a, b, c", HtmlDocumentationWriter.join(new String[]{"a", 
"b", "c"}, ", "));
-        assertEquals("a, b", HtmlDocumentationWriter.join(new String[]{"a", 
"b"}, ", "));
-        assertEquals("a", HtmlDocumentationWriter.join(new String[]{"a"}, ", 
"));
+        assertEquals("a, b, c", HtmlDocumentationWriter.join(new String[] { 
"a", "b", "c" }, ", "));
+        assertEquals("a, b", HtmlDocumentationWriter.join(new String[] { "a", 
"b" }, ", "));
+        assertEquals("a", HtmlDocumentationWriter.join(new String[] { "a" }, 
", "));
     }
 
     @Test
     public void testDocumentControllerService() throws 
InitializationException, IOException {
 
-        ControllerService controllerService = new 
FullyDocumentedControllerService();
-        controllerService.initialize(new 
MockControllerServiceInitializationContext());
+        FullyDocumentedControllerService controllerService = new 
FullyDocumentedControllerService();
+        ControllerServiceInitializer initializer = new 
ControllerServiceInitializer();
+        initializer.initialize(controllerService);
 
         DocumentationWriter writer = new HtmlDocumentationWriter();
 
@@ -71,13 +75,21 @@ public class HtmlDocumentationWriterTest {
         assertContains(results, "JKS");
         assertContains(results, "PKCS12");
         assertContains(results, "Sensitive Property: true");
+
+        // verify the right OnRemoved and OnShutdown methods were called
+        Assert.assertEquals(1, controllerService.getOnRemovedArgs());
+        Assert.assertEquals(1, controllerService.getOnRemovedNoArgs());
+
+        Assert.assertEquals(1, controllerService.getOnShutdownArgs());
+        Assert.assertEquals(1, controllerService.getOnShutdownNoArgs());
     }
 
     @Test
     public void testDocumentReportingTask() throws InitializationException, 
IOException {
 
-        ReportingTask reportingTask = new FullyDocumentedReportingTask();
-        reportingTask.initialize(new MockReportingInitializationContext());
+        FullyDocumentedReportingTask reportingTask = new 
FullyDocumentedReportingTask();
+        ReportingTaskingInitializer initializer = new 
ReportingTaskingInitializer();
+        initializer.initialize(reportingTask);
 
         DocumentationWriter writer = new HtmlDocumentationWriter();
 
@@ -99,6 +111,13 @@ public class HtmlDocumentationWriterTest {
         assertContains(results, "Specifies whether or not to show the 
difference in values between the current status and the previous status");
         assertContains(results, "true");
         assertContains(results, "false");
+
+        // verify the right OnRemoved and OnShutdown methods were called
+        Assert.assertEquals(1, reportingTask.getOnRemovedArgs());
+        Assert.assertEquals(1, reportingTask.getOnRemovedNoArgs());
+
+        Assert.assertEquals(1, reportingTask.getOnShutdownArgs());
+        Assert.assertEquals(1, reportingTask.getOnShutdownNoArgs());
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/53b86d7a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/ProcessorDocumentationWriterTest.java
----------------------------------------------------------------------
diff --git 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/ProcessorDocumentationWriterTest.java
 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/ProcessorDocumentationWriterTest.java
index c421148..fda81fd 100644
--- 
a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/ProcessorDocumentationWriterTest.java
+++ 
b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/src/test/java/org/apache/nifi/documentation/html/ProcessorDocumentationWriterTest.java
@@ -27,7 +27,8 @@ import org.apache.nifi.documentation.DocumentationWriter;
 import org.apache.nifi.documentation.example.FullyDocumentedProcessor;
 import org.apache.nifi.documentation.example.NakedProcessor;
 import org.apache.nifi.documentation.example.ProcessorWithLogger;
-import org.apache.nifi.documentation.mock.MockProcessorInitializationContext;
+import org.apache.nifi.documentation.init.ProcessorInitializer;
+import org.junit.Assert;
 import org.junit.Test;
 
 public class ProcessorDocumentationWriterTest {
@@ -35,7 +36,8 @@ public class ProcessorDocumentationWriterTest {
     @Test
     public void testFullyDocumentedProcessor() throws IOException {
         FullyDocumentedProcessor processor = new FullyDocumentedProcessor();
-        processor.initialize(new MockProcessorInitializationContext());
+        ProcessorInitializer initializer = new ProcessorInitializer();
+        initializer.initialize(processor);
 
         DocumentationWriter writer = new HtmlProcessorDocumentationWriter();
 
@@ -70,12 +72,20 @@ public class ProcessorDocumentationWriterTest {
         assertNotContains(results, "No description provided.");
         assertNotContains(results, "No Tags provided.");
         assertNotContains(results, "Additional Details...");
+
+        // verify the right OnRemoved and OnShutdown methods were called
+        Assert.assertEquals(1, processor.getOnRemovedArgs());
+        Assert.assertEquals(1, processor.getOnRemovedNoArgs());
+
+        Assert.assertEquals(1, processor.getOnShutdownArgs());
+        Assert.assertEquals(1, processor.getOnShutdownNoArgs());
     }
 
     @Test
     public void testNakedProcessor() throws IOException {
         NakedProcessor processor = new NakedProcessor();
-        processor.initialize(new MockProcessorInitializationContext());
+        ProcessorInitializer initializer = new ProcessorInitializer();
+        initializer.initialize(processor);
 
         DocumentationWriter writer = new HtmlProcessorDocumentationWriter();
 
@@ -103,7 +113,8 @@ public class ProcessorDocumentationWriterTest {
     @Test
     public void testProcessorWithLoggerInitialization() throws IOException {
         ProcessorWithLogger processor = new ProcessorWithLogger();
-        processor.initialize(new MockProcessorInitializationContext());
+        ProcessorInitializer initializer = new ProcessorInitializer();
+        initializer.initialize(processor);
 
         DocumentationWriter writer = new HtmlProcessorDocumentationWriter();
 


Reply via email to