Skip to content

Commit

Permalink
Refactor resource copy into class
Browse files Browse the repository at this point in the history
* Remove unused encoding from resource processing
* Created CopyResourcesProcessor
* ResourcesProcessor no longer throws MojoExecutionException
  • Loading branch information
abelsromero committed Aug 27, 2022
1 parent 6d578a9 commit 638923c
Show file tree
Hide file tree
Showing 10 changed files with 596 additions and 171 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ Improvements::
* Split plugin and site integration in sub-modules: asciidoctor-maven-plugin and asciidoctor-doxia-module (#595)
* Add 'asciidoc' as valid file extension in AsciidoctorDoxiaParserModule (#595)
* Fix throwing an exception when registering a non Extension (#596)
* Reimplemented resource copy using 'plexus.util.DirectorScanner' instead of maven-filtering to reduce dependencies and build time (#597)

Build / Infrastructure::

* Bump Doxia to v1.11.1 and maven-site-plugin in IT to 3.12.0 (#579)
* Bump netty-codec-http to v4.1.77.Final (fix CVE-2021-21290) (#582)
* Upgrade Asciidoctorj to v2.5.4 and jRuby to v9.3.4.0 (#584)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.asciidoctor.maven;

import org.apache.commons.io.FileUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
Expand All @@ -14,16 +13,15 @@
import org.asciidoctor.maven.extensions.AsciidoctorJExtensionRegistry;
import org.asciidoctor.maven.extensions.ExtensionConfiguration;
import org.asciidoctor.maven.extensions.ExtensionRegistry;
import org.asciidoctor.maven.io.AsciidoctorFileScanner;
import org.asciidoctor.maven.log.LogHandler;
import org.asciidoctor.maven.log.LogRecordFormatter;
import org.asciidoctor.maven.log.LogRecordsProcessors;
import org.asciidoctor.maven.log.MemoryLogHandler;
import org.asciidoctor.maven.model.Resource;
import org.asciidoctor.maven.process.CopyResourcesProcessor;
import org.asciidoctor.maven.process.ResourcesProcessor;
import org.asciidoctor.maven.process.SourceDirectoryFinder;
import org.asciidoctor.maven.process.SourceDocumentFinder;
import org.codehaus.plexus.util.DirectoryScanner;
import org.jruby.Ruby;

import javax.inject.Inject;
Expand All @@ -34,7 +32,6 @@
import java.util.logging.Logger;
import java.util.stream.Collectors;

import static org.asciidoctor.maven.commons.StringUtils.isBlank;
import static org.asciidoctor.maven.process.SourceDirectoryFinder.DEFAULT_SOURCE_DIR;


Expand All @@ -44,9 +41,6 @@
@Mojo(name = "process-asciidoc", threadSafe = true)
public class AsciidoctorMojo extends AbstractMojo {

@Parameter(defaultValue = "${project.build.sourceEncoding}")
protected String encoding;

@Parameter(property = AsciidoctorMaven.PREFIX + "sourceDirectory", defaultValue = "${basedir}/" + DEFAULT_SOURCE_DIR)
protected File sourceDirectory;

Expand Down Expand Up @@ -139,11 +133,7 @@ public class AsciidoctorMojo extends AbstractMojo {
protected MavenProject project;


protected final ResourcesProcessor defaultResourcesProcessor =
(sourcesRootDirectory, outputRootDirectory, encoding, configuration) -> {
final List<Resource> finalResources = prepareResources(sourcesRootDirectory, configuration);
copyResources(finalResources, outputRootDirectory);
};
protected final ResourcesProcessor defaultResourcesProcessor = new CopyResourcesProcessor();

@Override
public void execute() throws MojoExecutionException, MojoFailureException {
Expand Down Expand Up @@ -225,7 +215,7 @@ public void processSources(List<File> sourceFiles, ResourcesProcessor resourcesP

// Copy output resources
final File sourceDir = sourceDirectoryCandidate.get();
resourcesProcessor.process(sourceDir, outputDirectory, encoding, this);
resourcesProcessor.process(sourceDir, outputDirectory, this);

// register LogHandler to capture asciidoctor messages
final Boolean outputToConsole = logHandler.getOutputToConsole() == null ? Boolean.TRUE : logHandler.getOutputToConsole();
Expand Down Expand Up @@ -269,111 +259,6 @@ private boolean isRelativePath(String candidateName) {
return candidateName.startsWith("./") || candidateName.startsWith(".\\");
}

/**
* Initializes resources attribute excluding AsciiDoc documents, internal directories/files (those prefixed with
* underscore), and docinfo files.
* By default everything in the sources directories is copied.
*
* @return Collection of resources with properly configured includes and excludes conditions.
*/
private List<Resource> prepareResources(File sourceDirectory, AsciidoctorMojo configuration) {
final List<Resource> resources = configuration.getResources() != null
? configuration.getResources()
: new ArrayList<>();
if (resources.isEmpty()) {
// we don't want to copy files considered sources
Resource resource = new Resource();
resource.setDirectory(sourceDirectory.getAbsolutePath());
// exclude sourceDocumentName if defined
if (!isBlank(configuration.getSourceDocumentName())) {
resource.getExcludes()
.add(configuration.getSourceDocumentName());
}
// exclude filename extensions if defined
resources.add(resource);
}

// All resources must exclude AsciiDoc documents and folders beginning with underscore
for (Resource resource : resources) {
List<String> excludes = new ArrayList<>();
for (String value : AsciidoctorFileScanner.INTERNAL_FOLDERS_AND_FILES_PATTERNS) {
excludes.add(value);
}
for (String value : AsciidoctorFileScanner.IGNORED_FILE_NAMES) {
excludes.add("**/" + value);
}
for (String value : AsciidoctorFileScanner.DEFAULT_ASCIIDOC_EXTENSIONS) {
excludes.add(value);
}
for (String docExtension : configuration.getSourceDocumentExtensions()) {
resource.getExcludes().add("**/*." + docExtension);
}
// in case someone wants to include some of the default excluded files (e.g. AsciiDoc sources)
excludes.removeAll(resource.getIncludes());
resource.getExcludes().addAll(excludes);
}
return resources;
}

/**
* Copies the resources defined in the 'resources' attribute.
*
* @param resources Collection of {@link Resource} defining what resources to {@code outputDirectory}.
* @param outputDirectory Directory where to copy resources.
*/
private void copyResources(List<Resource> resources, File outputDirectory) {

resources.stream()
.filter(resource -> new File(resource.getDirectory()).exists())
.forEach(resource -> {
DirectoryScanner directoryScanner = new DirectoryScanner();
directoryScanner.setBasedir(resource.getDirectory());

if (resource.getIncludes().isEmpty())
directoryScanner.setIncludes(new String[]{"**/*.*", "**/*"});
else
directoryScanner.setIncludes(resource.getIncludes().toArray(new String[0]));

directoryScanner.setExcludes(resource.getExcludes().toArray(new String[0]));
directoryScanner.setFollowSymlinks(false);
directoryScanner.scan();

for (String includedFile : directoryScanner.getIncludedFiles()) {
// check if Basedir exists
// remove null check, baseDir is mandatory and already checked
File source = (directoryScanner.getBasedir() != null)
? new File(directoryScanner.getBasedir(), includedFile)
: new File(includedFile);

copyFileToDirectory(source, resource, outputDirectory);
}
});
}

private void copyFileToDirectory(File source, Resource resource, File outputDirectory) {
try {
// check if resource.getTargetPath() is absolute ??
File target = resource.getTargetPath() == null
? outputDirectory
: new File(outputDirectory, resource.getTargetPath());

Path sourceDirectoryPath = new File(resource.getDirectory()).toPath();
Path sourcePath = source.toPath();
Path relativize = sourceDirectoryPath.relativize(sourcePath);

if (relativize.getParent() == null) {
FileUtils.copyFileToDirectory(source, target);
} else {
Path realTarget = target.toPath().resolve(relativize.getParent());
File realTargetFile = realTarget.toFile();
FileUtils.forceMkdir(realTargetFile);
FileUtils.copyFileToDirectory(source, realTargetFile);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}

public static List<org.apache.maven.model.Resource> mapResources(List<Resource> resources) {
if (resources == null || resources.isEmpty())
return Collections.emptyList();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package org.asciidoctor.maven.process;

import org.apache.commons.io.FileUtils;
import org.asciidoctor.maven.AsciidoctorMojo;
import org.asciidoctor.maven.io.AsciidoctorFileScanner;
import org.asciidoctor.maven.model.Resource;
import org.codehaus.plexus.util.DirectoryScanner;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

import static org.asciidoctor.maven.commons.StringUtils.isBlank;

/**
* {@link ResourcesProcessor} implementation that copies all valid resources from
* a source directory to an output one.
* <p/>
* Following resources are not valid:
* - AsciiDoc documents: based on file extension.
* - Asciidoctor Docinfo files.
* - Internal files and folders: those not starting with underscore '_'.
*/
public class CopyResourcesProcessor implements ResourcesProcessor {

/*
* (non-Javadoc)
*
* @see
* org.asciidoctor.maven.process.ResourcesProcessor#process(File sourceRootDirectory, File outputRootDirectory, AsciidoctorMojo configuration)
*/
@Override
public void process(File sourceRootDirectory, File outputRootDirectory, AsciidoctorMojo configuration) {
final List<Resource> finalResources = prepareResources(sourceRootDirectory, configuration);
copyResources(finalResources, outputRootDirectory);
}

/**
* Initializes resources attribute excluding AsciiDoc documents, internal directories/files (those prefixed with
* underscore), and docinfo files.
* By default everything in the sources directories is copied.
*
* @return Collection of resources with properly configured includes and excludes conditions.
*/
private List<Resource> prepareResources(File sourceDirectory, AsciidoctorMojo configuration) {
final List<Resource> resources = configuration.getResources() != null
? configuration.getResources()
: new ArrayList<>();
if (resources.isEmpty()) {
// we don't want to copy files considered sources
Resource resource = new Resource();
resource.setDirectory(sourceDirectory.getAbsolutePath());
// exclude sourceDocumentName if defined
if (!isBlank(configuration.getSourceDocumentName())) {
resource.getExcludes()
.add(configuration.getSourceDocumentName());
}
resources.add(resource);
}

// All resources must exclude AsciiDoc documents and folders beginning with underscore
for (Resource resource : resources) {

List<String> excludes = new ArrayList<>();
for (String value : AsciidoctorFileScanner.INTERNAL_FOLDERS_AND_FILES_PATTERNS) {
excludes.add(value);
}
for (String value : AsciidoctorFileScanner.IGNORED_FILE_NAMES) {
excludes.add("**/" + value);
}
for (String value : AsciidoctorFileScanner.DEFAULT_ASCIIDOC_EXTENSIONS) {
excludes.add(value);
}
// exclude filename extensions if defined
for (String docExtension : configuration.getSourceDocumentExtensions()) {
resource.getExcludes().add("**/*." + docExtension);
}
// in case someone wants to include some of the default excluded files (e.g. AsciiDoc sources)
excludes.removeAll(resource.getIncludes());
resource.getExcludes().addAll(excludes);
}
return resources;
}

/**
* Copies the resources defined in the 'resources' attribute.
*
* @param resources Collection of {@link Resource} defining what resources to {@code outputDirectory}.
* @param outputDirectory Directory where to copy resources.
*/
private void copyResources(List<Resource> resources, File outputDirectory) {

resources.stream()
.filter(resource -> new File(resource.getDirectory()).exists())
.forEach(resource -> {
DirectoryScanner directoryScanner = new DirectoryScanner();
directoryScanner.setBasedir(resource.getDirectory());

if (resource.getIncludes().isEmpty())
directoryScanner.setIncludes(new String[]{"**/*.*", "**/*"});
else
directoryScanner.setIncludes(resource.getIncludes().toArray(new String[0]));

directoryScanner.setExcludes(resource.getExcludes().toArray(new String[0]));
directoryScanner.setFollowSymlinks(false);
directoryScanner.scan();

for (String includedFile : directoryScanner.getIncludedFiles()) {
File source = new File(directoryScanner.getBasedir(), includedFile);
copyFileToDirectory(source, resource, outputDirectory);
}
});
}


private void copyFileToDirectory(File source, Resource resource, File outputDirectory) {
try {
final File target = resource.getTargetPath() == null
? outputDirectory
: composeTargetPath(resource, outputDirectory);

Path sourceDirectoryPath = new File(resource.getDirectory()).toPath();
Path sourcePath = source.toPath();
Path relativize = sourceDirectoryPath.relativize(sourcePath);

if (relativize.getParent() == null) {
FileUtils.copyFileToDirectory(source, target);
} else {
Path realTarget = target.toPath().resolve(relativize.getParent());
File realTargetFile = realTarget.toFile();
FileUtils.forceMkdir(realTargetFile);
FileUtils.copyFileToDirectory(source, realTargetFile);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}

private static File composeTargetPath(Resource resource, File outputDirectory) {
final File targetFile = new File(resource.getTargetPath());
return targetFile.isAbsolute()
? targetFile
: new File(outputDirectory, resource.getTargetPath());
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
package org.asciidoctor.maven.process;

import org.apache.maven.plugin.MojoExecutionException;
import org.asciidoctor.maven.AsciidoctorMojo;

import java.io.File;

public interface ResourcesProcessor {

void process(File sourcesRootDirectory, File outputRootDirectory,
String encoding, AsciidoctorMojo configuration) throws MojoExecutionException;
/**
* Identifies requires resources and prepares them based on configuration.
*
* @param sourceRootDirectory starting directory to search resources. 'configuration' may add or modify it.
* @param outputRootDirectory target directory to place final resources when copying is required.
* @param configuration Asciidoctor conversion configuration
*/
void process(File sourceRootDirectory, File outputRootDirectory, AsciidoctorMojo configuration);

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@
import org.asciidoctor.maven.process.ResourcesProcessor;

import java.io.File;
import java.util.Collections;

public class AdditionalSourceFileAlterationListenerAdaptor extends AbstractFileAlterationListenerAdaptor {

private static final ResourcesProcessor EMPTY_RESOURCES_PROCESSOR = (sourcesDir, outputDir, encoding, configuration) -> {
private static final ResourcesProcessor EMPTY_RESOURCES_PROCESSOR = (sourcesDir, outputDir, configuration) -> {
};


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

public class AsciidoctorConverterFileAlterationListenerAdaptor extends AbstractFileAlterationListenerAdaptor {

private static final ResourcesProcessor EMPTY_RESOURCES_PROCESSOR = (sourcesDir, outputDir, encoding, configuration) -> {
private static final ResourcesProcessor EMPTY_RESOURCES_PROCESSOR = (sourcesDir, outputDir, configuration) -> {
};


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ synchronized void processFile(File file, String actionName) {
final File sourceDirectory = mojo.findSourceDirectory(mojo.getSourceDirectory(), mojo.getBaseDir()).get();
final File outputDirectory = mojo.getOutputDirectory();

// TODO understand this and see if can be reused
final List<Resource> resources = mapResources(mojo.getResources());
List<Resource> matchingResources = findMatchingResources(resources, file);
if (matchingResources.isEmpty()) {
Expand Down

0 comments on commit 638923c

Please sign in to comment.