Skip to content

Commit

Permalink
adds synchronization of resources for refresh mojo + hotfix to avoid …
Browse files Browse the repository at this point in the history
…blocking main thread in http mojo (#478)
  • Loading branch information
abelsromero committed Aug 4, 2020
1 parent ae49ced commit 3b78659
Show file tree
Hide file tree
Showing 13 changed files with 1,167 additions and 113 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Improvements::

* Inject Maven properties as attributes in `process-asciidoc` mojo (#459)
* Make `auto-refresh` (and `http` by inheritance) only convert modified and created sources (#474)
* Make `auto-refresh` only copy modified and created resources + taking into consideration <resources> options (#478)

Bug Fixes::

Expand Down
8 changes: 4 additions & 4 deletions src/main/java/org/asciidoctor/maven/AsciidoctorHttpMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ public class AsciidoctorHttpMojo extends AsciidoctorRefreshMojo {
@Parameter(property = PREFIX + "reload-interval", defaultValue = "0")
protected int autoReloadInterval;


@Override
protected void doWork() throws MojoFailureException, MojoExecutionException {
public void execute() throws MojoExecutionException, MojoFailureException {
final AsciidoctorHttpServer server = new AsciidoctorHttpServer(getLog(), port, outputDirectory, home);
server.start();

super.doWork();

doWork();
doWait();
server.stop();
}

Expand Down
7 changes: 4 additions & 3 deletions src/main/java/org/asciidoctor/maven/AsciidoctorMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@
public class AsciidoctorMojo extends AbstractMojo {
// copied from org.asciidoctor.AsciiDocDirectoryWalker.ASCIIDOC_REG_EXP_EXTENSION
// should probably be configured in AsciidoctorMojo through @Parameter 'extension'
protected static final String ASCIIDOC_REG_EXP_EXTENSION = "^[^_.].*\\.a((sc(iidoc)?)|d(oc)?)$";
protected static final String ASCIIDOC_FILE_EXTENSIONS_REG_EXP = "a((sc(iidoc)?)|d(oc)?)";
protected static final String ASCIIDOC_NON_INTERNAL_REG_EXP = "^[^_.].*\\." + ASCIIDOC_FILE_EXTENSIONS_REG_EXP + "$";

@Parameter(defaultValue = "${project.build.sourceEncoding}")
protected String encoding;
Expand Down Expand Up @@ -196,7 +197,7 @@ public void processSources(List<File> sourceFiles, ResourcesProcessor resourcesP
}

if (sourceDirectory == null) {
throw new MojoExecutionException("Required parameter 'asciidoctor.alternateSourceDir' not set.");
throw new MojoExecutionException("Required parameter 'asciidoctor.sourceDirectory' not set.");
}

Optional<File> sourceDirectoryCandidate = findSourceDirectory(sourceDirectory, project.getBasedir());
Expand Down Expand Up @@ -275,7 +276,7 @@ public void processSources(List<File> sourceFiles, ResourcesProcessor resourcesP
}
}

protected Optional<File> findSourceDirectory(File initialSourceDirectory, File baseDir) {
public Optional<File> findSourceDirectory(File initialSourceDirectory, File baseDir) {
Optional<File> sourceDirCandidate = new SourceDirectoryFinder(initialSourceDirectory, baseDir,
candidate -> {
String candidateName = candidate.toString();
Expand Down
126 changes: 56 additions & 70 deletions src/main/java/org/asciidoctor/maven/AsciidoctorRefreshMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,32 @@

package org.asciidoctor.maven;

import org.apache.commons.io.filefilter.*;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.filefilter.NameFileFilter;
import org.apache.commons.io.filefilter.RegexFileFilter;
import org.apache.commons.io.monitor.FileAlterationListener;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.asciidoctor.maven.process.ResourcesProcessor;
import org.asciidoctor.maven.refresh.AsciidoctorConverterFileAlterationListenerAdaptor;
import org.asciidoctor.maven.refresh.ResourceCopyFileAlterationListenerAdaptor;
import org.asciidoctor.maven.refresh.TimeCounter;

import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.Scanner;
import java.util.StringJoiner;
import java.util.concurrent.TimeUnit;
import java.io.FileFilter;
import java.util.*;

import static org.apache.commons.lang3.StringUtils.isBlank;

@Mojo(name = "auto-refresh")
public class AsciidoctorRefreshMojo extends AsciidoctorMojo {

public static final String PREFIX = AsciidoctorMaven.PREFIX + "refresher.";

private static final ResourcesProcessor EMPTY_RESOURCE_PROCESSOR =
(sourcesRootDirectory, outputRootDirectory, encoding, configuration) -> {
};

@Parameter(property = PREFIX + "interval")
protected int interval = 2000; // 2s

Expand All @@ -50,19 +48,19 @@ public class AsciidoctorRefreshMojo extends AsciidoctorMojo {
public void execute() throws MojoExecutionException, MojoFailureException {
startPolling();
doWork();
doWait();
stopMonitors();
}

protected void doWork() throws MojoFailureException, MojoExecutionException {
long timeInMillis = timed(() -> {
long timeInMillis = TimeCounter.timed(() -> {
try {
processAllSources(defaultResourcesProcessor);
} catch (MojoExecutionException e) {
getLog().error(e);
}
});
getLog().info("Converted document(s) in " + timeInMillis + "ms");
doWait();
}

protected void doWait() throws MojoExecutionException, MojoFailureException {
Expand All @@ -73,7 +71,7 @@ protected void doWait() throws MojoExecutionException, MojoFailureException {
while ((line = scanner.nextLine()) != null) {
line = line.trim();
if ("exit".equalsIgnoreCase(line) || "quit".equalsIgnoreCase(line)) {
break;
return;
}

if ("refresh".equalsIgnoreCase(line)) {
Expand Down Expand Up @@ -102,17 +100,34 @@ private void stopMonitors() throws MojoExecutionException {

private void startPolling() throws MojoExecutionException {

// TODO avoid duplication with AsciidoctorMojo
final Optional<File> sourceDirectoryCandidate = findSourceDirectory(sourceDirectory, project.getBasedir());
if (!sourceDirectoryCandidate.isPresent()) {
getLog().info("No sourceDirectory found. Skipping processing");
return;
}
final File sourceDirectory = sourceDirectoryCandidate.get();

final FileAlterationMonitor fileAlterationMonitor = new FileAlterationMonitor(interval);

{ // content monitor
final FileAlterationObserver observer = new FileAlterationObserver(sourceDirectory, buildFileFilter());
final FileAlterationObserver observer = new FileAlterationObserver(sourceDirectory, buildSourcesFileFilter());
final FileAlterationListener listener = new AsciidoctorConverterFileAlterationListenerAdaptor(this, () -> showWaitMessage(), getLog());
final FileAlterationMonitor monitor = new FileAlterationMonitor(interval);

observer.addListener(listener);
monitor.addObserver(observer);
fileAlterationMonitor.addObserver(observer);
}

monitors = Collections.singletonList(monitor);
{ // resources monitor
final FileAlterationObserver observer = new FileAlterationObserver(sourceDirectory, buildResourcesFileFilter());
final FileAlterationListener listener = new ResourceCopyFileAlterationListenerAdaptor(this, () -> showWaitMessage(), getLog());

observer.addListener(listener);
fileAlterationMonitor.addObserver(observer);
}

monitors = Collections.singletonList(fileAlterationMonitor);

for (final FileAlterationMonitor monitor : monitors) {
try {
monitor.start();
Expand All @@ -122,65 +137,36 @@ private void startPolling() throws MojoExecutionException {
}
}

private IOFileFilter buildFileFilter() {
if (sourceDocumentName != null)
private FileFilter buildResourcesFileFilter() {

final StringJoiner filePattern = new StringJoiner("|")
.add(ASCIIDOC_FILE_EXTENSIONS_REG_EXP);
if (!sourceDocumentExtensions.isEmpty())
filePattern.add(String.join("|", sourceDocumentExtensions));

final String includedResourcesPattern = new StringBuilder()
.append("^")
.append(isBlank(sourceDocumentName) ? "" : "(?!(" + sourceDocumentName + "))")
.append("[^_.].*\\.(?!(")
.append(filePattern.toString())
.append(")).*$")
.toString();
return FileFilterUtils.or(FileFilterUtils.directoryFileFilter(), new RegexFileFilter(includedResourcesPattern));
}

private IOFileFilter buildSourcesFileFilter() {
if (!isBlank(sourceDocumentName))
return new NameFileFilter(sourceDocumentName);

if (!sourceDocumentExtensions.isEmpty()) {
final StringJoiner stringJoiner = new StringJoiner("|", "^[^_.].*\\.(", ")$");
for (String extension : sourceDocumentExtensions) {
stringJoiner.add(extension);
}
return directoryRecursiveFileFilter(new RegexFileFilter(stringJoiner.toString()));
return FileFilterUtils.or(FileFilterUtils.directoryFileFilter(), new RegexFileFilter(stringJoiner.toString()));
}

return directoryRecursiveFileFilter(new RegexFileFilter(ASCIIDOC_REG_EXP_EXTENSION));
}

private IOFileFilter directoryRecursiveFileFilter(AbstractFileFilter fileFilter) {
return FileFilterUtils.or(FileFilterUtils.directoryFileFilter(), fileFilter);
return FileFilterUtils.or(FileFilterUtils.directoryFileFilter(), new RegexFileFilter(ASCIIDOC_NON_INTERNAL_REG_EXP));
}

private class AsciidoctorConverterFileAlterationListenerAdaptor extends FileAlterationListenerAdaptor {

private final AsciidoctorMojo mojo;
private final Runnable postAction;
private final Log log;

private AsciidoctorConverterFileAlterationListenerAdaptor(AsciidoctorMojo config, Runnable postAction, Log log) {
this.mojo = config;
this.postAction = postAction;
this.log = log;
}

@Override
public void onFileCreate(final File file) {
processFile(file, "created");
}

@Override
public void onFileChange(final File file) {
processFile(file, "updated");
}

private synchronized void processFile(File file, String actionName) {
log.info(String.format("Source file %s %s", file.getAbsolutePath(), actionName));
long timeInMillis = timed(() -> {
try {
mojo.processSources(Collections.singletonList(file), EMPTY_RESOURCE_PROCESSOR);
} catch (MojoExecutionException e) {
log.error(e);
}
});
getLog().info("Converted document in " + timeInMillis + "ms");
postAction.run();
}
}

public long timed(Runnable runnable) {
final long start = System.nanoTime();
runnable.run();
final long end = System.nanoTime();
return TimeUnit.NANOSECONDS.toMillis(end - start);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.asciidoctor.maven.refresh;

import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.maven.plugin.logging.Log;
import org.asciidoctor.maven.AsciidoctorRefreshMojo;

import java.io.File;

public abstract class AbstractFileAlterationListenerAdaptor extends FileAlterationListenerAdaptor {

private final AsciidoctorRefreshMojo mojo;
private final Runnable postAction;
private final Log log;

public AbstractFileAlterationListenerAdaptor(AsciidoctorRefreshMojo mojo, Runnable postAction, Log log) {
this.mojo = mojo;
this.postAction = postAction;
this.log = log;
}

@Override
public void onFileCreate(final File file) {
processFile(file, "created");
postAction.run();
}

@Override
public void onFileChange(final File file) {
processFile(file, "updated");
postAction.run();
}

abstract void processFile(File file, String actionName);

public AsciidoctorRefreshMojo getMojo() {
return mojo;
}

public Log getLog() {
return log;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.asciidoctor.maven.refresh;

import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.asciidoctor.maven.AsciidoctorRefreshMojo;
import org.asciidoctor.maven.process.ResourcesProcessor;

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

public class AsciidoctorConverterFileAlterationListenerAdaptor extends AbstractFileAlterationListenerAdaptor {

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


public AsciidoctorConverterFileAlterationListenerAdaptor(AsciidoctorRefreshMojo mojo, Runnable postAction, Log log) {
super(mojo, postAction, log);
}

@Override
synchronized void processFile(File file, String actionName) {
getLog().info(String.format("Source file %s %s", file.getAbsolutePath(), actionName));
long timeInMillis = TimeCounter.timed(() -> {
try {
getMojo().processSources(Collections.singletonList(file), EMPTY_RESOURCES_PROCESSOR);
} catch (MojoExecutionException e) {
getLog().error(e);
}
});
getLog().info("Converted document in " + timeInMillis + "ms");
}

}
Loading

0 comments on commit 3b78659

Please sign in to comment.