NIFI-280 - Adding new documentation framework component and incorporating

in framework
This commit is contained in:
danbress 2015-01-31 09:02:23 -05:00
parent 497767389d
commit d7cf25be9a
24 changed files with 1500 additions and 0 deletions

View File

@ -0,0 +1,49 @@
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- 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.nifi</groupId>
<artifactId>nifi-framework</artifactId>
<version>0.0.2-incubating-SNAPSHOT</version>
</parent>
<artifactId>nifi-documentation</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-nar-utils</artifactId>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-properties</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-processor-utils</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.documentation;
import org.apache.nifi.components.ConfigurableComponent;
import org.apache.nifi.reporting.InitializationException;
/**
* An interface for initializing 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;
}

View File

@ -0,0 +1,182 @@
/*
* 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.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.Set;
import org.apache.nifi.components.ConfigurableComponent;
import org.apache.nifi.controller.ControllerService;
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.nar.ExtensionManager;
import org.apache.nifi.processor.Processor;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.reporting.ReportingTask;
import org.apache.nifi.util.NiFiProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Uses the ExtensionManager to get a list of Processor, ControllerService, and
* Reporting Task classes that were loaded and generate documentation for them.
*
*
*/
public class DocGenerator {
private static final Logger logger = LoggerFactory.getLogger(DocGenerator.class);
/**
* Generates documentation into the work/docs dir specified by
* NiFiProperties.
*
* @param properties
*/
public static void generate(final NiFiProperties properties) {
@SuppressWarnings("rawtypes")
final Set<Class> extensionClasses = new HashSet<>();
extensionClasses.addAll(ExtensionManager.getExtensions(Processor.class));
extensionClasses.addAll(ExtensionManager.getExtensions(ControllerService.class));
extensionClasses.addAll(ExtensionManager.getExtensions(ReportingTask.class));
final File explodedNiFiDocsDir = properties.getComponentDocumentationWorkingDirectory();
logger.debug("Generating documentation for: " + extensionClasses.size() + " components in: "
+ explodedNiFiDocsDir);
for (final Class<?> extensionClass : extensionClasses) {
if (ConfigurableComponent.class.isAssignableFrom(extensionClass)) {
final Class<? extends ConfigurableComponent> componentClass = extensionClass
.asSubclass(ConfigurableComponent.class);
try {
logger.debug("Documenting: " + componentClass);
document(explodedNiFiDocsDir, componentClass);
} catch (Exception e) {
logger.warn("Unable to document: " + componentClass);
}
}
}
}
/**
* Generates the documentation for a particular configurable comopnent. Will
* check to see if an "additionalDetails.html" file exists and will link
* that from the generated documentation.
*
* @param docsDir
* the work\docs\components dir to stick component documentation
* in
* @param componentClass
* the class to document
* @throws InstantiationException
* @throws IllegalAccessException
* @throws IOException
* @throws InitializationException
*/
private static void document(final File docsDir, final Class<? extends ConfigurableComponent> componentClass)
throws InstantiationException, IllegalAccessException, IOException, InitializationException {
final ConfigurableComponent component = componentClass.newInstance();
final ConfigurableComponentInitializer initializer = getComponentInitializer(componentClass);
initializer.initialize(component);
final DocumentationWriter writer = getDocumentWriter(componentClass);
final File directory = new File(docsDir, componentClass.getCanonicalName());
directory.mkdirs();
final File baseDocumenationFile = new File(directory, "index.html");
if (baseDocumenationFile.exists()) {
logger.warn(baseDocumenationFile + " already exists! Overwriting!");
}
try (final OutputStream output = new BufferedOutputStream(new FileOutputStream(baseDocumenationFile))) {
writer.write(component, output, hasAdditionalInfo(directory));
}
}
/**
* Returns the DocumentationWriter for the type of component. Currently
* Processor, ControllerService, and ReportingTask are supported.
*
* @param componentClass
* the class that requires a DocumentationWriter
* @return a DocumentationWriter capable of generating documentation for
* that specific type of class
*/
private static DocumentationWriter getDocumentWriter(final Class<? extends ConfigurableComponent> componentClass) {
if (Processor.class.isAssignableFrom(componentClass)) {
return new HtmlProcessorDocumentationWriter();
} else if (ControllerService.class.isAssignableFrom(componentClass)) {
return new HtmlDocumentationWriter();
} else if (ReportingTask.class.isAssignableFrom(componentClass)) {
return new HtmlDocumentationWriter();
}
return null;
}
/**
* Returns a ConfigurableComponentInitializer for the type of component.
* Currently Processor, ControllerService and ReportingTask are supported.
*
* @param componentClass
* the class that requires a ConfigurableComponentInitializer
* @return a ConfigurableComponentInitializer capable of initializing that
* specific type of class
*/
private static ConfigurableComponentInitializer getComponentInitializer(
final Class<? extends ConfigurableComponent> componentClass) {
if (Processor.class.isAssignableFrom(componentClass)) {
return new ProcessorInitializer();
} else if (ControllerService.class.isAssignableFrom(componentClass)) {
return new ControllerServiceInitializer();
} else if (ReportingTask.class.isAssignableFrom(componentClass)) {
return new ReportingTaskingInitializer();
}
return null;
}
/**
* Checks to see if a directory to write to has an additionalDetails.html in
* it already.
*
* @param directory
* @return true if additionalDetails.html exists, false otherwise.
*/
private static boolean hasAdditionalInfo(File directory) {
return directory.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.equalsIgnoreCase(HtmlDocumentationWriter.ADDITIONAL_DETAILS_HTML);
}
}).length > 0;
}
}

View File

@ -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;
}

View File

@ -0,0 +1,415 @@
/*
* 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.List;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.components.AllowableValue;
import org.apache.nifi.components.ConfigurableComponent;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.documentation.DocumentationWriter;
import org.apache.nifi.annotation.documentation.CapabilityDescription;
import org.apache.nifi.annotation.documentation.Tags;
/**
* 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";
/**
* The apache licence to apply to the top of the generated html
*/
private static final String apacheLicense;
static {
String value = null;
try {
value = IOUtils.toString(ClassLoader.getSystemResourceAsStream("apache.license"));
} catch (IOException e) {
e.printStackTrace();
}
apacheLicense = value;
}
@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 {
// write the apache license
xmlStreamWriter.writeComment(apacheLicense);
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 final 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);
writeAdditionalBodyInfo(configurableComponent, xmlStreamWriter);
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 {
}
/**
* Writes the tags attached to a ConfigurableComponent.
*
* @param configurableComponent
* @param xmlStreamWriter
* @throws XMLStreamException
*/
private void writeTags(final ConfigurableComponent configurableComponent, final XMLStreamWriter xmlStreamWriter)
throws XMLStreamException {
final Tags tags = configurableComponent.getClass().getAnnotation(Tags.class);
xmlStreamWriter.writeStartElement("p");
if (tags != null) {
final String tagString = StringUtils.join(tags.value(), ", ");
xmlStreamWriter.writeCharacters("Tags: ");
xmlStreamWriter.writeCharacters(tagString);
} else {
xmlStreamWriter.writeCharacters("No Tags provided.");
}
xmlStreamWriter.writeEndElement();
}
/**
* 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 {
xmlStreamWriter.writeStartElement("p");
writeSimpleElement(xmlStreamWriter, "strong", "Properties: ");
xmlStreamWriter.writeEndElement();
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, whether a property supports the ");
writeLink(xmlStreamWriter, "NiFi Expression Language (or simply EL)",
"../../html/expression-language-guide.html");
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();
boolean containsSensitiveElement = false;
List<PropertyDescriptor> properties = configurableComponent.getPropertyDescriptors();
if (properties.size() > 0) {
xmlStreamWriter.writeStartElement("table");
// write the header row
xmlStreamWriter.writeStartElement("tr");
writeSimpleElement(xmlStreamWriter, "th", "Name");
writeSimpleElement(xmlStreamWriter, "th", "Description");
writeSimpleElement(xmlStreamWriter, "th", "Default Value");
writeSimpleElement(xmlStreamWriter, "th", "Valid Values");
xmlStreamWriter.writeStartElement("th");
writeLink(xmlStreamWriter, "EL", "../../html/expression-language-guide.html");
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeEndElement();
// write the individual properties
for (PropertyDescriptor property : properties) {
containsSensitiveElement |= property.isSensitive();
xmlStreamWriter.writeStartElement("tr");
xmlStreamWriter.writeStartElement("td");
if (property.isRequired()) {
writeSimpleElement(xmlStreamWriter, "strong", property.getDisplayName());
} else {
xmlStreamWriter.writeCharacters(property.getDisplayName());
}
if (property.isSensitive()) {
writeSensitiveImg(xmlStreamWriter);
}
xmlStreamWriter.writeEndElement();
writeSimpleElement(xmlStreamWriter, "td", property.getDescription());
writeSimpleElement(xmlStreamWriter, "td", property.getDefaultValue());
writeValidValues(xmlStreamWriter, property);
writeSimpleElement(xmlStreamWriter, "td", property.isExpressionLanguageSupported() ? "Yes" : "No");
xmlStreamWriter.writeEndElement();
}
// TODO support dynamic properties...
xmlStreamWriter.writeEndElement();
if (containsSensitiveElement) {
writeSensitiveImg(xmlStreamWriter);
xmlStreamWriter.writeCharacters(" indicates that a property is a sensitive property");
}
} else {
writeSimpleElement(xmlStreamWriter, "p", "This component has no required or optional properties.");
}
}
private void writeSensitiveImg(final XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
xmlStreamWriter.writeCharacters(" ");
xmlStreamWriter.writeStartElement("img");
xmlStreamWriter.writeAttribute("src", "../../html/images/iconSecure.png");
xmlStreamWriter.writeAttribute("alt", "Sensitive Property");
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 {
xmlStreamWriter.writeStartElement("td");
if (property.getAllowableValues() != null && property.getAllowableValues().size() > 0) {
xmlStreamWriter.writeStartElement("ul");
for (AllowableValue value : property.getAllowableValues()) {
writeSimpleElement(xmlStreamWriter, "li", value.getDisplayName());
}
xmlStreamWriter.writeEndElement();
}
xmlStreamWriter.writeEndElement();
}
/**
* Writes a begin element, then text, then end element for the element of a
* users choosing. Example: &lt;p&gt;text&lt;/p&gt;
*
* @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 {
writer.writeStartElement(elementName);
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: &lt;p&gt;text&lt;/p&gt;
*
* @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();
}
}

View File

@ -0,0 +1,60 @@
/*
* 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 javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
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;
xmlStreamWriter.writeStartElement("p");
writeSimpleElement(xmlStreamWriter, "strong", "Relationships: ");
xmlStreamWriter.writeEndElement();
if (processor.getRelationships().size() > 0) {
xmlStreamWriter.writeStartElement("table");
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.");
}
}
}

View File

@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.documentation.init;
import org.apache.nifi.components.ConfigurableComponent;
import org.apache.nifi.controller.ControllerService;
import org.apache.nifi.documentation.ConfigurableComponentInitializer;
import org.apache.nifi.documentation.mock.MockControllerServiceInitializationContext;
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());
}
}

View File

@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.documentation.init;
import org.apache.nifi.components.ConfigurableComponent;
import org.apache.nifi.documentation.ConfigurableComponentInitializer;
import org.apache.nifi.documentation.mock.MockProcessorInitializationContext;
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());
}
}

View File

@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.documentation.init;
import org.apache.nifi.components.ConfigurableComponent;
import org.apache.nifi.documentation.ConfigurableComponentInitializer;
import org.apache.nifi.documentation.mock.MockReportingInitializationContext;
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());
}
}

View File

@ -0,0 +1,40 @@
/*
* 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;
/**
* 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 "";
}
@Override
public ControllerServiceLookup getControllerServiceLookup() {
return new MockControllerServiceLookup();
}
}

View File

@ -0,0 +1,55 @@
/*
* 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();
}
}

View File

@ -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 "";
}
@Override
public ProcessorLog getLogger() {
return null;
}
@Override
public ControllerServiceLookup getControllerServiceLookup() {
return new MockControllerServiceLookup();
}
}

View File

@ -0,0 +1,63 @@
/*
* 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.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.
*
* @author Alligator
*
*/
public class MockReportingInitializationContext implements ReportingInitializationContext {
@Override
public String getIdentifier() {
return "";
}
@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;
}
}

View File

@ -0,0 +1,12 @@
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.

View File

@ -0,0 +1,57 @@
/*
* 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.example;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.nifi.annotation.documentation.CapabilityDescription;
import org.apache.nifi.annotation.documentation.Tags;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.controller.AbstractControllerService;
import org.apache.nifi.processor.util.StandardValidators;
@CapabilityDescription("A documented controller service that can help you do things")
@Tags({ "one", "two", "three" })
public class FullyDocumentedControllerService extends AbstractControllerService {
public static final PropertyDescriptor KEYSTORE = new PropertyDescriptor.Builder().name("Keystore Filename")
.description("The fully-qualified filename of the Keystore").defaultValue(null)
.addValidator(StandardValidators.FILE_EXISTS_VALIDATOR).sensitive(false).build();
public static final PropertyDescriptor KEYSTORE_TYPE = new PropertyDescriptor.Builder().name("Keystore Type")
.description("The Type of the Keystore").allowableValues("JKS", "PKCS12")
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR).defaultValue("JKS").sensitive(false).build();
public static final PropertyDescriptor KEYSTORE_PASSWORD = new PropertyDescriptor.Builder()
.name("Keystore Password").defaultValue(null).description("The password for the Keystore")
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR).sensitive(true).build();
private static final List<PropertyDescriptor> properties;
static {
List<PropertyDescriptor> props = new ArrayList<>();
props.add(KEYSTORE);
props.add(KEYSTORE_PASSWORD);
props.add(KEYSTORE_TYPE);
properties = Collections.unmodifiableList(props);
}
@Override
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
return properties;
}
}

View File

@ -0,0 +1,100 @@
/*
* 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.example;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.processor.AbstractProcessor;
import org.apache.nifi.processor.ProcessContext;
import org.apache.nifi.processor.ProcessSession;
import org.apache.nifi.processor.ProcessorInitializationContext;
import org.apache.nifi.processor.Relationship;
import org.apache.nifi.annotation.documentation.CapabilityDescription;
import org.apache.nifi.annotation.documentation.Tags;
import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.processor.util.StandardValidators;
@Tags({ "one", "two", "three" })
@CapabilityDescription("This is a processor that is used to test documentation.")
public class FullyDocumentedProcessor extends AbstractProcessor {
public static final PropertyDescriptor DIRECTORY = new PropertyDescriptor.Builder().name("Input Directory")
.description("The input directory from which to pull files").required(true)
.addValidator(StandardValidators.createDirectoryExistsValidator(true, false))
.expressionLanguageSupported(true).build();
public static final PropertyDescriptor RECURSE = new PropertyDescriptor.Builder().name("Recurse Subdirectories")
.description("Indicates whether or not to pull files from subdirectories").required(true)
.allowableValues("true", "false").defaultValue("true").build();
public static final PropertyDescriptor POLLING_INTERVAL = new PropertyDescriptor.Builder().name("Polling Interval")
.description("Indicates how long to wait before performing a directory listing").required(true)
.addValidator(StandardValidators.TIME_PERIOD_VALIDATOR).defaultValue("0 sec").build();
public static final PropertyDescriptor OPTIONAL_PROPERTY = new PropertyDescriptor.Builder()
.name("Optional Property").description("This is a property you can use or not").required(false).build();
public static final Relationship REL_SUCCESS = new Relationship.Builder().name("success")
.description("Successful files").build();
public static final Relationship REL_FAILURE = new Relationship.Builder().name("failure")
.description("Failing files").build();
private List<PropertyDescriptor> properties;
private Set<Relationship> relationships;
@Override
protected void init(ProcessorInitializationContext context) {
final List<PropertyDescriptor> properties = new ArrayList<>();
properties.add(DIRECTORY);
properties.add(RECURSE);
properties.add(POLLING_INTERVAL);
properties.add(OPTIONAL_PROPERTY);
this.properties = Collections.unmodifiableList(properties);
final Set<Relationship> relationships = new HashSet<>();
relationships.add(REL_SUCCESS);
relationships.add(REL_FAILURE);
this.relationships = Collections.unmodifiableSet(relationships);
}
@Override
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
return properties;
}
@Override
public Set<Relationship> getRelationships() {
return relationships;
}
@Override
public void onTrigger(ProcessContext context, ProcessSession session) throws ProcessException {
}
@Override
protected PropertyDescriptor getSupportedDynamicPropertyDescriptor(String propertyDescriptorName) {
return new PropertyDescriptor.Builder().name(propertyDescriptorName)
.description("This is a property you can use or not").dynamic(true).build();
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.example;
import java.util.ArrayList;
import java.util.List;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.annotation.documentation.CapabilityDescription;
import org.apache.nifi.annotation.documentation.Tags;
import org.apache.nifi.reporting.AbstractReportingTask;
import org.apache.nifi.reporting.ReportingContext;
@CapabilityDescription("A helper reporting task to do...")
@Tags({ "first", "second", "third" })
public class FullyDocumentedReportingTask extends AbstractReportingTask {
public static final PropertyDescriptor SHOW_DELTAS = new PropertyDescriptor.Builder()
.name("Show Deltas")
.description(
"Specifies whether or not to show the difference in values between the current status and the previous status")
.required(true).allowableValues("true", "false").defaultValue("true").build();
@Override
public final List<PropertyDescriptor> getSupportedPropertyDescriptors() {
final List<PropertyDescriptor> descriptors = new ArrayList<>();
descriptors.add(SHOW_DELTAS);
return descriptors;
}
@Override
public void onTrigger(ReportingContext context) {
// TODO Auto-generated method stub
}
}

View File

@ -0,0 +1,56 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.documentation.html;
import java.io.IOException;
import org.apache.nifi.controller.ControllerService;
import org.apache.nifi.documentation.DocumentationWriter;
import org.apache.nifi.documentation.example.FullyDocumentedControllerService;
import org.apache.nifi.documentation.example.FullyDocumentedReportingTask;
import org.apache.nifi.documentation.mock.MockControllerServiceInitializationContext;
import org.apache.nifi.documentation.mock.MockReportingInitializationContext;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.reporting.ReportingTask;
import org.junit.Test;
public class HtmlDocumentationWriterTest {
@Test
public void testDocumentControllerService() throws InitializationException, IOException {
ControllerService controllerService = new FullyDocumentedControllerService();
controllerService.initialize(new MockControllerServiceInitializationContext());
DocumentationWriter writer = new HtmlDocumentationWriter();
writer.write(controllerService, System.out, false);
}
@Test
public void testDocumentReportingTask() throws InitializationException, IOException {
ReportingTask reportingTask = new FullyDocumentedReportingTask();
reportingTask.initialize(new MockReportingInitializationContext());
DocumentationWriter writer = new HtmlDocumentationWriter();
writer.write(reportingTask, System.out, false);
}
}

View File

@ -0,0 +1,69 @@
/*
* 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 static org.apache.nifi.documentation.html.XmlValidator.assertContains;
import static org.apache.nifi.documentation.html.XmlValidator.assertNotContains;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.apache.nifi.annotation.documentation.CapabilityDescription;
import org.apache.nifi.documentation.DocumentationWriter;
import org.apache.nifi.documentation.example.FullyDocumentedProcessor;
import org.apache.nifi.documentation.mock.MockProcessorInitializationContext;
import org.junit.Test;
public class ProcessorDocumentationWriterTest {
@Test
public void testFullyDocumentedProcessor() throws IOException {
FullyDocumentedProcessor processor = new FullyDocumentedProcessor();
processor.initialize(new MockProcessorInitializationContext());
DocumentationWriter writer = new HtmlProcessorDocumentationWriter();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
writer.write(processor, baos, false);
String results = new String(baos.toByteArray());
assertContains(results, FullyDocumentedProcessor.DIRECTORY.getDisplayName());
assertContains(results, FullyDocumentedProcessor.DIRECTORY.getDescription());
assertContains(results, FullyDocumentedProcessor.OPTIONAL_PROPERTY.getDisplayName());
assertContains(results, FullyDocumentedProcessor.OPTIONAL_PROPERTY.getDescription());
assertContains(results, FullyDocumentedProcessor.POLLING_INTERVAL.getDisplayName());
assertContains(results, FullyDocumentedProcessor.POLLING_INTERVAL.getDescription());
assertContains(results, FullyDocumentedProcessor.POLLING_INTERVAL.getDefaultValue());
assertContains(results, FullyDocumentedProcessor.RECURSE.getDisplayName());
assertContains(results, FullyDocumentedProcessor.RECURSE.getDescription());
assertContains(results, FullyDocumentedProcessor.REL_SUCCESS.getName());
assertContains(results, FullyDocumentedProcessor.REL_SUCCESS.getDescription());
assertContains(results, FullyDocumentedProcessor.REL_FAILURE.getName());
assertContains(results, FullyDocumentedProcessor.REL_FAILURE.getDescription());
assertNotContains(results, "iconSecure.png");
assertContains(results, FullyDocumentedProcessor.class.getAnnotation(CapabilityDescription.class).value());
assertNotContains(results, "This component has no required or optional properties.");
assertNotContains(results, "No description provided.");
assertNotContains(results, "No Tags provided.");
assertNotContains(results, "Additional Details...");
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.StringReader;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.junit.Assert;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* A helper class to validate xml documents.
*
*
*/
public class XmlValidator {
public static void assertXmlValid(String xml) {
try {
DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
} catch (SAXException | IOException | ParserConfigurationException e) {
Assert.fail(e.getMessage());
}
}
public static void assertContains(String original, String subword) {
Assert.assertTrue(original + " did not contain: " + subword, original.contains(subword));
}
public static void assertNotContains(String original, String subword) {
Assert.assertFalse(original + " did contain: " + subword, original.contains(subword));
}
}

View File

@ -31,6 +31,11 @@
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-properties</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-documentation</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>

View File

@ -31,6 +31,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.nifi.documentation.DocGenerator;
import org.apache.nifi.nar.ExtensionManager;
import org.apache.nifi.nar.ExtensionMapping;
import org.apache.nifi.nar.NarClassLoaders;
@ -118,6 +119,8 @@ public class NiFi {
ExtensionManager.discoverExtensions();
ExtensionManager.logClassLoaderMapping();
DocGenerator.generate(properties);
// load the server from the framework classloader
Thread.currentThread().setContextClassLoader(frameworkClassLoader);
Class<?> jettyServer = Class.forName("org.apache.nifi.web.server.JettyServer", true, frameworkClassLoader);

View File

@ -40,6 +40,7 @@
<module>nifi-administration</module>
<module>nifi-web</module>
<module>nifi-resources</module>
<module>nifi-documentation</module>
</modules>
<dependencies>
<dependency>

View File

@ -109,6 +109,11 @@
<artifactId>nifi-web-security</artifactId>
<version>0.0.2-incubating-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-documentation</artifactId>
<version>0.0.2-incubating-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>