Skip to content

Commit d5312d3

Browse files
kwinmichael-o
authored andcommitted
[MSITE-1000] Introduce parser configuration parameter
This leverages PlexusConfigurator under the hood
1 parent 2002077 commit d5312d3

File tree

5 files changed

+264
-8
lines changed

5 files changed

+264
-8
lines changed

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;
@@ -58,6 +59,8 @@
5859
import org.apache.maven.reporting.exec.MavenReportExecutor;
5960
import org.apache.maven.reporting.exec.MavenReportExecutorRequest;
6061
import org.apache.maven.shared.utils.WriterFactory;
62+
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
63+
import org.codehaus.plexus.configuration.PlexusConfiguration;
6164
import org.codehaus.plexus.util.ReaderFactory;
6265

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

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

273-
protected SiteRenderingContext createSiteRenderingContext(Locale locale)
307+
protected ParserConfiguratorImpl createParserConfigurator() throws ComponentLookupException {
308+
return new ParserConfiguratorImpl(
309+
parserConfigurations, mavenSession.getContainer(), mojoExecution.getMojoDescriptor());
310+
}
311+
312+
protected SiteRenderingContext createSiteRenderingContext(Locale locale, ParserConfigurator parserConfigurator)
274313
throws MojoExecutionException, IOException, MojoFailureException {
275314
SiteModel siteModel = prepareSiteModel(locale);
276315
Map<String, Object> templateProperties = new HashMap<>();
@@ -332,7 +371,7 @@ protected SiteRenderingContext createSiteRenderingContext(Locale locale)
332371
context.setProcessedContentOutput(processedDir);
333372
}
334373
}
335-
374+
context.setParserConfigurator(parserConfigurator);
336375
return context;
337376
}
338377

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
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+
if (parserConfigurations != null) {
107+
for (Map.Entry<String, List<PlexusConfiguration>> parserConfigurationPerId :
108+
parserConfigurations.entrySet()) {
109+
String parserId = parserConfigurationPerId.getKey();
110+
for (PlexusConfiguration configuration : parserConfigurationPerId.getValue()) {
111+
ParserConfigurationKey key =
112+
new ParserConfigurationKey(parserId, configuration.getChild("patterns"));
113+
this.parserConfigurations.put(key, configuration);
114+
}
115+
}
116+
}
117+
pluginClassRealm = mojoDescriptor.getRealm();
118+
this.plexusContainer = plexusContainer;
119+
componentConfigurator = getComponentConfigurator(mojoDescriptor.getComponentConfigurator());
120+
}
121+
122+
ComponentConfigurator getComponentConfigurator(String configuratorId) throws ComponentLookupException {
123+
// logic copied from
124+
// https://github.com/apache/maven/blob/267de063eec17111688fd1a27d4e3aae6c8d0c51/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java#L696C9-L700C10
125+
if (configuratorId == null || configuratorId.isEmpty()) {
126+
configuratorId = "basic"; // TODO: support v4
127+
}
128+
return plexusContainer.lookup(ComponentConfigurator.class, configuratorId);
129+
}
130+
131+
public void configureParser(PlexusConfiguration configuration, Parser parser)
132+
throws ComponentConfigurationException {
133+
componentConfigurator.configureComponent(parser, configuration, pluginClassRealm);
134+
}
135+
136+
@Override
137+
public void close() throws IOException {
138+
try {
139+
plexusContainer.release(componentConfigurator);
140+
} catch (ComponentLifecycleException e) {
141+
throw new IOException(e);
142+
}
143+
}
144+
145+
@Override
146+
public boolean configure(String parserId, Path filePath, Parser parser) {
147+
Optional<PlexusConfiguration> config = parserConfigurations.entrySet().stream()
148+
.filter(c -> c.getKey().matches(parserId, filePath))
149+
.findFirst()
150+
.map(Map.Entry::getValue);
151+
config.ifPresent(c -> {
152+
try {
153+
configureParser(c, parser);
154+
} catch (ComponentConfigurationException e) {
155+
throw new IllegalStateException("Could not configure parser " + parser, e);
156+
}
157+
});
158+
return config.isPresent();
159+
}
160+
}
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
@@ -30,6 +30,7 @@
3030

3131
import org.apache.maven.doxia.siterenderer.DocumentRenderer;
3232
import org.apache.maven.doxia.siterenderer.DoxiaDocumentRenderer;
33+
import org.apache.maven.doxia.siterenderer.ParserConfigurator;
3334
import org.apache.maven.doxia.siterenderer.RendererException;
3435
import org.apache.maven.doxia.siterenderer.SiteRenderingContext;
3536
import org.apache.maven.doxia.tools.SiteTool;
@@ -43,6 +44,7 @@
4344
import org.apache.maven.reporting.MavenReportException;
4445
import org.apache.maven.reporting.exec.MavenReportExecution;
4546
import org.apache.maven.shared.utils.logging.MessageBuilder;
47+
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
4648

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

@@ -95,7 +97,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
9597

9698
checkInputEncoding();
9799

98-
try {
100+
try (ParserConfiguratorImpl parserConfigurator = createParserConfigurator()) {
99101
List<Locale> localesList = getLocales();
100102

101103
for (Locale locale : localesList) {
@@ -108,7 +110,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
108110
File outputDirectory = getOutputDirectory(locale);
109111
List<MavenReportExecution> reports =
110112
generateReports ? getReports(outputDirectory) : Collections.emptyList();
111-
renderLocale(locale, reports, localesList, outputDirectory);
113+
renderLocale(locale, reports, localesList, outputDirectory, parserConfigurator);
112114
}
113115
} catch (RendererException e) {
114116
if (e.getCause() instanceof MavenReportException) {
@@ -118,13 +120,19 @@ public void execute() throws MojoExecutionException, MojoFailureException {
118120
throw new MojoExecutionException("Failed to render site", e);
119121
} catch (IOException e) {
120122
throw new MojoExecutionException("Error during site generation", e);
123+
} catch (ComponentLookupException e) {
124+
throw new MojoExecutionException("Cannot lookup ComponentConfigurator for configuration of parsers", e);
121125
}
122126
}
123127

124128
private void renderLocale(
125-
Locale locale, List<MavenReportExecution> reports, List<Locale> supportedLocales, File outputDirectory)
129+
Locale locale,
130+
List<MavenReportExecution> reports,
131+
List<Locale> supportedLocales,
132+
File outputDirectory,
133+
ParserConfigurator parserConfigurator)
126134
throws IOException, RendererException, MojoFailureException, MojoExecutionException {
127-
SiteRenderingContext context = createSiteRenderingContext(locale);
135+
SiteRenderingContext context = createSiteRenderingContext(locale, parserConfigurator);
128136
context.addSiteLocales(supportedLocales);
129137
context.setInputEncoding(getInputEncoding());
130138
context.setOutputEncoding(getOutputEncoding());

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

Lines changed: 3 additions & 2 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,11 +126,11 @@ 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

0 commit comments

Comments
 (0)