Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions impl/maven-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,26 @@ under the License.
<name>Maven 4 Core</name>
<description>Maven Core classes.</description>

<properties>
<!-- Default lifecycle plugin versions.
Maintained here so that dependency-update bots (Dependabot, Renovate)
can propose version bumps automatically. Values are filtered into
plugin-versions.properties at build time and loaded at runtime. -->
<version.maven-clean-plugin>3.4.0</version.maven-clean-plugin>
<version.maven-compiler-plugin>3.13.0</version.maven-compiler-plugin>
<version.maven-deploy-plugin>3.1.3</version.maven-deploy-plugin>
<version.maven-ear-plugin>3.3.0</version.maven-ear-plugin>
<version.maven-ejb-plugin>3.2.1</version.maven-ejb-plugin>
<version.maven-install-plugin>3.1.3</version.maven-install-plugin>
<version.maven-jar-plugin>3.4.2</version.maven-jar-plugin>
<version.maven-plugin-plugin>3.15.1</version.maven-plugin-plugin>
<version.maven-rar-plugin>3.0.0</version.maven-rar-plugin>
<version.maven-resources-plugin>3.3.1</version.maven-resources-plugin>
<version.maven-site-plugin>3.21.0</version.maven-site-plugin>
<version.maven-surefire-plugin>3.5.2</version.maven-surefire-plugin>
<version.maven-war-plugin>3.4.0</version.maven-war-plugin>
</properties>

<dependencies>
<!-- Maven4 API -->
<dependency>
Expand Down Expand Up @@ -260,6 +280,74 @@ under the License.
</resources>
<pluginManagement>
<plugins>
<!-- Default lifecycle plugins declared here so that dependency-update bots
(Dependabot, Renovate) see the version.maven-*-plugin properties as
actual plugin version references and can propose automated bumps. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>${version.maven-clean-plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${version.maven-compiler-plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>${version.maven-deploy-plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>${version.maven-ear-plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<version>${version.maven-ejb-plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>${version.maven-install-plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${version.maven-jar-plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>${version.maven-plugin-plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-rar-plugin</artifactId>
<version>${version.maven-rar-plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>${version.maven-resources-plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>${version.maven-site-plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${version.maven-surefire-plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>${version.maven-war-plugin}</version>
</plugin>
<plugin>
<groupId>org.apache.rat</groupId>
<artifactId>apache-rat-plugin</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -529,7 +530,7 @@ public Collection<Alias> 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";
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
* <p>
* Versions are read from {@code plugin-versions.properties}, which is filtered
* at build time from POM properties ({@code version.maven-<name>-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");
}
Comment on lines +68 to +81

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 No test for the loading mechanism

The static initialiser, the filtering round-trip, and the null/placeholder guards are the critical path of this new class, yet there is no unit test. A minimal test verifying that every constant is non-null and does not look like an unfiltered placeholder (!CLEAN.startsWith("${")) would catch the filtering-skipped scenario and guard against future regressions (e.g. a new constant added to the class but forgotten in the properties file).

Example:

@Test
void pluginVersionsAreResolved() {
    // Verify all constants are loaded and not unfiltered placeholders
    for (Field f : PluginVersions.class.getFields()) {
        if (f.getType() == String.class) {
            String value = (String) f.get(null);
            assertNotNull(value, f.getName() + " is null");
            assertFalse(value.startsWith("${"), f.getName() + " is unfiltered: " + value);
        }
    }
}

Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -35,29 +36,51 @@
*/
public abstract class AbstractLifecycleMappingProvider implements Provider<LifecycleMapping> {
// 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;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe deprecate these fields, or just remove them if this is all new in 4.0.lx

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — since these fields are protected and could be referenced by extensions subclassing AbstractLifecycleMappingProvider, I'll deprecate them for 4.1.0 with @Deprecated(since = "4.1.0", forRemoval = true) rather than removing outright. They already delegate to PluginVersions.* constants, so the deprecation is purely a signal to migrate.

This comment was generated by an AI agent, Hermès, on behalf of @gnodet.


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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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-<name>-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}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Loading