diff --git a/maven-wrapper-plugin/src/it/projects/upgrade_with_existing_type/.mvn/wrapper/maven-wrapper.properties b/maven-wrapper-plugin/src/it/projects/upgrade_with_existing_type/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..3ba4302
--- /dev/null
+++ b/maven-wrapper-plugin/src/it/projects/upgrade_with_existing_type/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,19 @@
+# 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
+#
+# https://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.
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
+distributionType=bin
+wrapperVersion=3.3.1
\ No newline at end of file
diff --git a/maven-wrapper-plugin/src/it/projects/upgrade_with_existing_type/invoker.properties b/maven-wrapper-plugin/src/it/projects/upgrade_with_existing_type/invoker.properties
new file mode 100644
index 0000000..faac648
--- /dev/null
+++ b/maven-wrapper-plugin/src/it/projects/upgrade_with_existing_type/invoker.properties
@@ -0,0 +1,19 @@
+# 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.
+
+invoker.goals.1 = ${project.groupId}:${project.artifactId}:${project.version}:wrapper -Dmaven=3.9.6
+invoker.goals.2 = exec:exec
diff --git a/maven-wrapper-plugin/src/it/projects/upgrade_with_existing_type/pom.xml b/maven-wrapper-plugin/src/it/projects/upgrade_with_existing_type/pom.xml
new file mode 100644
index 0000000..cbec1de
--- /dev/null
+++ b/maven-wrapper-plugin/src/it/projects/upgrade_with_existing_type/pom.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+ 4.0.0
+
+ org.apache.maven.plugins.it.wrapper
+ extension
+ 1.0.0-SNAPSHOT
+ pom
+
+
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.0.0
+
+ mvnw${cmd}
+
+ -v
+
+
+ true
+
+
+
+
+
+
+
+
+
+ windows
+
+ windows
+
+
+ .cmd
+
+
+
+
\ No newline at end of file
diff --git a/maven-wrapper-plugin/src/it/projects/upgrade_with_existing_type/verify.groovy b/maven-wrapper-plugin/src/it/projects/upgrade_with_existing_type/verify.groovy
new file mode 100644
index 0000000..1eeca65
--- /dev/null
+++ b/maven-wrapper-plugin/src/it/projects/upgrade_with_existing_type/verify.groovy
@@ -0,0 +1,37 @@
+
+/*
+ * 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.
+ */
+
+assert new File(basedir,'mvnw').exists()
+assert new File(basedir,'mvnw.cmd').exists()
+assert new File(basedir,'.mvn/wrapper/maven-wrapper.jar').exists()
+
+wrapperProperties = new File(basedir,'.mvn/wrapper/maven-wrapper.properties')
+assert wrapperProperties.exists()
+
+Properties props = new Properties()
+wrapperProperties.withInputStream {
+ props.load(it)
+}
+
+// Assert that distribution type from previous Maven Wrapper is retained, without it being explicitly set via '-Dtype='
+assert props.distributionType.equals("bin")
+
+// Assert that distribution URL was updated to version specified via '-Dmaven='
+assert props.distributionUrl.endsWith("/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip")
diff --git a/maven-wrapper-plugin/src/main/java/org/apache/maven/plugins/wrapper/WrapperMojo.java b/maven-wrapper-plugin/src/main/java/org/apache/maven/plugins/wrapper/WrapperMojo.java
index 91bae30..4b0650f 100644
--- a/maven-wrapper-plugin/src/main/java/org/apache/maven/plugins/wrapper/WrapperMojo.java
+++ b/maven-wrapper-plugin/src/main/java/org/apache/maven/plugins/wrapper/WrapperMojo.java
@@ -36,7 +36,6 @@
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
@@ -84,7 +83,10 @@ public class WrapperMojo extends AbstractMojo {
private String mvndVersion;
/**
+ * The Maven Wrapper distribution type.
+ *
* Options are:
+ *
*
* - script
* - only mvnw scripts
@@ -95,11 +97,16 @@ public class WrapperMojo extends AbstractMojo {
* - only-script (default)
* - the new lite implementation of mvnw/mvnw.cmd scripts downloads the maven directly and skips maven-wrapper.jar - since 3.2.0
*
- * Value will be used as classifier of the downloaded file
+ *
+ * If {@code -Dtype={type}} is not explicitly provided, then {@code distributionType} from
+ * {@code .mvn/wrapper/maven-wrapper.properties} is used, if it exists.
+ * Otherwise, {@code only-script} is used as the default distribution type.
+ *
+ * This value will be used as the classifier of the downloaded file.
*
* @since 3.0.0
*/
- @Parameter(defaultValue = "only-script", property = "type")
+ @Parameter(property = "type")
private String distributionType;
/**
@@ -159,6 +166,16 @@ public class WrapperMojo extends AbstractMojo {
private static final String WRAPPER_DISTRIBUTION_EXTENSION = "zip";
+ private static final String WRAPPER_DIR = ".mvn/wrapper";
+
+ private static final String WRAPPER_PROPERTIES_FILENAME = "maven-wrapper.properties";
+
+ private static final String DISTRIBUTION_TYPE_PROPERTY_NAME = "distributionType";
+
+ private static final String TYPE_ONLY_SCRIPT = "only-script";
+
+ private static final String DEFAULT_DISTRIBUTION_TYPE = TYPE_ONLY_SCRIPT;
+
// COMPONENTS
@Inject
@@ -168,27 +185,53 @@ public class WrapperMojo extends AbstractMojo {
private Map unarchivers;
@Override
- public void execute() throws MojoExecutionException, MojoFailureException {
- if (mvndVersion != null && mvndVersion.length() > 0 && !"only-script".equals(distributionType)) {
+ public void execute() throws MojoExecutionException {
+ final Path baseDir = Paths.get(session.getRequest().getBaseDirectory());
+ final Path wrapperDir = baseDir.resolve(WRAPPER_DIR);
+
+ if (distributionType == null) {
+ distributionType = determineDistributionType(wrapperDir);
+ }
+
+ if (mvndVersion != null && mvndVersion.length() > 0 && !TYPE_ONLY_SCRIPT.equals(distributionType)) {
throw new MojoExecutionException("maven-wrapper with type=" + distributionType
- + " cannot work with mvnd, please set type to 'only-script'.");
+ + " cannot work with mvnd, please set type to '" + TYPE_ONLY_SCRIPT + "'.");
}
- Path baseDir = Paths.get(session.getRequest().getBaseDirectory());
mavenVersion = getVersion(mavenVersion, Maven.class, "org.apache.maven/maven-core");
String wrapperVersion = getVersion(null, this.getClass(), "org.apache.maven.plugins/maven-wrapper-plugin");
final Artifact artifact = downloadWrapperDistribution(wrapperVersion);
- final Path wrapperDir = createDirectories(baseDir.resolve(".mvn/wrapper"));
+ createDirectories(wrapperDir);
cleanup(wrapperDir);
unpack(artifact, baseDir);
replaceProperties(wrapperVersion, wrapperDir);
}
- private Path createDirectories(Path dir) throws MojoExecutionException {
+ private String determineDistributionType(final Path wrapperDir) {
+ final String typeFromMavenWrapperProperties = distributionTypeFromExistingMavenWrapperProperties(wrapperDir);
+ if (typeFromMavenWrapperProperties != null) {
+ return typeFromMavenWrapperProperties;
+ }
+
+ return DEFAULT_DISTRIBUTION_TYPE;
+ }
+
+ private String distributionTypeFromExistingMavenWrapperProperties(final Path wrapperDir) {
+ final Path mavenWrapperProperties = wrapperDir.resolve(WRAPPER_PROPERTIES_FILENAME);
+ try (InputStream inputStream = Files.newInputStream(mavenWrapperProperties)) {
+ Properties properties = new Properties();
+ properties.load(inputStream);
+ return properties.getProperty(DISTRIBUTION_TYPE_PROPERTY_NAME);
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ private void createDirectories(Path dir) throws MojoExecutionException {
try {
- return Files.createDirectories(dir);
+ Files.createDirectories(dir);
} catch (IOException ioe) {
throw new MojoExecutionException(ioe.getMessage(), ioe);
}
@@ -288,12 +331,12 @@ private void replaceProperties(String wrapperVersion, Path targetFolder) throws
try (BufferedWriter out = Files.newBufferedWriter(wrapperPropertiesFile, StandardCharsets.UTF_8)) {
out.append(String.format(Locale.ROOT, license));
out.append("wrapperVersion=" + wrapperVersion + System.lineSeparator());
- out.append("distributionType=" + distributionType + System.lineSeparator());
+ out.append(DISTRIBUTION_TYPE_PROPERTY_NAME + "=" + distributionType + System.lineSeparator());
out.append("distributionUrl=" + distributionUrl + System.lineSeparator());
if (distributionSha256Sum != null) {
out.append("distributionSha256Sum=" + distributionSha256Sum + System.lineSeparator());
}
- if (!distributionType.equals("only-script")) {
+ if (!distributionType.equals(TYPE_ONLY_SCRIPT)) {
out.append("wrapperUrl=" + wrapperUrl + System.lineSeparator());
}
if (wrapperSha256Sum != null) {
diff --git a/maven-wrapper-plugin/src/site/markdown/usage.md b/maven-wrapper-plugin/src/site/markdown/usage.md
index 3c22bca..4bba716 100644
--- a/maven-wrapper-plugin/src/site/markdown/usage.md
+++ b/maven-wrapper-plugin/src/site/markdown/usage.md
@@ -32,9 +32,9 @@ The scripts work like this:
Apache Maven Wrapper Distribution Types
-----
-There are 4 types available:
+There are 4 distribution types available:
-- **only-script** _(default)_: the lite implementation of `mvnw`/`mvnw.cmd` scripts will download the maven directly via wget or curl on *nix, or PowerShell on Windows,
+- **only-script** _(default for new installations)_: the lite implementation of `mvnw`/`mvnw.cmd` scripts will download the maven directly via wget or curl on *nix, or PowerShell on Windows,
then exec/call the original `mvn`/`mvn.cmd` scripts of the downloaded maven distribution. This type does not use `maven-wrapper.jar` nor `MavenWrapperDownloader.java`,
only the wrapper scripts are required.
@@ -46,13 +46,17 @@ The downside is that the project will contain a binary file in the source contro
- **source**: Since Maven already requires Java to run, why not compile and run a classfile to download the maven-wrapper jar?
This type comes with a `.mvn/wrapper/MavenWrapperDownloader.java` which will be compiled and executed on the fly.
-The type can be specified with `mvn wrapper:wrapper -Dtype=x`, where x is any of the types listed above.
+The type can be specified with `mvn wrapper:wrapper -Dtype={type}`, where `{type}` is any of the types listed above.
+
+When `wrapper:wrapper` is run in a Maven module which contains a `.mvn/wrapper/maven-wrapper.properties` file, then the distribution type of the existing Maven Wrapper is used for the execution of the goal.
+This allows updating Maven Wrapper, without unintentionally changing the distribution type for an existing project.
+You can still use `-Dtype={type}` to change the distribution type for an existing installation.
Maven Version
-------------
By default the plugin will assume the same version as the Maven runtime (calling `mvn -v`). But you can pick a different version.
-Either call `mvn wrapper:wrapper -Dmaven=x`, where x is any valid Apache Maven Release, see https://search.maven.org/artifact/org.apache.maven/apache-maven
-Another option is adjust the `distributionUrl` in `.mvn/wrapper/maven-wrapper.properties`
+You can call `mvn wrapper:wrapper -Dmaven=x`, where `x` is any valid Apache Maven Release (see [Maven Central](https://central.sonatype.com/artifact/org.apache.maven/apache-maven/versions)).
+Another option is to adjust the `distributionUrl` in `.mvn/wrapper/maven-wrapper.properties`.
Debugging
---------