NIFI-725 - adding nifi-documentation-plugin
Project: http://git-wip-us.apache.org/repos/asf/nifi/repo Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/af87b52b Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/af87b52b Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/af87b52b Branch: refs/heads/NIFI-725-master Commit: af87b52b8657582d6e0dec162d760a85d35eccfa Parents: 1d19a34 Author: danbress <[email protected]> Authored: Tue Aug 18 21:46:18 2015 -0400 Committer: danbress <[email protected]> Committed: Tue Aug 18 21:46:18 2015 -0400 ---------------------------------------------------------------------- nifi-documentation-plugin/pom.xml | 113 ++++ nifi-documentation-plugin/src/it/settings.xml | 55 ++ .../src/it/simple-it/pom.xml | 34 + .../src/it/simple-it/verify.groovy | 3 + .../main/java/org/apache/nifi/DocumentMojo.java | 177 ++++++ .../org/apache/nifi/ExtractDocumentation.java | 111 ++++ .../org/apache/nifi/NoCloseInputStream.java | 32 + .../ConfigurableComponentInitializer.java | 45 ++ .../nifi/documentation/DocumentationWriter.java | 33 + .../html/HtmlDocumentationWriter.java | 615 +++++++++++++++++++ .../html/HtmlProcessorDocumentationWriter.java | 256 ++++++++ .../init/ControllerServiceInitializer.java | 53 ++ .../init/ProcessorInitializer.java | 53 ++ .../init/ReportingTaskingInitializer.java | 52 ++ .../mock/MockConfigurationContext.java | 48 ++ ...kControllerServiceInitializationContext.java | 46 ++ .../mock/MockControllerServiceLookup.java | 65 ++ .../documentation/mock/MockProcessContext.java | 85 +++ .../MockProcessorInitializationContext.java | 45 ++ .../documentation/mock/MockProcessorLogger.java | 169 +++++ .../MockReportingInitializationContext.java | 67 ++ .../documentation/util/ReflectionUtils.java | 139 +++++ 22 files changed, 2296 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/pom.xml ---------------------------------------------------------------------- diff --git a/nifi-documentation-plugin/pom.xml b/nifi-documentation-plugin/pom.xml new file mode 100644 index 0000000..cc5e160 --- /dev/null +++ b/nifi-documentation-plugin/pom.xml @@ -0,0 +1,113 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <!-- + 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. + --> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache</groupId> + <artifactId>apache</artifactId> + <version>17</version> + <relativePath /> + </parent> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-documentation-plugin</artifactId> + <version>1.0.0-SNAPSHOT</version> + <packaging>maven-plugin</packaging> + + <name>nifi-documentation-plugin Maven Plugin</name> + + <!-- FIXME change it to the project's website --> + <url>http://maven.apache.org</url> + + <properties> + <maven.compiler.source>1.7</maven.compiler.source> + <maven.compiler.target>1.7</maven.compiler.target> + <maven.min-version>3.0.5</maven.min-version> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + <inceptionYear>2014</inceptionYear> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-plugin-api</artifactId> + <version>2.2.1</version> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-project</artifactId> + <version>2.2.1</version> + </dependency> + <dependency> + <groupId>org.apache.maven.plugin-tools</groupId> + <artifactId>maven-plugin-annotations</artifactId> + <version>3.3</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-utils</artifactId> + <version>3.0.8</version> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.8.2</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-api</artifactId> + <version>0.2.1</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>1.7.12</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + <version>17.0</version> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-plugin-plugin</artifactId> + <executions> + <execution> + <id>default-descriptor</id> + <goals> + <goal>descriptor</goal> + </goals> + <phase>process-classes</phase> + </execution> + <execution> + <id>help-descriptor</id> + <goals> + <goal>helpmojo</goal> + </goals> + <phase>process-classes</phase> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/src/it/settings.xml ---------------------------------------------------------------------- diff --git a/nifi-documentation-plugin/src/it/settings.xml b/nifi-documentation-plugin/src/it/settings.xml new file mode 100644 index 0000000..dc02120 --- /dev/null +++ b/nifi-documentation-plugin/src/it/settings.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- +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. +--> + +<settings> + <profiles> + <profile> + <id>it-repo</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + <repositories> + <repository> + <id>local.central</id> + <url>@localRepositoryUrl@</url> + <releases> + <enabled>true</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </repository> + </repositories> + <pluginRepositories> + <pluginRepository> + <id>local.central</id> + <url>@localRepositoryUrl@</url> + <releases> + <enabled>true</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </pluginRepository> + </pluginRepositories> + </profile> + </profiles> +</settings> http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/src/it/simple-it/pom.xml ---------------------------------------------------------------------- diff --git a/nifi-documentation-plugin/src/it/simple-it/pom.xml b/nifi-documentation-plugin/src/it/simple-it/pom.xml new file mode 100644 index 0000000..c8b4d7a --- /dev/null +++ b/nifi-documentation-plugin/src/it/simple-it/pom.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>org.apache.nifi.it</groupId> + <artifactId>simple-it</artifactId> + <version>1.0-SNAPSHOT</version> + + <description>A simple IT verifying the basic use case.</description> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <build> + <plugins> + <plugin> + <groupId>@project.groupId@</groupId> + <artifactId>@project.artifactId@</artifactId> + <version>@project.version@</version> + <executions> + <execution> + <id>touch</id> + <phase>validate</phase> + <goals> + <goal>touch</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/src/it/simple-it/verify.groovy ---------------------------------------------------------------------- diff --git a/nifi-documentation-plugin/src/it/simple-it/verify.groovy b/nifi-documentation-plugin/src/it/simple-it/verify.groovy new file mode 100644 index 0000000..ff79813 --- /dev/null +++ b/nifi-documentation-plugin/src/it/simple-it/verify.groovy @@ -0,0 +1,3 @@ +File touchFile = new File( basedir, "target/touch.txt" ); + +assert touchFile.isFile() http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/src/main/java/org/apache/nifi/DocumentMojo.java ---------------------------------------------------------------------- diff --git a/nifi-documentation-plugin/src/main/java/org/apache/nifi/DocumentMojo.java b/nifi-documentation-plugin/src/main/java/org/apache/nifi/DocumentMojo.java new file mode 100644 index 0000000..bd97149 --- /dev/null +++ b/nifi-documentation-plugin/src/main/java/org/apache/nifi/DocumentMojo.java @@ -0,0 +1,177 @@ +/* + * 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; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.List; +import java.util.ServiceConfigurationError; +import java.util.ServiceLoader; + +import org.apache.maven.artifact.DependencyResolutionRequiredException; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.project.MavenProject; +import org.apache.nifi.components.ConfigurableComponent; +import org.apache.nifi.controller.ControllerService; +import org.apache.nifi.documentation.ConfigurableComponentInitializer; +import org.apache.nifi.documentation.html.HtmlDocumentationWriter; +import org.apache.nifi.documentation.html.HtmlProcessorDocumentationWriter; +import org.apache.nifi.documentation.init.ControllerServiceInitializer; +import org.apache.nifi.documentation.init.ProcessorInitializer; +import org.apache.nifi.documentation.init.ReportingTaskingInitializer; +import org.apache.nifi.processor.Processor; +import org.apache.nifi.reporting.InitializationException; +import org.apache.nifi.reporting.ReportingTask; + +@Mojo(name = "document", defaultPhase = LifecyclePhase.PROCESS_CLASSES, threadSafe = false, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, requiresProject = true) +public class DocumentMojo extends AbstractMojo { + + /** + * Location of the file. + */ + @Parameter(defaultValue = "${project.build.outputDirectory}", property = "outputDir", required = true) + private File outputDirectory; + + @Parameter(defaultValue = "${project}", required = true) + private MavenProject mavenProject; + + public void execute() throws MojoExecutionException { + final File docsDir = new File(outputDirectory, "docs"); + if (!docsDir.exists()) { + docsDir.mkdirs(); + } + + try { + final List<?> compileClassPathElements = mavenProject.getCompileClasspathElements(); + // final List<?> compileClassPathElements = mavenProject.getRuntimeClasspathElements(); + final URL[] urls = new URL[compileClassPathElements.size()]; + + for (int i = 0; i < compileClassPathElements.size(); i++) { + final String path = compileClassPathElements.get(i).toString(); + final File filePath = new File(path); + final URL url = filePath.toURI().toURL(); + urls[i] = url; + getLog().info("Adding url: " + url); + } + + final ClassLoader myClassLoader = Thread.currentThread().getContextClassLoader(); + final ClassLoader projectClassLoader = new URLClassLoader(urls, myClassLoader); + + final List<ConfigurableComponent> components = new ArrayList<>(); + loadServices(projectClassLoader, components, Processor.class); + loadServices(projectClassLoader, components, ControllerService.class); + loadServices(projectClassLoader, components, ReportingTask.class); + + for (ConfigurableComponent component : components) { + initializeComponent(component); + generateDocumentation(component, projectClassLoader, docsDir); + tearDownComponent(component); + } + + } catch (DependencyResolutionRequiredException e) { + throw new MojoExecutionException("Unable to resolve classpath", e); + } catch (MalformedURLException e) { + throw new MojoExecutionException("Unable to resolve classpath", e); + } catch (InitializationException e) { + throw new MojoExecutionException("Unable to initializer component", e); + } catch (FileNotFoundException e) { + throw new MojoExecutionException("Unable to generate documentation", e); + } catch (IOException e) { + throw new MojoExecutionException("Unable to generate documentation", e); + } catch (ServiceConfigurationError e) { + throw new MojoExecutionException("Unable to generate documentation", e); + } + } + + private static <T extends ConfigurableComponent> void loadServices(final ClassLoader projectClassLoader, final List<ConfigurableComponent> components, final Class<T> service) { + final ServiceLoader<T> nifiServiceLoader = ServiceLoader.load(service, projectClassLoader); + + for (T processor : nifiServiceLoader) { + components.add(processor); + } + } + + private void tearDownComponent(ConfigurableComponent component) { + final ConfigurableComponentInitializer initializer; + if (component instanceof Processor) { + initializer = new ProcessorInitializer(); + } else if (component instanceof ReportingTask) { + initializer = new ReportingTaskingInitializer(); + } else if (component instanceof ControllerService) { + initializer = new ControllerServiceInitializer(); + } else { + throw new NullPointerException("Unknown type: " + component.getClass()); + } + + initializer.teardown(component); + + } + + private void generateDocumentation(ConfigurableComponent component, ClassLoader classLoader, File docsDirectory) throws FileNotFoundException, IOException { + final HtmlDocumentationWriter writer; + if (component instanceof Processor) { + writer = new HtmlProcessorDocumentationWriter(); + } else if (component instanceof ReportingTask) { + writer = new HtmlDocumentationWriter(); + } else if (component instanceof ControllerService) { + writer = new HtmlDocumentationWriter(); + } else { + throw new NullPointerException("Unknown type: " + component.getClass()); + } + + final String className = component.getClass().getName(); + + boolean hasAdditionalDetails = classLoader.getResource("docs" + File.separator + className + File.separator + "additionalDetails.html") != null; + final File componentDocumentationDir = new File(docsDirectory, className); + if (!componentDocumentationDir.exists()) { + componentDocumentationDir.mkdirs(); + } + + final File generatedFile = new File(componentDocumentationDir, "index.html"); + + try (FileOutputStream fos = new FileOutputStream(generatedFile); BufferedOutputStream bos = new BufferedOutputStream(fos)) { + writer.write(component, bos, hasAdditionalDetails); + } + } + + private void initializeComponent(ConfigurableComponent component) throws InitializationException { + final ConfigurableComponentInitializer initializer; + if (component instanceof Processor) { + initializer = new ProcessorInitializer(); + } else if (component instanceof ReportingTask) { + initializer = new ReportingTaskingInitializer(); + } else if (component instanceof ControllerService) { + initializer = new ControllerServiceInitializer(); + } else { + throw new NullPointerException("Unknown type: " + component.getClass()); + } + + initializer.initialize(component); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/src/main/java/org/apache/nifi/ExtractDocumentation.java ---------------------------------------------------------------------- diff --git a/nifi-documentation-plugin/src/main/java/org/apache/nifi/ExtractDocumentation.java b/nifi-documentation-plugin/src/main/java/org/apache/nifi/ExtractDocumentation.java new file mode 100644 index 0000000..957b757 --- /dev/null +++ b/nifi-documentation-plugin/src/main/java/org/apache/nifi/ExtractDocumentation.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.model.Dependency; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.project.MavenProject; + +import com.google.common.io.ByteStreams; + +@Mojo(name = "extract", defaultPhase = LifecyclePhase.GENERATE_RESOURCES, threadSafe = false, requiresProject = false, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME) +public class ExtractDocumentation extends AbstractMojo { + /** + * Location of the file. + */ + @Parameter(defaultValue = "${project.build.directory}", property = "outputDir", required = true) + private File outputDirectory; + + @Parameter(defaultValue = "${project}", required = true) + private MavenProject mavenProject; + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + + @SuppressWarnings("unchecked") + final List<Dependency> runtimeDependencies = mavenProject.getDependencies(); + + for (Dependency dependency : runtimeDependencies) { + getLog().debug("Looking at: " + dependency); + // TODO dedup + if (dependency.getType().equals("nar")) { + + final Artifact artifact = (Artifact) mavenProject.getArtifactMap().get(dependency.getGroupId() + ":" + dependency.getArtifactId()); + final File narFile = artifact.getFile(); + try (FileInputStream fos = new FileInputStream(narFile); BufferedInputStream bis = new BufferedInputStream(fos); JarInputStream jis = new JarInputStream(bis)) { + + JarEntry jarEntry = null; + + while ((jarEntry = jis.getNextJarEntry()) != null) { + if (jarEntry.getName().endsWith(".jar")) { + getLog().debug("Found a jar inside of a nar " + jarEntry + " -> " + narFile); + processJar(new NoCloseInputStream(jis)); + } + } + + } catch (IOException e) { + throw new MojoExecutionException("Unable to process: " + narFile, e); + } + + } + } + + } + + private void processJar(InputStream inputStream) throws IOException { + try (JarInputStream jis = new JarInputStream(inputStream)) { + JarEntry jarEntry = null; + + while ((jarEntry = jis.getNextJarEntry()) != null) { + + if (!jarEntry.isDirectory()) { + final String jarName = jarEntry.getName(); + if (jarName.startsWith("docs")) { + getLog().debug("Looking inside a jar at: " + jarEntry); + File outputFile = new File(outputDirectory, jarName); + File parentFile = outputFile.getParentFile(); + if (!parentFile.exists()) { + parentFile.mkdirs(); + } + + try (FileOutputStream fos = new FileOutputStream(outputFile)) { + ByteStreams.copy(jis, fos); + } + } + } + } + } + } + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/src/main/java/org/apache/nifi/NoCloseInputStream.java ---------------------------------------------------------------------- diff --git a/nifi-documentation-plugin/src/main/java/org/apache/nifi/NoCloseInputStream.java b/nifi-documentation-plugin/src/main/java/org/apache/nifi/NoCloseInputStream.java new file mode 100644 index 0000000..80b259e --- /dev/null +++ b/nifi-documentation-plugin/src/main/java/org/apache/nifi/NoCloseInputStream.java @@ -0,0 +1,32 @@ +/* + * 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; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + +public class NoCloseInputStream extends FilterInputStream { + + protected NoCloseInputStream(InputStream arg0) { + super(arg0); + } + + @Override + public void close() throws IOException { + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/ConfigurableComponentInitializer.java ---------------------------------------------------------------------- diff --git a/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/ConfigurableComponentInitializer.java b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/ConfigurableComponentInitializer.java new file mode 100644 index 0000000..ad21f21 --- /dev/null +++ b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/ConfigurableComponentInitializer.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; + +import org.apache.nifi.components.ConfigurableComponent; +import org.apache.nifi.reporting.InitializationException; + +/** + * An interface for initializing and tearing down a ConfigurableComponent. It is up to the + * implementer to call "init" so that you can call + * ConfigurableComponent.getPropertyDescriptors() + * + */ +public interface ConfigurableComponentInitializer { + + /** + * Initializes a configurable component to the point that you can call + * getPropertyDescriptors() on it + * + * @param component the component to initialize + * @throws InitializationException if the component could not be initialized + */ + void initialize(ConfigurableComponent component) throws InitializationException; + + /** + * Calls the lifecycle methods that should be called when a flow is shutdown. + * + * @param component the component to initialize + */ + void teardown(ConfigurableComponent component); +} http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/DocumentationWriter.java ---------------------------------------------------------------------- diff --git a/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/DocumentationWriter.java b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/DocumentationWriter.java new file mode 100644 index 0000000..d178636 --- /dev/null +++ b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/DocumentationWriter.java @@ -0,0 +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.documentation; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.nifi.components.ConfigurableComponent; + +/** + * Generates documentation for an instance of a ConfigurableComponent + * + * + */ +public interface DocumentationWriter { + + void write(ConfigurableComponent configurableComponent, OutputStream streamToWriteTo, + boolean includesAdditionalDocumentation) throws IOException; +} http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/html/HtmlDocumentationWriter.java ---------------------------------------------------------------------- diff --git a/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/html/HtmlDocumentationWriter.java b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/html/HtmlDocumentationWriter.java new file mode 100644 index 0000000..394897e --- /dev/null +++ b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/html/HtmlDocumentationWriter.java @@ -0,0 +1,615 @@ +/* + * 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.html; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javax.xml.stream.FactoryConfigurationError; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.nifi.annotation.behavior.DynamicProperties; +import org.apache.nifi.annotation.behavior.DynamicProperty; +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.components.AllowableValue; +import org.apache.nifi.components.ConfigurableComponent; +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.controller.ControllerService; +import org.apache.nifi.documentation.DocumentationWriter; + +import edu.emory.mathcs.backport.java.util.Collections; + +/** + * Generates HTML documentation for a ConfigurableComponent. This class is used + * to generate documentation for ControllerService and ReportingTask because + * they have no additional information. + * + * + */ +public class HtmlDocumentationWriter implements DocumentationWriter { + + /** + * The filename where additional user specified information may be stored. + */ + public static final String ADDITIONAL_DETAILS_HTML = "additionalDetails.html"; + + @Override + public void write(final ConfigurableComponent configurableComponent, final OutputStream streamToWriteTo, + final boolean includesAdditionalDocumentation) throws IOException { + + try { + XMLStreamWriter xmlStreamWriter = XMLOutputFactory.newInstance().createXMLStreamWriter( + streamToWriteTo, "UTF-8"); + xmlStreamWriter.writeDTD("<!DOCTYPE html>"); + xmlStreamWriter.writeStartElement("html"); + xmlStreamWriter.writeAttribute("lang", "en"); + writeHead(configurableComponent, xmlStreamWriter); + writeBody(configurableComponent, xmlStreamWriter, includesAdditionalDocumentation); + xmlStreamWriter.writeEndElement(); + xmlStreamWriter.close(); + } catch (XMLStreamException | FactoryConfigurationError e) { + throw new IOException("Unable to create XMLOutputStream", e); + } + } + + /** + * Writes the head portion of the HTML documentation. + * + * @param configurableComponent the component to describe + * @param xmlStreamWriter the stream to write to + * @throws XMLStreamException thrown if there was a problem writing to the + * stream + */ + protected void writeHead(final ConfigurableComponent configurableComponent, + final XMLStreamWriter xmlStreamWriter) throws XMLStreamException { + xmlStreamWriter.writeStartElement("head"); + xmlStreamWriter.writeStartElement("meta"); + xmlStreamWriter.writeAttribute("charset", "utf-8"); + xmlStreamWriter.writeEndElement(); + writeSimpleElement(xmlStreamWriter, "title", getTitle(configurableComponent)); + + xmlStreamWriter.writeStartElement("link"); + xmlStreamWriter.writeAttribute("rel", "stylesheet"); + xmlStreamWriter.writeAttribute("href", "../../css/component-usage.css"); + xmlStreamWriter.writeAttribute("type", "text/css"); + xmlStreamWriter.writeEndElement(); + + xmlStreamWriter.writeEndElement(); + } + + /** + * Gets the class name of the component. + * + * @param configurableComponent the component to describe + * @return the class name of the component + */ + protected String getTitle(final ConfigurableComponent configurableComponent) { + return configurableComponent.getClass().getSimpleName(); + } + + /** + * Writes the body section of the documentation, this consists of the + * component description, the tags, and the PropertyDescriptors. + * + * @param configurableComponent the component to describe + * @param xmlStreamWriter the stream writer + * @param hasAdditionalDetails whether there are additional details present + * or not + * @throws XMLStreamException thrown if there was a problem writing to the + * XML stream + */ + private void writeBody(final ConfigurableComponent configurableComponent, + final XMLStreamWriter xmlStreamWriter, final boolean hasAdditionalDetails) + throws XMLStreamException { + xmlStreamWriter.writeStartElement("body"); + writeDescription(configurableComponent, xmlStreamWriter, hasAdditionalDetails); + writeTags(configurableComponent, xmlStreamWriter); + writeProperties(configurableComponent, xmlStreamWriter); + writeDynamicProperties(configurableComponent, xmlStreamWriter); + writeAdditionalBodyInfo(configurableComponent, xmlStreamWriter); + writeSeeAlso(configurableComponent, xmlStreamWriter); + xmlStreamWriter.writeEndElement(); + } + + /** + * Writes the list of components that may be linked from this component. + * + * @param configurableComponent the component to describe + * @param xmlStreamWriter the stream writer to use + * @throws XMLStreamException thrown if there was a problem writing the XML + */ + private void writeSeeAlso(ConfigurableComponent configurableComponent, XMLStreamWriter xmlStreamWriter) + throws XMLStreamException { + final SeeAlso seeAlso = configurableComponent.getClass().getAnnotation(SeeAlso.class); + if (seeAlso != null) { + writeSimpleElement(xmlStreamWriter, "h3", "See Also:"); + xmlStreamWriter.writeStartElement("p"); + int index = 0; + for (final Class<? extends ConfigurableComponent> linkedComponent : seeAlso.value()) { + if (index != 0) { + xmlStreamWriter.writeCharacters(", "); + } + + writeLinkForComponent(xmlStreamWriter, linkedComponent); + + ++index; + } + + for (final String linkedComponent : seeAlso.classNames()) { + if (index != 0) { + xmlStreamWriter.writeCharacters(", "); + } + + final String link = "../" + linkedComponent + "/index.html"; + + final int indexOfLastPeriod = linkedComponent.lastIndexOf(".") + 1; + + writeLink(xmlStreamWriter, linkedComponent.substring(indexOfLastPeriod), link); + + ++index; + } + xmlStreamWriter.writeEndElement(); + } + } + + /** + * This method may be overridden by sub classes to write additional + * information to the body of the documentation. + * + * @param configurableComponent the component to describe + * @param xmlStreamWriter the stream writer + * @throws XMLStreamException thrown if there was a problem writing to the + * XML stream + */ + protected void writeAdditionalBodyInfo(final ConfigurableComponent configurableComponent, + final XMLStreamWriter xmlStreamWriter) throws XMLStreamException { + + } + + private void writeTags(final ConfigurableComponent configurableComponent, + final XMLStreamWriter xmlStreamWriter) throws XMLStreamException { + final Tags tags = configurableComponent.getClass().getAnnotation(Tags.class); + xmlStreamWriter.writeStartElement("h3"); + xmlStreamWriter.writeCharacters("Tags: "); + xmlStreamWriter.writeEndElement(); + xmlStreamWriter.writeStartElement("p"); + if (tags != null) { + final String tagString = join(tags.value(), ", "); + xmlStreamWriter.writeCharacters(tagString); + } else { + xmlStreamWriter.writeCharacters("None."); + } + xmlStreamWriter.writeEndElement(); + } + + static String join(final String[] toJoin, final String delimiter) { + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < toJoin.length; i++) { + sb.append(toJoin[i]); + if (i < toJoin.length - 1) { + sb.append(delimiter); + } + } + return sb.toString(); + } + + /** + * Writes a description of the configurable component. + * + * @param configurableComponent the component to describe + * @param xmlStreamWriter the stream writer + * @param hasAdditionalDetails whether there are additional details + * available as 'additionalDetails.html' + * @throws XMLStreamException thrown if there was a problem writing to the + * XML stream + */ + protected void writeDescription(final ConfigurableComponent configurableComponent, + final XMLStreamWriter xmlStreamWriter, final boolean hasAdditionalDetails) + throws XMLStreamException { + writeSimpleElement(xmlStreamWriter, "h2", "Description: "); + writeSimpleElement(xmlStreamWriter, "p", getDescription(configurableComponent)); + if (hasAdditionalDetails) { + xmlStreamWriter.writeStartElement("p"); + + writeLink(xmlStreamWriter, "Additional Details...", ADDITIONAL_DETAILS_HTML); + + xmlStreamWriter.writeEndElement(); + } + } + + /** + * Gets a description of the ConfigurableComponent using the + * CapabilityDescription annotation. + * + * @param configurableComponent the component to describe + * @return a description of the configurableComponent + */ + protected String getDescription(final ConfigurableComponent configurableComponent) { + final CapabilityDescription capabilityDescription = configurableComponent.getClass().getAnnotation( + CapabilityDescription.class); + + final String description; + if (capabilityDescription != null) { + description = capabilityDescription.value(); + } else { + description = "No description provided."; + } + + return description; + } + + /** + * Writes the PropertyDescriptors out as a table. + * + * @param configurableComponent the component to describe + * @param xmlStreamWriter the stream writer + * @throws XMLStreamException thrown if there was a problem writing to the + * XML Stream + */ + protected void writeProperties(final ConfigurableComponent configurableComponent, + final XMLStreamWriter xmlStreamWriter) throws XMLStreamException { + + final List<PropertyDescriptor> properties = configurableComponent.getPropertyDescriptors(); + writeSimpleElement(xmlStreamWriter, "h3", "Properties: "); + + if (properties.size() > 0) { + final boolean containsExpressionLanguage = containsExpressionLanguage(configurableComponent); + final boolean containsSensitiveProperties = containsSensitiveProperties(configurableComponent); + xmlStreamWriter.writeStartElement("p"); + xmlStreamWriter.writeCharacters("In the list below, the names of required properties appear in "); + writeSimpleElement(xmlStreamWriter, "strong", "bold"); + xmlStreamWriter.writeCharacters(". Any other properties (not in bold) are considered optional. " + + "The table also indicates any default values"); + if (containsExpressionLanguage) { + if (!containsSensitiveProperties) { + xmlStreamWriter.writeCharacters(", and "); + } else { + xmlStreamWriter.writeCharacters(", "); + } + xmlStreamWriter.writeCharacters("whether a property supports the "); + writeLink(xmlStreamWriter, "NiFi Expression Language", "../../html/expression-language-guide.html"); + } + if (containsSensitiveProperties) { + xmlStreamWriter.writeCharacters(", and whether a property is considered " + "\"sensitive\", meaning that its value will be encrypted. Before entering a " + + "value in a sensitive property, ensure that the "); + + writeSimpleElement(xmlStreamWriter, "strong", "nifi.properties"); + xmlStreamWriter.writeCharacters(" file has " + "an entry for the property "); + writeSimpleElement(xmlStreamWriter, "strong", "nifi.sensitive.props.key"); + } + xmlStreamWriter.writeCharacters("."); + xmlStreamWriter.writeEndElement(); + + xmlStreamWriter.writeStartElement("table"); + xmlStreamWriter.writeAttribute("id", "properties"); + + // write the header row + xmlStreamWriter.writeStartElement("tr"); + writeSimpleElement(xmlStreamWriter, "th", "Name"); + writeSimpleElement(xmlStreamWriter, "th", "Default Value"); + writeSimpleElement(xmlStreamWriter, "th", "Allowable Values"); + writeSimpleElement(xmlStreamWriter, "th", "Description"); + xmlStreamWriter.writeEndElement(); + + // write the individual properties + for (PropertyDescriptor property : properties) { + xmlStreamWriter.writeStartElement("tr"); + xmlStreamWriter.writeStartElement("td"); + xmlStreamWriter.writeAttribute("id", "name"); + if (property.isRequired()) { + writeSimpleElement(xmlStreamWriter, "strong", property.getDisplayName()); + } else { + xmlStreamWriter.writeCharacters(property.getDisplayName()); + } + + xmlStreamWriter.writeEndElement(); + writeSimpleElement(xmlStreamWriter, "td", property.getDefaultValue(), false, "default-value"); + xmlStreamWriter.writeStartElement("td"); + xmlStreamWriter.writeAttribute("id", "allowable-values"); + writeValidValues(xmlStreamWriter, property); + xmlStreamWriter.writeEndElement(); + xmlStreamWriter.writeStartElement("td"); + xmlStreamWriter.writeAttribute("id", "description"); + if (property.getDescription() != null && property.getDescription().trim().length() > 0) { + xmlStreamWriter.writeCharacters(property.getDescription()); + } else { + xmlStreamWriter.writeCharacters("No Description Provided."); + } + + if (property.isSensitive()) { + xmlStreamWriter.writeEmptyElement("br"); + writeSimpleElement(xmlStreamWriter, "strong", "Sensitive Property: true"); + } + + if (property.isExpressionLanguageSupported()) { + xmlStreamWriter.writeEmptyElement("br"); + writeSimpleElement(xmlStreamWriter, "strong", "Supports Expression Language: true"); + } + xmlStreamWriter.writeEndElement(); + + xmlStreamWriter.writeEndElement(); + } + + // TODO support dynamic properties... + xmlStreamWriter.writeEndElement(); + + } else { + writeSimpleElement(xmlStreamWriter, "p", "This component has no required or optional properties."); + } + } + + /** + * Indicates whether or not the component contains at least one sensitive property. + * + * @param component the component to interogate + * @return whether or not the component contains at least one sensitive property. + */ + private boolean containsSensitiveProperties(final ConfigurableComponent component) { + for (PropertyDescriptor descriptor : component.getPropertyDescriptors()) { + if (descriptor.isSensitive()) { + return true; + } + } + return false; + } + + /** + * Indicates whether or not the component contains at least one property that supports Expression Language. + * + * @param component the component to interogate + * @return whether or not the component contains at least one sensitive property. + */ + private boolean containsExpressionLanguage(final ConfigurableComponent component) { + for (PropertyDescriptor descriptor : component.getPropertyDescriptors()) { + if (descriptor.isExpressionLanguageSupported()) { + return true; + } + } + return false; + } + + private void writeDynamicProperties(final ConfigurableComponent configurableComponent, + final XMLStreamWriter xmlStreamWriter) throws XMLStreamException { + + final List<DynamicProperty> dynamicProperties = getDynamicProperties(configurableComponent); + + if (dynamicProperties != null && dynamicProperties.size() > 0) { + writeSimpleElement(xmlStreamWriter, "h3", "Dynamic Properties: "); + xmlStreamWriter.writeStartElement("p"); + xmlStreamWriter + .writeCharacters("Dynamic Properties allow the user to specify both the name and value of a property."); + xmlStreamWriter.writeStartElement("table"); + xmlStreamWriter.writeAttribute("id", "dynamic-properties"); + xmlStreamWriter.writeStartElement("tr"); + writeSimpleElement(xmlStreamWriter, "th", "Name"); + writeSimpleElement(xmlStreamWriter, "th", "Value"); + writeSimpleElement(xmlStreamWriter, "th", "Description"); + xmlStreamWriter.writeEndElement(); + for (final DynamicProperty dynamicProperty : dynamicProperties) { + xmlStreamWriter.writeStartElement("tr"); + writeSimpleElement(xmlStreamWriter, "td", dynamicProperty.name(), false, "name"); + writeSimpleElement(xmlStreamWriter, "td", dynamicProperty.value(), false, "value"); + xmlStreamWriter.writeStartElement("td"); + xmlStreamWriter.writeCharacters(dynamicProperty.description()); + if (dynamicProperty.supportsExpressionLanguage()) { + xmlStreamWriter.writeEmptyElement("br"); + writeSimpleElement(xmlStreamWriter, "strong", "Supports Expression Language: true"); + } + xmlStreamWriter.writeEndElement(); + xmlStreamWriter.writeEndElement(); + } + + xmlStreamWriter.writeEndElement(); + xmlStreamWriter.writeEndElement(); + } + } + + private List<DynamicProperty> getDynamicProperties(ConfigurableComponent configurableComponent) { + final List<DynamicProperty> dynamicProperties = new ArrayList<>(); + final DynamicProperties dynProps = configurableComponent.getClass().getAnnotation(DynamicProperties.class); + if (dynProps != null) { + for (final DynamicProperty dynProp : dynProps.value()) { + dynamicProperties.add(dynProp); + } + } + + final DynamicProperty dynProp = configurableComponent.getClass().getAnnotation(DynamicProperty.class); + if (dynProp != null) { + dynamicProperties.add(dynProp); + } + + return dynamicProperties; + } + + private void writeValidValueDescription(XMLStreamWriter xmlStreamWriter, String description) + throws XMLStreamException { + xmlStreamWriter.writeCharacters(" "); + xmlStreamWriter.writeStartElement("img"); + xmlStreamWriter.writeAttribute("src", "../../html/images/iconInfo.png"); + xmlStreamWriter.writeAttribute("alt", description); + xmlStreamWriter.writeAttribute("title", description); + xmlStreamWriter.writeEndElement(); + + } + + /** + * Interrogates a PropertyDescriptor to get a list of AllowableValues, if + * there are none, nothing is written to the stream. + * + * @param xmlStreamWriter the stream writer to use + * @param property the property to describe + * @throws XMLStreamException thrown if there was a problem writing to the + * XML Stream + */ + protected void writeValidValues(XMLStreamWriter xmlStreamWriter, PropertyDescriptor property) + throws XMLStreamException { + if (property.getAllowableValues() != null && property.getAllowableValues().size() > 0) { + xmlStreamWriter.writeStartElement("ul"); + for (AllowableValue value : property.getAllowableValues()) { + xmlStreamWriter.writeStartElement("li"); + xmlStreamWriter.writeCharacters(value.getDisplayName()); + + if (value.getDescription() != null) { + writeValidValueDescription(xmlStreamWriter, value.getDescription()); + } + xmlStreamWriter.writeEndElement(); + + } + xmlStreamWriter.writeEndElement(); + } else if (property.getControllerServiceDefinition() != null) { + Class<? extends ControllerService> controllerServiceClass = property.getControllerServiceDefinition(); + + writeSimpleElement(xmlStreamWriter, "strong", "Controller Service API: "); + xmlStreamWriter.writeEmptyElement("br"); + xmlStreamWriter.writeCharacters(controllerServiceClass.getSimpleName()); + + final List<Class<? extends ControllerService>> implementations = lookupControllerServiceImpls(controllerServiceClass); + xmlStreamWriter.writeEmptyElement("br"); + if (implementations.size() > 0) { + final String title = implementations.size() > 1 ? "Implementations: " : "Implementation:"; + writeSimpleElement(xmlStreamWriter, "strong", title); + for (int i = 0; i < implementations.size(); i++) { + xmlStreamWriter.writeEmptyElement("br"); + writeLinkForComponent(xmlStreamWriter, implementations.get(i)); + } + } else { + xmlStreamWriter.writeCharacters("No implementations found."); + } + } + } + + /** + * Writes a begin element, then text, then end element for the element of a + * users choosing. Example: <p>text</p> + * + * @param writer the stream writer to use + * @param elementName the name of the element + * @param characters the characters to insert into the element + * @param strong whether the characters should be strong or not. + * @throws XMLStreamException thrown if there was a problem writing to the + * stream. + */ + protected final static void writeSimpleElement(final XMLStreamWriter writer, final String elementName, + final String characters, boolean strong) throws XMLStreamException { + writeSimpleElement(writer, elementName, characters, strong, null); + } + + /** + * Writes a begin element, an id attribute(if specified), then text, then + * end element for element of the users choosing. Example: <p + * id="p-id">text</p> + * + * @param writer the stream writer to use + * @param elementName the name of the element + * @param characters the text of the element + * @param strong whether to bold the text of the element or not + * @param id the id of the element. specifying null will cause no element to + * be written. + * @throws XMLStreamException xse + */ + protected final static void writeSimpleElement(final XMLStreamWriter writer, final String elementName, + final String characters, boolean strong, String id) throws XMLStreamException { + writer.writeStartElement(elementName); + if (id != null) { + writer.writeAttribute("id", id); + } + if (strong) { + writer.writeStartElement("strong"); + } + writer.writeCharacters(characters); + if (strong) { + writer.writeEndElement(); + } + writer.writeEndElement(); + } + + /** + * Writes a begin element, then text, then end element for the element of a + * users choosing. Example: <p>text</p> + * + * @param writer the stream writer to use + * @param elementName the name of the element + * @param characters the characters to insert into the element + * @throws XMLStreamException thrown if there was a problem writing to the + * stream + */ + protected final static void writeSimpleElement(final XMLStreamWriter writer, final String elementName, + final String characters) throws XMLStreamException { + writeSimpleElement(writer, elementName, characters, false); + } + + /** + * A helper method to write a link + * + * @param xmlStreamWriter the stream to write to + * @param text the text of the link + * @param location the location of the link + * @throws XMLStreamException thrown if there was a problem writing to the + * stream + */ + protected void writeLink(final XMLStreamWriter xmlStreamWriter, final String text, final String location) + throws XMLStreamException { + xmlStreamWriter.writeStartElement("a"); + xmlStreamWriter.writeAttribute("href", location); + xmlStreamWriter.writeCharacters(text); + xmlStreamWriter.writeEndElement(); + } + + /** + * Writes a link to another configurable component + * + * @param xmlStreamWriter the xml stream writer + * @param clazz the configurable component to link to + * @throws XMLStreamException thrown if there is a problem writing the XML + */ + protected void writeLinkForComponent(final XMLStreamWriter xmlStreamWriter, final Class<?> clazz) throws XMLStreamException { + writeLink(xmlStreamWriter, clazz.getSimpleName(), "../" + clazz.getCanonicalName() + "/index.html"); + } + + /** + * Uses the {@link ExtensionManager} to discover any {@link ControllerService} implementations that implement a specific + * ControllerService API. + * + * @param parent the controller service API + * @return a list of controller services that implement the controller service API + */ + private List<Class<? extends ControllerService>> lookupControllerServiceImpls( + final Class<? extends ControllerService> parent) { + + final List<Class<? extends ControllerService>> implementations = new ArrayList<>(); + + // first get all ControllerService implementations + final Set<Class> controllerServices = Collections.emptySet(); + + // then iterate over all controller services looking for any that is a child of the parent + // ControllerService API that was passed in as a parameter + for (final Class<? extends ControllerService> controllerServiceClass : controllerServices) { + if (parent.isAssignableFrom(controllerServiceClass)) { + implementations.add(controllerServiceClass); + } + } + + return implementations; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/html/HtmlProcessorDocumentationWriter.java ---------------------------------------------------------------------- diff --git a/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/html/HtmlProcessorDocumentationWriter.java b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/html/HtmlProcessorDocumentationWriter.java new file mode 100644 index 0000000..4a15b50 --- /dev/null +++ b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/html/HtmlProcessorDocumentationWriter.java @@ -0,0 +1,256 @@ +/* + * 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.html; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.nifi.annotation.behavior.DynamicRelationship; +import org.apache.nifi.annotation.behavior.ReadsAttribute; +import org.apache.nifi.annotation.behavior.ReadsAttributes; +import org.apache.nifi.annotation.behavior.WritesAttribute; +import org.apache.nifi.annotation.behavior.WritesAttributes; +import org.apache.nifi.components.ConfigurableComponent; +import org.apache.nifi.processor.Processor; +import org.apache.nifi.processor.Relationship; + +/** + * Writes documentation specific for a Processor. This includes everything for a + * ConfigurableComponent as well as Relationship information. + * + * + */ +public class HtmlProcessorDocumentationWriter extends HtmlDocumentationWriter { + + @Override + protected void writeAdditionalBodyInfo(final ConfigurableComponent configurableComponent, + final XMLStreamWriter xmlStreamWriter) throws XMLStreamException { + final Processor processor = (Processor) configurableComponent; + writeRelationships(processor, xmlStreamWriter); + writeDynamicRelationships(processor, xmlStreamWriter); + writeAttributeInfo(processor, xmlStreamWriter); + } + + /** + * Writes all the attributes that a processor says it reads and writes + * + * @param processor the processor to describe + * @param xmlStreamWriter the xml stream writer to use + * @throws XMLStreamException thrown if there was a problem writing the XML + */ + private void writeAttributeInfo(Processor processor, XMLStreamWriter xmlStreamWriter) + throws XMLStreamException { + + handleReadsAttributes(xmlStreamWriter, processor); + handleWritesAttributes(xmlStreamWriter, processor); + } + + private String defaultIfBlank(final String test, final String defaultValue) { + if (test == null || test.trim().isEmpty()) { + return defaultValue; + } + return test; + } + + /** + * Writes out just the attributes that are being read in a table form. + * + * @param xmlStreamWriter the xml stream writer to use + * @param processor the processor to describe + * @throws XMLStreamException xse + */ + private void handleReadsAttributes(XMLStreamWriter xmlStreamWriter, final Processor processor) + throws XMLStreamException { + List<ReadsAttribute> attributesRead = getReadsAttributes(processor); + + writeSimpleElement(xmlStreamWriter, "h3", "Reads Attributes: "); + if (attributesRead.size() > 0) { + xmlStreamWriter.writeStartElement("table"); + xmlStreamWriter.writeAttribute("id", "reads-attributes"); + xmlStreamWriter.writeStartElement("tr"); + writeSimpleElement(xmlStreamWriter, "th", "Name"); + writeSimpleElement(xmlStreamWriter, "th", "Description"); + xmlStreamWriter.writeEndElement(); + for (ReadsAttribute attribute : attributesRead) { + xmlStreamWriter.writeStartElement("tr"); + writeSimpleElement(xmlStreamWriter, "td", + defaultIfBlank(attribute.attribute(), "Not Specified")); + // TODO allow for HTML characters here. + writeSimpleElement(xmlStreamWriter, "td", + defaultIfBlank(attribute.description(), "Not Specified")); + xmlStreamWriter.writeEndElement(); + + } + xmlStreamWriter.writeEndElement(); + + } else { + xmlStreamWriter.writeCharacters("None specified."); + } + } + + /** + * Writes out just the attributes that are being written to in a table form. + * + * @param xmlStreamWriter the xml stream writer to use + * @param processor the processor to describe + * @throws XMLStreamException xse + */ + private void handleWritesAttributes(XMLStreamWriter xmlStreamWriter, final Processor processor) + throws XMLStreamException { + List<WritesAttribute> attributesRead = getWritesAttributes(processor); + + writeSimpleElement(xmlStreamWriter, "h3", "Writes Attributes: "); + if (attributesRead.size() > 0) { + xmlStreamWriter.writeStartElement("table"); + xmlStreamWriter.writeAttribute("id", "writes-attributes"); + xmlStreamWriter.writeStartElement("tr"); + writeSimpleElement(xmlStreamWriter, "th", "Name"); + writeSimpleElement(xmlStreamWriter, "th", "Description"); + xmlStreamWriter.writeEndElement(); + for (WritesAttribute attribute : attributesRead) { + xmlStreamWriter.writeStartElement("tr"); + writeSimpleElement(xmlStreamWriter, "td", + defaultIfBlank(attribute.attribute(), "Not Specified")); + // TODO allow for HTML characters here. + writeSimpleElement(xmlStreamWriter, "td", + defaultIfBlank(attribute.description(), "Not Specified")); + xmlStreamWriter.writeEndElement(); + } + xmlStreamWriter.writeEndElement(); + + } else { + xmlStreamWriter.writeCharacters("None specified."); + } + } + + /** + * Collects the attributes that a processor is reading from. + * + * @param processor the processor to describe + * @return the list of attributes that processor is reading + */ + private List<ReadsAttribute> getReadsAttributes(Processor processor) { + List<ReadsAttribute> attributes = new ArrayList<>(); + + ReadsAttributes readsAttributes = processor.getClass().getAnnotation(ReadsAttributes.class); + if (readsAttributes != null) { + attributes.addAll(Arrays.asList(readsAttributes.value())); + } + + ReadsAttribute readsAttribute = processor.getClass().getAnnotation(ReadsAttribute.class); + if (readsAttribute != null) { + attributes.add(readsAttribute); + } + + return attributes; + } + + /** + * Collects the attributes that a processor is writing to. + * + * @param processor the processor to describe + * @return the list of attributes the processor is writing + */ + private List<WritesAttribute> getWritesAttributes(Processor processor) { + List<WritesAttribute> attributes = new ArrayList<>(); + + WritesAttributes writesAttributes = processor.getClass().getAnnotation(WritesAttributes.class); + if (writesAttributes != null) { + attributes.addAll(Arrays.asList(writesAttributes.value())); + } + + WritesAttribute writeAttribute = processor.getClass().getAnnotation(WritesAttribute.class); + if (writeAttribute != null) { + attributes.add(writeAttribute); + } + + return attributes; + } + + /** + * Writes a table describing the relations a processor has. + * + * @param processor the processor to describe + * @param xmlStreamWriter the stream writer to use + * @throws XMLStreamException thrown if there was a problem writing the xml + */ + private void writeRelationships(final Processor processor, final XMLStreamWriter xmlStreamWriter) + throws XMLStreamException { + + writeSimpleElement(xmlStreamWriter, "h3", "Relationships: "); + + if (processor.getRelationships().size() > 0) { + xmlStreamWriter.writeStartElement("table"); + xmlStreamWriter.writeAttribute("id", "relationships"); + xmlStreamWriter.writeStartElement("tr"); + writeSimpleElement(xmlStreamWriter, "th", "Name"); + writeSimpleElement(xmlStreamWriter, "th", "Description"); + xmlStreamWriter.writeEndElement(); + + for (Relationship relationship : processor.getRelationships()) { + xmlStreamWriter.writeStartElement("tr"); + writeSimpleElement(xmlStreamWriter, "td", relationship.getName()); + writeSimpleElement(xmlStreamWriter, "td", relationship.getDescription()); + xmlStreamWriter.writeEndElement(); + } + xmlStreamWriter.writeEndElement(); + } else { + xmlStreamWriter.writeCharacters("This processor has no relationships."); + } + } + + private void writeDynamicRelationships(final Processor processor, final XMLStreamWriter xmlStreamWriter) throws XMLStreamException { + + List<DynamicRelationship> dynamicRelationships = getDynamicRelationships(processor); + + if (dynamicRelationships.size() > 0) { + writeSimpleElement(xmlStreamWriter, "h3", "Dynamic Relationships: "); + xmlStreamWriter.writeStartElement("p"); + xmlStreamWriter.writeCharacters("A Dynamic Relationship may be created based on how the user configures the Processor."); + xmlStreamWriter.writeStartElement("table"); + xmlStreamWriter.writeAttribute("id", "dynamic-relationships"); + xmlStreamWriter.writeStartElement("tr"); + writeSimpleElement(xmlStreamWriter, "th", "Name"); + writeSimpleElement(xmlStreamWriter, "th", "Description"); + xmlStreamWriter.writeEndElement(); + + for (DynamicRelationship dynamicRelationship : dynamicRelationships) { + xmlStreamWriter.writeStartElement("tr"); + writeSimpleElement(xmlStreamWriter, "td", dynamicRelationship.name()); + writeSimpleElement(xmlStreamWriter, "td", dynamicRelationship.description()); + xmlStreamWriter.writeEndElement(); + } + xmlStreamWriter.writeEndElement(); + xmlStreamWriter.writeEndElement(); + } + } + + private List<DynamicRelationship> getDynamicRelationships(Processor processor) { + List<DynamicRelationship> results = new ArrayList<>(); + + DynamicRelationship dynamicRelationships = processor.getClass().getAnnotation(DynamicRelationship.class); + if (dynamicRelationships != null) { + results.add(dynamicRelationships); + } + + return results; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/init/ControllerServiceInitializer.java ---------------------------------------------------------------------- diff --git a/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/init/ControllerServiceInitializer.java b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/init/ControllerServiceInitializer.java new file mode 100644 index 0000000..dc9f82f --- /dev/null +++ b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/init/ControllerServiceInitializer.java @@ -0,0 +1,53 @@ +/* + * 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.init; + +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.reporting.InitializationException; + +/** + * Initializes a ControllerService using a MockControllerServiceInitializationContext + * + * + */ +public class ControllerServiceInitializer implements ConfigurableComponentInitializer { + + @Override + public void initialize(ConfigurableComponent component) throws InitializationException { + ControllerService controllerService = (ControllerService) component; + + controllerService.initialize(new MockControllerServiceInitializationContext()); + + } + + @Override + public void teardown(ConfigurableComponent component) { + + final ProcessorLog logger = new MockProcessorLogger(); + final MockConfigurationContext context = new MockConfigurationContext(); + ReflectionUtils.quietlyInvokeMethodsWithAnnotations(OnShutdown.class, org.apache.nifi.processor.annotation.OnShutdown.class, component, logger, context); + + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/init/ProcessorInitializer.java ---------------------------------------------------------------------- diff --git a/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/init/ProcessorInitializer.java b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/init/ProcessorInitializer.java new file mode 100644 index 0000000..f4ca36d --- /dev/null +++ b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/init/ProcessorInitializer.java @@ -0,0 +1,53 @@ +/* + * 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.init; + +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.processor.Processor; + +/** + * Initializes a Procesor using a MockProcessorInitializationContext + * + * + */ +public class ProcessorInitializer implements ConfigurableComponentInitializer { + + @Override + public void initialize(ConfigurableComponent component) { + Processor processor = (Processor) component; + + processor.initialize(new MockProcessorInitializationContext()); + + } + + @Override + public void teardown(ConfigurableComponent component) { + Processor processor = (Processor) component; + + final ProcessorLog logger = new MockProcessorLogger(); + final MockProcessContext context = new MockProcessContext(); + ReflectionUtils.quietlyInvokeMethodsWithAnnotations(OnShutdown.class, org.apache.nifi.processor.annotation.OnShutdown.class, processor, logger, context); + + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/init/ReportingTaskingInitializer.java ---------------------------------------------------------------------- diff --git a/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/init/ReportingTaskingInitializer.java b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/init/ReportingTaskingInitializer.java new file mode 100644 index 0000000..0a43f0b --- /dev/null +++ b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/init/ReportingTaskingInitializer.java @@ -0,0 +1,52 @@ +/* + * 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.init; + +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.reporting.InitializationException; +import org.apache.nifi.reporting.ReportingTask; + +/** + * Initializes a ReportingTask using a MockReportingInitializationContext; + * + * + */ +public class ReportingTaskingInitializer implements ConfigurableComponentInitializer { + + @Override + public void initialize(ConfigurableComponent component) throws InitializationException { + ReportingTask reportingTask = (ReportingTask) component; + + reportingTask.initialize(new MockReportingInitializationContext()); + + } + + @Override + public void teardown(ConfigurableComponent component) { + ReportingTask reportingTask = (ReportingTask) component; + + final MockConfigurationContext context = new MockConfigurationContext(); + ReflectionUtils.quietlyInvokeMethodsWithAnnotations(OnShutdown.class, org.apache.nifi.processor.annotation.OnShutdown.class, reportingTask, new MockProcessorLogger(), context); + + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockConfigurationContext.java ---------------------------------------------------------------------- diff --git a/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockConfigurationContext.java b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockConfigurationContext.java new file mode 100644 index 0000000..6c9ec9d --- /dev/null +++ b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockConfigurationContext.java @@ -0,0 +1,48 @@ +/* + * 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.concurrent.TimeUnit; + +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(); + } + + @Override + public String getSchedulingPeriod() { + return "0 secs"; + } + + @Override + public Long getSchedulingPeriod(final TimeUnit timeUnit) { + return 0L; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/af87b52b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockControllerServiceInitializationContext.java ---------------------------------------------------------------------- diff --git a/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockControllerServiceInitializationContext.java b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockControllerServiceInitializationContext.java new file mode 100644 index 0000000..14076a3 --- /dev/null +++ b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockControllerServiceInitializationContext.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.documentation.mock; + +import org.apache.nifi.controller.ControllerServiceInitializationContext; +import org.apache.nifi.controller.ControllerServiceLookup; +import org.apache.nifi.logging.ComponentLog; + +/** + * A Mock ControllerServiceInitializationContext so that ControllerServices can + * be initialized for the purpose of generating documentation. + * + * + */ +public class MockControllerServiceInitializationContext implements ControllerServiceInitializationContext { + + @Override + public String getIdentifier() { + return "mock-controller-service"; + } + + @Override + public ControllerServiceLookup getControllerServiceLookup() { + return new MockControllerServiceLookup(); + } + + @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/mock/MockControllerServiceLookup.java ---------------------------------------------------------------------- diff --git a/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockControllerServiceLookup.java b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockControllerServiceLookup.java new file mode 100644 index 0000000..5c60881 --- /dev/null +++ b/nifi-documentation-plugin/src/main/java/org/apache/nifi/documentation/mock/MockControllerServiceLookup.java @@ -0,0 +1,65 @@ +/* + * 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.Set; + +import org.apache.nifi.controller.ControllerService; +import org.apache.nifi.controller.ControllerServiceLookup; + +/** + * A Mock ControllerServiceLookup that can be used so that + * ConfigurableComponents can be initialized for the purpose of generating + * documentation + * + * + */ +public class MockControllerServiceLookup implements ControllerServiceLookup { + + @Override + public ControllerService getControllerService(String serviceIdentifier) { + return null; + } + + @Override + public boolean isControllerServiceEnabled(String serviceIdentifier) { + return false; + } + + @Override + public boolean isControllerServiceEnabled(ControllerService service) { + return false; + } + + @Override + public Set<String> getControllerServiceIdentifiers(Class<? extends ControllerService> serviceType) + throws IllegalArgumentException { + return Collections.emptySet(); + } + + @Override + public boolean isControllerServiceEnabling(String serviceIdentifier) { + return false; + } + + @Override + public String getControllerServiceName(String serviceIdentifier) { + return serviceIdentifier; + } + +}
