Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
abelsromero committed Jan 24, 2024
1 parent e947ff0 commit 118f74c
Show file tree
Hide file tree
Showing 6 changed files with 270 additions and 26 deletions.
6 changes: 6 additions & 0 deletions asciidoctor-maven-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@
<artifactId>netty-codec-http</artifactId>
<version>4.1.106.Final</version>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.14.11</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.asciidoctor.*;
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;
Expand All @@ -29,10 +34,18 @@
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.logging.Logger;

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;


Expand All @@ -52,10 +65,10 @@ public class AsciidoctorMojo extends AbstractMojo {
protected File outputFile;

@Parameter(property = AsciidoctorMaven.PREFIX + "preserveDirectories", defaultValue = "false")
protected boolean preserveDirectories = false;
protected boolean preserveDirectories;

@Parameter(property = AsciidoctorMaven.PREFIX + "relativeBaseDir", defaultValue = "false")
protected boolean relativeBaseDir = false;
protected boolean relativeBaseDir;

@Parameter(property = AsciidoctorMaven.PREFIX + "projectDirectory", defaultValue = "${basedir}")
protected File projectDirectory;
Expand All @@ -66,8 +79,8 @@ public class AsciidoctorMojo extends AbstractMojo {
@Parameter(property = AsciidoctorMaven.PREFIX + "baseDir")
protected File baseDir;

@Parameter(property = AsciidoctorMaven.PREFIX + "skip")
protected boolean skip = false;
@Parameter(property = AsciidoctorMaven.PREFIX + "skip", defaultValue = "false")
protected boolean skip;

@Parameter(property = AsciidoctorMaven.PREFIX + "gemPath")
protected String gemPath;
Expand All @@ -79,10 +92,10 @@ public class AsciidoctorMojo extends AbstractMojo {
protected Map<String, Object> attributes = new HashMap<>();

@Parameter(property = AsciidoctorMaven.PREFIX + Options.ATTRIBUTES)
protected String attributesChain = "";
protected String attributesChain;

@Parameter(property = AsciidoctorMaven.PREFIX + Options.BACKEND, defaultValue = "html5")
protected String backend = "html5";
protected String backend;

@Parameter(property = AsciidoctorMaven.PREFIX + Options.DOCTYPE)
protected String doctype;
Expand All @@ -91,41 +104,41 @@ public class AsciidoctorMojo extends AbstractMojo {
protected String eruby;

@Parameter(property = AsciidoctorMaven.PREFIX + "standalone", defaultValue = "true")
protected boolean standalone = true;
protected boolean standalone;

@Parameter(property = AsciidoctorMaven.PREFIX + "templateDirs")
protected List<File> templateDirs = new ArrayList<>();

@Parameter(property = AsciidoctorMaven.PREFIX + "templateEngine")
protected String templateEngine;

@Parameter(property = AsciidoctorMaven.PREFIX + "templateCache")
protected boolean templateCache = true;
@Parameter(property = AsciidoctorMaven.PREFIX + "templateCache", defaultValue = "true")
protected boolean templateCache;

@Parameter(property = AsciidoctorMaven.PREFIX + "sourceDocumentName")
protected String sourceDocumentName;

@Parameter(property = AsciidoctorMaven.PREFIX + "sourceDocumentExtensions")
protected List<String> sourceDocumentExtensions = new ArrayList<>();

@Parameter(property = AsciidoctorMaven.PREFIX + "sourcemap")
protected boolean sourcemap = false;
@Parameter(property = AsciidoctorMaven.PREFIX + "sourcemap", defaultValue = "false")
protected boolean sourcemap;

@Parameter(property = AsciidoctorMaven.PREFIX + "catalogAssets")
protected boolean catalogAssets = false;
@Parameter(property = AsciidoctorMaven.PREFIX + "catalogAssets", defaultValue = "false")
protected boolean catalogAssets;

@Parameter
protected List<ExtensionConfiguration> extensions = new ArrayList<>();

@Parameter(property = AsciidoctorMaven.PREFIX + "embedAssets", defaultValue = "false")
protected boolean embedAssets = false;
protected boolean embedAssets;

// List of resources to copy to the output directory (e.g., images, css). By default everything is copied
// List of resources to copy to the output directory (e.g., images, css). By default, everything is copied
@Parameter
protected List<Resource> resources;

@Parameter(property = AsciidoctorMaven.PREFIX + "verbose", defaultValue = "false")
protected boolean enableVerbose = false;
protected boolean enableVerbose;

@Parameter
private LogHandler logHandler = new LogHandler();
Expand Down Expand Up @@ -455,7 +468,7 @@ protected AttributesBuilder createAttributesBuilder(AsciidoctorMojo configuratio
AsciidoctorHelper.addProperties(mavenProject.getProperties(), attributesBuilder);
AsciidoctorHelper.addAttributes(configuration.getAttributes(), attributesBuilder);

if (!configuration.getAttributesChain().isEmpty()) {
if (isNotBlank(configuration.getAttributesChain())) {
getLog().info("Attributes: " + attributesChain);
attributesBuilder.arguments(attributesChain);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,10 @@ void should_create_simple_zip() throws IOException, MojoFailureException, MojoEx
"= Title\n\ntest", UTF_8);

AsciidoctorZipMojo mojo = mockAsciidoctorZipMojo();
mojo.backend = "html";
mojo.sourceDirectory = srcDir;
mojo.outputDirectory = outputDir;
mojo.zipDestination = zip;
mojo.zip = true;
mojo.attach = false;
mojo.execute();

// then: a zip is created
Expand All @@ -72,13 +71,12 @@ void should_replicate_source_structure_in_zip_standard_paths() throws MojoFailur

// when
AsciidoctorZipMojo mojo = mockAsciidoctorZipMojo();
mojo.backend = "html5";
mojo.sourceDirectory = srcDir;
mojo.outputDirectory = outputDir;
mojo.preserveDirectories = true;
mojo.relativeBaseDir = true;
mojo.zipDestination = zip;
mojo.zip = true;
mojo.attach = false;
mojo.execute();

// then
Expand Down Expand Up @@ -118,11 +116,10 @@ void should_not_replicate_source_structure_in_zip_standard_paths() throws IOExce

// when
AsciidoctorZipMojo mojo = mockAsciidoctorZipMojo();
mojo.backend = "html5";
mojo.sourceDirectory = srcDir;
mojo.outputDirectory = outputDir;
mojo.zipDestination = zip;
mojo.zip = true;
mojo.attach = false;
mojo.execute();

// then
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package org.asciidoctor.maven;

import net.bytebuddy.description.annotation.AnnotationDescription;
import net.bytebuddy.description.annotation.AnnotationValue;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.field.FieldList;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.pool.TypePool;
import org.apache.maven.plugins.annotations.Parameter;

import static org.asciidoctor.maven.commons.StringUtils.isBlank;
import static org.codehaus.plexus.util.ReflectionUtils.setVariableValueInObject;

/**
*
*/
class ParametersInitializer {

private static final ClassLoader CLASS_LOADER = ParametersInitializer.class.getClassLoader();

/**
* Returns instance of input class with fields initialized according to its
* respective {@link org.apache.maven.plugins.annotations.Parameter}.
*/
public <T> T initialize(T instance) {
try {
// Use ByteBuddy because annotations is Class retention, not Runtime
TypePool typePool = TypePool.Default.of(CLASS_LOADER);
TypeDescription typeDescription = typePool.describe(instance.getClass().getName()).resolve();

initParameterFields(instance, typeDescription);
return instance;
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}

private <T> void initParameterFields(T instance, TypeDescription typeDescription) throws IllegalAccessException {

FieldList<FieldDescription.InDefinedShape> declaredFields = typeDescription.getDeclaredFields();

for (FieldDescription field : declaredFields) {
String value = getAnnotationByType(field);
if (value != null) {
if (field.getType().getTypeName().equals(String.class.getName())) {
if (value.length() > 0 && !value.startsWith("$")) {
// TODO support Maven variable: pass Map<String, Object> ?
setVariableValueInObject(instance, field.getName(), value);
}
}
if (field.getType().getTypeName().equals("boolean")) {
// false is already the default
// TODO for PR, the booleans default should appear in XML plugin descriptor now
if (value.equals("true")) {
setVariableValueInObject(instance, field.getName(), Boolean.TRUE);
} else if (!value.equals("false")) {
throw new RuntimeException("Invalid boolean default: not-a-boolean");
}
}
// TODO
// if (field.getType().getTypeName().equals(File.class.getName())) {
}
}

TypeDescription superClass = typeDescription.getSuperClass().asErasure();

if (hasParent(superClass)) {
initParameterFields(instance, superClass);
}
}

private boolean hasParent(TypeDescription superClass) {
return superClass != null && !superClass.getTypeName().equals(Object.class.getName());
}

// Make MojoReader
private String getAnnotationByType(FieldDescription field) {
for (AnnotationDescription declaredAnnotation : field.getDeclaredAnnotations()) {
String annotationTypeName = declaredAnnotation.getAnnotationType().getName();
if (annotationTypeName.equals(Parameter.class.getCanonicalName())) {
AnnotationValue<?, ?> defaultValue = declaredAnnotation.getValue("defaultValue");
String stringValue = defaultValue.toString();
stringValue = stringValue.substring(1, stringValue.length() - 1).trim();
return isBlank(stringValue) ? null : stringValue;
}
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package org.asciidoctor.maven;

import org.apache.maven.plugins.annotations.Parameter;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;

class ParametersInitializerTest {

private final ParametersInitializer initializer = new ParametersInitializer();

@Test
void should_return_same_instance() {
final var instance = new Simple();
var actual = initializer.initialize(instance);
assertThat(actual).isEqualTo(instance);
}

@Nested
class ShouldInitialize {

@Test
void string_with_default_value() {
final var instance = new StringExampleMojo();
var initialized = initializer.initialize(instance);
assertThat(initialized.defaultValue).isEqualTo("a-value");
}

@Test
void boolean_with_default_value() {
final var instance = new BooleanExampleMojo();
var initialized = initializer.initialize(instance);
assertThat(initialized.defaultValue).isTrue();
}

@Test
void properties_in_class_and_parent() {
final var instance = new SubclassExampleMojo();
var initialized = initializer.initialize(instance);
assertThat(initialized.getDefaultValue()).isEqualTo("a-value");
assertThat(initialized.getNonDefaultValue()).isNull();
assertThat(initialized.anotherValue).isEqualTo("from-subclass");
}
}

@Nested
class ShouldNotInitialize {

@Test
void string_without_default_value() {
final var instance = new StringExampleMojo();
var initialized = initializer.initialize(instance);
assertThat(initialized.nonDefaultValue).isNull();
}

@Test
void boolean_without_default_value() {
final var instance = new BooleanExampleMojo();
var initialized = initializer.initialize(instance);
assertThat(initialized.nonDefaultValue).isFalse();
}
}

@Nested
class ShouldFail {
@Test
void boolean_with_invalid_value() {
final var instance = new FailingExampleMojo();
Throwable t = catchThrowable(() -> initializer.initialize(instance));

assertThat(t).isInstanceOf(RuntimeException.class)
.hasMessage("Invalid boolean default: not-a-boolean");
}
}


class Simple {

Simple() {
}

}

class StringExampleMojo {

@Parameter(defaultValue = "a-value")
private String defaultValue;

@Parameter
private String nonDefaultValue;

public String getDefaultValue() {
return defaultValue;
}

public String getNonDefaultValue() {
return nonDefaultValue;
}
}

class BooleanExampleMojo {

@Parameter(defaultValue = "true")
private boolean defaultValue;

@Parameter
private boolean nonDefaultValue;
}

class FailingExampleMojo {

@Parameter(defaultValue = "not-a-boolean")
private boolean invalidValue;
}

class SubclassExampleMojo extends StringExampleMojo {

@Parameter(defaultValue = "from-subclass")
private String anotherValue;
}
}
Loading

0 comments on commit 118f74c

Please sign in to comment.