This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/maven-plugin-testing.git
commit c6ef221ab068ee487e1c535aa2b8925ecc4f0db6 Author: Guillaume Nodet <[email protected]> AuthorDate: Tue Nov 28 18:28:40 2023 +0100 [MPLUGINTESTING-94] Switch to Maven 4.0.0-beta-3 --- .github/workflows/maven-verify.yml | 2 +- maven-plugin-testing-harness/pom.xml | 46 +- .../maven/api/di/testing/MavenDIExtension.java | 150 +++ .../testing/MavenDITest.java} | 18 +- .../testing/{MojoParameters.java => Basedir.java} | 6 +- .../maven/api/plugin/testing/InjectMojo.java | 6 +- .../maven/api/plugin/testing/MojoExtension.java | 598 ++++++++--- .../maven/api/plugin/testing/MojoParameter.java | 2 + .../maven/api/plugin/testing/MojoParameters.java | 2 + .../testing/ResolverExpressionEvaluatorStub.java | 12 +- .../api/plugin/testing/stubs/ArtifactStub.java | 23 +- .../plugin/testing/stubs/MojoExecutionStub.java | 67 +- .../maven/api/plugin/testing/stubs/PluginStub.java | 102 ++ .../api/plugin/testing/stubs/ProjectStub.java | 152 ++- .../testing/stubs/RepositorySystemSupplier.java | 1069 ++++++++++++++++++++ .../api/plugin/testing/stubs/SessionStub.java | 203 +++- .../apache/maven/api/di/testing/SimpleDITest.java | 50 + .../plugin/testing/ExpressionEvaluatorTest.java | 38 +- .../META-INF/maven/org.apache.maven.api.di.Inject | 18 +- .../src/test/resources/META-INF/maven/plugin.xml | 41 +- pom.xml | 6 +- 21 files changed, 2272 insertions(+), 339 deletions(-) diff --git a/.github/workflows/maven-verify.yml b/.github/workflows/maven-verify.yml index fa7dc4b..9177951 100644 --- a/.github/workflows/maven-verify.yml +++ b/.github/workflows/maven-verify.yml @@ -26,4 +26,4 @@ jobs: name: Verify uses: apache/maven-gh-actions-shared/.github/workflows/maven-verify.yml@v4 with: - jdk-matrix: '[ "8", "11", "17" ]' + jdk-matrix: '[ "17", "21" ]' diff --git a/maven-plugin-testing-harness/pom.xml b/maven-plugin-testing-harness/pom.xml index beaa39d..a1d4e4d 100644 --- a/maven-plugin-testing-harness/pom.xml +++ b/maven-plugin-testing-harness/pom.xml @@ -35,7 +35,7 @@ under the License. <dependency> <groupId>org.junit</groupId> <artifactId>junit-bom</artifactId> - <version>5.10.0</version> + <version>5.10.1</version> <type>pom</type> <scope>import</scope> </dependency> @@ -62,18 +62,33 @@ under the License. <version>${mavenVersion}</version> <scope>provided</scope> </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-model-builder</artifactId> + <version>${mavenVersion}</version> + <scope>provided</scope> + </dependency> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-plugin-api</artifactId> <version>${mavenVersion}</version> <scope>provided</scope> </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-xml-impl</artifactId> + <version>${mavenVersion}</version> + </dependency> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-resolver-provider</artifactId> <version>${mavenVersion}</version> <scope>provided</scope> </dependency> + <dependency> + <groupId>org.eclipse.sisu</groupId> + <artifactId>org.eclipse.sisu.plexus</artifactId> + </dependency> <!-- plexus --> <dependency> @@ -85,7 +100,7 @@ under the License. <!-- correct version must be provided by project depends on Maven version --> <groupId>org.codehaus.plexus</groupId> <artifactId>plexus-xml</artifactId> - <version>4.0.0</version> + <version>4.0.3</version> <optional>true</optional> </dependency> <dependency> @@ -97,14 +112,17 @@ under the License. <dependency> <groupId>org.codehaus.plexus</groupId> <artifactId>plexus-testing</artifactId> - <version>1.1.0</version> - <exclusions> - <exclusion> - <!-- we need as optional dependencies --> - <groupId>org.junit.jupiter</groupId> - <artifactId>junit-jupiter-api</artifactId> - </exclusion> - </exclusions> + <version>1.3.0</version> + </dependency> + <dependency> + <groupId>com.google.inject</groupId> + <artifactId>guice</artifactId> + <version>6.0.0</version> + </dependency> + <dependency> + <groupId>org.ow2.asm</groupId> + <artifactId>asm</artifactId> + <version>9.6</version> </dependency> <dependency> <!-- newer version is required by plexus-testing --> @@ -112,12 +130,6 @@ under the License. <artifactId>guava</artifactId> <version>32.0.1-jre</version> </dependency> - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <version>4.13.2</version> - <optional>true</optional> - </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> @@ -131,7 +143,7 @@ under the License. <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> - <version>1.7.36</version> + <version>2.0.13</version> <scope>test</scope> </dependency> </dependencies> diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/di/testing/MavenDIExtension.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/di/testing/MavenDIExtension.java new file mode 100644 index 0000000..c6f3b86 --- /dev/null +++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/di/testing/MavenDIExtension.java @@ -0,0 +1,150 @@ +/* + * 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.api.di.testing; + +import java.io.*; + +import org.apache.maven.di.Injector; +import org.apache.maven.di.Key; +import org.apache.maven.di.impl.DIException; +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +/** + * This is a slightly modified version of the original plexus class + * available at https://raw.githubusercontent.com/codehaus-plexus/plexus-containers/master/plexus-container-default/ + * src/main/java/org/codehaus/plexus/PlexusTestCase.java + * in order to migrate the tests to JUnit 4. + * + * @author Jason van Zyl + * @author <a href="mailto:[email protected]">Trygve Laugstøl</a> + * @author <a href="mailto:[email protected]">Michal Maczka</a> + * @author Guillaume Nodet + */ +public class MavenDIExtension implements BeforeEachCallback, AfterEachCallback { + protected static ExtensionContext context; + protected Injector injector; + protected static String basedir; + + @Override + public void beforeEach(ExtensionContext context) throws Exception { + basedir = getBasedir(); + + setContext(context); + + getInjector().bindInstance((Class<Object>) context.getRequiredTestClass(), context.getRequiredTestInstance()); + getInjector().injectInstance(context.getRequiredTestInstance()); + } + + protected void setContext(ExtensionContext context) { + this.context = context; + } + + @SuppressWarnings("unchecked") + protected void setupContainer() { + try { + injector = Injector.create(); + injector.bindInstance(ExtensionContext.class, this.context); + injector.discover(this.context.getRequiredTestClass().getClassLoader()); + injector.bindInstance(Injector.class, injector); + injector.bindInstance((Class) this.context.getRequiredTestClass(), this.context.getRequiredTestInstance()); + } catch (Exception e) { + throw new IllegalArgumentException("Failed to create DI injector.", e); + } + } + + @Override + public void afterEach(ExtensionContext context) throws Exception { + if (injector != null) { + // TODO: implement + // injector.dispose(); + injector = null; + } + } + + public Injector getInjector() { + if (injector == null) { + setupContainer(); + } + + return injector; + } + + // ---------------------------------------------------------------------- + // Container access + // ---------------------------------------------------------------------- + + protected <T> T lookup(Class<T> componentClass) throws DIException { + return getInjector().getInstance(componentClass); + } + + protected <T> T lookup(Class<T> componentClass, String roleHint) throws DIException { + return getInjector().getInstance(Key.ofType(componentClass, roleHint)); + } + + protected <T> T lookup(Class<T> componentClass, Object qualifier) throws DIException { + return getInjector().getInstance(Key.ofType(componentClass, qualifier)); + } + + protected void release(Object component) throws DIException { + // TODO: implement + // getInjector().release(component); + } + + // ---------------------------------------------------------------------- + // Helper methods for sub classes + // ---------------------------------------------------------------------- + + public static File getTestFile(String path) { + return new File(getBasedir(), path); + } + + public static File getTestFile(String basedir, String path) { + File basedirFile = new File(basedir); + + if (!basedirFile.isAbsolute()) { + basedirFile = getTestFile(basedir); + } + + return new File(basedirFile, path); + } + + public static String getTestPath(String path) { + return getTestFile(path).getAbsolutePath(); + } + + public static String getTestPath(String basedir, String path) { + return getTestFile(basedir, path).getAbsolutePath(); + } + + public static String getBasedir() { + if (basedir != null) { + return basedir; + } + + basedir = System.getProperty("basedir"); + + if (basedir == null) { + basedir = new File("").getAbsolutePath(); + } + + return basedir; + } +} diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoParameter.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/di/testing/MavenDITest.java similarity index 77% copy from maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoParameter.java copy to maven-plugin-testing-harness/src/main/java/org/apache/maven/api/di/testing/MavenDITest.java index 2a28f48..ddc6d2f 100644 --- a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoParameter.java +++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/di/testing/MavenDITest.java @@ -16,19 +16,19 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.maven.api.plugin.testing; +package org.apache.maven.api.di.testing; -import java.lang.annotation.Repeatable; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.junit.jupiter.api.extension.ExtendWith; /** - * Mojo parameter + * Plexus test */ @Retention(RetentionPolicy.RUNTIME) -@Repeatable(MojoParameters.class) -public @interface MojoParameter { - String name(); - - String value(); -} +@ExtendWith(MavenDIExtension.class) +@Target(ElementType.TYPE) +public @interface MavenDITest {} diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoParameters.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/Basedir.java similarity index 90% copy from maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoParameters.java copy to maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/Basedir.java index 434abe1..69eaba2 100644 --- a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoParameters.java +++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/Basedir.java @@ -18,6 +18,7 @@ */ package org.apache.maven.api.plugin.testing; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -25,6 +26,7 @@ import java.lang.annotation.RetentionPolicy; * Mojo parameters container */ @Retention(RetentionPolicy.RUNTIME) -public @interface MojoParameters { - MojoParameter[] value(); +@Inherited +public @interface Basedir { + String value() default ""; } diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/InjectMojo.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/InjectMojo.java index e094d06..272eb9b 100644 --- a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/InjectMojo.java +++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/InjectMojo.java @@ -18,6 +18,7 @@ */ package org.apache.maven.api.plugin.testing; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -25,11 +26,10 @@ import java.lang.annotation.RetentionPolicy; * */ @Retention(RetentionPolicy.RUNTIME) +@Inherited public @interface InjectMojo { String goal(); - String pom(); - - boolean empty() default false; + String pom() default ""; } diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoExtension.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoExtension.java index b217fab..0147261 100644 --- a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoExtension.java +++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoExtension.java @@ -18,68 +18,75 @@ */ package org.apache.maven.api.plugin.testing; -import java.io.BufferedReader; -import java.io.File; -import java.io.InputStream; -import java.io.Reader; -import java.io.StringReader; +import java.io.*; import java.lang.reflect.AccessibleObject; +import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Field; import java.net.URL; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; -import com.google.inject.internal.ProviderMethodsModule; import org.apache.maven.api.MojoExecution; import org.apache.maven.api.Project; import org.apache.maven.api.Session; +import org.apache.maven.api.di.Named; +import org.apache.maven.api.di.Priority; +import org.apache.maven.api.di.Provides; +import org.apache.maven.api.di.Singleton; +import org.apache.maven.api.di.testing.MavenDIExtension; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.ConfigurationContainer; +import org.apache.maven.api.model.Model; import org.apache.maven.api.plugin.Log; import org.apache.maven.api.plugin.Mojo; +import org.apache.maven.api.plugin.descriptor.MojoDescriptor; +import org.apache.maven.api.plugin.descriptor.Parameter; +import org.apache.maven.api.plugin.descriptor.PluginDescriptor; +import org.apache.maven.api.plugin.testing.stubs.*; +import org.apache.maven.api.services.ArtifactDeployer; +import org.apache.maven.api.services.ArtifactFactory; +import org.apache.maven.api.services.ArtifactInstaller; +import org.apache.maven.api.services.ArtifactManager; +import org.apache.maven.api.services.LocalRepositoryManager; +import org.apache.maven.api.services.ProjectBuilder; +import org.apache.maven.api.services.ProjectManager; +import org.apache.maven.api.services.RepositoryFactory; +import org.apache.maven.api.services.VersionParser; +import org.apache.maven.api.services.xml.ModelXmlFactory; import org.apache.maven.api.xml.XmlNode; import org.apache.maven.configuration.internal.EnhancedComponentConfigurator; +import org.apache.maven.di.Injector; +import org.apache.maven.di.Key; +import org.apache.maven.di.impl.DIException; import org.apache.maven.internal.impl.DefaultLog; +import org.apache.maven.internal.impl.InternalSession; +import org.apache.maven.internal.impl.model.DefaultModelPathTranslator; +import org.apache.maven.internal.impl.model.DefaultPathTranslator; import org.apache.maven.internal.xml.XmlNodeImpl; +import org.apache.maven.internal.xml.XmlPlexusConfiguration; import org.apache.maven.lifecycle.internal.MojoDescriptorCreator; +import org.apache.maven.model.v4.MavenMerger; +import org.apache.maven.model.v4.MavenStaxReader; import org.apache.maven.plugin.PluginParameterExpressionEvaluatorV4; -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.codehaus.plexus.DefaultPlexusContainer; -import org.codehaus.plexus.PlexusContainer; -import org.codehaus.plexus.component.configurator.ComponentConfigurator; +import org.apache.maven.plugin.descriptor.io.PluginDescriptorStaxReader; 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.eclipse.aether.RepositorySystem; +import org.junit.jupiter.api.extension.*; +import org.junit.platform.commons.support.AnnotationSupport; import org.slf4j.LoggerFactory; +import static java.util.Objects.requireNonNull; + /** * JUnit extension to help testing Mojos. The extension should be automatically registered * by adding the {@link MojoTest} annotation on the test class. @@ -87,8 +94,25 @@ import org.slf4j.LoggerFactory; * @see MojoTest * @see InjectMojo * @see MojoParameter + * @see Basedir */ -public class MojoExtension extends PlexusExtension implements ParameterResolver { +public class MojoExtension extends MavenDIExtension implements ParameterResolver, BeforeEachCallback { + + protected static String pluginBasedir; + protected static String basedir; + + public static String getTestId() { + return context.getRequiredTestClass().getSimpleName() + "-" + + context.getRequiredTestMethod().getName(); + } + + public static String getBasedir() { + return requireNonNull(basedir != null ? basedir : MavenDIExtension.basedir); + } + + public static String getPluginBasedir() { + return requireNonNull(pluginBasedir); + } @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) @@ -101,115 +125,382 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { try { - InjectMojo injectMojo = parameterContext - .findAnnotation(InjectMojo.class) - .orElseGet(() -> parameterContext.getDeclaringExecutable().getAnnotation(InjectMojo.class)); - - Set<MojoParameter> mojoParameters = - new HashSet<>(parameterContext.findRepeatableAnnotations(MojoParameter.class)); - - Optional.ofNullable(parameterContext.getDeclaringExecutable().getAnnotation(MojoParameter.class)) - .ifPresent(mojoParameters::add); - - Optional.ofNullable(parameterContext.getDeclaringExecutable().getAnnotation(MojoParameters.class)) - .map(MojoParameters::value) - .map(Arrays::asList) - .ifPresent(mojoParameters::addAll); - Class<?> holder = parameterContext.getTarget().get().getClass(); PluginDescriptor descriptor = extensionContext .getStore(ExtensionContext.Namespace.GLOBAL) .get(PluginDescriptor.class, PluginDescriptor.class); - return lookupMojo(holder, injectMojo, mojoParameters, descriptor); + Model model = + extensionContext.getStore(ExtensionContext.Namespace.GLOBAL).get(Model.class, Model.class); + InjectMojo parameterInjectMojo = + parameterContext.getAnnotatedElement().getAnnotation(InjectMojo.class); + String goal; + if (parameterInjectMojo != null) { + String pom = parameterInjectMojo.pom(); + if (pom != null && !pom.isEmpty()) { + try (Reader r = openPomUrl(holder, pom, new Path[1])) { + Model localModel = new MavenStaxReader().read(r); + model = new MavenMerger().merge(localModel, model, false, null); + model = new DefaultModelPathTranslator(new DefaultPathTranslator()) + .alignToBaseDirectory(model, Paths.get(getBasedir()), null); + } + } + goal = parameterInjectMojo.goal(); + } else { + InjectMojo methodInjectMojo = AnnotationSupport.findAnnotation( + parameterContext.getDeclaringExecutable(), InjectMojo.class) + .orElse(null); + if (methodInjectMojo != null) { + goal = methodInjectMojo.goal(); + } else { + goal = getGoalFromMojoImplementationClass( + parameterContext.getParameter().getType()); + } + } + + Set<MojoParameter> mojoParameters = new LinkedHashSet<>(); + for (AnnotatedElement ae : + Arrays.asList(parameterContext.getDeclaringExecutable(), parameterContext.getAnnotatedElement())) { + mojoParameters.addAll(AnnotationSupport.findRepeatableAnnotations(ae, MojoParameter.class)); + } + String[] coord = mojoCoordinates(goal); + + XmlNode pluginConfiguration = model.getBuild().getPlugins().stream() + .filter(p -> + Objects.equals(p.getGroupId(), coord[0]) && Objects.equals(p.getArtifactId(), coord[1])) + .map(ConfigurationContainer::getConfiguration) + .findFirst() + .orElseGet(() -> new XmlNodeImpl("config")); + List<XmlNode> children = mojoParameters.stream() + .map(mp -> new XmlNodeImpl(mp.name(), mp.value())) + .collect(Collectors.toList()); + XmlNode config = new XmlNodeImpl("configuration", null, null, children, null); + pluginConfiguration = XmlNode.merge(config, pluginConfiguration); + + // load default config + // 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.getGoal(), coord[3])) { + if (pluginConfiguration != null) { + pluginConfiguration = finalizeConfig(pluginConfiguration, mojoDescriptor); + } + } + } + + Session session = getInjector().getInstance(Session.class); + Project project = getInjector().getInstance(Project.class); + MojoExecution mojoExecution = getInjector().getInstance(MojoExecution.class); + ExpressionEvaluator evaluator = new WrapEvaluator( + getInjector(), new PluginParameterExpressionEvaluatorV4(session, project, mojoExecution)); + + EnhancedComponentConfigurator configurator = new EnhancedComponentConfigurator(); + configurator.configureComponent( + mojo, new XmlPlexusConfiguration(pluginConfiguration), evaluator, null, null); + return mojo; } catch (Exception e) { - throw new ParameterResolutionException("Unable to resolve parameter", e); + throw new ParameterResolutionException("Unable to resolve mojo", e); } } + /** + * The @Mojo annotation is only retained in the class file, not at runtime, + * so we need to actually read the class file with ASM to find the annotation and + * the goal. + */ + private static String getGoalFromMojoImplementationClass(Class<?> cl) throws IOException { + return cl.getAnnotation(Named.class).value(); + } + @Override public void beforeEach(ExtensionContext context) throws Exception { - // TODO provide protected setters in PlexusExtension - 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 DefaultLog(LoggerFactory.getLogger("anonymous"))); - }); + if (pluginBasedir == null) { + pluginBasedir = MavenDIExtension.getBasedir(); + } + basedir = AnnotationSupport.findAnnotation(context.getElement().get(), Basedir.class) + .map(Basedir::value) + .orElse(pluginBasedir); + if (basedir != null) { + if (basedir.isEmpty()) { + basedir = pluginBasedir + "/target/tests/" + + context.getRequiredTestClass().getSimpleName() + "/" + + context.getRequiredTestMethod().getName(); + } else { + basedir = basedir.replace("${basedir}", pluginBasedir); + } + } - Map<Object, Object> map = getContainer().getContext().getContextData(); + setContext(context); + + /* + binder.install(ProviderMethodsModule.forObject(context.getRequiredTestInstance())); + binder.requestInjection(context.getRequiredTestInstance()); + binder.bind(Log.class).toInstance(new DefaultLog(LoggerFactory.getLogger("anonymous"))); + binder.bind(ExtensionContext.class).toInstance(context); + // Load maven 4 api Services interfaces and try to bind them to the (possible) mock instances + // returned by the (possibly) mock InternalSession + try { + for (ClassPath.ClassInfo clazz : + ClassPath.from(getClassLoader()).getAllClasses()) { + if ("org.apache.maven.api.services".equals(clazz.getPackageName())) { + Class<?> load = clazz.load(); + if (Service.class.isAssignableFrom(load)) { + Class<Service> svc = (Class) load; + binder.bind(svc).toProvider(() -> { + try { + return getContainer() + .lookup(InternalSession.class) + .getService(svc); + } catch (ComponentLookupException e) { + throw new RuntimeException("Unable to lookup service " + svc.getName()); + } + }); + } + } + } + } catch (Exception e) { + throw new RuntimeException("Unable to bind session services", e); + } + + */ + + Path basedirPath = Paths.get(getBasedir()); + + InjectMojo mojo = AnnotationSupport.findAnnotation(context.getElement().get(), InjectMojo.class) + .orElse(null); + Model defaultModel = Model.newBuilder() + .groupId("myGroupId") + .artifactId("myArtifactId") + .version("1.0-SNAPSHOT") + .packaging("jar") + .build(Build.newBuilder() + .directory(basedirPath.resolve("target").toString()) + .outputDirectory(basedirPath.resolve("target/classes").toString()) + .sourceDirectory(basedirPath.resolve("src/main/java").toString()) + .testSourceDirectory( + basedirPath.resolve("src/test/java").toString()) + .testOutputDirectory( + basedirPath.resolve("target/test-classes").toString()) + .build()) + .build(); + Path[] modelPath = new Path[] {null}; + Model tmodel = null; + if (mojo != null) { + String pom = mojo.pom(); + if (pom != null && !pom.isEmpty()) { + try (Reader r = openPomUrl(context.getRequiredTestClass(), pom, modelPath)) { + tmodel = new MavenStaxReader().read(r); + } + } else { + Path pomPath = basedirPath.resolve("pom.xml"); + if (Files.exists(pomPath)) { + try (Reader r = Files.newBufferedReader(pomPath)) { + tmodel = new MavenStaxReader().read(r); + modelPath[0] = pomPath; + } + } + } + } + Model model; + if (tmodel == null) { + model = defaultModel; + } else { + model = new MavenMerger().merge(tmodel, defaultModel, false, null); + } + tmodel = new DefaultModelPathTranslator(new DefaultPathTranslator()) + .alignToBaseDirectory(tmodel, Paths.get(getBasedir()), null); + context.getStore(ExtensionContext.Namespace.GLOBAL).put(Model.class, tmodel); + // mojo execution + // Map<Object, Object> map = getInjector().getContext().getContextData(); + PluginDescriptor pluginDescriptor; ClassLoader classLoader = context.getRequiredTestClass().getClassLoader(); - try (InputStream is = Objects.requireNonNull( + try (InputStream is = requireNonNull( classLoader.getResourceAsStream(getPluginDescriptorLocation()), "Unable to find plugin descriptor: " + getPluginDescriptorLocation()); - Reader reader = new BufferedReader(new XmlStreamReader(is)); - InterpolationFilterReader interpolationReader = new InterpolationFilterReader(reader, map, "${", "}")) { + Reader reader = new BufferedReader(new XmlStreamReader(is))) { + // new InterpolationFilterReader(reader, map, "${", "}"); + pluginDescriptor = new PluginDescriptorStaxReader().read(reader); + } + context.getStore(ExtensionContext.Namespace.GLOBAL).put(PluginDescriptor.class, pluginDescriptor); + // for (ComponentDescriptor<?> desc : pluginDescriptor.getComponents()) { + // getContainer().addComponentDescriptor(desc); + // } + + @SuppressWarnings({"unused", "MagicNumber"}) + class Foo { + + @Provides + @Singleton + @Priority(-10) + private InternalSession createSession() { + return SessionStub.getMockSession(getBasedir()); + } + + @Provides + @Singleton + @Priority(-10) + private Project createProject(InternalSession s) { + ProjectStub stub = new ProjectStub(); + if (!"pom".equals(model.getPackaging())) { + ArtifactStub artifact = new ArtifactStub( + model.getGroupId(), model.getArtifactId(), "", model.getVersion(), model.getPackaging()); + stub.setMainArtifact(artifact); + } + stub.setModel(model); + stub.setBasedir(Paths.get(MojoExtension.getBasedir())); + stub.setPomPath(modelPath[0]); + s.getService(ArtifactManager.class).setPath(stub.getPomArtifact(), modelPath[0]); + return stub; + } + + @Provides + @Singleton + @Priority(-10) + private MojoExecution createMojoExecution() { + MojoExecutionStub mes = new MojoExecutionStub("executionId", null); + if (mojo != null) { + String goal = mojo.goal(); + int idx = goal.lastIndexOf(':'); + if (idx >= 0) { + goal = goal.substring(idx + 1); + } + mes.setGoal(goal); + for (MojoDescriptor md : pluginDescriptor.getMojos()) { + if (goal.equals(md.getGoal())) { + mes.setDescriptor(md); + } + } + requireNonNull(mes.getDescriptor()); + } + PluginStub plugin = new PluginStub(); + plugin.setDescriptor(pluginDescriptor); + mes.setPlugin(plugin); + return mes; + } + + @Provides + @Singleton + @Priority(-10) + private Log createLog() { + return new DefaultLog(LoggerFactory.getLogger("anonymous")); + } - PluginDescriptor pluginDescriptor = new PluginDescriptorBuilder().build(interpolationReader); + @Provides + static RepositorySystemSupplier newRepositorySystemSupplier() { + return new RepositorySystemSupplier(); + } + + @Provides + static RepositorySystem newRepositorySystem(RepositorySystemSupplier repositorySystemSupplier) { + return repositorySystemSupplier.getRepositorySystem(); + } + + @Provides + @Priority(10) + static RepositoryFactory newRepositoryFactory(Session session) { + return session.getService(RepositoryFactory.class); + } + + @Provides + @Priority(10) + static VersionParser newVersionParser(Session session) { + return session.getService(VersionParser.class); + } + + @Provides + @Priority(10) + static LocalRepositoryManager newLocalRepositoryManager(Session session) { + return session.getService(LocalRepositoryManager.class); + } + + @Provides + @Priority(10) + static ArtifactInstaller newArtifactInstaller(Session session) { + return session.getService(ArtifactInstaller.class); + } + + @Provides + @Priority(10) + static ArtifactDeployer newArtifactDeployer(Session session) { + return session.getService(ArtifactDeployer.class); + } + + @Provides + @Priority(10) + static ArtifactManager newArtifactManager(Session session) { + return session.getService(ArtifactManager.class); + } - context.getStore(ExtensionContext.Namespace.GLOBAL).put(PluginDescriptor.class, pluginDescriptor); + @Provides + @Priority(10) + static ProjectManager newProjectManager(Session session) { + return session.getService(ProjectManager.class); + } - for (ComponentDescriptor<?> desc : pluginDescriptor.getComponents()) { - getContainer().addComponentDescriptor(desc); + @Provides + @Priority(10) + static ArtifactFactory newArtifactFactory(Session session) { + return session.getService(ArtifactFactory.class); + } + + @Provides + @Priority(10) + static ProjectBuilder newProjectBuilder(Session session) { + return session.getService(ProjectBuilder.class); + } + + @Provides + @Priority(10) + static ModelXmlFactory newModelXmlFactory(Session session) { + return session.getService(ModelXmlFactory.class); } } - } - protected String getPluginDescriptorLocation() { - return "META-INF/maven/plugin.xml"; + getInjector().bindInstance(Foo.class, new Foo()); + + getInjector().injectInstance(context.getRequiredTestInstance()); + + // SessionScope sessionScope = getInjector().getInstance(SessionScope.class); + // sessionScope.enter(); + // sessionScope.seed(Session.class, s); + // sessionScope.seed(InternalSession.class, s); + + // MojoExecutionScope mojoExecutionScope = getInjector().getInstance(MojoExecutionScope.class); + // mojoExecutionScope.enter(); + // mojoExecutionScope.seed(Project.class, p); + // mojoExecutionScope.seed(MojoExecution.class, me); } - private Mojo lookupMojo( - Class<?> holder, - InjectMojo injectMojo, - Collection<MojoParameter> mojoParameters, - PluginDescriptor descriptor) - throws Exception { - String goal = injectMojo.goal(); - String pom = injectMojo.pom(); - String[] coord = mojoCoordinates(goal); - Xpp3Dom pomDom; + private Reader openPomUrl(Class<?> holder, String pom, Path[] modelPath) throws IOException { if (pom.startsWith("file:")) { Path path = Paths.get(getBasedir()).resolve(pom.substring("file:".length())); - pomDom = Xpp3DomBuilder.build(ReaderFactory.newXmlReader(path.toFile())); + modelPath[0] = path; + return Files.newBufferedReader(path); } 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())); + return new XmlStreamReader(url.openStream()); } else if (pom.contains("<project>")) { - pomDom = Xpp3DomBuilder.build(new StringReader(pom)); + return new StringReader(pom); } else { Path path = Paths.get(getBasedir()).resolve(pom); - pomDom = Xpp3DomBuilder.build(ReaderFactory.newXmlReader(path.toFile())); - } - XmlNode pluginConfiguration = extractPluginConfiguration(coord[1], pomDom); - if (!mojoParameters.isEmpty()) { - List<XmlNode> children = mojoParameters.stream() - .map(mp -> new XmlNodeImpl(mp.name(), mp.value())) - .collect(Collectors.toList()); - XmlNode config = new XmlNodeImpl("configuration", null, null, children, null); - pluginConfiguration = XmlNode.merge(config, pluginConfiguration); + modelPath[0] = path; + return Files.newBufferedReader(path); } - Mojo mojo = lookupMojo(coord, pluginConfiguration, descriptor); - return mojo; + } + + protected String getPluginDescriptorLocation() { + return "META-INF/maven/plugin.xml"; } 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())); + Path pluginPom = Paths.get(getPluginBasedir(), "pom.xml"); + Xpp3Dom pluginPomDom = Xpp3DomBuilder.build(Files.newBufferedReader(pluginPom)); String artifactId = pluginPomDom.getChild("artifactId").getValue(); String groupId = resolveFromRootThenParent(pluginPomDom, "groupId"); String version = resolveFromRootThenParent(pluginPomDom, "version"); @@ -217,55 +508,11 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver } } - /** - * lookup the mojo while we have all the relevent information - */ - protected Mojo lookupMojo(String[] coord, XmlNode 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) { - Session session = getContainer().lookup(Session.class); - Project project; - try { - project = getContainer().lookup(Project.class); - } catch (ComponentLookupException e) { - project = null; - } - org.apache.maven.plugin.MojoExecution mojoExecution; - try { - MojoExecution me = getContainer().lookup(MojoExecution.class); - mojoExecution = new org.apache.maven.plugin.MojoExecution( - new org.apache.maven.model.Plugin(me.getPlugin()), me.getGoal(), me.getExecutionId()); - } catch (ComponentLookupException e) { - mojoExecution = null; - } - ExpressionEvaluator evaluator = new WrapEvaluator( - getContainer(), new PluginParameterExpressionEvaluatorV4(session, project, mojoExecution)); - ComponentConfigurator configurator = new EnhancedComponentConfigurator(); - configurator.configureComponent( - mojo, - new XmlPlexusConfiguration(new Xpp3Dom(pluginConfiguration)), - evaluator, - getContainer().getContainerRealm()); - } - - return mojo; - } - private XmlNode finalizeConfig(XmlNode config, MojoDescriptor mojoDescriptor) { List<XmlNode> children = new ArrayList<>(); if (mojoDescriptor != null && mojoDescriptor.getParameters() != null) { - XmlNode defaultConfiguration = - MojoDescriptorCreator.convert(mojoDescriptor).getDom(); + XmlNode defaultConfiguration; + defaultConfiguration = MojoDescriptorCreator.convert(mojoDescriptor); for (Parameter parameter : mojoDescriptor.getParameters()) { XmlNode parameterConfiguration = config.getChild(parameter.getName()); if (parameterConfiguration == null) { @@ -275,10 +522,10 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver parameterConfiguration = XmlNode.merge(parameterConfiguration, parameterDefaults, Boolean.TRUE); if (parameterConfiguration != null) { Map<String, String> attributes = new HashMap<>(parameterConfiguration.getAttributes()); - if (isEmpty(parameterConfiguration.getAttribute("implementation")) - && !isEmpty(parameter.getImplementation())) { - attributes.put("implementation", parameter.getImplementation()); - } + // if (isEmpty(parameterConfiguration.getAttribute("implementation")) + // && !isEmpty(parameter.getImplementation())) { + // attributes.put("implementation", parameter.getImplementation()); + // } parameterConfiguration = new XmlNodeImpl( parameter.getName(), parameterConfiguration.getValue(), @@ -380,18 +627,18 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver public static void setVariableValueToObject(Object object, String variable, Object value) throws IllegalAccessException { Field field = ReflectionUtils.getFieldByNameIncludingSuperclasses(variable, object.getClass()); - Objects.requireNonNull(field, "Field " + variable + " not found"); + requireNonNull(field, "Field " + variable + " not found"); field.setAccessible(true); field.set(object, value); } static class WrapEvaluator implements TypeAwareExpressionEvaluator { - private final PlexusContainer container; + private final Injector injector; private final TypeAwareExpressionEvaluator evaluator; - WrapEvaluator(PlexusContainer container, TypeAwareExpressionEvaluator evaluator) { - this.container = container; + WrapEvaluator(Injector injector, TypeAwareExpressionEvaluator evaluator) { + this.injector = injector; this.evaluator = evaluator; } @@ -407,8 +654,8 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver String expr = stripTokens(expression); if (expr != null) { try { - value = container.lookup(type, expr); - } catch (ComponentLookupException e) { + value = injector.getInstance(Key.of(type, expr)); + } catch (DIException e) { // nothing } } @@ -428,4 +675,35 @@ public class MojoExtension extends PlexusExtension implements ParameterResolver return evaluator.alignToBaseDirectory(path); } } + + /* + private Scope getScopeInstanceOrNull(final Injector injector, final Binding<?> binding) { + return binding.acceptScopingVisitor(new DefaultBindingScopingVisitor<Scope>() { + + @Override + public Scope visitScopeAnnotation(Class<? extends Annotation> scopeAnnotation) { + throw new RuntimeException(String.format( + "I don't know how to handle the scopeAnnotation: %s", scopeAnnotation.getCanonicalName())); + } + + @Override + public Scope visitNoScoping() { + if (binding instanceof LinkedKeyBinding) { + Binding<?> childBinding = injector.getBinding(((LinkedKeyBinding) binding).getLinkedKey()); + return getScopeInstanceOrNull(injector, childBinding); + } + return null; + } + + @Override + public Scope visitEagerSingleton() { + return Scopes.SINGLETON; + } + + public Scope visitScope(Scope scope) { + return scope; + } + }); + }*/ + } diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoParameter.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoParameter.java index 2a28f48..8c37804 100644 --- a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoParameter.java +++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoParameter.java @@ -18,6 +18,7 @@ */ package org.apache.maven.api.plugin.testing; +import java.lang.annotation.Inherited; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -27,6 +28,7 @@ import java.lang.annotation.RetentionPolicy; */ @Retention(RetentionPolicy.RUNTIME) @Repeatable(MojoParameters.class) +@Inherited public @interface MojoParameter { String name(); diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoParameters.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoParameters.java index 434abe1..373c926 100644 --- a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoParameters.java +++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/MojoParameters.java @@ -18,6 +18,7 @@ */ package org.apache.maven.api.plugin.testing; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -25,6 +26,7 @@ import java.lang.annotation.RetentionPolicy; * Mojo parameters container */ @Retention(RetentionPolicy.RUNTIME) +@Inherited public @interface MojoParameters { MojoParameter[] value(); } diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/ResolverExpressionEvaluatorStub.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/ResolverExpressionEvaluatorStub.java index 4461071..1ca785d 100644 --- a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/ResolverExpressionEvaluatorStub.java +++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/ResolverExpressionEvaluatorStub.java @@ -21,11 +21,9 @@ package org.apache.maven.api.plugin.testing; import java.io.File; import java.util.Map; -import org.codehaus.plexus.PlexusTestCase; 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.testing.PlexusExtension; import org.eclipse.aether.repository.LocalRepository; /** @@ -81,14 +79,14 @@ public class ResolverExpressionEvaluatorStub implements TypeAwareExpressionEvalu return expression.contains("$$") ? expression.replaceAll("\\$\\$", "\\$") : expression; } else { if ("basedir".equals(expression) || "project.basedir".equals(expression)) { - value = PlexusExtension.getBasedir(); + value = MojoExtension.getBasedir(); } else if (expression.startsWith("basedir") || expression.startsWith("project.basedir")) { int pathSeparator = expression.indexOf("/"); if (pathSeparator > 0) { - value = PlexusTestCase.getBasedir() + expression.substring(pathSeparator); + value = MojoExtension.getBasedir() + expression.substring(pathSeparator); } } else if ("localRepository".equals(expression)) { - File localRepo = new File(PlexusTestCase.getBasedir(), "target/local-repo"); + File localRepo = new File(MojoExtension.getBasedir(), "target/local-repo"); return new LocalRepository("file://" + localRepo.getAbsolutePath()); } if (value == null && properties != null && properties.containsKey(expression)) { @@ -109,12 +107,12 @@ public class ResolverExpressionEvaluatorStub implements TypeAwareExpressionEvalu /** {@inheritDoc} */ @Override public File alignToBaseDirectory(File file) { - if (file.getAbsolutePath().startsWith(PlexusExtension.getBasedir())) { + if (file.getAbsolutePath().startsWith(MojoExtension.getBasedir())) { return file; } else if (file.isAbsolute()) { return file; } else { - return new File(PlexusExtension.getBasedir(), file.getPath()); + return new File(MojoExtension.getBasedir(), file.getPath()); } } } diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/ArtifactStub.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/ArtifactStub.java index 59be14f..b9b6416 100644 --- a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/ArtifactStub.java +++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/ArtifactStub.java @@ -23,9 +23,11 @@ import java.util.Objects; import org.apache.maven.api.Artifact; import org.apache.maven.api.ArtifactCoordinate; import org.apache.maven.api.Version; -import org.apache.maven.api.VersionRange; +import org.apache.maven.api.VersionConstraint; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.internal.impl.DefaultVersionParser; +import org.apache.maven.repository.internal.DefaultModelVersionParser; +import org.eclipse.aether.util.version.GenericVersionScheme; /** * @@ -35,6 +37,7 @@ public class ArtifactStub implements Artifact { private String artifactId; private String classifier; private String version; + private String baseVersion; private String extension; public ArtifactStub() { @@ -86,13 +89,21 @@ public class ArtifactStub implements Artifact { @Nonnull @Override public Version getVersion() { - return new DefaultVersionParser().parseVersion(version); + return getParser().parseVersion(version); } public void setVersion(String version) { this.version = version; } + public Version getBaseVersion() { + return getParser().parseVersion(baseVersion != null ? baseVersion : version); + } + + public void setBaseVersion(String baseVersion) { + this.baseVersion = baseVersion; + } + @Nonnull @Override public String getExtension() { @@ -127,8 +138,8 @@ public class ArtifactStub implements Artifact { } @Override - public VersionRange getVersion() { - return new DefaultVersionParser().parseVersionRange(version); + public VersionConstraint getVersion() { + return getParser().parseVersionConstraint(version); } @Override @@ -169,4 +180,8 @@ public class ArtifactStub implements Artifact { public int hashCode() { return Objects.hash(groupId, artifactId, classifier, version, extension); } + + private static DefaultVersionParser getParser() { + return new DefaultVersionParser(new DefaultModelVersionParser(new GenericVersionScheme())); + } } diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/MojoExecutionStub.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/MojoExecutionStub.java index a2d2b5b..2619b75 100644 --- a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/MojoExecutionStub.java +++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/MojoExecutionStub.java @@ -21,24 +21,28 @@ package org.apache.maven.api.plugin.testing.stubs; import java.util.Optional; import org.apache.maven.api.MojoExecution; -import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.Plugin; +import org.apache.maven.api.model.PluginExecution; +import org.apache.maven.api.plugin.descriptor.MojoDescriptor; import org.apache.maven.api.xml.XmlNode; /** * Stub for {@link MojoExecution}. */ public class MojoExecutionStub implements MojoExecution { - private final String artifactId; - private final String executionId; - private final String goal; - private final XmlNode dom; + private String executionId; + private String goal; + private XmlNode dom; + private Plugin plugin = new PluginStub(); + private PluginExecution model; + private MojoDescriptor descriptor; + private String lifecyclePhase; - public MojoExecutionStub(String artifactId, String executionId, String goal) { - this(artifactId, executionId, goal, null); + public MojoExecutionStub(String executionId, String goal) { + this(executionId, goal, null); } - public MojoExecutionStub(String artifactId, String executionId, String goal, XmlNode dom) { - this.artifactId = artifactId; + public MojoExecutionStub(String executionId, String goal, XmlNode dom) { this.executionId = executionId; this.goal = goal; this.dom = dom; @@ -46,7 +50,22 @@ public class MojoExecutionStub implements MojoExecution { @Override public Plugin getPlugin() { - return Plugin.newBuilder().artifactId(artifactId).build(); + return plugin; + } + + @Override + public PluginExecution getModel() { + return model; + } + + @Override + public MojoDescriptor getDescriptor() { + return descriptor; + } + + @Override + public String getLifecyclePhase() { + return lifecyclePhase; } @Override @@ -63,4 +82,32 @@ public class MojoExecutionStub implements MojoExecution { public Optional<XmlNode> getConfiguration() { return Optional.ofNullable(dom); } + + public void setExecutionId(String executionId) { + this.executionId = executionId; + } + + public void setGoal(String goal) { + this.goal = goal; + } + + public void setDom(XmlNode dom) { + this.dom = dom; + } + + public void setPlugin(Plugin plugin) { + this.plugin = plugin; + } + + public void setModel(PluginExecution model) { + this.model = model; + } + + public void setDescriptor(MojoDescriptor descriptor) { + this.descriptor = descriptor; + } + + public void setLifecyclePhase(String lifecyclePhase) { + this.lifecyclePhase = lifecyclePhase; + } } diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/PluginStub.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/PluginStub.java new file mode 100644 index 0000000..b7b4cfc --- /dev/null +++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/PluginStub.java @@ -0,0 +1,102 @@ +/* + * 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.api.plugin.testing.stubs; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Dependency; +import org.apache.maven.api.Plugin; +import org.apache.maven.api.plugin.descriptor.PluginDescriptor; +import org.apache.maven.api.plugin.descriptor.lifecycle.Lifecycle; + +public class PluginStub implements Plugin { + + org.apache.maven.api.model.Plugin model; + PluginDescriptor descriptor; + List<Lifecycle> lifecycles = Collections.emptyList(); + ClassLoader classLoader; + Artifact artifact; + List<Dependency> dependencies = Collections.emptyList(); + Map<String, Dependency> dependenciesMap = Collections.emptyMap(); + + @Override + public org.apache.maven.api.model.Plugin getModel() { + return model; + } + + public void setModel(org.apache.maven.api.model.Plugin model) { + this.model = model; + } + + @Override + public PluginDescriptor getDescriptor() { + return descriptor; + } + + public void setDescriptor(PluginDescriptor descriptor) { + this.descriptor = descriptor; + } + + @Override + public List<Lifecycle> getLifecycles() { + return lifecycles; + } + + public void setLifecycles(List<Lifecycle> lifecycles) { + this.lifecycles = lifecycles; + } + + @Override + public ClassLoader getClassLoader() { + return classLoader; + } + + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + @Override + public Artifact getArtifact() { + return artifact; + } + + public void setArtifact(Artifact artifact) { + this.artifact = artifact; + } + + @Override + public List<Dependency> getDependencies() { + return dependencies; + } + + public void setDependencies(List<Dependency> dependencies) { + this.dependencies = dependencies; + } + + public Map<String, Dependency> getDependenciesMap() { + return dependenciesMap; + } + + public void setDependenciesMap(Map<String, Dependency> dependenciesMap) { + this.dependenciesMap = dependenciesMap; + } +} diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/ProjectStub.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/ProjectStub.java index b3624cf..450cd1a 100644 --- a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/ProjectStub.java +++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/ProjectStub.java @@ -18,18 +18,16 @@ */ package org.apache.maven.api.plugin.testing.stubs; -import java.io.File; import java.nio.file.Path; -import java.util.Collections; -import java.util.List; -import java.util.Optional; - -import org.apache.maven.api.Artifact; -import org.apache.maven.api.DependencyCoordinate; -import org.apache.maven.api.Project; -import org.apache.maven.api.RemoteRepository; +import java.util.*; + +import org.apache.maven.api.*; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.PluginContainer; +import org.apache.maven.internal.impl.DefaultVersionParser; +import org.apache.maven.repository.internal.DefaultModelVersionParser; +import org.eclipse.aether.util.version.GenericVersionScheme; /** * @author Olivier Lamy @@ -40,10 +38,11 @@ public class ProjectStub implements Project { private Model model = Model.newInstance(); private Path basedir; - private File pomPath; + private Path pomPath; private boolean topProject; - private Artifact artifact; private Path rootDirectory; + private Map<String, String> properties = new HashMap<>(); + private Artifact mainArtifact; public void setModel(Model model) { this.model = model; @@ -73,14 +72,59 @@ public class ProjectStub implements Project { @Nonnull @Override - public String getPackaging() { - return model.getPackaging(); + public Packaging getPackaging() { + return new Packaging() { + @Override + public String id() { + return model.getPackaging(); + } + + @Override + public Type type() { + return new Type() { + @Override + public String id() { + return model.getPackaging(); + } + + @Override + public Language getLanguage() { + return null; + } + + @Override + public String getExtension() { + return model.getPackaging(); + } + + @Override + public String getClassifier() { + return ""; + } + + @Override + public boolean isIncludesDependencies() { + return false; + } + + @Override + public Set<PathType> getPathTypes() { + return Set.of(); + } + }; + } + + @Override + public Map<String, PluginContainer> plugins() { + return Map.of(); + } + }; } - @Nonnull @Override - public Artifact getArtifact() { - return artifact; + public List<Artifact> getArtifacts() { + Artifact pomArtifact = new ArtifactStub(getGroupId(), getArtifactId(), "", getVersion(), "pom"); + return mainArtifact != null ? Arrays.asList(pomArtifact, mainArtifact) : Arrays.asList(pomArtifact); } @Nonnull @@ -91,8 +135,8 @@ public class ProjectStub implements Project { @Nonnull @Override - public Optional<Path> getPomPath() { - return Optional.ofNullable(pomPath).map(File::toPath); + public Path getPomPath() { + return pomPath; } @Nonnull @@ -108,34 +152,19 @@ public class ProjectStub implements Project { } @Override - public Optional<Path> getBasedir() { - return Optional.ofNullable(basedir); + public Path getBasedir() { + return basedir; } public void setBasedir(Path basedir) { this.basedir = basedir; } - @Override - public boolean isExecutionRoot() { - return isTopProject(); - } - @Override public Optional<Project> getParent() { return Optional.empty(); } - @Override - public List<RemoteRepository> getRemoteProjectRepositories() { - return Collections.emptyList(); - } - - @Override - public List<RemoteRepository> getRemotePluginRepositories() { - return Collections.emptyList(); - } - @Override public boolean isTopProject() { return topProject; @@ -171,11 +200,11 @@ public class ProjectStub implements Project { model = model.withPackaging(packaging); } - public void setArtifact(Artifact artifact) { - this.artifact = artifact; + public void setMainArtifact(Artifact mainArtifact) { + this.mainArtifact = mainArtifact; } - public void setPomPath(File pomPath) { + public void setPomPath(Path pomPath) { this.pomPath = pomPath; } @@ -190,4 +219,51 @@ public class ProjectStub implements Project { public void setRootDirectory(Path rootDirectory) { this.rootDirectory = rootDirectory; } + + public void addProperty(String key, String value) { + properties.put(key, value); + } + + class ProjectArtifact implements Artifact { + @Override + public String getGroupId() { + return ProjectStub.this.getGroupId(); + } + + @Override + public String getArtifactId() { + return ProjectStub.this.getArtifactId(); + } + + @Override + public Version getVersion() { + return new DefaultVersionParser(new DefaultModelVersionParser(new GenericVersionScheme())) + .parseVersion(ProjectStub.this.getVersion()); + } + + @Override + public Version getBaseVersion() { + return null; + } + + @Override + public String getClassifier() { + return ""; + } + + @Override + public String getExtension() { + return "pom"; + } + + @Override + public boolean isSnapshot() { + return false; + } + + @Override + public ArtifactCoordinate toCoordinate() { + return null; + } + } } diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/RepositorySystemSupplier.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/RepositorySystemSupplier.java new file mode 100644 index 0000000..0e709b3 --- /dev/null +++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/RepositorySystemSupplier.java @@ -0,0 +1,1069 @@ +/* + * 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.api.plugin.testing.stubs; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Supplier; + +import org.apache.maven.api.services.ModelBuilder; +import org.apache.maven.internal.impl.DefaultModelUrlNormalizer; +import org.apache.maven.internal.impl.DefaultModelVersionParser; +import org.apache.maven.internal.impl.DefaultModelXmlFactory; +import org.apache.maven.internal.impl.DefaultPluginConfigurationExpander; +import org.apache.maven.internal.impl.DefaultSuperPomProvider; +import org.apache.maven.internal.impl.DefaultUrlNormalizer; +import org.apache.maven.internal.impl.model.BuildModelTransformer; +import org.apache.maven.internal.impl.model.DefaultDependencyManagementImporter; +import org.apache.maven.internal.impl.model.DefaultDependencyManagementInjector; +import org.apache.maven.internal.impl.model.DefaultInheritanceAssembler; +import org.apache.maven.internal.impl.model.DefaultModelBuilder; +import org.apache.maven.internal.impl.model.DefaultModelInterpolator; +import org.apache.maven.internal.impl.model.DefaultModelNormalizer; +import org.apache.maven.internal.impl.model.DefaultModelPathTranslator; +import org.apache.maven.internal.impl.model.DefaultModelProcessor; +import org.apache.maven.internal.impl.model.DefaultModelValidator; +import org.apache.maven.internal.impl.model.DefaultModelVersionProcessor; +import org.apache.maven.internal.impl.model.DefaultPathTranslator; +import org.apache.maven.internal.impl.model.DefaultPluginManagementInjector; +import org.apache.maven.internal.impl.model.DefaultProfileInjector; +import org.apache.maven.internal.impl.model.DefaultProfileSelector; +import org.apache.maven.internal.impl.model.DefaultRootLocator; +import org.apache.maven.internal.impl.model.ProfileActivationFilePathInterpolator; +import org.apache.maven.internal.impl.resolver.DefaultArtifactDescriptorReader; +import org.apache.maven.internal.impl.resolver.DefaultVersionRangeResolver; +import org.apache.maven.internal.impl.resolver.DefaultVersionResolver; +import org.apache.maven.internal.impl.resolver.MavenArtifactRelocationSource; +import org.apache.maven.internal.impl.resolver.PluginsMetadataGeneratorFactory; +import org.apache.maven.internal.impl.resolver.SnapshotMetadataGeneratorFactory; +import org.apache.maven.internal.impl.resolver.VersionsMetadataGeneratorFactory; +import org.apache.maven.internal.impl.resolver.relocation.DistributionManagementArtifactRelocationSource; +import org.apache.maven.internal.impl.resolver.relocation.UserPropertiesArtifactRelocationSource; +import org.eclipse.aether.RepositoryListener; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory; +import org.eclipse.aether.impl.ArtifactDescriptorReader; +import org.eclipse.aether.impl.ArtifactResolver; +import org.eclipse.aether.impl.DependencyCollector; +import org.eclipse.aether.impl.Deployer; +import org.eclipse.aether.impl.Installer; +import org.eclipse.aether.impl.LocalRepositoryProvider; +import org.eclipse.aether.impl.MetadataGeneratorFactory; +import org.eclipse.aether.impl.MetadataResolver; +import org.eclipse.aether.impl.OfflineController; +import org.eclipse.aether.impl.RemoteRepositoryFilterManager; +import org.eclipse.aether.impl.RemoteRepositoryManager; +import org.eclipse.aether.impl.RepositoryConnectorProvider; +import org.eclipse.aether.impl.RepositoryEventDispatcher; +import org.eclipse.aether.impl.RepositorySystemLifecycle; +import org.eclipse.aether.impl.UpdateCheckManager; +import org.eclipse.aether.impl.UpdatePolicyAnalyzer; +import org.eclipse.aether.impl.VersionRangeResolver; +import org.eclipse.aether.impl.VersionResolver; +import org.eclipse.aether.internal.impl.*; +import org.eclipse.aether.internal.impl.checksum.DefaultChecksumAlgorithmFactorySelector; +import org.eclipse.aether.internal.impl.checksum.Md5ChecksumAlgorithmFactory; +import org.eclipse.aether.internal.impl.checksum.Sha1ChecksumAlgorithmFactory; +import org.eclipse.aether.internal.impl.checksum.Sha256ChecksumAlgorithmFactory; +import org.eclipse.aether.internal.impl.checksum.Sha512ChecksumAlgorithmFactory; +import org.eclipse.aether.internal.impl.checksum.SparseDirectoryTrustedChecksumsSource; +import org.eclipse.aether.internal.impl.checksum.SummaryFileTrustedChecksumsSource; +import org.eclipse.aether.internal.impl.checksum.TrustedToProvidedChecksumsSourceAdapter; +import org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector; +import org.eclipse.aether.internal.impl.collect.DependencyCollectorDelegate; +import org.eclipse.aether.internal.impl.collect.bf.BfDependencyCollector; +import org.eclipse.aether.internal.impl.collect.df.DfDependencyCollector; +import org.eclipse.aether.internal.impl.filter.DefaultRemoteRepositoryFilterManager; +import org.eclipse.aether.internal.impl.filter.GroupIdRemoteRepositoryFilterSource; +import org.eclipse.aether.internal.impl.filter.PrefixesRemoteRepositoryFilterSource; +import org.eclipse.aether.internal.impl.resolution.TrustedChecksumsArtifactResolverPostProcessor; +import org.eclipse.aether.internal.impl.synccontext.DefaultSyncContextFactory; +import org.eclipse.aether.internal.impl.synccontext.named.NameMapper; +import org.eclipse.aether.internal.impl.synccontext.named.NameMappers; +import org.eclipse.aether.internal.impl.synccontext.named.NamedLockFactoryAdapterFactory; +import org.eclipse.aether.internal.impl.synccontext.named.NamedLockFactoryAdapterFactoryImpl; +import org.eclipse.aether.internal.impl.transport.http.DefaultChecksumExtractor; +import org.eclipse.aether.internal.impl.transport.http.Nx2ChecksumExtractor; +import org.eclipse.aether.internal.impl.transport.http.XChecksumExtractor; +import org.eclipse.aether.named.NamedLockFactory; +import org.eclipse.aether.named.providers.FileLockNamedLockFactory; +import org.eclipse.aether.named.providers.LocalReadWriteLockNamedLockFactory; +import org.eclipse.aether.named.providers.LocalSemaphoreNamedLockFactory; +import org.eclipse.aether.named.providers.NoopNamedLockFactory; +import org.eclipse.aether.spi.artifact.ArtifactPredicateFactory; +import org.eclipse.aether.spi.artifact.decorator.ArtifactDecoratorFactory; +import org.eclipse.aether.spi.artifact.generator.ArtifactGeneratorFactory; +import org.eclipse.aether.spi.checksums.ProvidedChecksumsSource; +import org.eclipse.aether.spi.checksums.TrustedChecksumsSource; +import org.eclipse.aether.spi.connector.RepositoryConnectorFactory; +import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory; +import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactorySelector; +import org.eclipse.aether.spi.connector.checksum.ChecksumPolicyProvider; +import org.eclipse.aether.spi.connector.filter.RemoteRepositoryFilterSource; +import org.eclipse.aether.spi.connector.layout.RepositoryLayoutFactory; +import org.eclipse.aether.spi.connector.layout.RepositoryLayoutProvider; +import org.eclipse.aether.spi.connector.transport.TransporterFactory; +import org.eclipse.aether.spi.connector.transport.TransporterProvider; +import org.eclipse.aether.spi.connector.transport.http.ChecksumExtractor; +import org.eclipse.aether.spi.connector.transport.http.ChecksumExtractorStrategy; +import org.eclipse.aether.spi.io.ChecksumProcessor; +import org.eclipse.aether.spi.io.PathProcessor; +import org.eclipse.aether.spi.localrepo.LocalRepositoryManagerFactory; +import org.eclipse.aether.spi.resolution.ArtifactResolverPostProcessor; +import org.eclipse.aether.spi.synccontext.SyncContextFactory; +import org.eclipse.aether.transport.apache.ApacheTransporterFactory; +import org.eclipse.aether.transport.file.FileTransporterFactory; +import org.eclipse.aether.util.version.GenericVersionScheme; +import org.eclipse.aether.version.VersionScheme; + +/** + * A simple memorizing {@link Supplier} of {@link RepositorySystem} instance, that on first call + * supplies lazily constructed instance, and on each subsequent call same instance. Hence, this instance should be + * thrown away immediately once repository system was created and there is no need for more instances. If new + * repository system instance needed, new instance of this class must be created. For proper shut down of returned + * repository system instance(s) use {@link RepositorySystem#shutdown()} method on supplied instance(s). + * <p> + * Since Resolver 2.0 this class offers access to various components via public getters, and allows even partial object + * graph construction. + * <p> + * Extend this class {@code createXXX()} methods and override to customize, if needed. The contract of this class makes + * sure that these (potentially overridden) methods are invoked only once, and instance created by those methods are + * memorized and kept as long as supplier instance is kept open. + * <p> + * This class is not thread safe and must be used from one thread only, while the constructed {@link RepositorySystem} + * is thread safe. + * <p> + * Important: Given the instance of supplier memorizes the supplier {@link RepositorySystem} instance it supplies, + * their lifecycle is shared as well: once supplied repository system is shut-down, this instance becomes closed as + * well. Any subsequent {@code getXXX} method invocation attempt will fail with {@link IllegalStateException}. + */ +public class RepositorySystemSupplier implements Supplier<RepositorySystem> { + private final AtomicBoolean closed = new AtomicBoolean(false); + + public RepositorySystemSupplier() {} + + private void checkClosed() { + if (closed.get()) { + throw new IllegalStateException("Supplier is closed"); + } + } + + private PathProcessor pathProcessor; + + public final PathProcessor getPathProcessor() { + checkClosed(); + if (pathProcessor == null) { + pathProcessor = createPathProcessor(); + } + return pathProcessor; + } + + protected PathProcessor createPathProcessor() { + return new DefaultPathProcessor(); + } + + private ChecksumProcessor checksumProcessor; + + public final ChecksumProcessor getChecksumProcessor() { + checkClosed(); + if (checksumProcessor == null) { + checksumProcessor = createChecksumProcessor(); + } + return checksumProcessor; + } + + protected ChecksumProcessor createChecksumProcessor() { + return new DefaultChecksumProcessor(getPathProcessor()); + } + + private TrackingFileManager trackingFileManager; + + public final TrackingFileManager getTrackingFileManager() { + checkClosed(); + if (trackingFileManager == null) { + trackingFileManager = createTrackingFileManager(); + } + return trackingFileManager; + } + + protected TrackingFileManager createTrackingFileManager() { + return new DefaultTrackingFileManager(); + } + + private LocalPathComposer localPathComposer; + + public final LocalPathComposer getLocalPathComposer() { + checkClosed(); + if (localPathComposer == null) { + localPathComposer = createLocalPathComposer(); + } + return localPathComposer; + } + + protected LocalPathComposer createLocalPathComposer() { + return new DefaultLocalPathComposer(); + } + + private LocalPathPrefixComposerFactory localPathPrefixComposerFactory; + + public final LocalPathPrefixComposerFactory getLocalPathPrefixComposerFactory() { + checkClosed(); + if (localPathPrefixComposerFactory == null) { + localPathPrefixComposerFactory = createLocalPathPrefixComposerFactory(); + } + return localPathPrefixComposerFactory; + } + + protected LocalPathPrefixComposerFactory createLocalPathPrefixComposerFactory() { + return new DefaultLocalPathPrefixComposerFactory(); + } + + private RepositorySystemLifecycle repositorySystemLifecycle; + + public final RepositorySystemLifecycle getRepositorySystemLifecycle() { + checkClosed(); + if (repositorySystemLifecycle == null) { + repositorySystemLifecycle = createRepositorySystemLifecycle(); + repositorySystemLifecycle.addOnSystemEndedHandler(() -> closed.set(true)); + } + return repositorySystemLifecycle; + } + + protected RepositorySystemLifecycle createRepositorySystemLifecycle() { + return new DefaultRepositorySystemLifecycle(); + } + + private OfflineController offlineController; + + public final OfflineController getOfflineController() { + checkClosed(); + if (offlineController == null) { + offlineController = createOfflineController(); + } + return offlineController; + } + + protected OfflineController createOfflineController() { + return new DefaultOfflineController(); + } + + private UpdatePolicyAnalyzer updatePolicyAnalyzer; + + public final UpdatePolicyAnalyzer getUpdatePolicyAnalyzer() { + checkClosed(); + if (updatePolicyAnalyzer == null) { + updatePolicyAnalyzer = createUpdatePolicyAnalyzer(); + } + return updatePolicyAnalyzer; + } + + protected UpdatePolicyAnalyzer createUpdatePolicyAnalyzer() { + return new DefaultUpdatePolicyAnalyzer(); + } + + private ChecksumPolicyProvider checksumPolicyProvider; + + public final ChecksumPolicyProvider getChecksumPolicyProvider() { + checkClosed(); + if (checksumPolicyProvider == null) { + checksumPolicyProvider = createChecksumPolicyProvider(); + } + return checksumPolicyProvider; + } + + protected ChecksumPolicyProvider createChecksumPolicyProvider() { + return new DefaultChecksumPolicyProvider(); + } + + private UpdateCheckManager updateCheckManager; + + public final UpdateCheckManager getUpdateCheckManager() { + checkClosed(); + if (updateCheckManager == null) { + updateCheckManager = createUpdateCheckManager(); + } + return updateCheckManager; + } + + protected UpdateCheckManager createUpdateCheckManager() { + return new DefaultUpdateCheckManager(getTrackingFileManager(), getUpdatePolicyAnalyzer(), getPathProcessor()); + } + + private Map<String, NamedLockFactory> namedLockFactories; + + public final Map<String, NamedLockFactory> getNamedLockFactories() { + checkClosed(); + if (namedLockFactories == null) { + namedLockFactories = createNamedLockFactories(); + } + return namedLockFactories; + } + + protected Map<String, NamedLockFactory> createNamedLockFactories() { + HashMap<String, NamedLockFactory> result = new HashMap<>(); + result.put(NoopNamedLockFactory.NAME, new NoopNamedLockFactory()); + result.put(LocalReadWriteLockNamedLockFactory.NAME, new LocalReadWriteLockNamedLockFactory()); + result.put(LocalSemaphoreNamedLockFactory.NAME, new LocalSemaphoreNamedLockFactory()); + result.put(FileLockNamedLockFactory.NAME, new FileLockNamedLockFactory()); + return result; + } + + private Map<String, NameMapper> nameMappers; + + public final Map<String, NameMapper> getNameMappers() { + checkClosed(); + if (nameMappers == null) { + nameMappers = createNameMappers(); + } + return nameMappers; + } + + protected Map<String, NameMapper> createNameMappers() { + HashMap<String, NameMapper> result = new HashMap<>(); + result.put(NameMappers.STATIC_NAME, NameMappers.staticNameMapper()); + result.put(NameMappers.GAV_NAME, NameMappers.gavNameMapper()); + result.put(NameMappers.DISCRIMINATING_NAME, NameMappers.discriminatingNameMapper()); + result.put(NameMappers.FILE_GAV_NAME, NameMappers.fileGavNameMapper()); + result.put(NameMappers.FILE_HGAV_NAME, NameMappers.fileHashingGavNameMapper()); + return result; + } + + private NamedLockFactoryAdapterFactory namedLockFactoryAdapterFactory; + + public final NamedLockFactoryAdapterFactory getNamedLockFactoryAdapterFactory() { + checkClosed(); + if (namedLockFactoryAdapterFactory == null) { + namedLockFactoryAdapterFactory = createNamedLockFactoryAdapterFactory(); + } + return namedLockFactoryAdapterFactory; + } + + protected NamedLockFactoryAdapterFactory createNamedLockFactoryAdapterFactory() { + return new NamedLockFactoryAdapterFactoryImpl( + getNamedLockFactories(), getNameMappers(), getRepositorySystemLifecycle()); + } + + private SyncContextFactory syncContextFactory; + + public final SyncContextFactory getSyncContextFactory() { + checkClosed(); + if (syncContextFactory == null) { + syncContextFactory = createSyncContextFactory(); + } + return syncContextFactory; + } + + protected SyncContextFactory createSyncContextFactory() { + return new DefaultSyncContextFactory(getNamedLockFactoryAdapterFactory()); + } + + private Map<String, ChecksumAlgorithmFactory> checksumAlgorithmFactories; + + public final Map<String, ChecksumAlgorithmFactory> getChecksumAlgorithmFactories() { + checkClosed(); + if (checksumAlgorithmFactories == null) { + checksumAlgorithmFactories = createChecksumAlgorithmFactories(); + } + return checksumAlgorithmFactories; + } + + protected Map<String, ChecksumAlgorithmFactory> createChecksumAlgorithmFactories() { + HashMap<String, ChecksumAlgorithmFactory> result = new HashMap<>(); + result.put(Sha512ChecksumAlgorithmFactory.NAME, new Sha512ChecksumAlgorithmFactory()); + result.put(Sha256ChecksumAlgorithmFactory.NAME, new Sha256ChecksumAlgorithmFactory()); + result.put(Sha1ChecksumAlgorithmFactory.NAME, new Sha1ChecksumAlgorithmFactory()); + result.put(Md5ChecksumAlgorithmFactory.NAME, new Md5ChecksumAlgorithmFactory()); + return result; + } + + private ChecksumAlgorithmFactorySelector checksumAlgorithmFactorySelector; + + public final ChecksumAlgorithmFactorySelector getChecksumAlgorithmFactorySelector() { + checkClosed(); + if (checksumAlgorithmFactorySelector == null) { + checksumAlgorithmFactorySelector = createChecksumAlgorithmFactorySelector(); + } + return checksumAlgorithmFactorySelector; + } + + protected ChecksumAlgorithmFactorySelector createChecksumAlgorithmFactorySelector() { + return new DefaultChecksumAlgorithmFactorySelector(getChecksumAlgorithmFactories()); + } + + private ArtifactPredicateFactory artifactPredicateFactory; + + public final ArtifactPredicateFactory getArtifactPredicateFactory() { + checkClosed(); + if (artifactPredicateFactory == null) { + artifactPredicateFactory = createArtifactPredicateFactory(); + } + return artifactPredicateFactory; + } + + protected ArtifactPredicateFactory createArtifactPredicateFactory() { + return new DefaultArtifactPredicateFactory(getChecksumAlgorithmFactorySelector()); + } + + private Map<String, RepositoryLayoutFactory> repositoryLayoutFactories; + + public final Map<String, RepositoryLayoutFactory> getRepositoryLayoutFactories() { + checkClosed(); + if (repositoryLayoutFactories == null) { + repositoryLayoutFactories = createRepositoryLayoutFactories(); + } + return repositoryLayoutFactories; + } + + protected Map<String, RepositoryLayoutFactory> createRepositoryLayoutFactories() { + HashMap<String, RepositoryLayoutFactory> result = new HashMap<>(); + result.put( + Maven2RepositoryLayoutFactory.NAME, + new Maven2RepositoryLayoutFactory( + getChecksumAlgorithmFactorySelector(), getArtifactPredicateFactory())); + return result; + } + + private RepositoryLayoutProvider repositoryLayoutProvider; + + public final RepositoryLayoutProvider getRepositoryLayoutProvider() { + checkClosed(); + if (repositoryLayoutProvider == null) { + repositoryLayoutProvider = createRepositoryLayoutProvider(); + } + return repositoryLayoutProvider; + } + + protected RepositoryLayoutProvider createRepositoryLayoutProvider() { + return new DefaultRepositoryLayoutProvider(getRepositoryLayoutFactories()); + } + + private LocalRepositoryProvider localRepositoryProvider; + + public final LocalRepositoryProvider getLocalRepositoryProvider() { + checkClosed(); + if (localRepositoryProvider == null) { + localRepositoryProvider = createLocalRepositoryProvider(); + } + return localRepositoryProvider; + } + + protected LocalRepositoryProvider createLocalRepositoryProvider() { + LocalPathComposer localPathComposer = getLocalPathComposer(); + HashMap<String, LocalRepositoryManagerFactory> localRepositoryProviders = new HashMap<>(2); + localRepositoryProviders.put( + SimpleLocalRepositoryManagerFactory.NAME, new SimpleLocalRepositoryManagerFactory(localPathComposer)); + localRepositoryProviders.put( + EnhancedLocalRepositoryManagerFactory.NAME, + new EnhancedLocalRepositoryManagerFactory( + localPathComposer, getTrackingFileManager(), getLocalPathPrefixComposerFactory())); + return new DefaultLocalRepositoryProvider(localRepositoryProviders); + } + + private RemoteRepositoryManager remoteRepositoryManager; + + public final RemoteRepositoryManager getRemoteRepositoryManager() { + checkClosed(); + if (remoteRepositoryManager == null) { + remoteRepositoryManager = createRemoteRepositoryManager(); + } + return remoteRepositoryManager; + } + + protected RemoteRepositoryManager createRemoteRepositoryManager() { + return new DefaultRemoteRepositoryManager(getUpdatePolicyAnalyzer(), getChecksumPolicyProvider()); + } + + private Map<String, RemoteRepositoryFilterSource> remoteRepositoryFilterSources; + + public final Map<String, RemoteRepositoryFilterSource> getRemoteRepositoryFilterSources() { + checkClosed(); + if (remoteRepositoryFilterSources == null) { + remoteRepositoryFilterSources = createRemoteRepositoryFilterSources(); + } + return remoteRepositoryFilterSources; + } + + protected Map<String, RemoteRepositoryFilterSource> createRemoteRepositoryFilterSources() { + HashMap<String, RemoteRepositoryFilterSource> result = new HashMap<>(); + result.put( + GroupIdRemoteRepositoryFilterSource.NAME, + new GroupIdRemoteRepositoryFilterSource(getRepositorySystemLifecycle())); + result.put( + PrefixesRemoteRepositoryFilterSource.NAME, + new PrefixesRemoteRepositoryFilterSource(getRepositoryLayoutProvider())); + return result; + } + + private RemoteRepositoryFilterManager remoteRepositoryFilterManager; + + public final RemoteRepositoryFilterManager getRemoteRepositoryFilterManager() { + checkClosed(); + if (remoteRepositoryFilterManager == null) { + remoteRepositoryFilterManager = createRemoteRepositoryFilterManager(); + } + return remoteRepositoryFilterManager; + } + + protected RemoteRepositoryFilterManager createRemoteRepositoryFilterManager() { + return new DefaultRemoteRepositoryFilterManager(getRemoteRepositoryFilterSources()); + } + + private Map<String, RepositoryListener> repositoryListeners; + + public final Map<String, RepositoryListener> getRepositoryListeners() { + checkClosed(); + if (repositoryListeners == null) { + repositoryListeners = createRepositoryListeners(); + } + return repositoryListeners; + } + + protected Map<String, RepositoryListener> createRepositoryListeners() { + return new HashMap<>(); + } + + private RepositoryEventDispatcher repositoryEventDispatcher; + + public final RepositoryEventDispatcher getRepositoryEventDispatcher() { + checkClosed(); + if (repositoryEventDispatcher == null) { + repositoryEventDispatcher = createRepositoryEventDispatcher(); + } + return repositoryEventDispatcher; + } + + protected RepositoryEventDispatcher createRepositoryEventDispatcher() { + return new DefaultRepositoryEventDispatcher(getRepositoryListeners()); + } + + private Map<String, TrustedChecksumsSource> trustedChecksumsSources; + + public final Map<String, TrustedChecksumsSource> getTrustedChecksumsSources() { + checkClosed(); + if (trustedChecksumsSources == null) { + trustedChecksumsSources = createTrustedChecksumsSources(); + } + return trustedChecksumsSources; + } + + protected Map<String, TrustedChecksumsSource> createTrustedChecksumsSources() { + HashMap<String, TrustedChecksumsSource> result = new HashMap<>(); + result.put( + SparseDirectoryTrustedChecksumsSource.NAME, + new SparseDirectoryTrustedChecksumsSource(getChecksumProcessor(), getLocalPathComposer())); + result.put( + SummaryFileTrustedChecksumsSource.NAME, + new SummaryFileTrustedChecksumsSource(getLocalPathComposer(), getRepositorySystemLifecycle())); + return result; + } + + private Map<String, ProvidedChecksumsSource> providedChecksumsSources; + + public final Map<String, ProvidedChecksumsSource> getProvidedChecksumsSources() { + checkClosed(); + if (providedChecksumsSources == null) { + providedChecksumsSources = createProvidedChecksumsSources(); + } + return providedChecksumsSources; + } + + protected Map<String, ProvidedChecksumsSource> createProvidedChecksumsSources() { + HashMap<String, ProvidedChecksumsSource> result = new HashMap<>(); + result.put( + TrustedToProvidedChecksumsSourceAdapter.NAME, + new TrustedToProvidedChecksumsSourceAdapter(getTrustedChecksumsSources())); + return result; + } + + private Map<String, ChecksumExtractorStrategy> checksumExtractorStrategies; + + public final Map<String, ChecksumExtractorStrategy> getChecksumExtractorStrategies() { + checkClosed(); + if (checksumExtractorStrategies == null) { + checksumExtractorStrategies = createChecksumExtractorStrategies(); + } + return checksumExtractorStrategies; + } + + protected Map<String, ChecksumExtractorStrategy> createChecksumExtractorStrategies() { + HashMap<String, ChecksumExtractorStrategy> result = new HashMap<>(); + result.put(XChecksumExtractor.NAME, new XChecksumExtractor()); + result.put(Nx2ChecksumExtractor.NAME, new Nx2ChecksumExtractor()); + return result; + } + + private ChecksumExtractor checksumExtractor; + + public final ChecksumExtractor getChecksumExtractor() { + checkClosed(); + if (checksumExtractor == null) { + checksumExtractor = createChecksumExtractor(); + } + return checksumExtractor; + } + + protected ChecksumExtractor createChecksumExtractor() { + return new DefaultChecksumExtractor(getChecksumExtractorStrategies()); + } + + private Map<String, TransporterFactory> transporterFactories; + + public final Map<String, TransporterFactory> getTransporterFactories() { + checkClosed(); + if (transporterFactories == null) { + transporterFactories = createTransporterFactories(); + } + return transporterFactories; + } + + protected Map<String, TransporterFactory> createTransporterFactories() { + HashMap<String, TransporterFactory> result = new HashMap<>(); + result.put(FileTransporterFactory.NAME, new FileTransporterFactory()); + result.put( + ApacheTransporterFactory.NAME, + new ApacheTransporterFactory(getChecksumExtractor(), getPathProcessor())); + return result; + } + + private TransporterProvider transporterProvider; + + public final TransporterProvider getTransporterProvider() { + checkClosed(); + if (transporterProvider == null) { + transporterProvider = createTransporterProvider(); + } + return transporterProvider; + } + + protected TransporterProvider createTransporterProvider() { + return new DefaultTransporterProvider(getTransporterFactories()); + } + + private BasicRepositoryConnectorFactory basicRepositoryConnectorFactory; + + public final BasicRepositoryConnectorFactory getBasicRepositoryConnectorFactory() { + checkClosed(); + if (basicRepositoryConnectorFactory == null) { + basicRepositoryConnectorFactory = createBasicRepositoryConnectorFactory(); + } + return basicRepositoryConnectorFactory; + } + + protected BasicRepositoryConnectorFactory createBasicRepositoryConnectorFactory() { + return new BasicRepositoryConnectorFactory( + getTransporterProvider(), + getRepositoryLayoutProvider(), + getChecksumPolicyProvider(), + getChecksumProcessor(), + getProvidedChecksumsSources()); + } + + private Map<String, RepositoryConnectorFactory> repositoryConnectorFactories; + + public final Map<String, RepositoryConnectorFactory> getRepositoryConnectorFactories() { + checkClosed(); + if (repositoryConnectorFactories == null) { + repositoryConnectorFactories = createRepositoryConnectorFactories(); + } + return repositoryConnectorFactories; + } + + protected Map<String, RepositoryConnectorFactory> createRepositoryConnectorFactories() { + HashMap<String, RepositoryConnectorFactory> result = new HashMap<>(); + result.put(BasicRepositoryConnectorFactory.NAME, getBasicRepositoryConnectorFactory()); + return result; + } + + private RepositoryConnectorProvider repositoryConnectorProvider; + + public final RepositoryConnectorProvider getRepositoryConnectorProvider() { + checkClosed(); + if (repositoryConnectorProvider == null) { + repositoryConnectorProvider = createRepositoryConnectorProvider(); + } + return repositoryConnectorProvider; + } + + protected RepositoryConnectorProvider createRepositoryConnectorProvider() { + return new DefaultRepositoryConnectorProvider( + getRepositoryConnectorFactories(), getRemoteRepositoryFilterManager()); + } + + private Installer installer; + + public final Installer getInstaller() { + checkClosed(); + if (installer == null) { + installer = createInstaller(); + } + return installer; + } + + protected Installer createInstaller() { + return new DefaultInstaller( + getPathProcessor(), + getRepositoryEventDispatcher(), + getArtifactGeneratorFactories(), + getMetadataGeneratorFactories(), + getSyncContextFactory()); + } + + private Deployer deployer; + + public final Deployer getDeployer() { + checkClosed(); + if (deployer == null) { + deployer = createDeployer(); + } + return deployer; + } + + protected Deployer createDeployer() { + return new DefaultDeployer( + getPathProcessor(), + getRepositoryEventDispatcher(), + getRepositoryConnectorProvider(), + getRemoteRepositoryManager(), + getUpdateCheckManager(), + getArtifactGeneratorFactories(), + getMetadataGeneratorFactories(), + getSyncContextFactory(), + getOfflineController()); + } + + private Map<String, DependencyCollectorDelegate> dependencyCollectorDelegates; + + public final Map<String, DependencyCollectorDelegate> getDependencyCollectorDelegates() { + checkClosed(); + if (dependencyCollectorDelegates == null) { + dependencyCollectorDelegates = createDependencyCollectorDelegates(); + } + return dependencyCollectorDelegates; + } + + protected Map<String, DependencyCollectorDelegate> createDependencyCollectorDelegates() { + RemoteRepositoryManager remoteRepositoryManager = getRemoteRepositoryManager(); + ArtifactDescriptorReader artifactDescriptorReader = getArtifactDescriptorReader(); + VersionRangeResolver versionRangeResolver = getVersionRangeResolver(); + HashMap<String, DependencyCollectorDelegate> result = new HashMap<>(); + result.put( + DfDependencyCollector.NAME, + new DfDependencyCollector( + remoteRepositoryManager, + artifactDescriptorReader, + versionRangeResolver, + getArtifactDecoratorFactories())); + result.put( + BfDependencyCollector.NAME, + new BfDependencyCollector( + remoteRepositoryManager, + artifactDescriptorReader, + versionRangeResolver, + getArtifactDecoratorFactories())); + return result; + } + + private DependencyCollector dependencyCollector; + + public final DependencyCollector getDependencyCollector() { + checkClosed(); + if (dependencyCollector == null) { + dependencyCollector = createDependencyCollector(); + } + return dependencyCollector; + } + + protected DependencyCollector createDependencyCollector() { + return new DefaultDependencyCollector(getDependencyCollectorDelegates()); + } + + private Map<String, ArtifactResolverPostProcessor> artifactResolverPostProcessors; + + public final Map<String, ArtifactResolverPostProcessor> getArtifactResolverPostProcessors() { + checkClosed(); + if (artifactResolverPostProcessors == null) { + artifactResolverPostProcessors = createArtifactResolverPostProcessors(); + } + return artifactResolverPostProcessors; + } + + protected Map<String, ArtifactResolverPostProcessor> createArtifactResolverPostProcessors() { + HashMap<String, ArtifactResolverPostProcessor> result = new HashMap<>(); + result.put( + TrustedChecksumsArtifactResolverPostProcessor.NAME, + new TrustedChecksumsArtifactResolverPostProcessor( + getChecksumAlgorithmFactorySelector(), getTrustedChecksumsSources())); + return result; + } + + private ArtifactResolver artifactResolver; + + public final ArtifactResolver getArtifactResolver() { + checkClosed(); + if (artifactResolver == null) { + artifactResolver = createArtifactResolver(); + } + return artifactResolver; + } + + protected ArtifactResolver createArtifactResolver() { + return new DefaultArtifactResolver( + getPathProcessor(), + getRepositoryEventDispatcher(), + getVersionResolver(), + getUpdateCheckManager(), + getRepositoryConnectorProvider(), + getRemoteRepositoryManager(), + getSyncContextFactory(), + getOfflineController(), + getArtifactResolverPostProcessors(), + getRemoteRepositoryFilterManager()); + } + + private MetadataResolver metadataResolver; + + public final MetadataResolver getMetadataResolver() { + checkClosed(); + if (metadataResolver == null) { + metadataResolver = createMetadataResolver(); + } + return metadataResolver; + } + + protected MetadataResolver createMetadataResolver() { + return new DefaultMetadataResolver( + getRepositoryEventDispatcher(), + getUpdateCheckManager(), + getRepositoryConnectorProvider(), + getRemoteRepositoryManager(), + getSyncContextFactory(), + getOfflineController(), + getRemoteRepositoryFilterManager(), + getPathProcessor()); + } + + private VersionScheme versionScheme; + + public final VersionScheme getVersionScheme() { + checkClosed(); + if (versionScheme == null) { + versionScheme = createVersionScheme(); + } + return versionScheme; + } + + protected VersionScheme createVersionScheme() { + return new GenericVersionScheme(); + } + + private Map<String, ArtifactGeneratorFactory> artifactGeneratorFactories; + + public final Map<String, ArtifactGeneratorFactory> getArtifactGeneratorFactories() { + checkClosed(); + if (artifactGeneratorFactories == null) { + artifactGeneratorFactories = createArtifactGeneratorFactories(); + } + return artifactGeneratorFactories; + } + + protected Map<String, ArtifactGeneratorFactory> createArtifactGeneratorFactories() { + // by default none, this is extension point + return new HashMap<>(); + } + + private Map<String, ArtifactDecoratorFactory> artifactDecoratorFactories; + + public final Map<String, ArtifactDecoratorFactory> getArtifactDecoratorFactories() { + checkClosed(); + if (artifactDecoratorFactories == null) { + artifactDecoratorFactories = createArtifactDecoratorFactories(); + } + return artifactDecoratorFactories; + } + + protected Map<String, ArtifactDecoratorFactory> createArtifactDecoratorFactories() { + // by default none, this is extension point + return new HashMap<>(); + } + + // Maven provided + + private Map<String, MetadataGeneratorFactory> metadataGeneratorFactories; + + public final Map<String, MetadataGeneratorFactory> getMetadataGeneratorFactories() { + checkClosed(); + if (metadataGeneratorFactories == null) { + metadataGeneratorFactories = createMetadataGeneratorFactories(); + } + return metadataGeneratorFactories; + } + + protected Map<String, MetadataGeneratorFactory> createMetadataGeneratorFactories() { + // from maven-resolver-provider + HashMap<String, MetadataGeneratorFactory> result = new HashMap<>(); + result.put(PluginsMetadataGeneratorFactory.NAME, new PluginsMetadataGeneratorFactory()); + result.put(VersionsMetadataGeneratorFactory.NAME, new VersionsMetadataGeneratorFactory()); + result.put(SnapshotMetadataGeneratorFactory.NAME, new SnapshotMetadataGeneratorFactory()); + return result; + } + + private LinkedHashMap<String, MavenArtifactRelocationSource> artifactRelocationSources; + + public final LinkedHashMap<String, MavenArtifactRelocationSource> getMavenArtifactRelocationSources() { + checkClosed(); + if (artifactRelocationSources == null) { + artifactRelocationSources = createMavenArtifactRelocationSources(); + } + return artifactRelocationSources; + } + + protected LinkedHashMap<String, MavenArtifactRelocationSource> createMavenArtifactRelocationSources() { + // from maven-resolver-provider + LinkedHashMap<String, MavenArtifactRelocationSource> result = new LinkedHashMap<>(); + result.put(UserPropertiesArtifactRelocationSource.NAME, new UserPropertiesArtifactRelocationSource()); + result.put( + DistributionManagementArtifactRelocationSource.NAME, + new DistributionManagementArtifactRelocationSource()); + return result; + } + + private ArtifactDescriptorReader artifactDescriptorReader; + + public final ArtifactDescriptorReader getArtifactDescriptorReader() { + checkClosed(); + if (artifactDescriptorReader == null) { + artifactDescriptorReader = createArtifactDescriptorReader(); + } + return artifactDescriptorReader; + } + + protected ArtifactDescriptorReader createArtifactDescriptorReader() { + // from maven-resolver-provider + return new DefaultArtifactDescriptorReader( + getRemoteRepositoryManager(), + getVersionResolver(), + getVersionRangeResolver(), + getArtifactResolver(), + getModelBuilder(), + getRepositoryEventDispatcher(), + getMavenArtifactRelocationSources()); + } + + private VersionResolver versionResolver; + + public final VersionResolver getVersionResolver() { + checkClosed(); + if (versionResolver == null) { + versionResolver = createVersionResolver(); + } + return versionResolver; + } + + protected VersionResolver createVersionResolver() { + // from maven-resolver-provider + return new DefaultVersionResolver( + getMetadataResolver(), getSyncContextFactory(), getRepositoryEventDispatcher()); + } + + private VersionRangeResolver versionRangeResolver; + + public final VersionRangeResolver getVersionRangeResolver() { + checkClosed(); + if (versionRangeResolver == null) { + versionRangeResolver = createVersionRangeResolver(); + } + return versionRangeResolver; + } + + protected VersionRangeResolver createVersionRangeResolver() { + // from maven-resolver-provider + return new DefaultVersionRangeResolver( + getMetadataResolver(), getSyncContextFactory(), getRepositoryEventDispatcher(), getVersionScheme()); + } + + private ModelBuilder modelBuilder; + + public final ModelBuilder getModelBuilder() { + checkClosed(); + if (modelBuilder == null) { + modelBuilder = createModelBuilder(); + } + return modelBuilder; + } + + protected ModelBuilder createModelBuilder() { + // from maven-model-builder + DefaultModelProcessor modelProcessor = new DefaultModelProcessor(new DefaultModelXmlFactory(), List.of()); + return new DefaultModelBuilder( + modelProcessor, + new DefaultModelValidator(new DefaultModelVersionProcessor()), + new DefaultModelNormalizer(), + new DefaultModelInterpolator( + new DefaultPathTranslator(), new DefaultUrlNormalizer(), new DefaultRootLocator()), + new DefaultModelPathTranslator(new DefaultPathTranslator()), + new DefaultModelUrlNormalizer(new DefaultUrlNormalizer()), + new DefaultSuperPomProvider(modelProcessor), + new DefaultInheritanceAssembler(), + new DefaultProfileSelector(), + new DefaultProfileInjector(), + new DefaultPluginManagementInjector(), + new DefaultDependencyManagementInjector(), + new DefaultDependencyManagementImporter(), + (m, r, b) -> m, + new DefaultPluginConfigurationExpander(), + new ProfileActivationFilePathInterpolator(new DefaultPathTranslator(), new DefaultRootLocator()), + new BuildModelTransformer(), + new DefaultModelVersionParser(getVersionScheme())); + } + + private RepositorySystem repositorySystem; + + public final RepositorySystem getRepositorySystem() { + checkClosed(); + if (repositorySystem == null) { + repositorySystem = createRepositorySystem(); + } + return repositorySystem; + } + + protected RepositorySystem createRepositorySystem() { + return new DefaultRepositorySystem( + getVersionResolver(), + getVersionRangeResolver(), + getArtifactResolver(), + getMetadataResolver(), + getArtifactDescriptorReader(), + getDependencyCollector(), + getInstaller(), + getDeployer(), + getLocalRepositoryProvider(), + getSyncContextFactory(), + getRemoteRepositoryManager(), + getRepositorySystemLifecycle(), + getArtifactDecoratorFactories()); + } + + @Override + public RepositorySystem get() { + return getRepositorySystem(); + } +} diff --git a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/SessionStub.java b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/SessionStub.java index 2b05567..799587a 100644 --- a/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/SessionStub.java +++ b/maven-plugin-testing-harness/src/main/java/org/apache/maven/api/plugin/testing/stubs/SessionStub.java @@ -22,17 +22,22 @@ import java.net.URI; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; import org.apache.maven.api.Artifact; import org.apache.maven.api.LocalRepository; import org.apache.maven.api.Project; import org.apache.maven.api.RemoteRepository; import org.apache.maven.api.Session; +import org.apache.maven.api.SessionData; import org.apache.maven.api.model.Model; import org.apache.maven.api.model.Repository; import org.apache.maven.api.services.ArtifactDeployer; @@ -48,9 +53,14 @@ import org.apache.maven.api.services.ProjectBuilderRequest; import org.apache.maven.api.services.ProjectBuilderResult; import org.apache.maven.api.services.ProjectManager; import org.apache.maven.api.services.RepositoryFactory; +import org.apache.maven.api.services.VersionParser; import org.apache.maven.api.services.xml.ModelXmlFactory; import org.apache.maven.internal.impl.DefaultModelXmlFactory; +import org.apache.maven.internal.impl.DefaultVersionParser; +import org.apache.maven.internal.impl.InternalSession; import org.apache.maven.model.v4.MavenStaxReader; +import org.apache.maven.repository.internal.DefaultModelVersionParser; +import org.eclipse.aether.util.version.GenericVersionScheme; import org.mockito.ArgumentMatchers; import static org.mockito.ArgumentMatchers.any; @@ -67,17 +77,27 @@ import static org.mockito.Mockito.withSettings; */ public class SessionStub { - public static Session getMockSession(String localRepo) { + public static InternalSession getMockSession(String localRepo) { LocalRepository localRepository = mock(LocalRepository.class); when(localRepository.getId()).thenReturn("local"); when(localRepository.getPath()).thenReturn(Paths.get(localRepo)); return getMockSession(localRepository); } - public static Session getMockSession(LocalRepository localRepository) { - Session session = mock(Session.class); + public static InternalSession getMockSession(LocalRepository localRepository) { + InternalSession session = mock(InternalSession.class); + // + // RepositoryFactory + // RepositoryFactory repositoryFactory = mock(RepositoryFactory.class); + when(session.createRemoteRepository(anyString(), anyString())).thenAnswer(iom -> { + String id = iom.getArgument(0, String.class); + String url = iom.getArgument(1, String.class); + return session.getService(RepositoryFactory.class).createRemote(id, url); + }); + when(session.createRemoteRepository(any())) + .thenAnswer(iom -> repositoryFactory.createRemote(iom.getArgument(0, Repository.class))); when(repositoryFactory.createRemote(any(Repository.class))).thenAnswer(iom -> { Repository repository = iom.getArgument(0, Repository.class); return repositoryFactory.createRemote(repository.getId(), repository.getUrl()); @@ -92,16 +112,56 @@ public class SessionStub { when(remoteRepository.getProtocol()).thenReturn(URI.create(url).getScheme()); return remoteRepository; }); + when(session.getService(RepositoryFactory.class)).thenReturn(repositoryFactory); + + // + // VersionParser + // + VersionParser versionParser = + new DefaultVersionParser(new DefaultModelVersionParser(new GenericVersionScheme())); + when(session.parseVersion(any())) + .thenAnswer(iom -> versionParser.parseVersion(iom.getArgument(0, String.class))); + when(session.getService(VersionParser.class)).thenReturn(versionParser); + // + // LocalRepositoryManager + // LocalRepositoryManager localRepositoryManager = mock(LocalRepositoryManager.class); + when(session.getPathForLocalArtifact(any(Artifact.class))) + .then(iom -> localRepositoryManager.getPathForLocalArtifact( + session, session.getLocalRepository(), iom.getArgument(0, Artifact.class))); + when(session.getPathForRemoteArtifact(any(), any())) + .thenAnswer(iom -> localRepositoryManager.getPathForRemoteArtifact( + session, + session.getLocalRepository(), + iom.getArgument(0, RemoteRepository.class), + iom.getArgument(1, Artifact.class))); when(localRepositoryManager.getPathForLocalArtifact(any(), any(), any())) .thenAnswer(iom -> { LocalRepository localRepo = iom.getArgument(1, LocalRepository.class); Artifact artifact = iom.getArgument(2, Artifact.class); return localRepo.getPath().resolve(getPathForArtifact(artifact, true)); }); + when(session.getService(LocalRepositoryManager.class)).thenReturn(localRepositoryManager); + // + // ArtifactInstaller + // ArtifactInstaller artifactInstaller = mock(ArtifactInstaller.class); + doAnswer(iom -> { + artifactInstaller.install( + ArtifactInstallerRequest.build(session, iom.getArgument(0, Collection.class))); + return null; + }) + .when(session) + .installArtifacts(any(Collection.class)); + doAnswer(iom -> { + artifactInstaller.install(ArtifactInstallerRequest.build( + session, Arrays.asList(iom.getArgument(0, Artifact[].class)))); + return null; + }) + .when(session) + .installArtifacts(any(Artifact[].class)); doAnswer(iom -> { artifactInstaller.install(ArtifactInstallerRequest.build( iom.getArgument(0, Session.class), iom.getArgument(1, Collection.class))); @@ -109,8 +169,21 @@ public class SessionStub { }) .when(artifactInstaller) .install(any(Session.class), ArgumentMatchers.<Collection<Artifact>>any()); + when(session.getService(ArtifactInstaller.class)).thenReturn(artifactInstaller); + // + // ArtifactDeployer + // ArtifactDeployer artifactDeployer = mock(ArtifactDeployer.class); + doAnswer(iom -> { + artifactDeployer.deploy(ArtifactDeployerRequest.build( + iom.getArgument(0, Session.class), + iom.getArgument(1, RemoteRepository.class), + Arrays.asList(iom.getArgument(2, Artifact[].class)))); + return null; + }) + .when(session) + .deployArtifact(any(), any()); doAnswer(iom -> { artifactDeployer.deploy(ArtifactDeployerRequest.build( iom.getArgument(0, Session.class), @@ -120,7 +193,11 @@ public class SessionStub { }) .when(artifactDeployer) .deploy(any(), any(), any()); + when(session.getService(ArtifactDeployer.class)).thenReturn(artifactDeployer); + // + // ArtifactManager + // ArtifactManager artifactManager = mock(ArtifactManager.class); Map<Artifact, Path> paths = new HashMap<>(); doAnswer(iom -> { @@ -132,7 +209,14 @@ public class SessionStub { doAnswer(iom -> Optional.ofNullable(paths.get(iom.getArgument(0, Artifact.class)))) .when(artifactManager) .getPath(any()); + doAnswer(iom -> artifactManager.getPath(iom.getArgument(0, Artifact.class))) + .when(session) + .getArtifactPath(any()); + when(session.getService(ArtifactManager.class)).thenReturn(artifactManager); + // + // ProjectManager + // ProjectManager projectManager = mock(ProjectManager.class); Map<Project, Collection<Artifact>> attachedArtifacts = new HashMap<>(); doAnswer(iom -> { @@ -164,7 +248,18 @@ public class SessionStub { when(projectManager.getAttachedArtifacts(any())) .then(iom -> attachedArtifacts.computeIfAbsent(iom.getArgument(0, Project.class), p -> new ArrayList<>())); + when(projectManager.getAllArtifacts(any())).then(iom -> { + Project project = iom.getArgument(0, Project.class); + List<Artifact> result = new ArrayList<>(); + result.addAll(project.getArtifacts()); + result.addAll(attachedArtifacts.computeIfAbsent(project, p -> new ArrayList<>())); + return result; + }); + when(session.getService(ProjectManager.class)).thenReturn(projectManager); + // + // ArtifactFactory + // ArtifactFactory artifactFactory = mock(ArtifactFactory.class); when(artifactFactory.create(any())).then(iom -> { ArtifactFactoryRequest request = iom.getArgument(0, ArtifactFactoryRequest.class); @@ -180,40 +275,6 @@ public class SessionStub { return new ArtifactStub( request.getGroupId(), request.getArtifactId(), classifier, request.getVersion(), extension); }); - - ProjectBuilder projectBuilder = mock(ProjectBuilder.class); - when(projectBuilder.build(any(ProjectBuilderRequest.class))).then(iom -> { - ProjectBuilderRequest request = iom.getArgument(0, ProjectBuilderRequest.class); - ProjectBuilderResult result = mock(ProjectBuilderResult.class); - Model model = new MavenStaxReader().read(request.getSource().get().openStream()); - ProjectStub projectStub = new ProjectStub(); - projectStub.setModel(model); - ArtifactStub artifactStub = new ArtifactStub( - model.getGroupId(), model.getArtifactId(), "", model.getVersion(), model.getPackaging()); - projectStub.setArtifact(artifactStub); - when(result.getProject()).thenReturn(Optional.of(projectStub)); - return result; - }); - - Properties sysProps = new Properties(); - Properties usrProps = new Properties(); - doReturn(sysProps).when(session).getSystemProperties(); - doReturn(usrProps).when(session).getUserProperties(); - - when(session.getLocalRepository()).thenReturn(localRepository); - when(session.getService(RepositoryFactory.class)).thenReturn(repositoryFactory); - when(session.getService(ProjectBuilder.class)).thenReturn(projectBuilder); - when(session.getService(LocalRepositoryManager.class)).thenReturn(localRepositoryManager); - when(session.getService(ProjectManager.class)).thenReturn(projectManager); - when(session.getService(ArtifactManager.class)).thenReturn(artifactManager); - when(session.getService(ArtifactInstaller.class)).thenReturn(artifactInstaller); - when(session.getService(ArtifactDeployer.class)).thenReturn(artifactDeployer); - when(session.getService(ArtifactFactory.class)).thenReturn(artifactFactory); - when(session.getService(ModelXmlFactory.class)).thenReturn(new DefaultModelXmlFactory()); - - when(session.getPathForLocalArtifact(any(Artifact.class))) - .then(iom -> localRepositoryManager.getPathForLocalArtifact( - session, session.getLocalRepository(), iom.getArgument(0, Artifact.class))); when(session.createArtifact(any(), any(), any(), any(), any(), any())).thenAnswer(iom -> { String groupId = iom.getArgument(0, String.class); String artifactId = iom.getArgument(1, String.class); @@ -246,17 +307,45 @@ public class SessionStub { .extension(extension) .build()); }); - when(session.createRemoteRepository(anyString(), anyString())).thenAnswer(iom -> { - String id = iom.getArgument(0, String.class); - String url = iom.getArgument(1, String.class); - return session.getService(RepositoryFactory.class).createRemote(id, url); + when(session.getService(ArtifactFactory.class)).thenReturn(artifactFactory); + + // + // ProjectBuilder + // + ProjectBuilder projectBuilder = mock(ProjectBuilder.class); + when(projectBuilder.build(any(ProjectBuilderRequest.class))).then(iom -> { + ProjectBuilderRequest request = iom.getArgument(0, ProjectBuilderRequest.class); + ProjectBuilderResult result = mock(ProjectBuilderResult.class); + Model model = new MavenStaxReader().read(request.getSource().get().openStream()); + ProjectStub projectStub = new ProjectStub(); + projectStub.setModel(model); + ArtifactStub artifactStub = new ArtifactStub( + model.getGroupId(), model.getArtifactId(), "", model.getVersion(), model.getPackaging()); + if (!"pom".equals(model.getPackaging())) { + projectStub.setMainArtifact(artifactStub); + } + when(result.getProject()).thenReturn(Optional.of(projectStub)); + return result; }); - doAnswer(iom -> artifactManager.getPath(iom.getArgument(0, Artifact.class))) - .when(session) - .getArtifactPath(any()); + when(session.getService(ProjectBuilder.class)).thenReturn(projectBuilder); + + // + // ModelXmlFactory + // + when(session.getService(ModelXmlFactory.class)).thenReturn(new DefaultModelXmlFactory()); + // + // Other + // + Properties sysProps = new Properties(); + Properties usrProps = new Properties(); + doReturn(sysProps).when(session).getSystemProperties(); + doReturn(usrProps).when(session).getUserProperties(); + when(session.getLocalRepository()).thenReturn(localRepository); + when(session.getData()).thenReturn(new TestSessionData()); when(session.withLocalRepository(any())) .thenAnswer(iom -> getMockSession(iom.getArgument(0, LocalRepository.class))); + return session; } @@ -275,4 +364,30 @@ public class SessionStub { } return path.toString(); } + + static class TestSessionData implements SessionData { + private final Map<Key<?>, Object> map = new ConcurrentHashMap<>(); + + @Override + public <T> void set(Key<T> key, T value) { + map.put(key, value); + } + + @Override + public <T> boolean replace(Key<T> key, T oldValue, T newValue) { + return map.replace(key, oldValue, newValue); + } + + @Override + @SuppressWarnings("unchecked") + public <T> T get(Key<T> key) { + return (T) map.get(key); + } + + @Override + @SuppressWarnings("unchecked") + public <T> T computeIfAbsent(Key<T> key, Supplier<T> supplier) { + return (T) map.computeIfAbsent(key, k -> supplier.get()); + } + } } diff --git a/maven-plugin-testing-harness/src/test/java/org/apache/maven/api/di/testing/SimpleDITest.java b/maven-plugin-testing-harness/src/test/java/org/apache/maven/api/di/testing/SimpleDITest.java new file mode 100644 index 0000000..429a3f5 --- /dev/null +++ b/maven-plugin-testing-harness/src/test/java/org/apache/maven/api/di/testing/SimpleDITest.java @@ -0,0 +1,50 @@ +/* + * 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.api.di.testing; + +import java.io.File; + +import org.apache.maven.api.Session; +import org.apache.maven.api.di.Inject; +import org.apache.maven.api.di.Provides; +import org.apache.maven.api.plugin.testing.stubs.SessionStub; +import org.junit.jupiter.api.Test; + +import static org.apache.maven.api.di.testing.MavenDIExtension.getBasedir; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +@MavenDITest +public class SimpleDITest { + + private static final String LOCAL_REPO = getBasedir() + File.separator + "target" + File.separator + "local-repo"; + + @Inject + Session session; + + @Test + void testSession() { + assertNotNull(session); + assertNotNull(session.getLocalRepository()); + } + + @Provides + Session createSession() { + return SessionStub.getMockSession(LOCAL_REPO); + } +} diff --git a/maven-plugin-testing-harness/src/test/java/org/apache/maven/api/plugin/testing/ExpressionEvaluatorTest.java b/maven-plugin-testing-harness/src/test/java/org/apache/maven/api/plugin/testing/ExpressionEvaluatorTest.java index b287bbf..51b1ed9 100644 --- a/maven-plugin-testing-harness/src/test/java/org/apache/maven/api/plugin/testing/ExpressionEvaluatorTest.java +++ b/maven-plugin-testing-harness/src/test/java/org/apache/maven/api/plugin/testing/ExpressionEvaluatorTest.java @@ -18,14 +18,17 @@ */ package org.apache.maven.api.plugin.testing; -import javax.inject.Named; - +import java.nio.file.Path; import java.nio.file.Paths; import java.util.Properties; -import com.google.inject.Provides; +import org.apache.maven.api.Project; import org.apache.maven.api.Session; +import org.apache.maven.api.di.Named; +import org.apache.maven.api.di.Provides; import org.apache.maven.api.plugin.MojoException; +import org.apache.maven.api.plugin.annotations.Mojo; +import org.apache.maven.api.plugin.testing.stubs.ProjectStub; import org.apache.maven.api.plugin.testing.stubs.SessionStub; import org.junit.jupiter.api.Test; @@ -42,16 +45,18 @@ import static org.mockito.Mockito.doReturn; public class ExpressionEvaluatorTest { private static final String LOCAL_REPO = "target/local-repo/"; - private static final String ARTIFACT_ID = "maven-test-mojo"; - private static final String COORDINATES = "groupId:" + ARTIFACT_ID + ":version:goal"; + private static final String GROUP_ID = "test"; + private static final String ARTIFACT_ID = "test-plugin"; + private static final String COORDINATES = GROUP_ID + ":" + ARTIFACT_ID + ":0.0.1-SNAPSHOT:goal"; private static final String CONFIG = "<project>\n" + " <build>\n" + " <plugins>\n" + " <plugin>\n" + + " <groupId>" + GROUP_ID + "</groupId>\n" + " <artifactId>" + ARTIFACT_ID + "</artifactId>\n" + " <configuration>\n" - + " <basedir>${basedir}</basedir>\n" - + " <workdir>${basedir}/workDirectory</workdir>\n" + + " <basedir>${project.basedir}</basedir>\n" + + " <workdir>${project.basedir}/workDirectory</workdir>\n" + " </configuration>\n" + " </plugin>\n" + " </plugins>\n" @@ -68,6 +73,7 @@ public class ExpressionEvaluatorTest { @Test @InjectMojo(goal = COORDINATES, pom = CONFIG) + @Basedir("${basedir}/target/test-classes") @MojoParameter(name = "param", value = "paramValue") public void testParam(ExpressionEvaluatorMojo mojo) { assertNotNull(mojo.basedir); @@ -88,11 +94,12 @@ public class ExpressionEvaluatorTest { assertDoesNotThrow(mojo::execute); } - @Named(COORDINATES) + @Mojo(name = "goal") + @Named("test:test-plugin:0.0.1-SNAPSHOT:goal") // this one is usually generated by maven-plugin-plugin public static class ExpressionEvaluatorMojo implements org.apache.maven.api.plugin.Mojo { - private String basedir; + private Path basedir; - private String workdir; + private Path workdir; private String param; @@ -101,11 +108,11 @@ public class ExpressionEvaluatorTest { /** {@inheritDoc} */ @Override public void execute() throws MojoException { - if (basedir == null || basedir.isEmpty()) { + if (basedir == null) { throw new MojoException("basedir was not injected."); } - if (workdir == null || workdir.isEmpty()) { + if (workdir == null) { throw new MojoException("workdir was not injected."); } else if (!workdir.startsWith(basedir)) { throw new MojoException("workdir does not start with basedir."); @@ -122,4 +129,11 @@ public class ExpressionEvaluatorTest { doAnswer(iom -> Paths.get(MojoExtension.getBasedir())).when(session).getRootDirectory(); return session; } + + @Provides + Project project() { + ProjectStub project = new ProjectStub(); + project.setBasedir(Paths.get(MojoExtension.getBasedir())); + return project; + } } diff --git a/.github/workflows/maven-verify.yml b/maven-plugin-testing-harness/src/test/resources/META-INF/maven/org.apache.maven.api.di.Inject similarity index 74% copy from .github/workflows/maven-verify.yml copy to maven-plugin-testing-harness/src/test/resources/META-INF/maven/org.apache.maven.api.di.Inject index fa7dc4b..2a771d7 100644 --- a/.github/workflows/maven-verify.yml +++ b/maven-plugin-testing-harness/src/test/resources/META-INF/maven/org.apache.maven.api.di.Inject @@ -1,3 +1,4 @@ +# # 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 @@ -6,7 +7,7 @@ # "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 +# 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 @@ -14,16 +15,5 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. - -name: Verify - -on: - push: - pull_request: - -jobs: - build: - name: Verify - uses: apache/maven-gh-actions-shared/.github/workflows/maven-verify.yml@v4 - with: - jdk-matrix: '[ "8", "11", "17" ]' +# +org.apache.maven.api.plugin.testing.ExpressionEvaluatorTest$ExpressionEvaluatorMojo \ No newline at end of file diff --git a/maven-plugin-testing-harness/src/test/resources/META-INF/maven/plugin.xml b/maven-plugin-testing-harness/src/test/resources/META-INF/maven/plugin.xml index d442272..6657446 100644 --- a/maven-plugin-testing-harness/src/test/resources/META-INF/maven/plugin.xml +++ b/maven-plugin-testing-harness/src/test/resources/META-INF/maven/plugin.xml @@ -20,7 +20,7 @@ specific language governing permissions and limitations under the License. --> -<plugin> +<plugin xmlns="http://maven.apache.org/PLUGIN/2.0.0" > <name>test-plugin</name> <description></description> <groupId>test</groupId> @@ -31,19 +31,31 @@ under the License. <inheritedByDefault>true</inheritedByDefault> <mojos> <mojo> - <goal>parameters</goal> - <requiresDirectInvocation>false</requiresDirectInvocation> - <requiresProject>true</requiresProject> - <requiresReports>false</requiresReports> + <goal>goal</goal> + <projectRequired>true</projectRequired> <aggregator>false</aggregator> - <requiresOnline>false</requiresOnline> + <onlineRequired>false</onlineRequired> <inheritedByDefault>true</inheritedByDefault> <implementation>org.apache.maven.plugin.testing.ParametersMojo</implementation> <language>java</language> - <instantiationStrategy>per-lookup</instantiationStrategy> - <executionStrategy>once-per-session</executionStrategy> - <threadSafe>false</threadSafe> <parameters> + <parameter> + <name>basedir</name> + <type>java.nio.file.Path</type> + </parameter> + <parameter> + <name>workdir</name> + <type>java.nio.file.Path</type> + </parameter> + <parameter> + <name>param</name> + <type>java.lang.String</type> + </parameter> + <parameter> + <name>param2</name> + <type>java.lang.String</type> + </parameter> + <!-- <parameter> <name>plain</name> <type>java.lang.String</type> @@ -57,6 +69,7 @@ under the License. <required>false</required> <editable>true</editable> <description></description> + <defaultValue>default</defaultValue> </parameter> <parameter> <name>withProperty</name> @@ -64,6 +77,7 @@ under the License. <required>false</required> <editable>true</editable> <description></description> + <expression>${property}</expression> </parameter> <parameter> <name>withPropertyAndDefault</name> @@ -71,14 +85,11 @@ under the License. <required>false</required> <editable>true</editable> <description></description> + <defaultValue>default</defaultValue> + <expression>${property}</expression> </parameter> + --> </parameters> - <configuration> - <withDefault implementation="java.lang.String" default-value="default"/> - <withProperty implementation="java.lang.String">${property}</withProperty> - <withPropertyAndDefault implementation="java.lang.String" default-value="default">${property}</withPropertyAndDefault> - </configuration> </mojo> </mojos> - <dependencies/> </plugin> \ No newline at end of file diff --git a/pom.xml b/pom.xml index 4cea8e8..6d530ae 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ under the License. <parent> <groupId>org.apache.maven</groupId> <artifactId>maven-parent</artifactId> - <version>40</version> + <version>42</version> <relativePath /> </parent> @@ -65,9 +65,9 @@ under the License. <properties> <surefire.version>3.2.1</surefire.version> - <mavenVersion>4.0.0-alpha-8</mavenVersion> + <mavenVersion>4.0.0-beta-3</mavenVersion> <maven.site.path>plugin-testing-archives/LATEST</maven.site.path> - <javaVersion>8</javaVersion> + <javaVersion>17</javaVersion> <project.build.outputTimestamp>2023-11-07T21:58:12Z</project.build.outputTimestamp> </properties>
