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



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to