mirror of
https://github.com/apache/nifi.git
synced 2025-02-06 10:08:42 +00:00
NIFI-12392 Corrected Component Documentation NAR Unpacking
- Corrected component documentation directory comparison for finding bundled documentation in a JAR - Added unit test for unpacking of component documentation from JAR included in NAR Signed-off-by: Pierre Villard <pierre.villard.fr@gmail.com> This closes #8052.
This commit is contained in:
parent
e81d7254ec
commit
d5c7fcb5dd
@ -16,13 +16,17 @@
|
||||
*/
|
||||
package org.apache.nifi.nar;
|
||||
|
||||
import org.apache.nifi.bundle.BundleCoordinate;
|
||||
import org.apache.nifi.util.NiFiProperties;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
@ -36,10 +40,14 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@ -47,6 +55,28 @@ public class NarUnpackerTest {
|
||||
|
||||
private static final String PROPERTIES_PATH = "/NarUnpacker/conf/nifi.properties";
|
||||
|
||||
private static final String GROUP_ID = "org.apache.nifi";
|
||||
|
||||
private static final String ARTIFACT_ID = "nifi-nar";
|
||||
|
||||
private static final String VERSION = "1.0.0";
|
||||
|
||||
private static final String DOCS_DIR = "docs";
|
||||
|
||||
private static final String COMPONENT_JAR = String.format("component-%s.jar", VERSION);
|
||||
|
||||
private static final String PROCESSOR = "org.apache.nifi.processors.UnpackNar";
|
||||
|
||||
private static final String PROCESSOR_PATH = "META-INF/services/org.apache.nifi.processor.Processor";
|
||||
|
||||
private static final String COMPONENT_DOCS_PATH = String.format("docs/%s/", PROCESSOR);
|
||||
|
||||
private static final String ADDITIONAL_DETAILS_HTML = "additionalDetails.html";
|
||||
|
||||
private static final String ADDITIONAL_DETAILS_PATH = String.format("docs/%s/%s", PROCESSOR, ADDITIONAL_DETAILS_HTML);
|
||||
|
||||
private static final String HTML = "<html></html>";
|
||||
|
||||
@BeforeAll
|
||||
public static void copyResources() throws IOException {
|
||||
final Path sourcePath = Paths.get("./src/test/resources");
|
||||
@ -174,6 +204,66 @@ public class NarUnpackerTest {
|
||||
assertNull(extensionMapping);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapExtensionNoDependencies(@TempDir final Path tempDir) throws IOException {
|
||||
final File unpackedNarDir = tempDir.resolve(ARTIFACT_ID).toFile();
|
||||
final File docsDir = tempDir.resolve(DOCS_DIR).toFile();
|
||||
|
||||
final BundleCoordinate bundleCoordinate = new BundleCoordinate(GROUP_ID, ARTIFACT_ID, VERSION);
|
||||
final ExtensionMapping extensionMapping = new ExtensionMapping();
|
||||
|
||||
NarUnpacker.mapExtension(unpackedNarDir, bundleCoordinate, docsDir, extensionMapping);
|
||||
|
||||
assertNull(docsDir.listFiles());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapExtensionAdditionalDetails(@TempDir final Path tempDir) throws IOException {
|
||||
final File unpackedNarDir = tempDir.resolve(ARTIFACT_ID).toFile();
|
||||
final File docsDir = tempDir.resolve(DOCS_DIR).toFile();
|
||||
|
||||
final BundleCoordinate bundleCoordinate = new BundleCoordinate(GROUP_ID, ARTIFACT_ID, VERSION);
|
||||
final ExtensionMapping extensionMapping = new ExtensionMapping();
|
||||
extensionMapping.addProcessor(bundleCoordinate, PROCESSOR);
|
||||
|
||||
final Path unpackedNarDependenciesDir = unpackedNarDir.toPath().resolve(NarUnpacker.BUNDLED_DEPENDENCIES_DIRECTORY);
|
||||
assertTrue(unpackedNarDependenciesDir.toFile().mkdirs());
|
||||
|
||||
final File componentJar = unpackedNarDependenciesDir.resolve(COMPONENT_JAR).toFile();
|
||||
writeComponentJar(componentJar);
|
||||
|
||||
NarUnpacker.mapExtension(unpackedNarDir, bundleCoordinate, docsDir, extensionMapping);
|
||||
|
||||
final File[] documentationFiles = docsDir.listFiles();
|
||||
assertNotNull(documentationFiles, "Documentation Files not found");
|
||||
|
||||
final Path expectedRelativePath = Paths.get(GROUP_ID, ARTIFACT_ID, VERSION, PROCESSOR, ADDITIONAL_DETAILS_HTML);
|
||||
final Path documentationFilePath = docsDir.toPath().resolve(expectedRelativePath);
|
||||
assertTrue(Files.exists(documentationFilePath), "Documentation File not found");
|
||||
|
||||
final byte[] documentationBytes = Files.readAllBytes(documentationFilePath);
|
||||
assertArrayEquals(HTML.getBytes(StandardCharsets.UTF_8), documentationBytes);
|
||||
}
|
||||
|
||||
private void writeComponentJar(final File componentJar) throws IOException {
|
||||
try (JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream(componentJar))) {
|
||||
final JarEntry processorJarEntry = new JarEntry(PROCESSOR_PATH);
|
||||
jarOutputStream.putNextEntry(processorJarEntry);
|
||||
jarOutputStream.write(PROCESSOR.getBytes(StandardCharsets.UTF_8));
|
||||
jarOutputStream.write(System.lineSeparator().getBytes(StandardCharsets.UTF_8));
|
||||
jarOutputStream.closeEntry();
|
||||
|
||||
final JarEntry docDirectoryEntry = new JarEntry(COMPONENT_DOCS_PATH);
|
||||
jarOutputStream.putNextEntry(docDirectoryEntry);
|
||||
jarOutputStream.closeEntry();
|
||||
|
||||
final JarEntry docJarEntry = new JarEntry(ADDITIONAL_DETAILS_PATH);
|
||||
jarOutputStream.putNextEntry(docJarEntry);
|
||||
jarOutputStream.write(HTML.getBytes(StandardCharsets.UTF_8));
|
||||
jarOutputStream.closeEntry();
|
||||
}
|
||||
}
|
||||
|
||||
private NiFiProperties loadSpecifiedProperties(final Map<String, String> others) {
|
||||
String filePath;
|
||||
try {
|
||||
|
@ -61,6 +61,8 @@ public final class NarUnpacker {
|
||||
|
||||
private static final String BUNDLED_DEPENDENCIES_PREFIX = "META-INF/bundled-dependencies";
|
||||
|
||||
private static final String JAR_DOCUMENTATION_ROOT_PATH = "docs";
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(NarUnpacker.class);
|
||||
private static final String HASH_FILENAME = "nar-digest";
|
||||
private static final FileFilter NAR_FILTER = pathname -> {
|
||||
@ -554,22 +556,23 @@ public final class NarUnpacker {
|
||||
// look for all documentation related to each component
|
||||
try (final JarFile jarFile = new JarFile(jar)) {
|
||||
for (final String componentName : jarExtensionMapping.getAllExtensionNames().keySet()) {
|
||||
final String entryName = "docs/" + componentName;
|
||||
// Build documentation path based on component class using Paths.get() for platform compatibility
|
||||
final String componentDocumentationDirectory = Paths.get(JAR_DOCUMENTATION_ROOT_PATH, componentName).toString();
|
||||
|
||||
// go through each entry in this jar
|
||||
for (final Enumeration<JarEntry> jarEnumeration = jarFile.entries(); jarEnumeration.hasMoreElements();) {
|
||||
final JarEntry jarEntry = jarEnumeration.nextElement();
|
||||
final File jarEntryFile = getJarEntryFile(docsDirectory, jarEntry.getName());
|
||||
final String jarEntryName = jarEntryFile.getName();
|
||||
final String jarEntryFileAbsolutePath = jarEntryFile.getAbsolutePath();
|
||||
|
||||
// if this entry is documentation for this component
|
||||
if (jarEntryName.startsWith(entryName)) {
|
||||
final String name = StringUtils.substringAfter(jarEntryName, "docs/");
|
||||
final String path = coordinate.getGroup() + "/" + coordinate.getId() + "/" + coordinate.getVersion() + "/" + name;
|
||||
if (jarEntryFileAbsolutePath.contains(componentDocumentationDirectory)) {
|
||||
final String relativePath = StringUtils.substringAfter(jarEntryFileAbsolutePath, componentDocumentationDirectory);
|
||||
final String outputPath = Paths.get(coordinate.getGroup(), coordinate.getId(), coordinate.getVersion(), componentName, relativePath).toString();
|
||||
|
||||
// if this is a directory create it
|
||||
if (jarEntry.isDirectory()) {
|
||||
final File componentDocsDirectory = new File(docsDirectory, path);
|
||||
final File componentDocsDirectory = new File(docsDirectory, outputPath);
|
||||
|
||||
// ensure the documentation directory can be created
|
||||
if (!componentDocsDirectory.exists() && !componentDocsDirectory.mkdirs()) {
|
||||
@ -578,7 +581,7 @@ public final class NarUnpacker {
|
||||
}
|
||||
} else {
|
||||
// if this is a file, write to it
|
||||
final File componentDoc = new File(docsDirectory, path);
|
||||
final File componentDoc = new File(docsDirectory, outputPath);
|
||||
makeFile(jarFile.getInputStream(jarEntry), componentDoc);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user