You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by kw...@apache.org on 2024/03/20 16:06:14 UTC
(maven-site-plugin) 01/01: [MSITE-1000] Introduce parser configuration parameter
This is an automated email from the ASF dual-hosted git repository.
kwin pushed a commit to branch feature/configure-parser-with-plexus-configurator
in repository https://gitbox.apache.org/repos/asf/maven-site-plugin.git
commit 614a05759cd41ef63ed3c7ce351c49ec89a480a9
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Sat Dec 30 12:47:52 2023 +0100
[MSITE-1000] Introduce parser configuration parameter
This leverages PlexusConfigurator under the hood
---
pom.xml | 2 +-
.../site/render/AbstractSiteRenderingMojo.java | 43 +++++-
.../site/render/ParserConfiguratorImpl.java | 156 +++++++++++++++++++++
.../site/render/PlexusConfigurationUtils.java | 48 +++++++
.../apache/maven/plugins/site/render/SiteMojo.java | 16 ++-
.../apache/maven/plugins/site/run/SiteRunMojo.java | 7 +-
6 files changed, 262 insertions(+), 10 deletions(-)
diff --git a/pom.xml b/pom.xml
index b9d095c4..a53174eb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -199,7 +199,7 @@ under the License.
<!-- for dependencies -->
<jettyVersion>9.4.53.v20231009</jettyVersion>
<doxiaVersion>2.0.0-M8</doxiaVersion>
- <doxiaSitetoolsVersion>2.0.0-M16</doxiaSitetoolsVersion>
+ <doxiaSitetoolsVersion>2.0.0-M18-SNAPSHOT</doxiaSitetoolsVersion>
<wagonVersion>3.5.3</wagonVersion>
<slf4jVersion>1.7.36</slf4jVersion>
<!-- for ITs -->
diff --git a/src/main/java/org/apache/maven/plugins/site/render/AbstractSiteRenderingMojo.java b/src/main/java/org/apache/maven/plugins/site/render/AbstractSiteRenderingMojo.java
index 8906cbc8..2d9049f7 100644
--- a/src/main/java/org/apache/maven/plugins/site/render/AbstractSiteRenderingMojo.java
+++ b/src/main/java/org/apache/maven/plugins/site/render/AbstractSiteRenderingMojo.java
@@ -37,6 +37,7 @@ import org.apache.maven.doxia.site.MenuItem;
import org.apache.maven.doxia.site.SiteModel;
import org.apache.maven.doxia.siterenderer.DocumentRenderer;
import org.apache.maven.doxia.siterenderer.DocumentRenderingContext;
+import org.apache.maven.doxia.siterenderer.ParserConfigurator;
import org.apache.maven.doxia.siterenderer.RendererException;
import org.apache.maven.doxia.siterenderer.SiteRenderer;
import org.apache.maven.doxia.siterenderer.SiteRenderingContext;
@@ -57,6 +58,8 @@ import org.apache.maven.reporting.exec.MavenReportExecution;
import org.apache.maven.reporting.exec.MavenReportExecutor;
import org.apache.maven.reporting.exec.MavenReportExecutorRequest;
import org.apache.maven.shared.utils.WriterFactory;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.util.ReaderFactory;
import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
@@ -94,6 +97,37 @@ public abstract class AbstractSiteRenderingMojo extends AbstractSiteDescriptorMo
@Parameter
private Map<String, Object> attributes;
+ /**
+ * Parser configurations (per matching Doxia markup source file path patterns).
+ * Each configuration item has the following format:
+ * <p/>
+ * <pre><code>
+ * <parserId>
+ * <configurations>
+ * <configuration>
+ * <patterns>
+ * <pattern>glob:**/*.md</pattern><!-- is either glob or regex syntax with the according prefix -->
+ * </patterns>
+ * <!-- all configurations apart from pattern are directly applied to the underlying parser -->
+ * <emitComments>true</emitComments><!-- false by default -->
+ * <emitAnchorsForIndexableEntries>false</emitAnchorsForIndexableEntries><!-- true by default -->
+ * </configuration>
+ * </configurations>
+ * </parserId>
+ * </code></pre>
+ * The configuration is only applied if both
+ * <ul>
+ * <li>the parser id matches the parser used for a specific markup source file and</li>
+ * <li>one of the given patterns matches the Doxia markup source file path (or no pattern is given at all).</li>
+ * </ul>
+ *
+ * The first matching configuration wins (i.e. is applied).
+ * @since 4.0.0
+ * @see java.nio.file.FileSystem#getPathMatcher(String) FileSystem.getPathMatcher(String) for the supported patterns
+ */
+ @Parameter
+ private Map<String, List<PlexusConfiguration>> parserConfigurations;
+
/**
* Site renderer.
*/
@@ -269,7 +303,12 @@ public abstract class AbstractSiteRenderingMojo extends AbstractSiteDescriptorMo
return reportingPlugins.toArray(new ReportPlugin[0]);
}
- protected SiteRenderingContext createSiteRenderingContext(Locale locale)
+ protected ParserConfiguratorImpl createParserConfigurator() throws ComponentLookupException {
+ return new ParserConfiguratorImpl(
+ parserConfigurations, mavenSession.getContainer(), mojoExecution.getMojoDescriptor());
+ }
+
+ protected SiteRenderingContext createSiteRenderingContext(Locale locale, ParserConfigurator parserConfigurator)
throws MojoExecutionException, IOException, MojoFailureException {
SiteModel siteModel = prepareSiteModel(locale);
Map<String, Object> templateProperties = new HashMap<>();
@@ -329,7 +368,7 @@ public abstract class AbstractSiteRenderingMojo extends AbstractSiteDescriptorMo
context.setProcessedContentOutput(processedDir);
}
}
-
+ context.setParserConfigurator(parserConfigurator);
return context;
}
diff --git a/src/main/java/org/apache/maven/plugins/site/render/ParserConfiguratorImpl.java b/src/main/java/org/apache/maven/plugins/site/render/ParserConfiguratorImpl.java
new file mode 100644
index 00000000..c240db01
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugins/site/render/ParserConfiguratorImpl.java
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.plugins.site.render;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import org.apache.maven.doxia.parser.Parser;
+import org.apache.maven.doxia.siterenderer.ParserConfigurator;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
+import org.codehaus.plexus.component.configurator.ComponentConfigurator;
+import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.codehaus.plexus.configuration.PlexusConfiguration;
+
+/**
+ * Configures a parser based on a {@link PlexusConfiguration} for a particular parser id and optionally matching one of multiple patterns.
+ * It internally leverages the {@link ComponentConfigurator} for calling the right methods inside the parser implementation.
+ */
+public class ParserConfiguratorImpl implements ParserConfigurator, Closeable {
+
+ private static final class ParserConfigurationKey {
+
+ ParserConfigurationKey(String parserId, PlexusConfiguration patternsConfiguration) {
+ this(parserId, PlexusConfigurationUtils.getStringArrayValues(patternsConfiguration));
+ }
+
+ ParserConfigurationKey(String parserId, Collection<String> patterns) {
+ this.parserId = parserId;
+ // lazily populate all matchers
+ matchers = patterns.stream()
+ .map(p -> FileSystems.getDefault().getPathMatcher(p))
+ .collect(Collectors.toList());
+ }
+
+ private final String parserId;
+
+ /**
+ * List of {@link PathMatcher}s for all of the patterns passed to the constructor
+ */
+ private List<PathMatcher> matchers;
+
+ /**
+ * Returns {@code true} the given file path matches one of the {@link #patterns} given via {@link #addPattern(String)}
+ * @param filePath the file path to check
+ * @return {@code true} if the given file path matches at least one of the patterns, {@code false} otherwise.
+ * @throws IllegalArgumentException
+ * If one of the patterns does not comply with the form: {@code syntax:pattern}
+ * @throws java.util.regex.PatternSyntaxException
+ * If one of the regex patterns is invalid
+ * @throws UnsupportedOperationException
+ * If one of the patterns syntax prefix is not known to the implementation
+ * @see FileSystem#getPathMatcher(String)
+ */
+ public boolean matches(String parserId, Path filePath) {
+ if (this.parserId.equals(parserId)) {
+ return false;
+ }
+ if (matchers.isEmpty()) {
+ return true; // no patterns mean always match
+ }
+ return matchers.stream().anyMatch(m -> m.matches(filePath));
+ }
+ }
+
+ private final org.codehaus.plexus.classworlds.realm.ClassRealm pluginClassRealm;
+ private final PlexusContainer plexusContainer;
+ private final ComponentConfigurator componentConfigurator;
+
+ private final Map<ParserConfigurationKey, PlexusConfiguration> parserConfigurations;
+
+ public ParserConfiguratorImpl(
+ Map<String, List<PlexusConfiguration>> parserConfigurations,
+ PlexusContainer plexusContainer,
+ MojoDescriptor mojoDescriptor)
+ throws ComponentLookupException {
+ this.parserConfigurations = new LinkedHashMap<>();
+ for (Map.Entry<String, List<PlexusConfiguration>> parserConfigurationPerId : parserConfigurations.entrySet()) {
+ String parserId = parserConfigurationPerId.getKey();
+ for (PlexusConfiguration configuration : parserConfigurationPerId.getValue()) {
+ ParserConfigurationKey key = new ParserConfigurationKey(parserId, configuration.getChild("patterns"));
+ this.parserConfigurations.put(key, configuration);
+ }
+ }
+ pluginClassRealm = mojoDescriptor.getRealm();
+ this.plexusContainer = plexusContainer;
+ componentConfigurator = getComponentConfigurator(mojoDescriptor.getComponentConfigurator());
+ }
+
+ ComponentConfigurator getComponentConfigurator(String configuratorId) throws ComponentLookupException {
+ // logic copied from
+ // https://github.com/apache/maven/blob/267de063eec17111688fd1a27d4e3aae6c8d0c51/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java#L696C9-L700C10
+ if (configuratorId == null || configuratorId.isEmpty()) {
+ configuratorId = "basic"; // TODO: support v4
+ }
+ return plexusContainer.lookup(ComponentConfigurator.class, configuratorId);
+ }
+
+ public void configureParser(PlexusConfiguration configuration, Parser parser)
+ throws ComponentConfigurationException {
+ componentConfigurator.configureComponent(parser, configuration, pluginClassRealm);
+ }
+
+ @Override
+ public void close() throws IOException {
+ try {
+ plexusContainer.release(componentConfigurator);
+ } catch (ComponentLifecycleException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public boolean configure(String parserId, Path filePath, Parser parser) {
+ Optional<PlexusConfiguration> config = parserConfigurations.entrySet().stream()
+ .filter(c -> c.getKey().matches(parserId, filePath))
+ .findFirst()
+ .map(Map.Entry::getValue);
+ config.ifPresent(c -> {
+ try {
+ configureParser(c, parser);
+ } catch (ComponentConfigurationException e) {
+ throw new IllegalStateException("Could not configure parser " + parser + " due to ", e);
+ }
+ });
+ return config.isPresent();
+ }
+}
diff --git a/src/main/java/org/apache/maven/plugins/site/render/PlexusConfigurationUtils.java b/src/main/java/org/apache/maven/plugins/site/render/PlexusConfigurationUtils.java
new file mode 100644
index 00000000..09d53b92
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugins/site/render/PlexusConfigurationUtils.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.plugins.site.render;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.codehaus.plexus.configuration.PlexusConfiguration;
+
+public class PlexusConfigurationUtils {
+
+ private PlexusConfigurationUtils() {
+ // not supposed to be instantiated
+ }
+
+ /**
+ * Retrieves all string values from the children of the given {@link PlexusConfiguration}
+ * @param arrayContainer the configuration containing the array container (may be {@code null})
+ * @return the list of string values
+ */
+ static List<String> getStringArrayValues(PlexusConfiguration arrayContainer) {
+ if (arrayContainer == null) {
+ return Collections.emptyList();
+ }
+ List<String> stringValues = new ArrayList<>();
+ for (PlexusConfiguration item : arrayContainer.getChildren()) {
+ stringValues.add(item.getValue());
+ }
+ return stringValues;
+ }
+}
diff --git a/src/main/java/org/apache/maven/plugins/site/render/SiteMojo.java b/src/main/java/org/apache/maven/plugins/site/render/SiteMojo.java
index 7b261ac7..d22bac0b 100644
--- a/src/main/java/org/apache/maven/plugins/site/render/SiteMojo.java
+++ b/src/main/java/org/apache/maven/plugins/site/render/SiteMojo.java
@@ -29,6 +29,7 @@ import java.util.TreeMap;
import org.apache.maven.doxia.siterenderer.DocumentRenderer;
import org.apache.maven.doxia.siterenderer.DoxiaDocumentRenderer;
+import org.apache.maven.doxia.siterenderer.ParserConfigurator;
import org.apache.maven.doxia.siterenderer.RendererException;
import org.apache.maven.doxia.siterenderer.SiteRenderingContext;
import org.apache.maven.doxia.tools.SiteTool;
@@ -42,6 +43,7 @@ import org.apache.maven.project.MavenProject;
import org.apache.maven.reporting.MavenReportException;
import org.apache.maven.reporting.exec.MavenReportExecution;
import org.apache.maven.shared.utils.logging.MessageBuilder;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
@@ -94,7 +96,7 @@ public class SiteMojo extends AbstractSiteRenderingMojo {
checkInputEncoding();
- try {
+ try (ParserConfiguratorImpl parserConfigurator = createParserConfigurator()) {
List<Locale> localesList = getLocales();
for (Locale locale : localesList) {
@@ -107,7 +109,7 @@ public class SiteMojo extends AbstractSiteRenderingMojo {
File outputDirectory = getOutputDirectory(locale);
List<MavenReportExecution> reports =
generateReports ? getReports(outputDirectory) : Collections.emptyList();
- renderLocale(locale, reports, localesList, outputDirectory);
+ renderLocale(locale, reports, localesList, outputDirectory, parserConfigurator);
}
} catch (RendererException e) {
if (e.getCause() instanceof MavenReportException) {
@@ -117,13 +119,19 @@ public class SiteMojo extends AbstractSiteRenderingMojo {
throw new MojoExecutionException("Failed to render reports", e);
} catch (IOException e) {
throw new MojoExecutionException("Error during site generation", e);
+ } catch (ComponentLookupException e) {
+ throw new MojoExecutionException("Cannot lookup ComponentConfigurator for configuration of parsers", e);
}
}
private void renderLocale(
- Locale locale, List<MavenReportExecution> reports, List<Locale> supportedLocales, File outputDirectory)
+ Locale locale,
+ List<MavenReportExecution> reports,
+ List<Locale> supportedLocales,
+ File outputDirectory,
+ ParserConfigurator parserConfigurator)
throws IOException, RendererException, MojoFailureException, MojoExecutionException {
- SiteRenderingContext context = createSiteRenderingContext(locale);
+ SiteRenderingContext context = createSiteRenderingContext(locale, parserConfigurator);
context.addSiteLocales(supportedLocales);
if (!locale.equals(SiteTool.DEFAULT_LOCALE)) {
context.addSiteDirectory(new File(generatedSiteDirectory, locale.toString()));
diff --git a/src/main/java/org/apache/maven/plugins/site/run/SiteRunMojo.java b/src/main/java/org/apache/maven/plugins/site/run/SiteRunMojo.java
index f5430e00..ae5105b5 100644
--- a/src/main/java/org/apache/maven/plugins/site/run/SiteRunMojo.java
+++ b/src/main/java/org/apache/maven/plugins/site/run/SiteRunMojo.java
@@ -37,6 +37,7 @@ import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.plugins.site.render.AbstractSiteRenderingMojo;
+import org.apache.maven.plugins.site.render.ParserConfiguratorImpl;
import org.apache.maven.reporting.exec.MavenReportExecution;
import org.codehaus.plexus.util.IOUtil;
import org.eclipse.jetty.server.Server;
@@ -125,15 +126,15 @@ public class SiteRunMojo extends AbstractSiteRenderingMojo {
List<Locale> localesList = getLocales();
webapp.setAttribute(DoxiaFilter.LOCALES_LIST_KEY, localesList);
- try {
+ try (ParserConfiguratorImpl parserConfigurator = createParserConfigurator()) {
Map<String, DoxiaBean> i18nDoxiaContexts = new HashMap<>();
for (Locale locale : localesList) {
- SiteRenderingContext i18nContext = createSiteRenderingContext(locale);
+ SiteRenderingContext i18nContext = createSiteRenderingContext(locale, parserConfigurator);
i18nContext.setInputEncoding(getInputEncoding());
i18nContext.setOutputEncoding(getOutputEncoding());
- SiteRenderingContext i18nGeneratedSiteContext = createSiteRenderingContext(locale);
+ SiteRenderingContext i18nGeneratedSiteContext = createSiteRenderingContext(locale, parserConfigurator);
i18nGeneratedSiteContext.setInputEncoding(getInputEncoding());
i18nGeneratedSiteContext.setOutputEncoding(getOutputEncoding());
i18nGeneratedSiteContext.getSiteDirectories().clear();