[ 
https://issues.apache.org/jira/browse/MPLUGINTESTING-84?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17733180#comment-17733180
 ] 

ASF GitHub Bot commented on MPLUGINTESTING-84:
----------------------------------------------

elharo commented on code in PR #31:
URL: 
https://github.com/apache/maven-plugin-testing/pull/31#discussion_r1231341186


##########
maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/MojoExtension.java:
##########
@@ -0,0 +1,426 @@
+/*
+ * 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.plugin.testing.junit5;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import com.google.inject.internal.ProviderMethodsModule;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.lifecycle.internal.MojoDescriptorCreator;
+import org.apache.maven.plugin.Mojo;
+import org.apache.maven.plugin.MojoExecution;
+import org.apache.maven.plugin.PluginParameterExpressionEvaluator;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.apache.maven.plugin.descriptor.Parameter;
+import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.plugin.testing.ConfigurationException;
+import org.apache.maven.plugin.testing.MojoLogWrapper;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.DefaultPlexusContainer;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.component.configurator.BasicComponentConfigurator;
+import org.codehaus.plexus.component.configurator.ComponentConfigurator;
+import 
org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
+import 
org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
+import 
org.codehaus.plexus.component.configurator.expression.TypeAwareExpressionEvaluator;
+import org.codehaus.plexus.component.repository.ComponentDescriptor;
+import 
org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
+import org.codehaus.plexus.testing.PlexusExtension;
+import org.codehaus.plexus.util.InterpolationFilterReader;
+import org.codehaus.plexus.util.ReaderFactory;
+import org.codehaus.plexus.util.ReflectionUtils;
+import org.codehaus.plexus.util.xml.XmlStreamReader;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolutionException;
+import org.junit.jupiter.api.extension.ParameterResolver;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ */
+public class MojoExtension extends PlexusExtension implements 
ParameterResolver {
+
+    @Override
+    public boolean supportsParameter(ParameterContext parameterContext, 
ExtensionContext extensionContext)
+            throws ParameterResolutionException {
+        return parameterContext.isAnnotated(InjectMojo.class)
+                || 
parameterContext.getDeclaringExecutable().isAnnotationPresent(InjectMojo.class);
+    }
+
+    @Override
+    public Object resolveParameter(ParameterContext parameterContext, 
ExtensionContext extensionContext)
+            throws ParameterResolutionException {
+        try {
+            InjectMojo injectMojo = parameterContext
+                    .findAnnotation(InjectMojo.class)
+                    .orElseGet(() -> 
parameterContext.getDeclaringExecutable().getAnnotation(InjectMojo.class));
+            List<MojoParameter> mojoParameters = 
parameterContext.findRepeatableAnnotations(MojoParameter.class);
+            Class<?> holder = parameterContext.getTarget().get().getClass();
+            PluginDescriptor descriptor = extensionContext
+                    .getStore(ExtensionContext.Namespace.GLOBAL)
+                    .get(PluginDescriptor.class, PluginDescriptor.class);
+            return lookupMojo(holder, injectMojo, mojoParameters, descriptor);
+        } catch (Exception e) {
+            throw new ParameterResolutionException("Unable to resolve 
parameter", e);
+        }
+    }
+
+    @Override
+    public void beforeEach(ExtensionContext context) throws Exception {
+        Field field = PlexusExtension.class.getDeclaredField("basedir");
+        field.setAccessible(true);
+        field.set(null, getBasedir());
+        field = PlexusExtension.class.getDeclaredField("context");
+        field.setAccessible(true);
+        field.set(this, context);
+
+        getContainer().addComponent(getContainer(), 
PlexusContainer.class.getName());
+
+        ((DefaultPlexusContainer) 
getContainer()).addPlexusInjector(Collections.emptyList(), binder -> {
+            
binder.install(ProviderMethodsModule.forObject(context.getRequiredTestInstance()));
+            binder.requestInjection(context.getRequiredTestInstance());
+            binder.bind(Log.class).toInstance(new 
MojoLogWrapper(LoggerFactory.getLogger("anonymous")));
+        });
+
+        Map<Object, Object> map = getContainer().getContext().getContextData();
+
+        ClassLoader classLoader = 
context.getRequiredTestClass().getClassLoader();
+        try (InputStream is = Objects.requireNonNull(
+                        
classLoader.getResourceAsStream(getPluginDescriptorLocation()),
+                        "Unable to find plugin descriptor: " + 
getPluginDescriptorLocation());
+                Reader reader = new BufferedReader(new XmlStreamReader(is));
+                InterpolationFilterReader interpolationReader = new 
InterpolationFilterReader(reader, map, "${", "}")) {
+
+            PluginDescriptor pluginDescriptor = new 
PluginDescriptorBuilder().build(interpolationReader);
+
+            //            Artifact artifact =

Review Comment:
   delete commented out code



##########
maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/MojoExtension.java:
##########
@@ -0,0 +1,426 @@
+/*
+ * 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.plugin.testing.junit5;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import com.google.inject.internal.ProviderMethodsModule;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.lifecycle.internal.MojoDescriptorCreator;
+import org.apache.maven.plugin.Mojo;
+import org.apache.maven.plugin.MojoExecution;
+import org.apache.maven.plugin.PluginParameterExpressionEvaluator;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.apache.maven.plugin.descriptor.Parameter;
+import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.plugin.testing.ConfigurationException;
+import org.apache.maven.plugin.testing.MojoLogWrapper;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.DefaultPlexusContainer;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.component.configurator.BasicComponentConfigurator;
+import org.codehaus.plexus.component.configurator.ComponentConfigurator;
+import 
org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
+import 
org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
+import 
org.codehaus.plexus.component.configurator.expression.TypeAwareExpressionEvaluator;
+import org.codehaus.plexus.component.repository.ComponentDescriptor;
+import 
org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
+import org.codehaus.plexus.testing.PlexusExtension;
+import org.codehaus.plexus.util.InterpolationFilterReader;
+import org.codehaus.plexus.util.ReaderFactory;
+import org.codehaus.plexus.util.ReflectionUtils;
+import org.codehaus.plexus.util.xml.XmlStreamReader;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolutionException;
+import org.junit.jupiter.api.extension.ParameterResolver;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ */
+public class MojoExtension extends PlexusExtension implements 
ParameterResolver {
+
+    @Override
+    public boolean supportsParameter(ParameterContext parameterContext, 
ExtensionContext extensionContext)
+            throws ParameterResolutionException {
+        return parameterContext.isAnnotated(InjectMojo.class)
+                || 
parameterContext.getDeclaringExecutable().isAnnotationPresent(InjectMojo.class);
+    }
+
+    @Override
+    public Object resolveParameter(ParameterContext parameterContext, 
ExtensionContext extensionContext)
+            throws ParameterResolutionException {
+        try {
+            InjectMojo injectMojo = parameterContext
+                    .findAnnotation(InjectMojo.class)
+                    .orElseGet(() -> 
parameterContext.getDeclaringExecutable().getAnnotation(InjectMojo.class));
+            List<MojoParameter> mojoParameters = 
parameterContext.findRepeatableAnnotations(MojoParameter.class);
+            Class<?> holder = parameterContext.getTarget().get().getClass();
+            PluginDescriptor descriptor = extensionContext
+                    .getStore(ExtensionContext.Namespace.GLOBAL)
+                    .get(PluginDescriptor.class, PluginDescriptor.class);
+            return lookupMojo(holder, injectMojo, mojoParameters, descriptor);
+        } catch (Exception e) {
+            throw new ParameterResolutionException("Unable to resolve 
parameter", e);
+        }
+    }
+
+    @Override
+    public void beforeEach(ExtensionContext context) throws Exception {
+        Field field = PlexusExtension.class.getDeclaredField("basedir");
+        field.setAccessible(true);
+        field.set(null, getBasedir());
+        field = PlexusExtension.class.getDeclaredField("context");
+        field.setAccessible(true);
+        field.set(this, context);
+
+        getContainer().addComponent(getContainer(), 
PlexusContainer.class.getName());
+
+        ((DefaultPlexusContainer) 
getContainer()).addPlexusInjector(Collections.emptyList(), binder -> {
+            
binder.install(ProviderMethodsModule.forObject(context.getRequiredTestInstance()));
+            binder.requestInjection(context.getRequiredTestInstance());
+            binder.bind(Log.class).toInstance(new 
MojoLogWrapper(LoggerFactory.getLogger("anonymous")));
+        });
+
+        Map<Object, Object> map = getContainer().getContext().getContextData();
+
+        ClassLoader classLoader = 
context.getRequiredTestClass().getClassLoader();
+        try (InputStream is = Objects.requireNonNull(
+                        
classLoader.getResourceAsStream(getPluginDescriptorLocation()),
+                        "Unable to find plugin descriptor: " + 
getPluginDescriptorLocation());
+                Reader reader = new BufferedReader(new XmlStreamReader(is));
+                InterpolationFilterReader interpolationReader = new 
InterpolationFilterReader(reader, map, "${", "}")) {
+
+            PluginDescriptor pluginDescriptor = new 
PluginDescriptorBuilder().build(interpolationReader);
+
+            //            Artifact artifact =
+            //                    lookup( RepositorySystem.class 
).createArtifact( pluginDescriptor.getGroupId(),
+            //                            pluginDescriptor.getArtifactId(),
+            //                            pluginDescriptor.getVersion(), 
".jar" );
+            //
+            //            artifact.setFile( getPluginArtifactFile() );
+            //            pluginDescriptor.setPluginArtifact( artifact );
+            //            pluginDescriptor.setArtifacts( 
Collections.singletonList( artifact ) );
+
+            
context.getStore(ExtensionContext.Namespace.GLOBAL).put(PluginDescriptor.class, 
pluginDescriptor);
+
+            for (ComponentDescriptor<?> desc : 
pluginDescriptor.getComponents()) {
+                getContainer().addComponentDescriptor(desc);
+            }
+        }
+    }
+
+    protected String getPluginDescriptorLocation() {
+        return "META-INF/maven/plugin.xml";
+    }
+
+    private Mojo lookupMojo(
+            Class<?> holder, InjectMojo injectMojo, List<MojoParameter> 
mojoParameters, PluginDescriptor descriptor)
+            throws Exception {
+        String goal = injectMojo.goal();
+        String pom = injectMojo.pom();
+        String[] coord = mojoCoordinates(goal);
+        Xpp3Dom pomDom;
+        if (pom.startsWith("file:")) {
+            Path path = 
Paths.get(getBasedir()).resolve(pom.substring("file:".length()));
+            pomDom = 
Xpp3DomBuilder.build(ReaderFactory.newXmlReader(path.toFile()));
+        } else if (pom.startsWith("classpath:")) {
+            URL url = holder.getResource(pom.substring("classpath:".length()));
+            if (url == null) {
+                throw new IllegalStateException("Unable to find pom on 
classpath: " + pom);
+            }
+            pomDom = 
Xpp3DomBuilder.build(ReaderFactory.newXmlReader(url.openStream()));
+        } else if (pom.contains("<project>")) {
+            pomDom = Xpp3DomBuilder.build(new StringReader(pom));
+        } else {
+            Path path = Paths.get(getBasedir()).resolve(pom);
+            pomDom = 
Xpp3DomBuilder.build(ReaderFactory.newXmlReader(path.toFile()));
+        }
+        Xpp3Dom pluginConfiguration = extractPluginConfiguration(coord[1], 
pomDom);
+        if (!mojoParameters.isEmpty()) {
+            List<Xpp3Dom> children = mojoParameters.stream()
+                    .map(mp -> {
+                        Xpp3Dom c = new Xpp3Dom(mp.name());
+                        c.setValue(mp.value());
+                        return c;
+                    })
+                    .collect(Collectors.toList());
+            Xpp3Dom config = new Xpp3Dom("configuration");
+            children.forEach(config::addChild);
+            pluginConfiguration = Xpp3Dom.mergeXpp3Dom(config, 
pluginConfiguration);
+        }
+        Mojo mojo = lookupMojo(coord, pluginConfiguration, descriptor);
+        return mojo;
+    }
+
+    protected String[] mojoCoordinates(String goal) throws Exception {
+        if (goal.matches(".*:.*:.*:.*")) {
+            return goal.split(":");
+        } else {
+            Path pluginPom = Paths.get(getBasedir(), "pom.xml");
+            Xpp3Dom pluginPomDom = 
Xpp3DomBuilder.build(ReaderFactory.newXmlReader(pluginPom.toFile()));
+            String artifactId = pluginPomDom.getChild("artifactId").getValue();
+            String groupId = resolveFromRootThenParent(pluginPomDom, 
"groupId");
+            String version = resolveFromRootThenParent(pluginPomDom, 
"version");
+            return new String[] {groupId, artifactId, version, goal};
+        }
+    }
+
+    /**
+     * lookup the mojo while we have all of the relavent information
+     */
+    protected Mojo lookupMojo(String[] coord, Xpp3Dom pluginConfiguration, 
PluginDescriptor descriptor)
+            throws Exception {
+        // pluginkey = groupId : artifactId : version : goal
+        Mojo mojo = lookup(Mojo.class, coord[0] + ":" + coord[1] + ":" + 
coord[2] + ":" + coord[3]);
+        for (MojoDescriptor mojoDescriptor : descriptor.getMojos()) {
+            if (Objects.equals(
+                    mojoDescriptor.getImplementation(), 
mojo.getClass().getName())) {
+                if (pluginConfiguration != null) {
+                    pluginConfiguration = finalizeConfig(pluginConfiguration, 
mojoDescriptor);
+                }
+            }
+        }
+        if (pluginConfiguration != null) {
+            MavenSession session = getContainer().lookup(MavenSession.class);
+            MavenProject project;
+            try {
+                project = getContainer().lookup(MavenProject.class);
+            } catch (ComponentLookupException e) {
+                project = null;
+            }
+            MojoExecution mojoExecution;
+            try {
+                mojoExecution = getContainer().lookup(MojoExecution.class);
+            } catch (ComponentLookupException e) {
+                mojoExecution = null;
+            }
+            ExpressionEvaluator evaluator =
+                    new WrapEvaluator(getContainer(), new 
PluginParameterExpressionEvaluator(session, mojoExecution));
+            ComponentConfigurator configurator = new 
BasicComponentConfigurator();
+            configurator.configureComponent(
+                    mojo,
+                    new XmlPlexusConfiguration(pluginConfiguration),
+                    evaluator,
+                    getContainer().getContainerRealm());
+        }
+
+        return mojo;
+    }
+
+    private Xpp3Dom finalizeConfig(Xpp3Dom config, MojoDescriptor 
mojoDescriptor) {
+        List<Xpp3Dom> children = new ArrayList<>();
+        if (mojoDescriptor != null && mojoDescriptor.getParameters() != null) {
+            Xpp3Dom defaultConfiguration = 
MojoDescriptorCreator.convert(mojoDescriptor);
+            for (Parameter parameter : mojoDescriptor.getParameters()) {
+                Xpp3Dom parameterConfiguration = 
config.getChild(parameter.getName());
+                if (parameterConfiguration == null) {
+                    parameterConfiguration = 
config.getChild(parameter.getAlias());
+                }
+                Xpp3Dom parameterDefaults = 
defaultConfiguration.getChild(parameter.getName());
+                parameterConfiguration = 
Xpp3Dom.mergeXpp3Dom(parameterConfiguration, parameterDefaults, Boolean.TRUE);
+                if (parameterConfiguration != null) {
+                    if 
(isEmpty(parameterConfiguration.getAttribute("implementation"))
+                            && !isEmpty(parameter.getImplementation())) {
+                        parameterConfiguration.setAttribute("implementation", 
parameter.getImplementation());
+                    }
+                    children.add(parameterConfiguration);
+                }
+            }
+        }
+        Xpp3Dom c = new Xpp3Dom("configuration");
+        children.forEach(c::addChild);
+        return c;
+    }
+
+    private boolean isEmpty(String str) {
+        return str == null || str.isEmpty();
+    }
+
+    private static Optional<Xpp3Dom> child(Xpp3Dom element, String name) {
+        return Optional.ofNullable(element.getChild(name));
+    }
+
+    private static Stream<Xpp3Dom> children(Xpp3Dom element) {
+        return Stream.of(element.getChildren());
+    }
+
+    public static Xpp3Dom extractPluginConfiguration(String artifactId, 
Xpp3Dom pomDom) throws Exception {
+        Xpp3Dom pluginConfigurationElement = child(pomDom, "build")
+                .flatMap(buildElement -> child(buildElement, "plugins"))
+                .map(MojoExtension::children)
+                .orElseGet(Stream::empty)
+                .filter(e -> 
e.getChild("artifactId").getValue().equals(artifactId))
+                .findFirst()
+                .flatMap(buildElement -> child(buildElement, "configuration"))
+                .orElseThrow(
+                        () -> new ConfigurationException("Cannot find a 
configuration element for a plugin with an "
+                                + "artifactId of " + artifactId + "."));
+        return pluginConfigurationElement;
+    }
+
+    /**
+     * sometimes the parent element might contain the correct value so 
generalize that access
+     *
+     * TODO find out where this is probably done elsewhere
+     */
+    private static String resolveFromRootThenParent(Xpp3Dom pluginPomDom, 
String element) throws Exception {
+        return Optional.ofNullable(child(pluginPomDom, element).orElseGet(() 
-> child(pluginPomDom, "parent")
+                        .flatMap(e -> child(e, element))
+                        .orElse(null)))
+                .map(Xpp3Dom::getValue)
+                .orElseThrow(() -> new Exception("unable to determine " + 
element));
+    }
+
+    /**
+     * Convenience method to obtain the value of a variable on a mojo that 
might not have a getter.
+     *
+     * NOTE: the caller is responsible for casting to to what the desired type 
is.
+     *
+     * @param object
+     * @param variable
+     * @return object value of variable
+     * @throws IllegalArgumentException
+     */
+    public static Object getVariableValueFromObject(Object object, String 
variable) throws IllegalAccessException {
+        Field field = 
ReflectionUtils.getFieldByNameIncludingSuperclasses(variable, 
object.getClass());
+        field.setAccessible(true);
+        return field.get(object);
+    }
+
+    /**
+     * Convenience method to obtain all variables and values from the mojo 
(including its superclasses)
+     *
+     * Note: the values in the map are of type Object so the caller is 
responsible for casting to desired types.
+     *
+     * @param object
+     * @return map of variable names and values
+     */
+    public static Map<String, Object> getVariablesAndValuesFromObject(Object 
object) throws IllegalAccessException {
+        return getVariablesAndValuesFromObject(object.getClass(), object);
+    }
+
+    /**
+     * Convenience method to obtain all variables and values from the mojo 
(including its superclasses)
+     *
+     * Note: the values in the map are of type Object so the caller is 
responsible for casting to desired types.
+     *
+     * @param clazz
+     * @param object
+     * @return map of variable names and values
+     */
+    public static Map<String, Object> getVariablesAndValuesFromObject(Class<?> 
clazz, Object object)
+            throws IllegalAccessException {
+        Map<String, Object> map = new HashMap<>();
+        Field[] fields = clazz.getDeclaredFields();
+        AccessibleObject.setAccessible(fields, true);
+        for (Field field : fields) {
+            map.put(field.getName(), field.get(object));
+        }
+        Class<?> superclass = clazz.getSuperclass();
+        if (!Object.class.equals(superclass)) {
+            map.putAll(getVariablesAndValuesFromObject(superclass, object));
+        }
+        return map;
+    }
+
+    /**
+     * Convenience method to set values to variables in objects that don't 
have setters
+     *
+     * @param object

Review Comment:
   describe these or delete



##########
maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/MojoExtension.java:
##########
@@ -0,0 +1,426 @@
+/*
+ * 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.plugin.testing.junit5;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import com.google.inject.internal.ProviderMethodsModule;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.lifecycle.internal.MojoDescriptorCreator;
+import org.apache.maven.plugin.Mojo;
+import org.apache.maven.plugin.MojoExecution;
+import org.apache.maven.plugin.PluginParameterExpressionEvaluator;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.apache.maven.plugin.descriptor.Parameter;
+import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.plugin.testing.ConfigurationException;
+import org.apache.maven.plugin.testing.MojoLogWrapper;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.DefaultPlexusContainer;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.component.configurator.BasicComponentConfigurator;
+import org.codehaus.plexus.component.configurator.ComponentConfigurator;
+import 
org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
+import 
org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
+import 
org.codehaus.plexus.component.configurator.expression.TypeAwareExpressionEvaluator;
+import org.codehaus.plexus.component.repository.ComponentDescriptor;
+import 
org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
+import org.codehaus.plexus.testing.PlexusExtension;
+import org.codehaus.plexus.util.InterpolationFilterReader;
+import org.codehaus.plexus.util.ReaderFactory;
+import org.codehaus.plexus.util.ReflectionUtils;
+import org.codehaus.plexus.util.xml.XmlStreamReader;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolutionException;
+import org.junit.jupiter.api.extension.ParameterResolver;
+import org.slf4j.LoggerFactory;
+
+/**

Review Comment:
   These lines can be deleted



##########
maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/MojoExtension.java:
##########
@@ -0,0 +1,426 @@
+/*
+ * 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.plugin.testing.junit5;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import com.google.inject.internal.ProviderMethodsModule;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.lifecycle.internal.MojoDescriptorCreator;
+import org.apache.maven.plugin.Mojo;
+import org.apache.maven.plugin.MojoExecution;
+import org.apache.maven.plugin.PluginParameterExpressionEvaluator;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.apache.maven.plugin.descriptor.Parameter;
+import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.plugin.testing.ConfigurationException;
+import org.apache.maven.plugin.testing.MojoLogWrapper;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.DefaultPlexusContainer;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.component.configurator.BasicComponentConfigurator;
+import org.codehaus.plexus.component.configurator.ComponentConfigurator;
+import 
org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
+import 
org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
+import 
org.codehaus.plexus.component.configurator.expression.TypeAwareExpressionEvaluator;
+import org.codehaus.plexus.component.repository.ComponentDescriptor;
+import 
org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
+import org.codehaus.plexus.testing.PlexusExtension;
+import org.codehaus.plexus.util.InterpolationFilterReader;
+import org.codehaus.plexus.util.ReaderFactory;
+import org.codehaus.plexus.util.ReflectionUtils;
+import org.codehaus.plexus.util.xml.XmlStreamReader;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolutionException;
+import org.junit.jupiter.api.extension.ParameterResolver;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ */
+public class MojoExtension extends PlexusExtension implements 
ParameterResolver {
+
+    @Override
+    public boolean supportsParameter(ParameterContext parameterContext, 
ExtensionContext extensionContext)
+            throws ParameterResolutionException {
+        return parameterContext.isAnnotated(InjectMojo.class)
+                || 
parameterContext.getDeclaringExecutable().isAnnotationPresent(InjectMojo.class);
+    }
+
+    @Override
+    public Object resolveParameter(ParameterContext parameterContext, 
ExtensionContext extensionContext)
+            throws ParameterResolutionException {
+        try {
+            InjectMojo injectMojo = parameterContext
+                    .findAnnotation(InjectMojo.class)
+                    .orElseGet(() -> 
parameterContext.getDeclaringExecutable().getAnnotation(InjectMojo.class));
+            List<MojoParameter> mojoParameters = 
parameterContext.findRepeatableAnnotations(MojoParameter.class);
+            Class<?> holder = parameterContext.getTarget().get().getClass();
+            PluginDescriptor descriptor = extensionContext
+                    .getStore(ExtensionContext.Namespace.GLOBAL)
+                    .get(PluginDescriptor.class, PluginDescriptor.class);
+            return lookupMojo(holder, injectMojo, mojoParameters, descriptor);
+        } catch (Exception e) {
+            throw new ParameterResolutionException("Unable to resolve 
parameter", e);
+        }
+    }
+
+    @Override
+    public void beforeEach(ExtensionContext context) throws Exception {
+        Field field = PlexusExtension.class.getDeclaredField("basedir");
+        field.setAccessible(true);
+        field.set(null, getBasedir());
+        field = PlexusExtension.class.getDeclaredField("context");
+        field.setAccessible(true);
+        field.set(this, context);
+
+        getContainer().addComponent(getContainer(), 
PlexusContainer.class.getName());
+
+        ((DefaultPlexusContainer) 
getContainer()).addPlexusInjector(Collections.emptyList(), binder -> {
+            
binder.install(ProviderMethodsModule.forObject(context.getRequiredTestInstance()));
+            binder.requestInjection(context.getRequiredTestInstance());
+            binder.bind(Log.class).toInstance(new 
MojoLogWrapper(LoggerFactory.getLogger("anonymous")));
+        });
+
+        Map<Object, Object> map = getContainer().getContext().getContextData();
+
+        ClassLoader classLoader = 
context.getRequiredTestClass().getClassLoader();
+        try (InputStream is = Objects.requireNonNull(
+                        
classLoader.getResourceAsStream(getPluginDescriptorLocation()),
+                        "Unable to find plugin descriptor: " + 
getPluginDescriptorLocation());
+                Reader reader = new BufferedReader(new XmlStreamReader(is));
+                InterpolationFilterReader interpolationReader = new 
InterpolationFilterReader(reader, map, "${", "}")) {
+
+            PluginDescriptor pluginDescriptor = new 
PluginDescriptorBuilder().build(interpolationReader);
+
+            //            Artifact artifact =
+            //                    lookup( RepositorySystem.class 
).createArtifact( pluginDescriptor.getGroupId(),
+            //                            pluginDescriptor.getArtifactId(),
+            //                            pluginDescriptor.getVersion(), 
".jar" );
+            //
+            //            artifact.setFile( getPluginArtifactFile() );
+            //            pluginDescriptor.setPluginArtifact( artifact );
+            //            pluginDescriptor.setArtifacts( 
Collections.singletonList( artifact ) );
+
+            
context.getStore(ExtensionContext.Namespace.GLOBAL).put(PluginDescriptor.class, 
pluginDescriptor);
+
+            for (ComponentDescriptor<?> desc : 
pluginDescriptor.getComponents()) {
+                getContainer().addComponentDescriptor(desc);
+            }
+        }
+    }
+
+    protected String getPluginDescriptorLocation() {
+        return "META-INF/maven/plugin.xml";
+    }
+
+    private Mojo lookupMojo(
+            Class<?> holder, InjectMojo injectMojo, List<MojoParameter> 
mojoParameters, PluginDescriptor descriptor)
+            throws Exception {
+        String goal = injectMojo.goal();
+        String pom = injectMojo.pom();
+        String[] coord = mojoCoordinates(goal);
+        Xpp3Dom pomDom;
+        if (pom.startsWith("file:")) {
+            Path path = 
Paths.get(getBasedir()).resolve(pom.substring("file:".length()));
+            pomDom = 
Xpp3DomBuilder.build(ReaderFactory.newXmlReader(path.toFile()));
+        } else if (pom.startsWith("classpath:")) {
+            URL url = holder.getResource(pom.substring("classpath:".length()));
+            if (url == null) {
+                throw new IllegalStateException("Unable to find pom on 
classpath: " + pom);
+            }
+            pomDom = 
Xpp3DomBuilder.build(ReaderFactory.newXmlReader(url.openStream()));
+        } else if (pom.contains("<project>")) {
+            pomDom = Xpp3DomBuilder.build(new StringReader(pom));
+        } else {
+            Path path = Paths.get(getBasedir()).resolve(pom);
+            pomDom = 
Xpp3DomBuilder.build(ReaderFactory.newXmlReader(path.toFile()));
+        }
+        Xpp3Dom pluginConfiguration = extractPluginConfiguration(coord[1], 
pomDom);
+        if (!mojoParameters.isEmpty()) {
+            List<Xpp3Dom> children = mojoParameters.stream()
+                    .map(mp -> {
+                        Xpp3Dom c = new Xpp3Dom(mp.name());
+                        c.setValue(mp.value());
+                        return c;
+                    })
+                    .collect(Collectors.toList());
+            Xpp3Dom config = new Xpp3Dom("configuration");
+            children.forEach(config::addChild);
+            pluginConfiguration = Xpp3Dom.mergeXpp3Dom(config, 
pluginConfiguration);
+        }
+        Mojo mojo = lookupMojo(coord, pluginConfiguration, descriptor);
+        return mojo;
+    }
+
+    protected String[] mojoCoordinates(String goal) throws Exception {
+        if (goal.matches(".*:.*:.*:.*")) {
+            return goal.split(":");
+        } else {
+            Path pluginPom = Paths.get(getBasedir(), "pom.xml");
+            Xpp3Dom pluginPomDom = 
Xpp3DomBuilder.build(ReaderFactory.newXmlReader(pluginPom.toFile()));
+            String artifactId = pluginPomDom.getChild("artifactId").getValue();
+            String groupId = resolveFromRootThenParent(pluginPomDom, 
"groupId");
+            String version = resolveFromRootThenParent(pluginPomDom, 
"version");
+            return new String[] {groupId, artifactId, version, goal};
+        }
+    }
+
+    /**
+     * lookup the mojo while we have all of the relavent information
+     */
+    protected Mojo lookupMojo(String[] coord, Xpp3Dom pluginConfiguration, 
PluginDescriptor descriptor)
+            throws Exception {
+        // pluginkey = groupId : artifactId : version : goal
+        Mojo mojo = lookup(Mojo.class, coord[0] + ":" + coord[1] + ":" + 
coord[2] + ":" + coord[3]);
+        for (MojoDescriptor mojoDescriptor : descriptor.getMojos()) {
+            if (Objects.equals(
+                    mojoDescriptor.getImplementation(), 
mojo.getClass().getName())) {
+                if (pluginConfiguration != null) {
+                    pluginConfiguration = finalizeConfig(pluginConfiguration, 
mojoDescriptor);
+                }
+            }
+        }
+        if (pluginConfiguration != null) {
+            MavenSession session = getContainer().lookup(MavenSession.class);
+            MavenProject project;
+            try {
+                project = getContainer().lookup(MavenProject.class);
+            } catch (ComponentLookupException e) {
+                project = null;
+            }
+            MojoExecution mojoExecution;
+            try {
+                mojoExecution = getContainer().lookup(MojoExecution.class);
+            } catch (ComponentLookupException e) {
+                mojoExecution = null;
+            }
+            ExpressionEvaluator evaluator =
+                    new WrapEvaluator(getContainer(), new 
PluginParameterExpressionEvaluator(session, mojoExecution));
+            ComponentConfigurator configurator = new 
BasicComponentConfigurator();
+            configurator.configureComponent(
+                    mojo,
+                    new XmlPlexusConfiguration(pluginConfiguration),
+                    evaluator,
+                    getContainer().getContainerRealm());
+        }
+
+        return mojo;
+    }
+
+    private Xpp3Dom finalizeConfig(Xpp3Dom config, MojoDescriptor 
mojoDescriptor) {
+        List<Xpp3Dom> children = new ArrayList<>();
+        if (mojoDescriptor != null && mojoDescriptor.getParameters() != null) {
+            Xpp3Dom defaultConfiguration = 
MojoDescriptorCreator.convert(mojoDescriptor);
+            for (Parameter parameter : mojoDescriptor.getParameters()) {
+                Xpp3Dom parameterConfiguration = 
config.getChild(parameter.getName());
+                if (parameterConfiguration == null) {
+                    parameterConfiguration = 
config.getChild(parameter.getAlias());
+                }
+                Xpp3Dom parameterDefaults = 
defaultConfiguration.getChild(parameter.getName());
+                parameterConfiguration = 
Xpp3Dom.mergeXpp3Dom(parameterConfiguration, parameterDefaults, Boolean.TRUE);
+                if (parameterConfiguration != null) {
+                    if 
(isEmpty(parameterConfiguration.getAttribute("implementation"))
+                            && !isEmpty(parameter.getImplementation())) {
+                        parameterConfiguration.setAttribute("implementation", 
parameter.getImplementation());
+                    }
+                    children.add(parameterConfiguration);
+                }
+            }
+        }
+        Xpp3Dom c = new Xpp3Dom("configuration");
+        children.forEach(c::addChild);
+        return c;
+    }
+
+    private boolean isEmpty(String str) {
+        return str == null || str.isEmpty();
+    }
+
+    private static Optional<Xpp3Dom> child(Xpp3Dom element, String name) {
+        return Optional.ofNullable(element.getChild(name));
+    }
+
+    private static Stream<Xpp3Dom> children(Xpp3Dom element) {
+        return Stream.of(element.getChildren());
+    }
+
+    public static Xpp3Dom extractPluginConfiguration(String artifactId, 
Xpp3Dom pomDom) throws Exception {
+        Xpp3Dom pluginConfigurationElement = child(pomDom, "build")
+                .flatMap(buildElement -> child(buildElement, "plugins"))
+                .map(MojoExtension::children)
+                .orElseGet(Stream::empty)
+                .filter(e -> 
e.getChild("artifactId").getValue().equals(artifactId))
+                .findFirst()
+                .flatMap(buildElement -> child(buildElement, "configuration"))
+                .orElseThrow(
+                        () -> new ConfigurationException("Cannot find a 
configuration element for a plugin with an "
+                                + "artifactId of " + artifactId + "."));
+        return pluginConfigurationElement;
+    }
+
+    /**
+     * sometimes the parent element might contain the correct value so 
generalize that access
+     *
+     * TODO find out where this is probably done elsewhere
+     */
+    private static String resolveFromRootThenParent(Xpp3Dom pluginPomDom, 
String element) throws Exception {
+        return Optional.ofNullable(child(pluginPomDom, element).orElseGet(() 
-> child(pluginPomDom, "parent")
+                        .flatMap(e -> child(e, element))
+                        .orElse(null)))
+                .map(Xpp3Dom::getValue)
+                .orElseThrow(() -> new Exception("unable to determine " + 
element));
+    }
+
+    /**
+     * Convenience method to obtain the value of a variable on a mojo that 
might not have a getter.
+     *
+     * NOTE: the caller is responsible for casting to to what the desired type 
is.

Review Comment:
   double "to"



##########
maven-plugin-testing-harness/src/main/java/org/apache/maven/plugin/testing/junit5/MojoExtension.java:
##########
@@ -0,0 +1,426 @@
+/*
+ * 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.plugin.testing.junit5;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import com.google.inject.internal.ProviderMethodsModule;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.lifecycle.internal.MojoDescriptorCreator;
+import org.apache.maven.plugin.Mojo;
+import org.apache.maven.plugin.MojoExecution;
+import org.apache.maven.plugin.PluginParameterExpressionEvaluator;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.apache.maven.plugin.descriptor.Parameter;
+import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.plugin.testing.ConfigurationException;
+import org.apache.maven.plugin.testing.MojoLogWrapper;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.DefaultPlexusContainer;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.component.configurator.BasicComponentConfigurator;
+import org.codehaus.plexus.component.configurator.ComponentConfigurator;
+import 
org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
+import 
org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
+import 
org.codehaus.plexus.component.configurator.expression.TypeAwareExpressionEvaluator;
+import org.codehaus.plexus.component.repository.ComponentDescriptor;
+import 
org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
+import org.codehaus.plexus.testing.PlexusExtension;
+import org.codehaus.plexus.util.InterpolationFilterReader;
+import org.codehaus.plexus.util.ReaderFactory;
+import org.codehaus.plexus.util.ReflectionUtils;
+import org.codehaus.plexus.util.xml.XmlStreamReader;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolutionException;
+import org.junit.jupiter.api.extension.ParameterResolver;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ */
+public class MojoExtension extends PlexusExtension implements 
ParameterResolver {
+
+    @Override
+    public boolean supportsParameter(ParameterContext parameterContext, 
ExtensionContext extensionContext)
+            throws ParameterResolutionException {
+        return parameterContext.isAnnotated(InjectMojo.class)
+                || 
parameterContext.getDeclaringExecutable().isAnnotationPresent(InjectMojo.class);
+    }
+
+    @Override
+    public Object resolveParameter(ParameterContext parameterContext, 
ExtensionContext extensionContext)
+            throws ParameterResolutionException {
+        try {
+            InjectMojo injectMojo = parameterContext
+                    .findAnnotation(InjectMojo.class)
+                    .orElseGet(() -> 
parameterContext.getDeclaringExecutable().getAnnotation(InjectMojo.class));
+            List<MojoParameter> mojoParameters = 
parameterContext.findRepeatableAnnotations(MojoParameter.class);
+            Class<?> holder = parameterContext.getTarget().get().getClass();
+            PluginDescriptor descriptor = extensionContext
+                    .getStore(ExtensionContext.Namespace.GLOBAL)
+                    .get(PluginDescriptor.class, PluginDescriptor.class);
+            return lookupMojo(holder, injectMojo, mojoParameters, descriptor);
+        } catch (Exception e) {
+            throw new ParameterResolutionException("Unable to resolve 
parameter", e);
+        }
+    }
+
+    @Override
+    public void beforeEach(ExtensionContext context) throws Exception {
+        Field field = PlexusExtension.class.getDeclaredField("basedir");
+        field.setAccessible(true);
+        field.set(null, getBasedir());
+        field = PlexusExtension.class.getDeclaredField("context");
+        field.setAccessible(true);
+        field.set(this, context);
+
+        getContainer().addComponent(getContainer(), 
PlexusContainer.class.getName());
+
+        ((DefaultPlexusContainer) 
getContainer()).addPlexusInjector(Collections.emptyList(), binder -> {
+            
binder.install(ProviderMethodsModule.forObject(context.getRequiredTestInstance()));
+            binder.requestInjection(context.getRequiredTestInstance());
+            binder.bind(Log.class).toInstance(new 
MojoLogWrapper(LoggerFactory.getLogger("anonymous")));
+        });
+
+        Map<Object, Object> map = getContainer().getContext().getContextData();
+
+        ClassLoader classLoader = 
context.getRequiredTestClass().getClassLoader();
+        try (InputStream is = Objects.requireNonNull(
+                        
classLoader.getResourceAsStream(getPluginDescriptorLocation()),
+                        "Unable to find plugin descriptor: " + 
getPluginDescriptorLocation());
+                Reader reader = new BufferedReader(new XmlStreamReader(is));
+                InterpolationFilterReader interpolationReader = new 
InterpolationFilterReader(reader, map, "${", "}")) {
+
+            PluginDescriptor pluginDescriptor = new 
PluginDescriptorBuilder().build(interpolationReader);
+
+            //            Artifact artifact =
+            //                    lookup( RepositorySystem.class 
).createArtifact( pluginDescriptor.getGroupId(),
+            //                            pluginDescriptor.getArtifactId(),
+            //                            pluginDescriptor.getVersion(), 
".jar" );
+            //
+            //            artifact.setFile( getPluginArtifactFile() );
+            //            pluginDescriptor.setPluginArtifact( artifact );
+            //            pluginDescriptor.setArtifacts( 
Collections.singletonList( artifact ) );
+
+            
context.getStore(ExtensionContext.Namespace.GLOBAL).put(PluginDescriptor.class, 
pluginDescriptor);
+
+            for (ComponentDescriptor<?> desc : 
pluginDescriptor.getComponents()) {
+                getContainer().addComponentDescriptor(desc);
+            }
+        }
+    }
+
+    protected String getPluginDescriptorLocation() {
+        return "META-INF/maven/plugin.xml";
+    }
+
+    private Mojo lookupMojo(
+            Class<?> holder, InjectMojo injectMojo, List<MojoParameter> 
mojoParameters, PluginDescriptor descriptor)
+            throws Exception {
+        String goal = injectMojo.goal();
+        String pom = injectMojo.pom();
+        String[] coord = mojoCoordinates(goal);
+        Xpp3Dom pomDom;
+        if (pom.startsWith("file:")) {
+            Path path = 
Paths.get(getBasedir()).resolve(pom.substring("file:".length()));
+            pomDom = 
Xpp3DomBuilder.build(ReaderFactory.newXmlReader(path.toFile()));
+        } else if (pom.startsWith("classpath:")) {
+            URL url = holder.getResource(pom.substring("classpath:".length()));
+            if (url == null) {
+                throw new IllegalStateException("Unable to find pom on 
classpath: " + pom);
+            }
+            pomDom = 
Xpp3DomBuilder.build(ReaderFactory.newXmlReader(url.openStream()));
+        } else if (pom.contains("<project>")) {
+            pomDom = Xpp3DomBuilder.build(new StringReader(pom));
+        } else {
+            Path path = Paths.get(getBasedir()).resolve(pom);
+            pomDom = 
Xpp3DomBuilder.build(ReaderFactory.newXmlReader(path.toFile()));
+        }
+        Xpp3Dom pluginConfiguration = extractPluginConfiguration(coord[1], 
pomDom);
+        if (!mojoParameters.isEmpty()) {
+            List<Xpp3Dom> children = mojoParameters.stream()
+                    .map(mp -> {
+                        Xpp3Dom c = new Xpp3Dom(mp.name());
+                        c.setValue(mp.value());
+                        return c;
+                    })
+                    .collect(Collectors.toList());
+            Xpp3Dom config = new Xpp3Dom("configuration");
+            children.forEach(config::addChild);
+            pluginConfiguration = Xpp3Dom.mergeXpp3Dom(config, 
pluginConfiguration);
+        }
+        Mojo mojo = lookupMojo(coord, pluginConfiguration, descriptor);
+        return mojo;
+    }
+
+    protected String[] mojoCoordinates(String goal) throws Exception {
+        if (goal.matches(".*:.*:.*:.*")) {
+            return goal.split(":");
+        } else {
+            Path pluginPom = Paths.get(getBasedir(), "pom.xml");
+            Xpp3Dom pluginPomDom = 
Xpp3DomBuilder.build(ReaderFactory.newXmlReader(pluginPom.toFile()));
+            String artifactId = pluginPomDom.getChild("artifactId").getValue();
+            String groupId = resolveFromRootThenParent(pluginPomDom, 
"groupId");
+            String version = resolveFromRootThenParent(pluginPomDom, 
"version");
+            return new String[] {groupId, artifactId, version, goal};
+        }
+    }
+
+    /**
+     * lookup the mojo while we have all of the relavent information
+     */
+    protected Mojo lookupMojo(String[] coord, Xpp3Dom pluginConfiguration, 
PluginDescriptor descriptor)
+            throws Exception {
+        // pluginkey = groupId : artifactId : version : goal
+        Mojo mojo = lookup(Mojo.class, coord[0] + ":" + coord[1] + ":" + 
coord[2] + ":" + coord[3]);
+        for (MojoDescriptor mojoDescriptor : descriptor.getMojos()) {
+            if (Objects.equals(
+                    mojoDescriptor.getImplementation(), 
mojo.getClass().getName())) {
+                if (pluginConfiguration != null) {
+                    pluginConfiguration = finalizeConfig(pluginConfiguration, 
mojoDescriptor);
+                }
+            }
+        }
+        if (pluginConfiguration != null) {
+            MavenSession session = getContainer().lookup(MavenSession.class);
+            MavenProject project;
+            try {
+                project = getContainer().lookup(MavenProject.class);
+            } catch (ComponentLookupException e) {
+                project = null;
+            }
+            MojoExecution mojoExecution;
+            try {
+                mojoExecution = getContainer().lookup(MojoExecution.class);
+            } catch (ComponentLookupException e) {
+                mojoExecution = null;
+            }
+            ExpressionEvaluator evaluator =
+                    new WrapEvaluator(getContainer(), new 
PluginParameterExpressionEvaluator(session, mojoExecution));
+            ComponentConfigurator configurator = new 
BasicComponentConfigurator();
+            configurator.configureComponent(
+                    mojo,
+                    new XmlPlexusConfiguration(pluginConfiguration),
+                    evaluator,
+                    getContainer().getContainerRealm());
+        }
+
+        return mojo;
+    }
+
+    private Xpp3Dom finalizeConfig(Xpp3Dom config, MojoDescriptor 
mojoDescriptor) {
+        List<Xpp3Dom> children = new ArrayList<>();
+        if (mojoDescriptor != null && mojoDescriptor.getParameters() != null) {
+            Xpp3Dom defaultConfiguration = 
MojoDescriptorCreator.convert(mojoDescriptor);
+            for (Parameter parameter : mojoDescriptor.getParameters()) {
+                Xpp3Dom parameterConfiguration = 
config.getChild(parameter.getName());
+                if (parameterConfiguration == null) {
+                    parameterConfiguration = 
config.getChild(parameter.getAlias());
+                }
+                Xpp3Dom parameterDefaults = 
defaultConfiguration.getChild(parameter.getName());
+                parameterConfiguration = 
Xpp3Dom.mergeXpp3Dom(parameterConfiguration, parameterDefaults, Boolean.TRUE);
+                if (parameterConfiguration != null) {
+                    if 
(isEmpty(parameterConfiguration.getAttribute("implementation"))
+                            && !isEmpty(parameter.getImplementation())) {
+                        parameterConfiguration.setAttribute("implementation", 
parameter.getImplementation());
+                    }
+                    children.add(parameterConfiguration);
+                }
+            }
+        }
+        Xpp3Dom c = new Xpp3Dom("configuration");
+        children.forEach(c::addChild);
+        return c;
+    }
+
+    private boolean isEmpty(String str) {
+        return str == null || str.isEmpty();
+    }
+
+    private static Optional<Xpp3Dom> child(Xpp3Dom element, String name) {
+        return Optional.ofNullable(element.getChild(name));
+    }
+
+    private static Stream<Xpp3Dom> children(Xpp3Dom element) {
+        return Stream.of(element.getChildren());
+    }
+
+    public static Xpp3Dom extractPluginConfiguration(String artifactId, 
Xpp3Dom pomDom) throws Exception {
+        Xpp3Dom pluginConfigurationElement = child(pomDom, "build")
+                .flatMap(buildElement -> child(buildElement, "plugins"))
+                .map(MojoExtension::children)
+                .orElseGet(Stream::empty)
+                .filter(e -> 
e.getChild("artifactId").getValue().equals(artifactId))
+                .findFirst()
+                .flatMap(buildElement -> child(buildElement, "configuration"))
+                .orElseThrow(
+                        () -> new ConfigurationException("Cannot find a 
configuration element for a plugin with an "
+                                + "artifactId of " + artifactId + "."));
+        return pluginConfigurationElement;
+    }
+
+    /**
+     * sometimes the parent element might contain the correct value so 
generalize that access
+     *
+     * TODO find out where this is probably done elsewhere
+     */
+    private static String resolveFromRootThenParent(Xpp3Dom pluginPomDom, 
String element) throws Exception {
+        return Optional.ofNullable(child(pluginPomDom, element).orElseGet(() 
-> child(pluginPomDom, "parent")
+                        .flatMap(e -> child(e, element))
+                        .orElse(null)))
+                .map(Xpp3Dom::getValue)
+                .orElseThrow(() -> new Exception("unable to determine " + 
element));
+    }
+
+    /**
+     * Convenience method to obtain the value of a variable on a mojo that 
might not have a getter.
+     *
+     * NOTE: the caller is responsible for casting to to what the desired type 
is.
+     *
+     * @param object

Review Comment:
   fill in or delete





> Support JUnit 5 on Maven 3
> --------------------------
>
>                 Key: MPLUGINTESTING-84
>                 URL: https://issues.apache.org/jira/browse/MPLUGINTESTING-84
>             Project: Maven Plugin Testing
>          Issue Type: New Feature
>            Reporter: Guillaume Nodet
>            Priority: Major
>             Fix For: 4.0.0-alpha-2
>
>




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to