diff --git a/impl/maven-core/pom.xml b/impl/maven-core/pom.xml index 07ffa6662b12..fe8f6d10de38 100644 --- a/impl/maven-core/pom.xml +++ b/impl/maven-core/pom.xml @@ -31,6 +31,26 @@ under the License. Maven 4 Core Maven Core classes. + + + 3.4.0 + 3.13.0 + 3.1.3 + 3.3.0 + 3.2.1 + 3.1.3 + 3.4.2 + 3.15.1 + 3.0.0 + 3.3.1 + 3.21.0 + 3.5.2 + 3.4.0 + + @@ -260,6 +280,74 @@ under the License. + + + org.apache.maven.plugins + maven-clean-plugin + ${version.maven-clean-plugin} + + + org.apache.maven.plugins + maven-compiler-plugin + ${version.maven-compiler-plugin} + + + org.apache.maven.plugins + maven-deploy-plugin + ${version.maven-deploy-plugin} + + + org.apache.maven.plugins + maven-ear-plugin + ${version.maven-ear-plugin} + + + org.apache.maven.plugins + maven-ejb-plugin + ${version.maven-ejb-plugin} + + + org.apache.maven.plugins + maven-install-plugin + ${version.maven-install-plugin} + + + org.apache.maven.plugins + maven-jar-plugin + ${version.maven-jar-plugin} + + + org.apache.maven.plugins + maven-plugin-plugin + ${version.maven-plugin-plugin} + + + org.apache.maven.plugins + maven-rar-plugin + ${version.maven-rar-plugin} + + + org.apache.maven.plugins + maven-resources-plugin + ${version.maven-resources-plugin} + + + org.apache.maven.plugins + maven-site-plugin + ${version.maven-site-plugin} + + + org.apache.maven.plugins + maven-surefire-plugin + ${version.maven-surefire-plugin} + + + org.apache.maven.plugins + maven-war-plugin + ${version.maven-war-plugin} + org.apache.rat apache-rat-plugin diff --git a/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLifecycleRegistry.java b/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLifecycleRegistry.java index c2006cb7325d..39e0c77d12ab 100644 --- a/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLifecycleRegistry.java +++ b/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLifecycleRegistry.java @@ -46,6 +46,7 @@ import org.apache.maven.api.services.LookupException; import org.apache.maven.api.spi.ExtensibleEnumProvider; import org.apache.maven.api.spi.LifecycleProvider; +import org.apache.maven.lifecycle.PluginVersions; import org.apache.maven.lifecycle.mapping.LifecyclePhase; import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; @@ -416,7 +417,7 @@ static class SiteLifecycleProvider extends BaseLifecycleProvider { static class CleanLifecycle implements Lifecycle { - private static final String MAVEN_CLEAN_PLUGIN_VERSION = "3.4.0"; + private static final String MAVEN_CLEAN_PLUGIN_VERSION = PluginVersions.CLEAN; @Override public String id() { @@ -529,7 +530,7 @@ public Collection aliases() { static class SiteLifecycle implements Lifecycle { - private static final String MAVEN_SITE_PLUGIN_VERSION = "3.21.0"; + private static final String MAVEN_SITE_PLUGIN_VERSION = PluginVersions.SITE; private static final String MAVEN_SITE_PLUGIN = MAVEN_PLUGINS + "maven-site-plugin:" + MAVEN_SITE_PLUGIN_VERSION + ":"; private static final String PHASE_SITE = "site"; diff --git a/impl/maven-core/src/main/java/org/apache/maven/lifecycle/PluginVersions.java b/impl/maven-core/src/main/java/org/apache/maven/lifecycle/PluginVersions.java new file mode 100644 index 000000000000..0a1e4a7ee9be --- /dev/null +++ b/impl/maven-core/src/main/java/org/apache/maven/lifecycle/PluginVersions.java @@ -0,0 +1,81 @@ +/* + * 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.lifecycle; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +/** + * Provides default plugin versions for the built-in lifecycle bindings. + *

+ * Versions are read from {@code plugin-versions.properties}, which is filtered + * at build time from POM properties ({@code version.maven--plugin}). + * Centralising them in the POM makes them visible to dependency-update bots + * such as Dependabot and Renovate. + * + * @since 4.1.0 + */ +public final class PluginVersions { + + private static final Properties VERSIONS = new Properties(); + + static { + try (InputStream in = PluginVersions.class.getResourceAsStream("plugin-versions.properties")) { + if (in == null) { + throw new ExceptionInInitializerError("plugin-versions.properties not found on classpath"); + } + VERSIONS.load(in); + } catch (IOException e) { + throw new ExceptionInInitializerError(e); + } + } + + private PluginVersions() {} + + private static String version(String pluginArtifactId) { + String key = "version." + pluginArtifactId; + String version = VERSIONS.getProperty(key); + if (version == null) { + throw new IllegalArgumentException("No default version defined for " + pluginArtifactId + "; add " + key + + " to plugin-versions.properties"); + } + if (version.startsWith("${")) { + throw new ExceptionInInitializerError("plugin-versions.properties was not filtered at build time; " + key + + " still contains placeholder: " + version); + } + return version; + } + + // --- convenience constants used by lifecycle mapping providers --- + + public static final String CLEAN = version("maven-clean-plugin"); + public static final String COMPILER = version("maven-compiler-plugin"); + public static final String DEPLOY = version("maven-deploy-plugin"); + public static final String EAR = version("maven-ear-plugin"); + public static final String EJB = version("maven-ejb-plugin"); + public static final String INSTALL = version("maven-install-plugin"); + public static final String JAR = version("maven-jar-plugin"); + public static final String PLUGIN = version("maven-plugin-plugin"); + public static final String RAR = version("maven-rar-plugin"); + public static final String RESOURCES = version("maven-resources-plugin"); + public static final String SITE = version("maven-site-plugin"); + public static final String SUREFIRE = version("maven-surefire-plugin"); + public static final String WAR = version("maven-war-plugin"); +} diff --git a/impl/maven-core/src/main/java/org/apache/maven/lifecycle/providers/packaging/AbstractLifecycleMappingProvider.java b/impl/maven-core/src/main/java/org/apache/maven/lifecycle/providers/packaging/AbstractLifecycleMappingProvider.java index ed841bcccdd9..3802905b4331 100644 --- a/impl/maven-core/src/main/java/org/apache/maven/lifecycle/providers/packaging/AbstractLifecycleMappingProvider.java +++ b/impl/maven-core/src/main/java/org/apache/maven/lifecycle/providers/packaging/AbstractLifecycleMappingProvider.java @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.HashMap; +import org.apache.maven.lifecycle.PluginVersions; import org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping; import org.apache.maven.lifecycle.mapping.Lifecycle; import org.apache.maven.lifecycle.mapping.LifecycleMapping; @@ -35,29 +36,51 @@ */ public abstract class AbstractLifecycleMappingProvider implements Provider { // START SNIPPET: versions - protected static final String RESOURCES_PLUGIN_VERSION = "3.3.1"; + /** @deprecated Use {@link PluginVersions#RESOURCES} instead. */ + @Deprecated(since = "4.1.0", forRemoval = true) + protected static final String RESOURCES_PLUGIN_VERSION = PluginVersions.RESOURCES; - protected static final String COMPILER_PLUGIN_VERSION = "3.13.0"; + /** @deprecated Use {@link PluginVersions#COMPILER} instead. */ + @Deprecated(since = "4.1.0", forRemoval = true) + protected static final String COMPILER_PLUGIN_VERSION = PluginVersions.COMPILER; - protected static final String SUREFIRE_PLUGIN_VERSION = "3.5.2"; + /** @deprecated Use {@link PluginVersions#SUREFIRE} instead. */ + @Deprecated(since = "4.1.0", forRemoval = true) + protected static final String SUREFIRE_PLUGIN_VERSION = PluginVersions.SUREFIRE; - protected static final String INSTALL_PLUGIN_VERSION = "3.1.3"; + /** @deprecated Use {@link PluginVersions#INSTALL} instead. */ + @Deprecated(since = "4.1.0", forRemoval = true) + protected static final String INSTALL_PLUGIN_VERSION = PluginVersions.INSTALL; - protected static final String DEPLOY_PLUGIN_VERSION = "3.1.3"; + /** @deprecated Use {@link PluginVersions#DEPLOY} instead. */ + @Deprecated(since = "4.1.0", forRemoval = true) + protected static final String DEPLOY_PLUGIN_VERSION = PluginVersions.DEPLOY; // packaging - protected static final String JAR_PLUGIN_VERSION = "3.4.2"; + /** @deprecated Use {@link PluginVersions#JAR} instead. */ + @Deprecated(since = "4.1.0", forRemoval = true) + protected static final String JAR_PLUGIN_VERSION = PluginVersions.JAR; - protected static final String EAR_PLUGIN_VERSION = "3.3.0"; + /** @deprecated Use {@link PluginVersions#EAR} instead. */ + @Deprecated(since = "4.1.0", forRemoval = true) + protected static final String EAR_PLUGIN_VERSION = PluginVersions.EAR; - protected static final String EJB_PLUGIN_VERSION = "3.2.1"; + /** @deprecated Use {@link PluginVersions#EJB} instead. */ + @Deprecated(since = "4.1.0", forRemoval = true) + protected static final String EJB_PLUGIN_VERSION = PluginVersions.EJB; - protected static final String PLUGIN_PLUGIN_VERSION = "3.15.1"; + /** @deprecated Use {@link PluginVersions#PLUGIN} instead. */ + @Deprecated(since = "4.1.0", forRemoval = true) + protected static final String PLUGIN_PLUGIN_VERSION = PluginVersions.PLUGIN; - protected static final String RAR_PLUGIN_VERSION = "3.0.0"; + /** @deprecated Use {@link PluginVersions#RAR} instead. */ + @Deprecated(since = "4.1.0", forRemoval = true) + protected static final String RAR_PLUGIN_VERSION = PluginVersions.RAR; - protected static final String WAR_PLUGIN_VERSION = "3.4.0"; + /** @deprecated Use {@link PluginVersions#WAR} instead. */ + @Deprecated(since = "4.1.0", forRemoval = true) + protected static final String WAR_PLUGIN_VERSION = PluginVersions.WAR; // END SNIPPET: versions private final LifecycleMapping lifecycleMapping; diff --git a/impl/maven-core/src/main/resources/org/apache/maven/lifecycle/plugin-versions.properties b/impl/maven-core/src/main/resources/org/apache/maven/lifecycle/plugin-versions.properties new file mode 100644 index 000000000000..701d8a30fc43 --- /dev/null +++ b/impl/maven-core/src/main/resources/org/apache/maven/lifecycle/plugin-versions.properties @@ -0,0 +1,35 @@ +# 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. + +# Default lifecycle plugin versions. +# Values are substituted by Maven resource filtering at build time from +# POM properties (version.maven--plugin), making them visible to +# dependency-update bots such as Dependabot and Renovate. + +version.maven-clean-plugin=${version.maven-clean-plugin} +version.maven-compiler-plugin=${version.maven-compiler-plugin} +version.maven-deploy-plugin=${version.maven-deploy-plugin} +version.maven-ear-plugin=${version.maven-ear-plugin} +version.maven-ejb-plugin=${version.maven-ejb-plugin} +version.maven-install-plugin=${version.maven-install-plugin} +version.maven-jar-plugin=${version.maven-jar-plugin} +version.maven-plugin-plugin=${version.maven-plugin-plugin} +version.maven-rar-plugin=${version.maven-rar-plugin} +version.maven-resources-plugin=${version.maven-resources-plugin} +version.maven-site-plugin=${version.maven-site-plugin} +version.maven-surefire-plugin=${version.maven-surefire-plugin} +version.maven-war-plugin=${version.maven-war-plugin} diff --git a/impl/maven-core/src/test/java/org/apache/maven/lifecycle/PluginVersionsTest.java b/impl/maven-core/src/test/java/org/apache/maven/lifecycle/PluginVersionsTest.java new file mode 100644 index 000000000000..0f28b9029789 --- /dev/null +++ b/impl/maven-core/src/test/java/org/apache/maven/lifecycle/PluginVersionsTest.java @@ -0,0 +1,54 @@ +/* + * 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.lifecycle; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Verifies that {@link PluginVersions} constants are properly loaded + * from the filtered {@code plugin-versions.properties} resource. + */ +class PluginVersionsTest { + + @Test + void allConstantsAreResolvedAndNotPlaceholders() throws Exception { + int count = 0; + for (Field field : PluginVersions.class.getFields()) { + if (field.getType() == String.class + && Modifier.isStatic(field.getModifiers()) + && Modifier.isFinal(field.getModifiers())) { + String value = (String) field.get(null); + assertNotNull(value, field.getName() + " is null"); + assertFalse(value.startsWith("${"), field.getName() + " contains unfiltered placeholder: " + value); + assertFalse(value.isEmpty(), field.getName() + " is empty"); + count++; + } + } + // Ensure we actually tested something — catches the case where + // all constants are accidentally removed or made non-public. + assertTrue(count >= 13, "Expected at least 13 plugin version constants, found " + count); + } +}