Skip to content

Commit 7669152

Browse files
authored
Use Maven Eclipse Sisu to inject components (#977)
* Refactor asciidoctor-maven-plugin to use DI * Refactor Doxia modules to use DI * Refactors in Doxia modules to reduce code duplication * Refactor SiteConversionConfigurationParser to reduce duplication and return only '<asciidoc>' configuration always * Centralize Maven4 configurations in a profile in the parent. Required to modify dependencies and properties. Notes: * Log instance passed to methods for simplicity. With Maven 4 that will be removed in favor of normal Slf4j. * This already helped with refactors * Constructor injection reduced the need for reflection in unit tests Fixes #945
1 parent 4d21189 commit 7669152

30 files changed

+897
-621
lines changed

.github/workflows/build-maven-4.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,5 @@ jobs:
3939
- name: Maven version
4040
run: mvn -version
4141
- name: Build & Test
42-
run: mvn -B -Prun-its clean verify -D"maven.version=${{ matrix.maven }}" -D"plexus-utils.version=4.0.2"
42+
run: mvn -B -Prun-its -Pmaven4 clean verify
4343

CHANGELOG.adoc

+5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ For a detailed view of what has changed, refer to the {uri-repo}/commits/main[co
1313

1414
== Unreleased
1515

16+
Improvements (for all modules)::
17+
18+
* Use Maven Eclipse Sisu to inject components (allowed refactors to increase code re-use) (#945)
19+
* Centralize Maven4 configurations in a profile in the parent (#945)
20+
1621
Bug Fixes (Site Modules)::
1722

1823
* Fix resolution of baseDir for Doxia modules (#968)
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package org.asciidoctor.maven.site;
22

33
import javax.inject.Inject;
4-
import javax.inject.Provider;
54
import java.io.File;
65
import java.io.IOException;
76
import java.io.Reader;
@@ -12,14 +11,8 @@
1211
import org.apache.maven.doxia.sink.Sink;
1312
import org.apache.maven.project.MavenProject;
1413
import org.asciidoctor.Asciidoctor;
15-
import org.asciidoctor.Attributes;
16-
import org.asciidoctor.AttributesBuilder;
17-
import org.asciidoctor.Options;
18-
import org.asciidoctor.OptionsBuilder;
19-
import org.asciidoctor.SafeMode;
2014
import org.asciidoctor.maven.commons.StringUtils;
2115
import org.asciidoctor.maven.log.LogHandler;
22-
import org.asciidoctor.maven.log.LogRecordFormatter;
2316
import org.asciidoctor.maven.log.LogRecordsProcessors;
2417
import org.asciidoctor.maven.log.MemoryLogHandler;
2518
import org.asciidoctor.maven.site.SiteConverterDecorator.Result;
@@ -29,8 +22,6 @@
2922
import org.slf4j.Logger;
3023
import org.slf4j.LoggerFactory;
3124

32-
import static org.asciidoctor.maven.site.SiteBaseDirResolver.resolveBaseDir;
33-
3425
/**
3526
* This class is used by <a href="https://maven.apache.org/doxia/overview.html">the Doxia framework</a>
3627
* to handle the actual parsing of the AsciiDoc input files into HTML to be consumed/wrapped
@@ -43,15 +34,28 @@
4334
@Component(role = Parser.class, hint = AsciidoctorConverterDoxiaParser.ROLE_HINT)
4435
public class AsciidoctorConverterDoxiaParser extends AbstractTextParser {
4536

46-
private static final Logger logger = LoggerFactory.getLogger(AsciidoctorConverterDoxiaParser.class);
47-
48-
@Inject
49-
protected Provider<MavenProject> mavenProjectProvider;
50-
5137
/**
5238
* The role hint for the {@link AsciidoctorConverterDoxiaParser} Plexus component.
5339
*/
54-
public static final String ROLE_HINT = "asciidoc";
40+
static final String ROLE_HINT = "asciidoc";
41+
42+
private static final Logger logger = LoggerFactory.getLogger(AsciidoctorConverterDoxiaParser.class);
43+
44+
private final MavenProject mavenProject;
45+
private final SiteConversionConfigurationParser siteConfigParser;
46+
private final LogHandlerFactory logHandlerFactory;
47+
private final SiteConverterDecorator siteConverter;
48+
49+
@Inject
50+
public AsciidoctorConverterDoxiaParser(MavenProject mavenProject,
51+
SiteConversionConfigurationParser siteConfigParser,
52+
LogHandlerFactory logHandlerFactory,
53+
SiteConverterDecorator siteConverter) {
54+
this.mavenProject = mavenProject;
55+
this.siteConfigParser = siteConfigParser;
56+
this.logHandlerFactory = logHandlerFactory;
57+
this.siteConverter = siteConverter;
58+
}
5559

5660
/**
5761
* {@inheritDoc}
@@ -68,27 +72,24 @@ public void parse(Reader reader, Sink sink, String reference) throws ParseExcept
6872
return;
6973
}
7074

71-
final MavenProject project = mavenProjectProvider.get();
72-
final Xpp3Dom siteConfig = getSiteConfig(project);
73-
final File siteDirectory = resolveBaseDir(project.getBasedir(), siteConfig);
75+
final SiteConversionConfiguration conversionConfig = siteConfigParser.processAsciiDocConfig(mavenProject, ROLE_HINT);
76+
final Xpp3Dom asciidocConfig = conversionConfig.getAsciidocConfig();
77+
final File siteDirectory = conversionConfig.getSiteBaseDir();
7478

7579
// Doxia handles a single instance of this class and invokes it multiple times.
7680
// We need to ensure certain elements are initialized only once to avoid errors.
7781
// Note, this cannot be done in the constructor because mavenProjectProvider in set after construction.
7882
// And overriding init and other methods form parent classes does not work.
7983
final Asciidoctor asciidoctor = Asciidoctor.Factory.create();
8084

81-
SiteConversionConfiguration conversionConfig = new SiteConversionConfigurationParser(project)
82-
.processAsciiDocConfig(siteConfig, defaultOptions(siteDirectory), defaultAttributes());
8385
for (String require : conversionConfig.getRequires()) {
8486
requireLibrary(asciidoctor, require);
8587
}
8688

87-
final LogHandler logHandler = getLogHandlerConfig(siteConfig);
88-
final MemoryLogHandler memoryLogHandler = asciidoctorLoggingSetup(asciidoctor, siteDirectory);
89+
final LogHandler logHandler = logHandlerFactory.getConfiguration(asciidocConfig);
90+
final MemoryLogHandler memoryLogHandler = logHandlerFactory.create(asciidoctor, siteDirectory, logger);
8991

90-
final SiteConverterDecorator siteConverter = new SiteConverterDecorator(asciidoctor);
91-
final Result headerMetadata = siteConverter.process(source, conversionConfig.getOptions());
92+
final Result headerMetadata = siteConverter.process(asciidoctor, source, conversionConfig.getOptions());
9293

9394
try {
9495
// process log messages according to mojo configuration
@@ -97,7 +98,7 @@ public void parse(Reader reader, Sink sink, String reference) throws ParseExcept
9798
if (logHandler.getOutputToConsole() && StringUtils.isNotBlank(reference)) {
9899
memoryLogHandler.processAll();
99100
}
100-
new LogRecordsProcessors(logHandler, siteDirectory, errorMessage -> logger.error(errorMessage))
101+
new LogRecordsProcessors(logHandler, siteDirectory, logger::error)
101102
.processLogRecords(memoryLogHandler);
102103
}
103104
} catch (Exception exception) {
@@ -110,45 +111,6 @@ public void parse(Reader reader, Sink sink, String reference) throws ParseExcept
110111
sink.rawText(headerMetadata.getHtml());
111112
}
112113

113-
private MemoryLogHandler asciidoctorLoggingSetup(Asciidoctor asciidoctor, File siteDirectory) {
114-
115-
final MemoryLogHandler memoryLogHandler = new MemoryLogHandler(false,
116-
logRecord -> logger.info(LogRecordFormatter.format(logRecord, siteDirectory)));
117-
asciidoctor.registerLogHandler(memoryLogHandler);
118-
// disable default console output of AsciidoctorJ
119-
java.util.logging.Logger.getLogger("asciidoctor").setUseParentHandlers(false);
120-
return memoryLogHandler;
121-
}
122-
123-
private LogHandler getLogHandlerConfig(Xpp3Dom siteConfig) {
124-
Xpp3Dom asciidoc = siteConfig == null ? null : siteConfig.getChild("asciidoc");
125-
return new SiteLogHandlerDeserializer().deserialize(asciidoc);
126-
}
127-
128-
protected Xpp3Dom getSiteConfig(MavenProject project) {
129-
return project.getGoalConfiguration("org.apache.maven.plugins", "maven-site-plugin", "site", "site");
130-
}
131-
132-
133-
// The possible baseDir based on configuration are:
134-
//
135-
// with nothing : src/site + /asciidoc
136-
// with locale : src/site + {locale} + /asciidoc
137-
// with siteDirectory : {siteDirectory} + /asciidoc
138-
// with siteDirectory + locale : {siteDirectory} + {locale} + /asciidoc
139-
protected OptionsBuilder defaultOptions(File siteDirectory) {
140-
return Options.builder()
141-
.backend("xhtml")
142-
.safe(SafeMode.UNSAFE)
143-
.baseDir(new File(siteDirectory, ROLE_HINT).getAbsoluteFile());
144-
}
145-
146-
protected AttributesBuilder defaultAttributes() {
147-
return Attributes.builder()
148-
.attribute("idprefix", "@")
149-
.attribute("showtitle", "@");
150-
}
151-
152114
private void requireLibrary(Asciidoctor asciidoctor, String require) {
153115
if (!(require = require.trim()).isEmpty()) {
154116
try {
@@ -158,4 +120,5 @@ private void requireLibrary(Asciidoctor asciidoctor, String require) {
158120
}
159121
}
160122
}
123+
161124
}

asciidoctor-converter-doxia-module/src/main/java/org/asciidoctor/maven/site/AsciidoctorConverterDoxiaParserModule.java

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
* <a href="https://maven.apache.org/doxia/references/">Doxia provided modules</a>.
1212
*
1313
* @author jdlee
14+
* @since 0.1.2.1
1415
*/
1516
@Component(role = ParserModule.class, hint = AsciidoctorConverterDoxiaParser.ROLE_HINT)
1617
public class AsciidoctorConverterDoxiaParserModule extends AbstractParserModule {

asciidoctor-converter-doxia-module/src/main/java/org/asciidoctor/maven/site/SiteConverterDecorator.java

+6-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.asciidoctor.maven.site;
22

3+
import javax.inject.Singleton;
34
import java.util.Map;
45

56
import org.asciidoctor.Asciidoctor;
@@ -10,16 +11,14 @@
1011
/**
1112
* Asciidoctor conversion wrapper for maven-site integration.
1213
* In addition to conversion, handles header metadata extraction.
14+
*
15+
* @author abelsromero
16+
* @since 3.0.0
1317
*/
18+
@Singleton
1419
class SiteConverterDecorator {
1520

16-
private final Asciidoctor asciidoctor;
17-
18-
SiteConverterDecorator(Asciidoctor asciidoctor) {
19-
this.asciidoctor = asciidoctor;
20-
}
21-
22-
Result process(String content, Options options) {
21+
Result process(Asciidoctor asciidoctor, String content, Options options) {
2322
final Document document = asciidoctor.load(content, headerProcessingMetadata(options));
2423
final HeaderMetadata headerMetadata = HeaderMetadata.from(document);
2524

@@ -61,5 +60,4 @@ String getHtml() {
6160
}
6261
}
6362

64-
6563
}

asciidoctor-converter-doxia-module/src/test/java/org/asciidoctor/maven/site/AsciidoctorConverterDoxiaParserTest.java

+9-7
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import static org.asciidoctor.maven.site.AsciidoctorConverterDoxiaParser.ROLE_HINT;
2020
import static org.assertj.core.api.Assertions.assertThat;
2121
import static org.assertj.core.api.Assertions.catchThrowable;
22-
import static org.codehaus.plexus.util.ReflectionUtils.setVariableValueInObject;
2322
import static org.mockito.ArgumentMatchers.anyString;
2423
import static org.mockito.Mockito.when;
2524

@@ -247,14 +246,14 @@ void should_fail_when_logHandler_failIf_is_WARNING() {
247246
}
248247

249248
@SneakyThrows
250-
private javax.inject.Provider<MavenProject> createMavenProjectMock(String configuration) {
249+
private MavenProject createMockMavenProject(String configuration) {
251250
MavenProject mockProject = Mockito.mock(MavenProject.class);
252251
when(mockProject.getBasedir())
253252
.thenReturn(new File("."));
254253
when(mockProject.getGoalConfiguration(anyString(), anyString(), anyString(), anyString()))
255254
.thenReturn(configuration != null ? Xpp3DomBuilder.build(new StringReader(configuration)) : null);
256255

257-
return () -> mockProject;
256+
return mockProject;
258257
}
259258

260259
@SneakyThrows
@@ -264,16 +263,19 @@ private AsciidoctorConverterDoxiaParser mockAsciidoctorDoxiaParser() {
264263

265264
@SneakyThrows
266265
private AsciidoctorConverterDoxiaParser mockAsciidoctorDoxiaParser(String configuration) {
267-
AsciidoctorConverterDoxiaParser parser = new AsciidoctorConverterDoxiaParser();
268-
setVariableValueInObject(parser, "mavenProjectProvider", createMavenProjectMock(configuration));
269-
return parser;
266+
return new AsciidoctorConverterDoxiaParser(
267+
createMockMavenProject(configuration),
268+
new SiteConversionConfigurationParser(new SiteBaseDirResolver()),
269+
new LogHandlerFactory(),
270+
new SiteConverterDecorator()
271+
);
270272
}
271273

272274
private Sink createSinkMock() {
273275
return new TextProviderSink();
274276
}
275277

276-
class TextProviderSink extends AbstractTextSink {
278+
static class TextProviderSink extends AbstractTextSink {
277279
String text;
278280

279281
@Override

asciidoctor-converter-doxia-module/src/test/java/org/asciidoctor/maven/site/SiteConverterDecoratorTest.java

+14-14
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ class SiteConverterDecoratorTest {
2828
"Hello, AsciiDoc!\n================"
2929
})
3030
void should_extract_title_from_header(String title) {
31-
SiteConverterDecorator siteConverter = new SiteConverterDecorator(asciidoctor);
31+
SiteConverterDecorator siteConverter = new SiteConverterDecorator();
3232

3333
Options options = defaultOptions();
34-
Result result = siteConverter.process(title + "\n", options);
34+
Result result = siteConverter.process(asciidoctor, title + "\n", options);
3535

3636
HeaderMetadata headerMetadata = result.getHeaderMetadata();
3737
assertThat(headerMetadata.getTitle()).isEqualTo("Hello, AsciiDoc!");
@@ -40,7 +40,7 @@ void should_extract_title_from_header(String title) {
4040

4141
@Test
4242
void should_extract_title_from_attribute() {
43-
SiteConverterDecorator siteConverter = new SiteConverterDecorator(asciidoctor);
43+
SiteConverterDecorator siteConverter = new SiteConverterDecorator();
4444

4545
Options options = Options.builder()
4646
.safe(SafeMode.UNSAFE)
@@ -51,7 +51,7 @@ void should_extract_title_from_attribute() {
5151
.attribute("who", "me")
5252
.build())
5353
.build();
54-
Result result = siteConverter.process("= Hello, {who}!\n", options);
54+
Result result = siteConverter.process(asciidoctor, "= Hello, {who}!\n", options);
5555

5656
HeaderMetadata headerMetadata = result.getHeaderMetadata();
5757
assertThat(headerMetadata.getTitle()).isEqualTo("Hello, me!");
@@ -62,10 +62,10 @@ void should_extract_title_from_attribute() {
6262
@ParameterizedTest
6363
@MethodSource("authorsProvider")
6464
void should_extract_author(String content, String expected) {
65-
SiteConverterDecorator siteConverter = new SiteConverterDecorator(asciidoctor);
65+
SiteConverterDecorator siteConverter = new SiteConverterDecorator();
6666

6767
Options options = defaultOptions();
68-
Result result = siteConverter.process(content + "\n", options);
68+
Result result = siteConverter.process(asciidoctor, content + "\n", options);
6969

7070
HeaderMetadata headerMetadata = result.getHeaderMetadata();
7171
assertThat(headerMetadata.getAuthors())
@@ -84,11 +84,11 @@ private static Stream<Arguments> authorsProvider() {
8484

8585
@Test
8686
void should_extract_author_from_attribute() {
87-
SiteConverterDecorator siteConverter = new SiteConverterDecorator(asciidoctor);
87+
SiteConverterDecorator siteConverter = new SiteConverterDecorator();
8888

8989
String content = "= Hello, AsciiDoc!";
9090
Options options = optionsWithAttributes(Collections.singletonMap("author", "From Attr"));
91-
Result result = siteConverter.process(content + "\n", options);
91+
Result result = siteConverter.process(asciidoctor, content + "\n", options);
9292

9393
HeaderMetadata headerMetadata = result.getHeaderMetadata();
9494
assertThat(headerMetadata.getAuthors())
@@ -98,10 +98,10 @@ void should_extract_author_from_attribute() {
9898

9999
@Test
100100
void should_extract_multiple_authors() {
101-
SiteConverterDecorator siteConverter = new SiteConverterDecorator(asciidoctor);
101+
SiteConverterDecorator siteConverter = new SiteConverterDecorator();
102102

103103
String content = "= Hello, AsciiDoc!\nfirstname1 lastname2; firstname3 middlename4 lastname5";
104-
Result result = siteConverter.process(content + "\n", defaultOptions());
104+
Result result = siteConverter.process(asciidoctor, content + "\n", defaultOptions());
105105

106106
HeaderMetadata headerMetadata = result.getHeaderMetadata();
107107
assertThat(headerMetadata.getAuthors())
@@ -111,10 +111,10 @@ void should_extract_multiple_authors() {
111111

112112
@Test
113113
void should_extract_datetime_generated() {
114-
SiteConverterDecorator siteConverter = new SiteConverterDecorator(asciidoctor);
114+
SiteConverterDecorator siteConverter = new SiteConverterDecorator();
115115

116116
String content = "= Hello, AsciiDoc!";
117-
Result result = siteConverter.process(content + "\n", defaultOptions());
117+
Result result = siteConverter.process(asciidoctor, content + "\n", defaultOptions());
118118

119119
HeaderMetadata headerMetadata = result.getHeaderMetadata();
120120
assertThat(headerMetadata.getDateTime()).matches("(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2}) .*");
@@ -123,11 +123,11 @@ void should_extract_datetime_generated() {
123123

124124
@Test
125125
void should_extract_datetime_from_attribute() {
126-
SiteConverterDecorator siteConverter = new SiteConverterDecorator(asciidoctor);
126+
SiteConverterDecorator siteConverter = new SiteConverterDecorator();
127127

128128
String content = "= Hello, AsciiDoc!";
129129
Options options = optionsWithAttributes(Collections.singletonMap("docdatetime", "2024-11-22"));
130-
Result result = siteConverter.process(content + "\n", options);
130+
Result result = siteConverter.process(asciidoctor, content + "\n", options);
131131

132132
HeaderMetadata headerMetadata = result.getHeaderMetadata();
133133
assertThat(headerMetadata.getDateTime()).isEqualTo("2024-11-22");

asciidoctor-maven-commons/pom.xml

+1-4
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@
2121
</description>
2222
<url>https://github.com/asciidoctor/asciidoctor-maven-plugin</url>
2323

24-
<properties>
25-
<plexus-utils.version>3.5.1</plexus-utils.version>
26-
</properties>
27-
2824
<dependencies>
2925
<dependency>
3026
<groupId>org.asciidoctor</groupId>
@@ -37,6 +33,7 @@
3733
<version>${maven.version}</version>
3834
<scope>provided</scope>
3935
</dependency>
36+
<!-- Required: see https://issues.apache.org/jira/browse/MNG-6965 -->
4037
<dependency>
4138
<groupId>org.codehaus.plexus</groupId>
4239
<artifactId>plexus-utils</artifactId>

0 commit comments

Comments
 (0)