diff --git a/asciidoctor-maven-commons/pom.xml b/asciidoctor-maven-commons/pom.xml index d41012c6..168a45e4 100644 --- a/asciidoctor-maven-commons/pom.xml +++ b/asciidoctor-maven-commons/pom.xml @@ -37,6 +37,7 @@ ${maven.version} provided + org.codehaus.plexus plexus-utils diff --git a/asciidoctor-maven-plugin/src/main/java/org/asciidoctor/maven/AsciidoctorJFactory.java b/asciidoctor-maven-plugin/src/main/java/org/asciidoctor/maven/AsciidoctorJFactory.java new file mode 100644 index 00000000..a065b89a --- /dev/null +++ b/asciidoctor-maven-plugin/src/main/java/org/asciidoctor/maven/AsciidoctorJFactory.java @@ -0,0 +1,55 @@ +package org.asciidoctor.maven; + +import java.io.File; + +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.logging.Log; +import org.asciidoctor.Asciidoctor; +import org.asciidoctor.jruby.AsciidoctorJRuby; +import org.asciidoctor.jruby.internal.JRubyRuntimeContext; +import org.jruby.Ruby; + +import javax.inject.Singleton; + +@Singleton +public class AsciidoctorJFactory { + + Asciidoctor create(String gemPath, Log log) throws MojoExecutionException { + Asciidoctor asciidoctor; + if (gemPath == null) { + asciidoctor = AsciidoctorJRuby.Factory.create(); + } else { + // Replace Windows path separator to avoid paths with mixed \ and /. + // This happens for instance when setting: ${project.build.directory}/gems-provided + // because the project's path is converted to string. + String normalizedGemPath = (File.separatorChar == '\\') ? gemPath.replaceAll("\\\\", "/") : gemPath; + asciidoctor = AsciidoctorJRuby.Factory.create(normalizedGemPath); + } + + Ruby rubyInstance = null; + try { + rubyInstance = (Ruby) JRubyRuntimeContext.class.getMethod("get") + .invoke(null); + } catch (NoSuchMethodException e) { + if (rubyInstance == null) { + try { + rubyInstance = (Ruby) JRubyRuntimeContext.class.getMethod("get", Asciidoctor.class).invoke(null, asciidoctor); + } catch (Exception e1) { + throw new MojoExecutionException("Failed to invoke get(AsciiDoctor) for JRubyRuntimeContext", e1); + } + + } + } catch (Exception e) { + throw new MojoExecutionException("Failed to invoke get for JRubyRuntimeContext", e); + } + + String gemHome = rubyInstance.evalScriptlet("ENV['GEM_HOME']").toString(); + String gemHomeExpected = (gemPath == null || "".equals(gemPath)) ? "" : gemPath.split(java.io.File.pathSeparator)[0]; + + if (!"".equals(gemHome) && !gemHomeExpected.equals(gemHome)) { + log.warn("Using inherited external environment to resolve gems (" + gemHome + "), i.e. build is platform dependent!"); + } + + return asciidoctor; + } +} diff --git a/asciidoctor-maven-plugin/src/main/java/org/asciidoctor/maven/AsciidoctorMojo.java b/asciidoctor-maven-plugin/src/main/java/org/asciidoctor/maven/AsciidoctorMojo.java index a51bc12b..5e5fac7d 100644 --- a/asciidoctor-maven-plugin/src/main/java/org/asciidoctor/maven/AsciidoctorMojo.java +++ b/asciidoctor-maven-plugin/src/main/java/org/asciidoctor/maven/AsciidoctorMojo.java @@ -5,7 +5,6 @@ import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -22,14 +21,8 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; import org.asciidoctor.Asciidoctor; -import org.asciidoctor.Attributes; -import org.asciidoctor.AttributesBuilder; import org.asciidoctor.Options; import org.asciidoctor.OptionsBuilder; -import org.asciidoctor.SafeMode; -import org.asciidoctor.jruby.AsciidoctorJRuby; -import org.asciidoctor.jruby.internal.JRubyRuntimeContext; -import org.asciidoctor.maven.commons.AsciidoctorHelper; import org.asciidoctor.maven.extensions.AsciidoctorJExtensionRegistry; import org.asciidoctor.maven.extensions.ExtensionConfiguration; import org.asciidoctor.maven.extensions.ExtensionRegistry; @@ -38,14 +31,10 @@ 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.jruby.Ruby; -import static org.asciidoctor.maven.commons.StringUtils.isBlank; -import static org.asciidoctor.maven.commons.StringUtils.isNotBlank; import static org.asciidoctor.maven.process.SourceDirectoryFinder.DEFAULT_SOURCE_DIR; @@ -145,9 +134,14 @@ public class AsciidoctorMojo extends AbstractMojo { @Inject protected MavenProject project; - - - protected final ResourcesProcessor defaultResourcesProcessor = new CopyResourcesProcessor(); + @Inject + private AsciidoctorJFactory asciidoctorJFactory; + @Inject + private SourceDocumentFinder finder; + @Inject + protected ResourcesProcessor defaultResourcesProcessor; + @Inject + private AsciidoctorOptionsFactory asciidoctorOptionsFactory; @Override public void execute() throws MojoExecutionException, MojoFailureException { @@ -209,7 +203,8 @@ public void processSources(List sourceFiles, ResourcesProcessor resourcesP } } - final Asciidoctor asciidoctor = getAsciidoctorInstance(gemPath); + final Asciidoctor asciidoctor = asciidoctorJFactory.create(gemPath, getLog()); + if (enableVerbose) { asciidoctor.requireLibrary("enable_verbose.rb"); } @@ -224,8 +219,7 @@ public void processSources(List sourceFiles, ResourcesProcessor resourcesP } } - AttributesBuilder attributesBuilder = createAttributesBuilder(this, project); - OptionsBuilder optionsBuilder = createOptionsBuilder(this, attributesBuilder); + OptionsBuilder optionsBuilder = asciidoctorOptionsFactory.create(this, project, getLog()); // Copy output resources final File sourceDir = sourceDirectoryCandidate.get(); @@ -234,7 +228,7 @@ public void processSources(List sourceFiles, ResourcesProcessor resourcesP // register LogHandler to capture asciidoctor messages final Boolean outputToConsole = logHandler.getOutputToConsole() == null ? Boolean.TRUE : logHandler.getOutputToConsole(); final MemoryLogHandler memoryLogHandler = new MemoryLogHandler(outputToConsole, - logRecord -> getLog().info(LogRecordFormatter.format(logRecord, sourceDir))); + logRecord -> getLog().info(LogRecordFormatter.format(logRecord, sourceDir))); asciidoctor.registerLogHandler(memoryLogHandler); // disable default console output of AsciidoctorJ Logger.getLogger("asciidoctor").setUseParentHandlers(false); @@ -257,7 +251,7 @@ public void processSources(List sourceFiles, ResourcesProcessor resourcesP try { // process log messages according to mojo configuration new LogRecordsProcessors(logHandler, sourceDir, errorMessage -> getLog().error(errorMessage)) - .processLogRecords(memoryLogHandler); + .processLogRecords(memoryLogHandler); } catch (Exception exception) { throw new MojoExecutionException(exception.getMessage()); } @@ -266,12 +260,12 @@ public void processSources(List sourceFiles, ResourcesProcessor resourcesP public Optional findSourceDirectory(File initialSourceDirectory, File baseDir) { Optional sourceDirCandidate = new SourceDirectoryFinder(initialSourceDirectory, baseDir, - candidate -> { - String candidateName = candidate.toString(); - if (isRelativePath(candidateName)) candidateName = candidateName.substring(2); - getLog().info("sourceDirectory " + candidateName + " does not exist"); - }) - .find(); + candidate -> { + String candidateName = candidate.toString(); + if (isRelativePath(candidateName)) candidateName = candidateName.substring(2); + getLog().info("sourceDirectory " + candidateName + " does not exist"); + }) + .find(); return sourceDirCandidate; } @@ -317,8 +311,8 @@ public Destination setDestinationPaths(final File sourceFile, final OptionsBuild // allow overriding the output file name optionsBuilder.toFile(outputFile); return outputFile.isAbsolute() - ? new Destination(outputFile, true) - : new Destination(new File(toDir, outputFile.getPath()), true); + ? new Destination(outputFile, true) + : new Destination(new File(toDir, outputFile.getPath()), true); } else { return new Destination(new File(toDir, sourceFile.getName()), false); } @@ -338,59 +332,14 @@ class Destination { } } - protected Asciidoctor getAsciidoctorInstance(String gemPath) throws MojoExecutionException { - Asciidoctor asciidoctor; - if (gemPath == null) { - asciidoctor = AsciidoctorJRuby.Factory.create(); - } else { - // Replace Windows path separator to avoid paths with mixed \ and /. - // This happens for instance when setting: ${project.build.directory}/gems-provided - // because the project's path is converted to string. - String normalizedGemPath = (File.separatorChar == '\\') ? gemPath.replaceAll("\\\\", "/") : gemPath; - asciidoctor = AsciidoctorJRuby.Factory.create(normalizedGemPath); - } - - Ruby rubyInstance = null; - try { - rubyInstance = (Ruby) JRubyRuntimeContext.class.getMethod("get") - .invoke(null); - } catch (NoSuchMethodException e) { - if (rubyInstance == null) { - try { - rubyInstance = (Ruby) JRubyRuntimeContext.class.getMethod( - "get", Asciidoctor.class).invoke(null, asciidoctor); - } catch (Exception e1) { - throw new MojoExecutionException( - "Failed to invoke get(AsciiDoctor) for JRubyRuntimeContext", - e1); - } - - } - } catch (Exception e) { - throw new MojoExecutionException( - "Failed to invoke get for JRubyRuntimeContext", e); - } - - String gemHome = rubyInstance.evalScriptlet("ENV['GEM_HOME']").toString(); - String gemHomeExpected = (gemPath == null || "".equals(gemPath)) ? "" : gemPath.split(java.io.File.pathSeparator)[0]; - - if (!"".equals(gemHome) && !gemHomeExpected.equals(gemHome)) { - getLog().warn("Using inherited external environment to resolve gems (" + gemHome + "), i.e. build is platform dependent!"); - } - - return asciidoctor; - } - protected List findSourceFiles(File sourceDirectory) { if (sourceDocumentName != null) - return Arrays.asList(new File(sourceDirectory, sourceDocumentName)); - - Path sourceDirectoryPath = sourceDirectory.toPath(); - SourceDocumentFinder finder = new SourceDocumentFinder(); + return List.of(new File(sourceDirectory, sourceDocumentName)); + final Path sourceDirectoryPath = sourceDirectory.toPath(); return sourceDocumentExtensions.isEmpty() ? - finder.find(sourceDirectoryPath) : - finder.find(sourceDirectoryPath, sourceDocumentExtensions); + finder.find(sourceDirectoryPath) : + finder.find(sourceDirectoryPath, sourceDocumentExtensions); } protected void convertFile(Asciidoctor asciidoctor, Options options, File f) { @@ -409,73 +358,6 @@ protected boolean ensureOutputExists() { return true; } - /** - * Creates an OptionsBuilder instance with the options defined in the configuration. - * - * @param configuration AsciidoctorMojo containing conversion configuration. - * @param attributesBuilder If not null, Asciidoctor attributes to add to the OptionsBuilder created. - * @return initialized optionsBuilder. - */ - protected OptionsBuilder createOptionsBuilder(AsciidoctorMojo configuration, AttributesBuilder attributesBuilder) { - - final OptionsBuilder optionsBuilder = Options.builder() - .backend(configuration.getBackend()) - .safe(SafeMode.UNSAFE) - .standalone(configuration.standalone) - .mkDirs(true); - - if (!isBlank(configuration.getEruby())) - optionsBuilder.eruby(configuration.getEruby()); - - if (configuration.isSourcemap()) - optionsBuilder.option(Options.SOURCEMAP, true); - - if (configuration.isCatalogAssets()) - optionsBuilder.option(Options.CATALOG_ASSETS, true); - - if (!configuration.isTemplateCache()) - optionsBuilder.option(Options.TEMPLATE_CACHE, false); - - if (configuration.getDoctype() != null) - optionsBuilder.docType(doctype); - - if (configuration.getTemplateEngine() != null) - optionsBuilder.templateEngine(templateEngine); - - if (!configuration.getTemplateDirs().isEmpty()) - optionsBuilder.templateDirs(templateDirs.toArray(new File[]{})); - - optionsBuilder.attributes(attributesBuilder.build()); - return optionsBuilder; - } - - /** - * Creates an AttributesBuilder instance with the attributes defined in the configuration. - * - * @param configuration AsciidoctorMojo containing conversion configuration. - * @param mavenProject Current {@link MavenProject} instance. - * @return initialized attributesBuilder. - */ - protected AttributesBuilder createAttributesBuilder(AsciidoctorMojo configuration, MavenProject mavenProject) { - - final AttributesBuilder attributesBuilder = Attributes.builder(); - - if (configuration.isEmbedAssets()) { - attributesBuilder.linkCss(false); - attributesBuilder.dataUri(true); - } - - AsciidoctorHelper.addProperties(mavenProject.getProperties(), attributesBuilder); - AsciidoctorHelper.addAttributes(configuration.getAttributes(), attributesBuilder); - - if (isNotBlank(configuration.getAttributesChain())) { - getLog().info("Attributes: " + attributesChain); - attributesBuilder.arguments(attributesChain); - } - - return attributesBuilder; - } - public File getSourceDirectory() { return sourceDirectory; } diff --git a/asciidoctor-maven-plugin/src/main/java/org/asciidoctor/maven/AsciidoctorOptionsFactory.java b/asciidoctor-maven-plugin/src/main/java/org/asciidoctor/maven/AsciidoctorOptionsFactory.java new file mode 100644 index 00000000..70d52033 --- /dev/null +++ b/asciidoctor-maven-plugin/src/main/java/org/asciidoctor/maven/AsciidoctorOptionsFactory.java @@ -0,0 +1,90 @@ +package org.asciidoctor.maven; + +import javax.inject.Singleton; +import java.io.File; + +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.asciidoctor.Attributes; +import org.asciidoctor.AttributesBuilder; +import org.asciidoctor.Options; +import org.asciidoctor.OptionsBuilder; +import org.asciidoctor.SafeMode; +import org.asciidoctor.maven.commons.AsciidoctorHelper; + +import static org.asciidoctor.maven.commons.StringUtils.isBlank; +import static org.asciidoctor.maven.commons.StringUtils.isNotBlank; + +@Singleton +public class AsciidoctorOptionsFactory { + + /** + * Creates an AttributesBuilder instance with the attributes defined in the configuration. + * + * @param configuration AsciidoctorMojo containing conversion configuration. + * @param mavenProject Current {@link MavenProject} instance. + * @param log The mojo's {@link Log} reference. + * @return initialized attributesBuilder. + */ + private Attributes createAttributes(AsciidoctorMojo configuration, MavenProject mavenProject, Log log) { + + final AttributesBuilder attributesBuilder = Attributes.builder(); + + if (configuration.isEmbedAssets()) { + attributesBuilder.linkCss(false); + attributesBuilder.dataUri(true); + } + + AsciidoctorHelper.addProperties(mavenProject.getProperties(), attributesBuilder); + AsciidoctorHelper.addAttributes(configuration.getAttributes(), attributesBuilder); + + if (isNotBlank(configuration.getAttributesChain())) { + log.info("Attributes: " + configuration.getAttributesChain()); + attributesBuilder.arguments(configuration.getAttributesChain()); + } + + return attributesBuilder.build(); + } + + /** + * Creates an OptionsBuilder instance with the options defined in the configuration. + * + * @param configuration AsciidoctorMojo containing conversion configuration. + * @param project Current {@link MavenProject} instance. + * @param log The mojo's {@link Log} reference. + * @return initialized optionsBuilder. + */ + OptionsBuilder create(AsciidoctorMojo configuration, MavenProject project, Log log) { + + final OptionsBuilder optionsBuilder = Options.builder() + .backend(configuration.getBackend()) + .safe(SafeMode.UNSAFE) + .standalone(configuration.standalone) + .mkDirs(true); + + if (!isBlank(configuration.getEruby())) + optionsBuilder.eruby(configuration.getEruby()); + + if (configuration.isSourcemap()) + optionsBuilder.option(Options.SOURCEMAP, true); + + if (configuration.isCatalogAssets()) + optionsBuilder.option(Options.CATALOG_ASSETS, true); + + if (!configuration.isTemplateCache()) + optionsBuilder.option(Options.TEMPLATE_CACHE, false); + + if (configuration.getDoctype() != null) + optionsBuilder.docType(configuration.getDoctype()); + + if (configuration.getTemplateEngine() != null) + optionsBuilder.templateEngine(configuration.getTemplateEngine()); + + if (!configuration.getTemplateDirs().isEmpty()) + optionsBuilder.templateDirs(configuration.getTemplateDirs().toArray(new File[]{})); + + final Attributes attributes = createAttributes(configuration, project, log); + return optionsBuilder.attributes(attributes); + } + +} diff --git a/asciidoctor-maven-plugin/src/main/java/org/asciidoctor/maven/AsciidoctorZipMojo.java b/asciidoctor-maven-plugin/src/main/java/org/asciidoctor/maven/AsciidoctorZipMojo.java index 0557fec4..cc5385e1 100644 --- a/asciidoctor-maven-plugin/src/main/java/org/asciidoctor/maven/AsciidoctorZipMojo.java +++ b/asciidoctor-maven-plugin/src/main/java/org/asciidoctor/maven/AsciidoctorZipMojo.java @@ -3,6 +3,7 @@ import java.io.File; import java.io.IOException; +import jnr.ffi.annotations.In; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Component; @@ -10,6 +11,9 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProjectHelper; import org.asciidoctor.maven.io.Zips; +import org.asciidoctor.maven.process.SourceDocumentFinder; + +import javax.inject.Inject; @Deprecated(since = "3.0.0", forRemoval = true) @Mojo(name = "zip") diff --git a/asciidoctor-maven-plugin/src/main/java/org/asciidoctor/maven/http/AsciidoctorHandler.java b/asciidoctor-maven-plugin/src/main/java/org/asciidoctor/maven/http/AsciidoctorHandler.java index 8744b353..d1827e25 100644 --- a/asciidoctor-maven-plugin/src/main/java/org/asciidoctor/maven/http/AsciidoctorHandler.java +++ b/asciidoctor-maven-plugin/src/main/java/org/asciidoctor/maven/http/AsciidoctorHandler.java @@ -21,7 +21,7 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; -public class AsciidoctorHandler extends SimpleChannelInboundHandler { +class AsciidoctorHandler extends SimpleChannelInboundHandler { private static final String HTML_MEDIA_TYPE = "text/html"; public static final String HTML_EXTENSION = ".html"; @@ -29,7 +29,7 @@ public class AsciidoctorHandler extends SimpleChannelInboundHandler T mock(Class clazz, Map mavenProperties, LogHandler logHa parametersInitializer.initialize(mojo); setVariableValueInObject(mojo, "log", new SystemStreamLog()); setVariableValueInObject(mojo, "project", mockMavenProject(mavenProperties)); + setVariableValueInObject(mojo, "asciidoctorJFactory", new AsciidoctorJFactory()); + setVariableValueInObject(mojo, "asciidoctorOptionsFactory", new AsciidoctorOptionsFactory()); + setVariableValueInObject(mojo, "defaultResourcesProcessor", new CopyResourcesProcessor()); + setVariableValueInObject(mojo, "finder", new SourceDocumentFinder()); + if (logHandler != null) setVariableValueInObject(mojo, "logHandler", logHandler); diff --git a/pom.xml b/pom.xml index 7fb70c42..23b9d5bd 100644 --- a/pom.xml +++ b/pom.xml @@ -146,6 +146,20 @@ ${project.java.version} + + + org.eclipse.sisu + sisu-maven-plugin + 0.9.0.M3 + + + generate-index + + main-index + + + +