http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockProcessContext.java
----------------------------------------------------------------------
diff --git 
a/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockProcessContext.java
 
b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockProcessContext.java
new file mode 100644
index 0000000..76d7d3d
--- /dev/null
+++ 
b/nifi-documentation-plugin/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/nifi/blob/af87b52b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockProcessorInitializationContext.java
----------------------------------------------------------------------
diff --git 
a/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockProcessorInitializationContext.java
 
b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockProcessorInitializationContext.java
new file mode 100644
index 0000000..2b6ccc2
--- /dev/null
+++ 
b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockProcessorInitializationContext.java
@@ -0,0 +1,45 @@
+/*
+ * 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 org.apache.nifi.controller.ControllerServiceLookup;
+import org.apache.nifi.logging.ProcessorLog;
+import org.apache.nifi.processor.ProcessorInitializationContext;
+
+/**
+ * A Mock ProcessorInitializationContext that can be used so that Processors 
can
+ * be initialized for the purpose of generating documentation.
+ *
+ *
+ */
+public class MockProcessorInitializationContext implements 
ProcessorInitializationContext {
+
+    @Override
+    public String getIdentifier() {
+        return "mock-processor";
+    }
+
+    @Override
+    public ProcessorLog getLogger() {
+        return new MockProcessorLogger();
+    }
+
+    @Override
+    public ControllerServiceLookup getControllerServiceLookup() {
+        return new MockControllerServiceLookup();
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockProcessorLogger.java
----------------------------------------------------------------------
diff --git 
a/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockProcessorLogger.java
 
b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockProcessorLogger.java
new file mode 100644
index 0000000..82a5f8b
--- /dev/null
+++ 
b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockProcessorLogger.java
@@ -0,0 +1,169 @@
+/*
+ * 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 org.apache.nifi.logging.ProcessorLog;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Stubs out the functionality of a ProcessorLog/ComponentLog so that it can
+ * be used during initialization of a component.
+ *
+ */
+public class MockProcessorLogger implements ProcessorLog {
+
+    private static final Logger logger = LoggerFactory
+            .getLogger(MockProcessorLogger.class);
+
+    @Override
+    public void warn(String msg, Throwable t) {
+        logger.warn(msg, t);
+    }
+
+    @Override
+    public void warn(String msg, Object[] os) {
+        logger.warn(msg, os);
+    }
+
+    @Override
+    public void warn(String msg, Object[] os, Throwable t) {
+        logger.warn(msg, os);
+        logger.warn("", t);
+    }
+
+    @Override
+    public void warn(String msg) {
+        logger.warn(msg);
+    }
+
+    @Override
+    public void trace(String msg, Throwable t) {
+        logger.trace(msg, t);
+    }
+
+    @Override
+    public void trace(String msg, Object[] os) {
+        logger.trace(msg, os);
+    }
+
+    @Override
+    public void trace(String msg) {
+        logger.trace(msg);
+    }
+
+    @Override
+    public void trace(String msg, Object[] os, Throwable t) {
+        logger.trace(msg, os);
+        logger.trace("", t);
+    }
+
+    @Override
+    public boolean isWarnEnabled() {
+        return logger.isWarnEnabled();
+    }
+
+    @Override
+    public boolean isTraceEnabled() {
+        return logger.isTraceEnabled();
+    }
+
+    @Override
+    public boolean isInfoEnabled() {
+        return logger.isInfoEnabled();
+    }
+
+    @Override
+    public boolean isErrorEnabled() {
+        return logger.isErrorEnabled();
+    }
+
+    @Override
+    public boolean isDebugEnabled() {
+        return logger.isDebugEnabled();
+    }
+
+    @Override
+    public void info(String msg, Throwable t) {
+        logger.info(msg, t);
+    }
+
+    @Override
+    public void info(String msg, Object[] os) {
+        logger.info(msg, os);
+    }
+
+    @Override
+    public void info(String msg) {
+        logger.info(msg);
+
+    }
+
+    @Override
+    public void info(String msg, Object[] os, Throwable t) {
+        logger.trace(msg, os);
+        logger.trace("", t);
+
+    }
+
+    @Override
+    public String getName() {
+        return logger.getName();
+    }
+
+    @Override
+    public void error(String msg, Throwable t) {
+        logger.error(msg, t);
+    }
+
+    @Override
+    public void error(String msg, Object[] os) {
+        logger.error(msg, os);
+    }
+
+    @Override
+    public void error(String msg) {
+        logger.error(msg);
+    }
+
+    @Override
+    public void error(String msg, Object[] os, Throwable t) {
+        logger.error(msg, os);
+        logger.error("", t);
+    }
+
+    @Override
+    public void debug(String msg, Throwable t) {
+        logger.debug(msg, t);
+    }
+
+    @Override
+    public void debug(String msg, Object[] os) {
+        logger.debug(msg, os);
+    }
+
+    @Override
+    public void debug(String msg, Object[] os, Throwable t) {
+        logger.debug(msg, os);
+        logger.debug("", t);
+    }
+
+    @Override
+    public void debug(String msg) {
+        logger.debug(msg);
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockReportingInitializationContext.java
----------------------------------------------------------------------
diff --git 
a/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockReportingInitializationContext.java
 
b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockReportingInitializationContext.java
new file mode 100644
index 0000000..9d0db64
--- /dev/null
+++ 
b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockReportingInitializationContext.java
@@ -0,0 +1,67 @@
+/*
+ * 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.concurrent.TimeUnit;
+
+import org.apache.nifi.controller.ControllerServiceLookup;
+import org.apache.nifi.logging.ComponentLog;
+import org.apache.nifi.reporting.ReportingInitializationContext;
+import org.apache.nifi.scheduling.SchedulingStrategy;
+
+/**
+ * A Mock ReportingInitializationContext that can be used to initialize a
+ * ReportingTask for the purposes of documentation generation.
+ *
+ */
+public class MockReportingInitializationContext implements 
ReportingInitializationContext {
+
+    @Override
+    public String getIdentifier() {
+        return "mock-reporting-task";
+    }
+
+    @Override
+    public String getName() {
+        return "";
+    }
+
+    @Override
+    public long getSchedulingPeriod(TimeUnit timeUnit) {
+        return 0;
+    }
+
+    @Override
+    public ControllerServiceLookup getControllerServiceLookup() {
+        return new MockControllerServiceLookup();
+    }
+
+    @Override
+    public String getSchedulingPeriod() {
+        return "";
+    }
+
+    @Override
+    public SchedulingStrategy getSchedulingStrategy() {
+        return SchedulingStrategy.TIMER_DRIVEN;
+    }
+
+    @Override
+    public ComponentLog getLogger() {
+        return new MockProcessorLogger();
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/util/ReflectionUtils.java
----------------------------------------------------------------------
diff --git 
a/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/util/ReflectionUtils.java
 
b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/util/ReflectionUtils.java
new file mode 100644
index 0000000..449bd07
--- /dev/null
+++ 
b/nifi-documentation-plugin/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;
+    }
+}

Reply via email to