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 <k...@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>
+     * &lt;parserId&gt
+     *   &lt;configurations&gt;
+     *     &lt;configuration&gt;
+     *       &lt;patterns&gt;
+     *         &lt;pattern&gt;glob:**&#47;*.md&lt;/pattern&gt;&lt;!-- is 
either glob or regex syntax with the according prefix --&gt;
+     *       &lt;/patterns&gt;
+     *       &lt;!-- all configurations apart from pattern are directly 
applied to the underlying parser --&gt;
+     *       &lt;emitComments&gt;true&lt;/emitComments&gt;&lt;!-- false by 
default --&gt;
+     *       
&lt;emitAnchorsForIndexableEntries&gt;false&lt;/emitAnchorsForIndexableEntries&gt;&lt;!--
 true by default --&gt;
+     *     &lt;/configuration&gt;
+     *   &lt;/configurations&gt;
+     * &lt;/parserId&gt
+     * </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();

Reply via email to