This is an automated email from the ASF dual-hosted git repository.

sjaranowski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-pmd-plugin.git


The following commit(s) were added to refs/heads/master by this push:
     new 6cd4f55  Introduce service executors for CPD, PMD executors (#206)
6cd4f55 is described below

commit 6cd4f55e31a92910b1c1959414dc1b0963d3fe66
Author: Slawomir Jaranowski <s.jaranow...@gmail.com>
AuthorDate: Fri May 23 22:56:55 2025 +0200

    Introduce service executors for CPD, PMD executors (#206)
    
    * Introduce service executors for Cpd, Pdm executors
    
    Standard mojos and reports have different parent classes,
    so we need to extract tasks which both will execute.
    
    We cannot use one abstract for both.
    
    * fix logger
    
    Co-authored-by: Andreas Dangel <andreas.dan...@adangel.org>
    
    ---------
    
    Co-authored-by: Andreas Dangel <andreas.dan...@adangel.org>
---
 pom.xml                                            |  5 ++
 .../maven/plugins/pmd/AbstractPmdReport.java       | 45 +------------
 .../maven/plugins/pmd/AggregatorCpdReport.java     |  6 +-
 .../plugins/pmd/AggregatorPmdNoForkReport.java     |  8 +--
 .../maven/plugins/pmd/AggregatorPmdReport.java     |  8 +--
 .../org/apache/maven/plugins/pmd/CpdReport.java    | 20 +++---
 .../org/apache/maven/plugins/pmd/PmdReport.java    | 21 +++----
 .../apache/maven/plugins/pmd/exec/CpdExecutor.java | 21 +------
 .../apache/maven/plugins/pmd/exec/CpdRequest.java  | 11 ++--
 .../maven/plugins/pmd/exec/CpdServiceExecutor.java | 59 +++++++++++++++++
 .../apache/maven/plugins/pmd/exec/PmdExecutor.java | 22 +------
 .../apache/maven/plugins/pmd/exec/PmdRequest.java  | 11 ++--
 .../maven/plugins/pmd/exec/PmdServiceExecutor.java | 59 +++++++++++++++++
 .../maven/plugins/pmd/exec/ServiceExecutor.java    | 73 ++++++++++++++++++++++
 .../plugins/pmd/AbstractPmdReportTestCase.java     | 17 ++++-
 15 files changed, 258 insertions(+), 128 deletions(-)

diff --git a/pom.xml b/pom.xml
index ddb9138..5362737 100644
--- a/pom.xml
+++ b/pom.xml
@@ -370,6 +370,11 @@ under the License.
         </executions>
       </plugin>
 
+      <plugin>
+        <groupId>org.eclipse.sisu</groupId>
+        <artifactId>sisu-maven-plugin</artifactId>
+      </plugin>
+
       <plugin>
         <groupId>org.codehaus.modello</groupId>
         <artifactId>modello-maven-plugin</artifactId>
diff --git a/src/main/java/org/apache/maven/plugins/pmd/AbstractPmdReport.java 
b/src/main/java/org/apache/maven/plugins/pmd/AbstractPmdReport.java
index fc582b6..3c3164a 100644
--- a/src/main/java/org/apache/maven/plugins/pmd/AbstractPmdReport.java
+++ b/src/main/java/org/apache/maven/plugins/pmd/AbstractPmdReport.java
@@ -20,8 +20,6 @@ package org.apache.maven.plugins.pmd;
 
 import java.io.File;
 import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -42,8 +40,6 @@ import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.reporting.AbstractMavenReport;
 import org.apache.maven.reporting.MavenReportException;
-import org.apache.maven.toolchain.Toolchain;
-import org.apache.maven.toolchain.ToolchainManager;
 import org.codehaus.plexus.util.FileUtils;
 import org.codehaus.plexus.util.StringUtils;
 
@@ -260,15 +256,9 @@ public abstract class AbstractPmdReport extends 
AbstractMavenReport {
     @Parameter(defaultValue = "${session}", required = true, readonly = true)
     protected MavenSession session;
 
-    private final ToolchainManager toolchainManager;
-
     /** The files that are being analyzed. */
     protected Map<File, PmdFileInfo> filesToProcess;
 
-    protected AbstractPmdReport(ToolchainManager toolchainManager) {
-        this.toolchainManager = toolchainManager;
-    }
-
     @Override
     protected MavenProject getProject() {
         return project;
@@ -479,39 +469,8 @@ public abstract class AbstractPmdReport extends 
AbstractMavenReport {
         return PMDVersion.VERSION;
     }
 
-    // TODO remove the part with ToolchainManager lookup once we depend on
-    // 3.0.9 (have it as prerequisite). Define as regular component field then.
-    protected final Toolchain getToolchain() {
-        Toolchain tc = null;
-
-        if (jdkToolchain != null) {
-            // Maven 3.3.1 has plugin execution scoped Toolchain Support
-            try {
-                Method getToolchainsMethod = toolchainManager
-                        .getClass()
-                        .getMethod("getToolchains", MavenSession.class, 
String.class, Map.class);
-
-                @SuppressWarnings("unchecked")
-                List<Toolchain> tcs =
-                        (List<Toolchain>) 
getToolchainsMethod.invoke(toolchainManager, session, "jdk", jdkToolchain);
-
-                if (tcs != null && !tcs.isEmpty()) {
-                    tc = tcs.get(0);
-                }
-            } catch (NoSuchMethodException
-                    | SecurityException
-                    | IllegalAccessException
-                    | IllegalArgumentException
-                    | InvocationTargetException e) {
-                // ignore
-            }
-        }
-
-        if (tc == null) {
-            tc = toolchainManager.getToolchainFromBuildContext("jdk", session);
-        }
-
-        return tc;
+    public Map<String, String> getJdkToolchain() {
+        return jdkToolchain;
     }
 
     protected boolean isAggregator() {
diff --git 
a/src/main/java/org/apache/maven/plugins/pmd/AggregatorCpdReport.java 
b/src/main/java/org/apache/maven/plugins/pmd/AggregatorCpdReport.java
index 91700ff..2c0c323 100644
--- a/src/main/java/org/apache/maven/plugins/pmd/AggregatorCpdReport.java
+++ b/src/main/java/org/apache/maven/plugins/pmd/AggregatorCpdReport.java
@@ -21,7 +21,7 @@ package org.apache.maven.plugins.pmd;
 import javax.inject.Inject;
 
 import org.apache.maven.plugins.annotations.Mojo;
-import org.apache.maven.toolchain.ToolchainManager;
+import org.apache.maven.plugins.pmd.exec.CpdServiceExecutor;
 import org.codehaus.plexus.i18n.I18N;
 
 /**
@@ -37,8 +37,8 @@ import org.codehaus.plexus.i18n.I18N;
 public class AggregatorCpdReport extends CpdReport {
 
     @Inject
-    public AggregatorCpdReport(ToolchainManager toolchainManager, I18N i18n) {
-        super(toolchainManager, i18n);
+    public AggregatorCpdReport(I18N i18n, CpdServiceExecutor serviceExecutor) {
+        super(i18n, serviceExecutor);
     }
 
     @Override
diff --git 
a/src/main/java/org/apache/maven/plugins/pmd/AggregatorPmdNoForkReport.java 
b/src/main/java/org/apache/maven/plugins/pmd/AggregatorPmdNoForkReport.java
index 08c8b64..8932ce3 100644
--- a/src/main/java/org/apache/maven/plugins/pmd/AggregatorPmdNoForkReport.java
+++ b/src/main/java/org/apache/maven/plugins/pmd/AggregatorPmdNoForkReport.java
@@ -24,8 +24,8 @@ import org.apache.maven.plugins.annotations.Execute;
 import org.apache.maven.plugins.annotations.LifecyclePhase;
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.apache.maven.plugins.pmd.exec.PmdServiceExecutor;
 import 
org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolver;
-import org.apache.maven.toolchain.ToolchainManager;
 import org.codehaus.plexus.i18n.I18N;
 import org.codehaus.plexus.resource.ResourceManager;
 
@@ -44,10 +44,10 @@ public class AggregatorPmdNoForkReport extends 
AggregatorPmdReport {
 
     @Inject
     public AggregatorPmdNoForkReport(
-            ToolchainManager toolchainManager,
             ResourceManager locator,
             DependencyResolver dependencyResolver,
-            I18N i18n) {
-        super(toolchainManager, locator, dependencyResolver, i18n);
+            I18N i18n,
+            PmdServiceExecutor serviceExecutor) {
+        super(locator, dependencyResolver, i18n, serviceExecutor);
     }
 }
diff --git 
a/src/main/java/org/apache/maven/plugins/pmd/AggregatorPmdReport.java 
b/src/main/java/org/apache/maven/plugins/pmd/AggregatorPmdReport.java
index 0414c21..822820b 100644
--- a/src/main/java/org/apache/maven/plugins/pmd/AggregatorPmdReport.java
+++ b/src/main/java/org/apache/maven/plugins/pmd/AggregatorPmdReport.java
@@ -24,8 +24,8 @@ import org.apache.maven.plugins.annotations.Execute;
 import org.apache.maven.plugins.annotations.LifecyclePhase;
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.apache.maven.plugins.pmd.exec.PmdServiceExecutor;
 import 
org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolver;
-import org.apache.maven.toolchain.ToolchainManager;
 import org.codehaus.plexus.i18n.I18N;
 import org.codehaus.plexus.resource.ResourceManager;
 
@@ -41,11 +41,11 @@ public class AggregatorPmdReport extends PmdReport {
 
     @Inject
     public AggregatorPmdReport(
-            ToolchainManager toolchainManager,
             ResourceManager locator,
             DependencyResolver dependencyResolver,
-            I18N i18n) {
-        super(toolchainManager, locator, dependencyResolver, i18n);
+            I18N i18n,
+            PmdServiceExecutor serviceExecutor) {
+        super(locator, dependencyResolver, i18n, serviceExecutor);
     }
 
     @Override
diff --git a/src/main/java/org/apache/maven/plugins/pmd/CpdReport.java 
b/src/main/java/org/apache/maven/plugins/pmd/CpdReport.java
index 4970628..d117f3d 100644
--- a/src/main/java/org/apache/maven/plugins/pmd/CpdReport.java
+++ b/src/main/java/org/apache/maven/plugins/pmd/CpdReport.java
@@ -26,12 +26,10 @@ import java.util.Locale;
 
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
-import org.apache.maven.plugins.pmd.exec.CpdExecutor;
 import org.apache.maven.plugins.pmd.exec.CpdRequest;
 import org.apache.maven.plugins.pmd.exec.CpdResult;
+import org.apache.maven.plugins.pmd.exec.CpdServiceExecutor;
 import org.apache.maven.reporting.MavenReportException;
-import org.apache.maven.toolchain.Toolchain;
-import org.apache.maven.toolchain.ToolchainManager;
 import org.codehaus.plexus.i18n.I18N;
 
 /**
@@ -101,6 +99,8 @@ public class CpdReport extends AbstractPmdReport {
      */
     private final I18N i18n;
 
+    private final CpdServiceExecutor serviceExecutor;
+
     /**
      * Contains the result of the last CPD execution.
      * It might be <code>null</code> which means, that CPD
@@ -109,9 +109,9 @@ public class CpdReport extends AbstractPmdReport {
     private CpdResult cpdResult;
 
     @Inject
-    public CpdReport(ToolchainManager toolchainManager, I18N i18n) {
-        super(toolchainManager);
+    public CpdReport(I18N i18n, CpdServiceExecutor serviceExecutor) {
         this.i18n = i18n;
+        this.serviceExecutor = serviceExecutor;
     }
 
     /** {@inheritDoc} */
@@ -191,15 +191,9 @@ public class CpdReport extends AbstractPmdReport {
             request.setFormat(format);
             request.setIncludeXmlInReports(includeXmlInReports);
             
request.setReportOutputDirectory(getReportOutputDirectory().getAbsolutePath());
+            request.setJdkToolchain(getJdkToolchain());
 
-            Toolchain tc = getToolchain();
-            if (tc != null) {
-                getLog().info("Toolchain in maven-pmd-plugin: " + tc);
-                String javaExecutable = tc.findTool("java"); // NOI18N
-                request.setJavaExecutable(javaExecutable);
-            }
-
-            cpdResult = CpdExecutor.execute(request);
+            cpdResult = serviceExecutor.execute(request);
         } catch (UnsupportedEncodingException e) {
             throw new MavenReportException("Encoding '" + getInputEncoding() + 
"' is not supported.", e);
         } catch (IOException e) {
diff --git a/src/main/java/org/apache/maven/plugins/pmd/PmdReport.java 
b/src/main/java/org/apache/maven/plugins/pmd/PmdReport.java
index a3cc784..3a2899f 100644
--- a/src/main/java/org/apache/maven/plugins/pmd/PmdReport.java
+++ b/src/main/java/org/apache/maven/plugins/pmd/PmdReport.java
@@ -35,6 +35,7 @@ import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.plugins.pmd.exec.PmdExecutor;
 import org.apache.maven.plugins.pmd.exec.PmdRequest;
 import org.apache.maven.plugins.pmd.exec.PmdResult;
+import org.apache.maven.plugins.pmd.exec.PmdServiceExecutor;
 import org.apache.maven.project.DefaultProjectBuildingRequest;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.project.ProjectBuildingRequest;
@@ -45,8 +46,6 @@ import 
org.apache.maven.shared.artifact.filter.resolve.ScopeFilter;
 import org.apache.maven.shared.artifact.filter.resolve.TransformableFilter;
 import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult;
 import 
org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolver;
-import org.apache.maven.toolchain.Toolchain;
-import org.apache.maven.toolchain.ToolchainManager;
 import org.codehaus.plexus.i18n.I18N;
 import org.codehaus.plexus.resource.ResourceManager;
 import org.codehaus.plexus.resource.loader.FileResourceCreationException;
@@ -242,6 +241,8 @@ public class PmdReport extends AbstractPmdReport {
      */
     private final I18N i18n;
 
+    private final PmdServiceExecutor serviceExecutor;
+
     /**
      * Contains the result of the last PMD execution.
      * It might be <code>null</code> which means, that PMD
@@ -251,14 +252,14 @@ public class PmdReport extends AbstractPmdReport {
 
     @Inject
     public PmdReport(
-            ToolchainManager toolchainManager,
             ResourceManager locator,
             DependencyResolver dependencyResolver,
-            I18N i18n) {
-        super(toolchainManager);
+            I18N i18n,
+            PmdServiceExecutor serviceExecutor) {
         this.locator = locator;
         this.dependencyResolver = dependencyResolver;
         this.i18n = i18n;
+        this.serviceExecutor = serviceExecutor;
     }
 
     /** {@inheritDoc} */
@@ -375,16 +376,10 @@ public class PmdReport extends AbstractPmdReport {
         request.setIncludeXmlInReports(includeXmlInReports);
         
request.setReportOutputDirectory(getReportOutputDirectory().getAbsolutePath());
         request.setLogLevel(determineCurrentRootLogLevel());
-
-        Toolchain tc = getToolchain();
-        if (tc != null) {
-            getLog().info("Toolchain in maven-pmd-plugin: " + tc);
-            String javaExecutable = tc.findTool("java"); // NOI18N
-            request.setJavaExecutable(javaExecutable);
-        }
+        request.setJdkToolchain(getJdkToolchain());
 
         getLog().info("PMD version: " + AbstractPmdReport.getPmdVersion());
-        pmdResult = PmdExecutor.execute(request);
+        pmdResult = serviceExecutor.execute(request);
     }
 
     /**
diff --git a/src/main/java/org/apache/maven/plugins/pmd/exec/CpdExecutor.java 
b/src/main/java/org/apache/maven/plugins/pmd/exec/CpdExecutor.java
index dc55fba..f84162e 100644
--- a/src/main/java/org/apache/maven/plugins/pmd/exec/CpdExecutor.java
+++ b/src/main/java/org/apache/maven/plugins/pmd/exec/CpdExecutor.java
@@ -46,22 +46,7 @@ import org.slf4j.LoggerFactory;
 public class CpdExecutor extends Executor {
     private static final Logger LOG = 
LoggerFactory.getLogger(CpdExecutor.class);
 
-    public static CpdResult execute(CpdRequest request) throws 
MavenReportException {
-        if (request.getJavaExecutable() != null) {
-            return fork(request);
-        }
-
-        ClassLoader origLoader = 
Thread.currentThread().getContextClassLoader();
-        try {
-            
Thread.currentThread().setContextClassLoader(CpdExecutor.class.getClassLoader());
-            CpdExecutor cpdExecutor = new CpdExecutor(request);
-            return cpdExecutor.run();
-        } finally {
-            Thread.currentThread().setContextClassLoader(origLoader);
-        }
-    }
-
-    private static CpdResult fork(CpdRequest request) throws 
MavenReportException {
+    public CpdResult fork(String javaExecutable) throws MavenReportException {
         File basePmdDir = new File(request.getTargetDirectory(), "pmd");
         basePmdDir.mkdirs();
         File cpdRequestFile = new File(basePmdDir, "cpdrequest.bin");
@@ -75,7 +60,7 @@ public class CpdExecutor extends Executor {
         ProcessBuilder pb = new ProcessBuilder();
         // note: using env variable instead of -cp cli arg to avoid length 
limitations under Windows
         pb.environment().put("CLASSPATH", classpath);
-        pb.command().add(request.getJavaExecutable());
+        pb.command().add(javaExecutable);
         pb.command().add(CpdExecutor.class.getName());
         pb.command().add(cpdRequestFile.getAbsolutePath());
 
@@ -134,7 +119,7 @@ public class CpdExecutor extends Executor {
         this.request = Objects.requireNonNull(request);
     }
 
-    private CpdResult run() throws MavenReportException {
+    public CpdResult run() throws MavenReportException {
         try {
             
excludeDuplicationsFromFile.loadExcludeFromFailuresData(request.getExcludeFromFailureFile());
         } catch (MojoExecutionException e) {
diff --git a/src/main/java/org/apache/maven/plugins/pmd/exec/CpdRequest.java 
b/src/main/java/org/apache/maven/plugins/pmd/exec/CpdRequest.java
index 32e3c39..f972bbf 100644
--- a/src/main/java/org/apache/maven/plugins/pmd/exec/CpdRequest.java
+++ b/src/main/java/org/apache/maven/plugins/pmd/exec/CpdRequest.java
@@ -23,6 +23,7 @@ import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 
 /**
@@ -36,7 +37,7 @@ import java.util.Properties;
 public class CpdRequest implements Serializable {
     private static final long serialVersionUID = -7585852992660240668L;
 
-    private String javaExecutable;
+    private Map<String, String> jdkToolchain;
 
     private int minimumTokens;
     private String language;
@@ -56,8 +57,8 @@ public class CpdRequest implements Serializable {
     private boolean ignoreIdentifiers;
     private boolean ignoreLiterals;
 
-    public void setJavaExecutable(String javaExecutable) {
-        this.javaExecutable = javaExecutable;
+    public void setJdkToolchain(Map<String, String> jdkToolchain) {
+        this.jdkToolchain = jdkToolchain;
     }
 
     public void setMinimumTokens(int minimumTokens) {
@@ -108,8 +109,8 @@ public class CpdRequest implements Serializable {
         this.logLevel = logLevel;
     }
 
-    public String getJavaExecutable() {
-        return javaExecutable;
+    public Map<String, String> getJdkToolchain() {
+        return jdkToolchain;
     }
 
     public int getMinimumTokens() {
diff --git 
a/src/main/java/org/apache/maven/plugins/pmd/exec/CpdServiceExecutor.java 
b/src/main/java/org/apache/maven/plugins/pmd/exec/CpdServiceExecutor.java
new file mode 100644
index 0000000..4da87b8
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugins/pmd/exec/CpdServiceExecutor.java
@@ -0,0 +1,59 @@
+/*
+ * 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.pmd.exec;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.reporting.MavenReportException;
+import org.apache.maven.toolchain.ToolchainManager;
+
+/**
+ * Service for executing CPD.
+ */
+@Named
+@Singleton
+public class CpdServiceExecutor extends ServiceExecutor {
+
+    @Inject
+    public CpdServiceExecutor(ToolchainManager toolchainManager, 
Provider<MavenSession> sessionProvider) {
+        super(toolchainManager, sessionProvider);
+    }
+
+    public CpdResult execute(CpdRequest request) throws MavenReportException {
+
+        ClassLoader origLoader = 
Thread.currentThread().getContextClassLoader();
+        try {
+            
Thread.currentThread().setContextClassLoader(CpdExecutor.class.getClassLoader());
+            CpdExecutor executor = new CpdExecutor(request);
+
+            String javaExecutable = 
getJavaExecutable(request.getJdkToolchain());
+            if (javaExecutable != null) {
+                return executor.fork(javaExecutable);
+            }
+
+            return executor.run();
+        } finally {
+            Thread.currentThread().setContextClassLoader(origLoader);
+        }
+    }
+}
diff --git a/src/main/java/org/apache/maven/plugins/pmd/exec/PmdExecutor.java 
b/src/main/java/org/apache/maven/plugins/pmd/exec/PmdExecutor.java
index 5c9d0fd..09a3ca2 100644
--- a/src/main/java/org/apache/maven/plugins/pmd/exec/PmdExecutor.java
+++ b/src/main/java/org/apache/maven/plugins/pmd/exec/PmdExecutor.java
@@ -62,23 +62,7 @@ import org.slf4j.LoggerFactory;
 public class PmdExecutor extends Executor {
     private static final Logger LOG = 
LoggerFactory.getLogger(PmdExecutor.class);
 
-    public static PmdResult execute(PmdRequest request) throws 
MavenReportException {
-        if (request.getJavaExecutable() != null) {
-            return fork(request);
-        }
-
-        // make sure the class loaders are correct and call this in the same 
JVM
-        ClassLoader origLoader = 
Thread.currentThread().getContextClassLoader();
-        try {
-            
Thread.currentThread().setContextClassLoader(PmdExecutor.class.getClassLoader());
-            PmdExecutor executor = new PmdExecutor(request);
-            return executor.run();
-        } finally {
-            Thread.currentThread().setContextClassLoader(origLoader);
-        }
-    }
-
-    private static PmdResult fork(PmdRequest request) throws 
MavenReportException {
+    public PmdResult fork(String javaExecutable) throws MavenReportException {
         File basePmdDir = new File(request.getTargetDirectory(), "pmd");
         basePmdDir.mkdirs();
         File pmdRequestFile = new File(basePmdDir, "pmdrequest.bin");
@@ -92,7 +76,7 @@ public class PmdExecutor extends Executor {
         ProcessBuilder pb = new ProcessBuilder();
         // note: using env variable instead of -cp cli arg to avoid length 
limitations under Windows
         pb.environment().put("CLASSPATH", classpath);
-        pb.command().add(request.getJavaExecutable());
+        pb.command().add(javaExecutable);
         pb.command().add(PmdExecutor.class.getName());
         pb.command().add(pmdRequestFile.getAbsolutePath());
 
@@ -148,7 +132,7 @@ public class PmdExecutor extends Executor {
         this.request = Objects.requireNonNull(request);
     }
 
-    private PmdResult run() throws MavenReportException {
+    public PmdResult run() throws MavenReportException {
         PMDConfiguration configuration = new PMDConfiguration();
         LanguageVersion languageVersion = null;
         Language language = configuration
diff --git a/src/main/java/org/apache/maven/plugins/pmd/exec/PmdRequest.java 
b/src/main/java/org/apache/maven/plugins/pmd/exec/PmdRequest.java
index 1982e00..b923fad 100644
--- a/src/main/java/org/apache/maven/plugins/pmd/exec/PmdRequest.java
+++ b/src/main/java/org/apache/maven/plugins/pmd/exec/PmdRequest.java
@@ -23,6 +23,7 @@ import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Data object to store all configuration options needed to execute PMD
@@ -35,7 +36,7 @@ import java.util.List;
 public class PmdRequest implements Serializable {
     private static final long serialVersionUID = -6324416880563476455L;
 
-    private String javaExecutable;
+    private Map<String, String> jdkToolchain;
 
     private String language;
     private String languageVersion;
@@ -77,8 +78,8 @@ public class PmdRequest implements Serializable {
         }
     }
 
-    public void setJavaExecutable(String javaExecutable) {
-        this.javaExecutable = javaExecutable;
+    public void setJdkToolchain(Map<String, String> jdkToolchain) {
+        this.jdkToolchain = jdkToolchain;
     }
 
     public void setMinimumPriority(int minimumPriority) {
@@ -145,8 +146,8 @@ public class PmdRequest implements Serializable {
         this.excludeFromFailureFile = excludeFromFailureFile;
     }
 
-    public String getJavaExecutable() {
-        return javaExecutable;
+    public Map<String, String> getJdkToolchain() {
+        return jdkToolchain;
     }
 
     public String getLanguage() {
diff --git 
a/src/main/java/org/apache/maven/plugins/pmd/exec/PmdServiceExecutor.java 
b/src/main/java/org/apache/maven/plugins/pmd/exec/PmdServiceExecutor.java
new file mode 100644
index 0000000..af45a8e
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugins/pmd/exec/PmdServiceExecutor.java
@@ -0,0 +1,59 @@
+/*
+ * 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.pmd.exec;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.reporting.MavenReportException;
+import org.apache.maven.toolchain.ToolchainManager;
+
+/**
+ * Service for executing PMD.
+ */
+@Named
+@Singleton
+public class PmdServiceExecutor extends ServiceExecutor {
+
+    @Inject
+    public PmdServiceExecutor(ToolchainManager toolchainManager, 
Provider<MavenSession> sessionProvider) {
+        super(toolchainManager, sessionProvider);
+    }
+
+    public PmdResult execute(PmdRequest request) throws MavenReportException {
+
+        // make sure the class loaders are correct and call this in the same 
JVM
+        ClassLoader origLoader = 
Thread.currentThread().getContextClassLoader();
+        try {
+            
Thread.currentThread().setContextClassLoader(PmdExecutor.class.getClassLoader());
+            PmdExecutor executor = new PmdExecutor(request);
+
+            String javaExecutable = 
getJavaExecutable(request.getJdkToolchain());
+            if (javaExecutable != null) {
+                return executor.fork(javaExecutable);
+            }
+            return executor.run();
+        } finally {
+            Thread.currentThread().setContextClassLoader(origLoader);
+        }
+    }
+}
diff --git 
a/src/main/java/org/apache/maven/plugins/pmd/exec/ServiceExecutor.java 
b/src/main/java/org/apache/maven/plugins/pmd/exec/ServiceExecutor.java
new file mode 100644
index 0000000..3881f82
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugins/pmd/exec/ServiceExecutor.java
@@ -0,0 +1,73 @@
+/*
+ * 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.pmd.exec;
+
+import javax.inject.Provider;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.toolchain.Toolchain;
+import org.apache.maven.toolchain.ToolchainManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstract service executor for CPD and PMD.
+ */
+abstract class ServiceExecutor {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(ServiceExecutor.class);
+
+    private final ToolchainManager toolchainManager;
+
+    private final Provider<MavenSession> sessionProvider;
+
+    protected ServiceExecutor(ToolchainManager toolchainManager, 
Provider<MavenSession> sessionProvider) {
+        this.toolchainManager = toolchainManager;
+        this.sessionProvider = sessionProvider;
+    }
+
+    protected final Toolchain getToolchain(Map<String, String> jdkToolchain) {
+        Toolchain tc = null;
+
+        if (jdkToolchain != null) {
+            List<Toolchain> tcs = 
toolchainManager.getToolchains(sessionProvider.get(), "jdk", jdkToolchain);
+            if (tcs != null && !tcs.isEmpty()) {
+                tc = tcs.get(0);
+            }
+        }
+
+        if (tc == null) {
+            tc = toolchainManager.getToolchainFromBuildContext("jdk", 
sessionProvider.get());
+        }
+
+        return tc;
+    }
+
+    protected String getJavaExecutable(Map<String, String> jdkToolchain) {
+        Toolchain tc = getToolchain(jdkToolchain);
+        if (tc != null) {
+            LOG.info("Toolchain in maven-pmd-plugin: {}", tc);
+            return tc.findTool("java"); // NOI18N
+        }
+        return null;
+    }
+}
diff --git 
a/src/test/java/org/apache/maven/plugins/pmd/AbstractPmdReportTestCase.java 
b/src/test/java/org/apache/maven/plugins/pmd/AbstractPmdReportTestCase.java
index 2ad4015..7f821af 100644
--- a/src/test/java/org/apache/maven/plugins/pmd/AbstractPmdReportTestCase.java
+++ b/src/test/java/org/apache/maven/plugins/pmd/AbstractPmdReportTestCase.java
@@ -25,6 +25,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
 
+import org.apache.maven.execution.MavenSession;
 import org.apache.maven.model.Plugin;
 import org.apache.maven.plugin.LegacySupport;
 import org.apache.maven.plugin.MojoExecution;
@@ -36,6 +37,7 @@ import org.apache.maven.plugin.testing.stubs.MavenProjectStub;
 import org.apache.maven.project.DefaultProjectBuildingRequest;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.project.ProjectBuildingRequest;
+import org.apache.maven.session.scope.internal.SessionScope;
 import org.eclipse.aether.DefaultRepositorySystemSession;
 import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory;
 import org.eclipse.aether.repository.LocalRepository;
@@ -55,6 +57,15 @@ public abstract class AbstractPmdReportTestCase extends 
AbstractMojoTestCase {
 
         artifactStubFactory = new 
DependencyArtifactStubFactory(getTestFile("target"), true, false);
         artifactStubFactory.getWorkingDir().mkdirs();
+        SessionScope sessionScope = lookup(SessionScope.class);
+        sessionScope.enter();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        SessionScope lookup = lookup(SessionScope.class);
+        lookup.exit();
+        super.tearDown();
     }
 
     /**
@@ -75,8 +86,12 @@ public abstract class AbstractPmdReportTestCase extends 
AbstractMojoTestCase {
         AbstractPmdReport mojo = (AbstractPmdReport) lookupMojo(goal, 
pluginXmlFile);
         assertNotNull("Mojo not found.", mojo);
 
+        SessionScope sessionScope = lookup(SessionScope.class);
+        MavenSession mavenSession = newMavenSession(new MavenProjectStub());
+        sessionScope.seed(MavenSession.class, mavenSession);
+
         LegacySupport legacySupport = lookup(LegacySupport.class);
-        legacySupport.setSession(newMavenSession(new MavenProjectStub()));
+        legacySupport.setSession(mavenSession);
         DefaultRepositorySystemSession repoSession =
                 (DefaultRepositorySystemSession) 
legacySupport.getRepositorySession();
         repoSession.setLocalRepositoryManager(new 
SimpleLocalRepositoryManagerFactory()

Reply via email to