Skip to content

Commit 58db21e

Browse files
committed
[MSITE-1000] Introduce parser configuration parameter
This leverages PlexusConfigurator under the hood
1 parent d78b8da commit 58db21e

File tree

6 files changed

+262
-10
lines changed

6 files changed

+262
-10
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ under the License.
199199
<!-- for dependencies -->
200200
<jettyVersion>9.4.53.v20231009</jettyVersion>
201201
<doxiaVersion>2.0.0-M8</doxiaVersion>
202-
<doxiaSitetoolsVersion>2.0.0-M16</doxiaSitetoolsVersion>
202+
<doxiaSitetoolsVersion>2.0.0-M18</doxiaSitetoolsVersion>
203203
<wagonVersion>3.5.3</wagonVersion>
204204
<slf4jVersion>1.7.36</slf4jVersion>
205205
<!-- for ITs -->

src/main/java/org/apache/maven/plugins/site/render/AbstractSiteRenderingMojo.java

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.apache.maven.doxia.site.SiteModel;
3838
import org.apache.maven.doxia.siterenderer.DocumentRenderer;
3939
import org.apache.maven.doxia.siterenderer.DocumentRenderingContext;
40+
import org.apache.maven.doxia.siterenderer.ParserConfigurator;
4041
import org.apache.maven.doxia.siterenderer.RendererException;
4142
import org.apache.maven.doxia.siterenderer.SiteRenderer;
4243
import org.apache.maven.doxia.siterenderer.SiteRenderingContext;
@@ -57,6 +58,8 @@
5758
import org.apache.maven.reporting.exec.MavenReportExecutor;
5859
import org.apache.maven.reporting.exec.MavenReportExecutorRequest;
5960
import org.apache.maven.shared.utils.WriterFactory;
61+
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
62+
import org.codehaus.plexus.configuration.PlexusConfiguration;
6063
import org.codehaus.plexus.util.ReaderFactory;
6164

6265
import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
@@ -94,6 +97,37 @@ public abstract class AbstractSiteRenderingMojo extends AbstractSiteDescriptorMo
9497
@Parameter
9598
private Map<String, Object> attributes;
9699

100+
/**
101+
* Parser configurations (per matching Doxia markup source file path patterns).
102+
* Each configuration item has the following format:
103+
* <p/>
104+
* <pre><code>
105+
* &lt;parserId&gt
106+
* &lt;configurations&gt;
107+
* &lt;configuration&gt;
108+
* &lt;patterns&gt;
109+
* &lt;pattern&gt;glob:**&#47;*.md&lt;/pattern&gt;&lt;!-- is either glob or regex syntax with the according prefix --&gt;
110+
* &lt;/patterns&gt;
111+
* &lt;!-- all configurations apart from pattern are directly applied to the underlying parser --&gt;
112+
* &lt;emitComments&gt;true&lt;/emitComments&gt;&lt;!-- false by default --&gt;
113+
* &lt;emitAnchorsForIndexableEntries&gt;false&lt;/emitAnchorsForIndexableEntries&gt;&lt;!-- true by default --&gt;
114+
* &lt;/configuration&gt;
115+
* &lt;/configurations&gt;
116+
* &lt;/parserId&gt
117+
* </code></pre>
118+
* The configuration is only applied if both
119+
* <ul>
120+
* <li>the parser id matches the parser used for a specific markup source file and</li>
121+
* <li>one of the given patterns matches the Doxia markup source file path (or no pattern is given at all).</li>
122+
* </ul>
123+
*
124+
* The first matching configuration wins (i.e. is applied).
125+
* @since 4.0.0
126+
* @see java.nio.file.FileSystem#getPathMatcher(String) FileSystem.getPathMatcher(String) for the supported patterns
127+
*/
128+
@Parameter
129+
private Map<String, List<PlexusConfiguration>> parserConfigurations;
130+
97131
/**
98132
* Site renderer.
99133
*/
@@ -269,7 +303,12 @@ private ReportPlugin[] getReportingPlugins() {
269303
return reportingPlugins.toArray(new ReportPlugin[0]);
270304
}
271305

272-
protected SiteRenderingContext createSiteRenderingContext(Locale locale)
306+
protected ParserConfiguratorImpl createParserConfigurator() throws ComponentLookupException {
307+
return new ParserConfiguratorImpl(
308+
parserConfigurations, mavenSession.getContainer(), mojoExecution.getMojoDescriptor());
309+
}
310+
311+
protected SiteRenderingContext createSiteRenderingContext(Locale locale, ParserConfigurator parserConfigurator)
273312
throws MojoExecutionException, IOException, MojoFailureException {
274313
SiteModel siteModel = prepareSiteModel(locale);
275314
Map<String, Object> templateProperties = new HashMap<>();
@@ -329,7 +368,7 @@ protected SiteRenderingContext createSiteRenderingContext(Locale locale)
329368
context.setProcessedContentOutput(processedDir);
330369
}
331370
}
332-
371+
context.setParserConfigurator(parserConfigurator);
333372
return context;
334373
}
335374

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.maven.plugins.site.render;
20+
21+
import java.io.Closeable;
22+
import java.io.IOException;
23+
import java.nio.file.FileSystem;
24+
import java.nio.file.FileSystems;
25+
import java.nio.file.Path;
26+
import java.nio.file.PathMatcher;
27+
import java.util.Collection;
28+
import java.util.LinkedHashMap;
29+
import java.util.List;
30+
import java.util.Map;
31+
import java.util.Optional;
32+
import java.util.stream.Collectors;
33+
34+
import org.apache.maven.doxia.parser.Parser;
35+
import org.apache.maven.doxia.siterenderer.ParserConfigurator;
36+
import org.apache.maven.plugin.descriptor.MojoDescriptor;
37+
import org.codehaus.plexus.PlexusContainer;
38+
import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
39+
import org.codehaus.plexus.component.configurator.ComponentConfigurator;
40+
import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
41+
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
42+
import org.codehaus.plexus.configuration.PlexusConfiguration;
43+
44+
/**
45+
* Configures a parser based on a {@link PlexusConfiguration} for a particular parser id and optionally matching one of multiple patterns.
46+
* It internally leverages the {@link ComponentConfigurator} for calling the right methods inside the parser implementation.
47+
*/
48+
public class ParserConfiguratorImpl implements ParserConfigurator, Closeable {
49+
50+
private static final class ParserConfigurationKey {
51+
52+
ParserConfigurationKey(String parserId, PlexusConfiguration patternsConfiguration) {
53+
this(parserId, PlexusConfigurationUtils.getStringArrayValues(patternsConfiguration));
54+
}
55+
56+
ParserConfigurationKey(String parserId, Collection<String> patterns) {
57+
this.parserId = parserId;
58+
// lazily populate all matchers
59+
matchers = patterns.stream()
60+
.map(p -> FileSystems.getDefault().getPathMatcher(p))
61+
.collect(Collectors.toList());
62+
}
63+
64+
private final String parserId;
65+
66+
/**
67+
* List of {@link PathMatcher}s for all of the patterns passed to the constructor
68+
*/
69+
private List<PathMatcher> matchers;
70+
71+
/**
72+
* Returns {@code true} the given file path matches one of the {@link #patterns} given via {@link #addPattern(String)}
73+
* @param filePath the file path to check
74+
* @return {@code true} if the given file path matches at least one of the patterns, {@code false} otherwise.
75+
* @throws IllegalArgumentException
76+
* If one of the patterns does not comply with the form: {@code syntax:pattern}
77+
* @throws java.util.regex.PatternSyntaxException
78+
* If one of the regex patterns is invalid
79+
* @throws UnsupportedOperationException
80+
* If one of the patterns syntax prefix is not known to the implementation
81+
* @see FileSystem#getPathMatcher(String)
82+
*/
83+
public boolean matches(String parserId, Path filePath) {
84+
if (this.parserId.equals(parserId)) {
85+
return false;
86+
}
87+
if (matchers.isEmpty()) {
88+
return true; // no patterns mean always match
89+
}
90+
return matchers.stream().anyMatch(m -> m.matches(filePath));
91+
}
92+
}
93+
94+
private final org.codehaus.plexus.classworlds.realm.ClassRealm pluginClassRealm;
95+
private final PlexusContainer plexusContainer;
96+
private final ComponentConfigurator componentConfigurator;
97+
98+
private final Map<ParserConfigurationKey, PlexusConfiguration> parserConfigurations;
99+
100+
public ParserConfiguratorImpl(
101+
Map<String, List<PlexusConfiguration>> parserConfigurations,
102+
PlexusContainer plexusContainer,
103+
MojoDescriptor mojoDescriptor)
104+
throws ComponentLookupException {
105+
this.parserConfigurations = new LinkedHashMap<>();
106+
for (Map.Entry<String, List<PlexusConfiguration>> parserConfigurationPerId : parserConfigurations.entrySet()) {
107+
String parserId = parserConfigurationPerId.getKey();
108+
for (PlexusConfiguration configuration : parserConfigurationPerId.getValue()) {
109+
ParserConfigurationKey key = new ParserConfigurationKey(parserId, configuration.getChild("patterns"));
110+
this.parserConfigurations.put(key, configuration);
111+
}
112+
}
113+
pluginClassRealm = mojoDescriptor.getRealm();
114+
this.plexusContainer = plexusContainer;
115+
componentConfigurator = getComponentConfigurator(mojoDescriptor.getComponentConfigurator());
116+
}
117+
118+
ComponentConfigurator getComponentConfigurator(String configuratorId) throws ComponentLookupException {
119+
// logic copied from
120+
// https://github.com/apache/maven/blob/267de063eec17111688fd1a27d4e3aae6c8d0c51/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java#L696C9-L700C10
121+
if (configuratorId == null || configuratorId.isEmpty()) {
122+
configuratorId = "basic"; // TODO: support v4
123+
}
124+
return plexusContainer.lookup(ComponentConfigurator.class, configuratorId);
125+
}
126+
127+
public void configureParser(PlexusConfiguration configuration, Parser parser)
128+
throws ComponentConfigurationException {
129+
componentConfigurator.configureComponent(parser, configuration, pluginClassRealm);
130+
}
131+
132+
@Override
133+
public void close() throws IOException {
134+
try {
135+
plexusContainer.release(componentConfigurator);
136+
} catch (ComponentLifecycleException e) {
137+
throw new IOException(e);
138+
}
139+
}
140+
141+
@Override
142+
public boolean configure(String parserId, Path filePath, Parser parser) {
143+
Optional<PlexusConfiguration> config = parserConfigurations.entrySet().stream()
144+
.filter(c -> c.getKey().matches(parserId, filePath))
145+
.findFirst()
146+
.map(Map.Entry::getValue);
147+
config.ifPresent(c -> {
148+
try {
149+
configureParser(c, parser);
150+
} catch (ComponentConfigurationException e) {
151+
throw new IllegalStateException("Could not configure parser " + parser, e);
152+
}
153+
});
154+
return config.isPresent();
155+
}
156+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.maven.plugins.site.render;
20+
21+
import java.util.ArrayList;
22+
import java.util.Collections;
23+
import java.util.List;
24+
25+
import org.codehaus.plexus.configuration.PlexusConfiguration;
26+
27+
public class PlexusConfigurationUtils {
28+
29+
private PlexusConfigurationUtils() {
30+
// not supposed to be instantiated
31+
}
32+
33+
/**
34+
* Retrieves all string values from the children of the given {@link PlexusConfiguration}
35+
* @param arrayContainer the configuration containing the array container (may be {@code null})
36+
* @return the list of string values
37+
*/
38+
static List<String> getStringArrayValues(PlexusConfiguration arrayContainer) {
39+
if (arrayContainer == null) {
40+
return Collections.emptyList();
41+
}
42+
List<String> stringValues = new ArrayList<>();
43+
for (PlexusConfiguration item : arrayContainer.getChildren()) {
44+
stringValues.add(item.getValue());
45+
}
46+
return stringValues;
47+
}
48+
}

src/main/java/org/apache/maven/plugins/site/render/SiteMojo.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
import org.apache.maven.doxia.siterenderer.DocumentRenderer;
3131
import org.apache.maven.doxia.siterenderer.DoxiaDocumentRenderer;
32+
import org.apache.maven.doxia.siterenderer.ParserConfigurator;
3233
import org.apache.maven.doxia.siterenderer.RendererException;
3334
import org.apache.maven.doxia.siterenderer.SiteRenderingContext;
3435
import org.apache.maven.doxia.tools.SiteTool;
@@ -42,6 +43,7 @@
4243
import org.apache.maven.reporting.MavenReportException;
4344
import org.apache.maven.reporting.exec.MavenReportExecution;
4445
import org.apache.maven.shared.utils.logging.MessageBuilder;
46+
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
4547

4648
import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
4749

@@ -94,7 +96,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
9496

9597
checkInputEncoding();
9698

97-
try {
99+
try (ParserConfiguratorImpl parserConfigurator = createParserConfigurator()) {
98100
List<Locale> localesList = getLocales();
99101

100102
for (Locale locale : localesList) {
@@ -107,7 +109,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
107109
File outputDirectory = getOutputDirectory(locale);
108110
List<MavenReportExecution> reports =
109111
generateReports ? getReports(outputDirectory) : Collections.emptyList();
110-
renderLocale(locale, reports, localesList, outputDirectory);
112+
renderLocale(locale, reports, localesList, outputDirectory, parserConfigurator);
111113
}
112114
} catch (RendererException e) {
113115
if (e.getCause() instanceof MavenReportException) {
@@ -117,13 +119,19 @@ public void execute() throws MojoExecutionException, MojoFailureException {
117119
throw new MojoExecutionException("Failed to render reports", e);
118120
} catch (IOException e) {
119121
throw new MojoExecutionException("Error during site generation", e);
122+
} catch (ComponentLookupException e) {
123+
throw new MojoExecutionException("Cannot lookup ComponentConfigurator for configuration of parsers", e);
120124
}
121125
}
122126

123127
private void renderLocale(
124-
Locale locale, List<MavenReportExecution> reports, List<Locale> supportedLocales, File outputDirectory)
128+
Locale locale,
129+
List<MavenReportExecution> reports,
130+
List<Locale> supportedLocales,
131+
File outputDirectory,
132+
ParserConfigurator parserConfigurator)
125133
throws IOException, RendererException, MojoFailureException, MojoExecutionException {
126-
SiteRenderingContext context = createSiteRenderingContext(locale);
134+
SiteRenderingContext context = createSiteRenderingContext(locale, parserConfigurator);
127135
context.addSiteLocales(supportedLocales);
128136
if (!locale.equals(SiteTool.DEFAULT_LOCALE)) {
129137
context.addSiteDirectory(new File(generatedSiteDirectory, locale.toString()));

src/main/java/org/apache/maven/plugins/site/run/SiteRunMojo.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.apache.maven.plugins.annotations.Parameter;
3838
import org.apache.maven.plugins.annotations.ResolutionScope;
3939
import org.apache.maven.plugins.site.render.AbstractSiteRenderingMojo;
40+
import org.apache.maven.plugins.site.render.ParserConfiguratorImpl;
4041
import org.apache.maven.reporting.exec.MavenReportExecution;
4142
import org.codehaus.plexus.util.IOUtil;
4243
import org.eclipse.jetty.server.Server;
@@ -125,15 +126,15 @@ private WebAppContext createWebApplication() throws MojoExecutionException {
125126
List<Locale> localesList = getLocales();
126127
webapp.setAttribute(DoxiaFilter.LOCALES_LIST_KEY, localesList);
127128

128-
try {
129+
try (ParserConfiguratorImpl parserConfigurator = createParserConfigurator()) {
129130
Map<String, DoxiaBean> i18nDoxiaContexts = new HashMap<>();
130131

131132
for (Locale locale : localesList) {
132-
SiteRenderingContext i18nContext = createSiteRenderingContext(locale);
133+
SiteRenderingContext i18nContext = createSiteRenderingContext(locale, parserConfigurator);
133134
i18nContext.setInputEncoding(getInputEncoding());
134135
i18nContext.setOutputEncoding(getOutputEncoding());
135136

136-
SiteRenderingContext i18nGeneratedSiteContext = createSiteRenderingContext(locale);
137+
SiteRenderingContext i18nGeneratedSiteContext = createSiteRenderingContext(locale, parserConfigurator);
137138
i18nGeneratedSiteContext.setInputEncoding(getInputEncoding());
138139
i18nGeneratedSiteContext.setOutputEncoding(getOutputEncoding());
139140
i18nGeneratedSiteContext.getSiteDirectories().clear();

0 commit comments

Comments
 (0)