carlossg / docker-maven

Official Docker image with Maven
Apache License 2.0
528 stars 424 forks source link

Add the JDK to the default toolchains.xml #303

Open maffe opened 2 years ago

maffe commented 2 years ago

It would be useful to have the JDK included in the default toolchains file.

Currently I have something like this in my pom.xml:

  <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.release>17</maven.compiler.release>
    </properties>

  <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-toolchains-plugin</artifactId>
                <version>3.1.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>toolchain</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <toolchains>
                        <jdk>
                            <version>[${maven.compiler.release},)</version>
                        </jdk>
                    </toolchains>
                </configuration>
            </plugin>

When running mvn clean package in maven:3-eclipse-temurin-17-alpine, I get this error:

[INFO] --- maven-toolchains-plugin:3.1.0:toolchain (default) @ gitlab-maven-test --- Downloading from central: https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar Downloaded from central: https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar (169 kB at 2.8 MB/s) [INFO] Required toolchain: jdk [ version='[17,)' ] [ERROR] No toolchain found for type jdk [ERROR] Cannot find matching toolchain definitions for the following toolchain types: jdk [ version='[17,)' ]

Adding the following section to /usr/share/maven/conf/toolchains.xml resolved the issue:

  <toolchain>
    <type>jdk</type>
    <provides>
      <version>17.0.4.1</version>
      <vendor>Eclipse Adoptium</vendor>
    </provides>
    <configuration>
      <jdkHome>/opt/java/openjdk</jdkHome>
    </configuration>
  </toolchain>

Values are taken from mvn --version, the <vendor> element is not required, <version> could also just include the major version (17).

maffe commented 1 year ago

The toolchains file can be generated using this Java code (requires Java 15 or higher):

import java.util.stream.Stream;
public class Toolchains {
    public static void main(final String[] args) {
        final String toolchains = """
            <?xml version="1.0" encoding="UTF8"?>
            <toolchains>
                <toolchain>
                   <type>jdk</type>
                   <provides>
                        <version>%s</version>
                        <vendor>%s</vendor>
                   </provides>
                   <configuration>
                        <jdkHome>%s</jdkHome>
                   </configuration>
                </toolchain>
            </toolchains>""";
        System.out.println(toolchains.formatted(Stream.of("version", "vendor", "home")
                        .map(s -> System.getProperty("java." + s))
                        .map(Toolchains::escapeXML1_0)
                        .toArray(Object[]::new)));
    }
    private static String escapeXML1_0(final String value) {
        final StringBuilder sb = new StringBuilder(value.length());
        value.codePoints().forEachOrdered(codePoint -> {
            if (codePoint == '&') {
                sb.append("&amp;");
            } else if (codePoint == '<') {
                sb.append("&lt;");
            } else if (codePoint == '>') {
                sb.append("&gt;");
            } else if (codePoint == '\'') {
                sb.append("&apos;");
            } else if (codePoint == '"') {
                sb.append("&quot;");
            } else if (codePoint == '\t' || codePoint == '\r' || codePoint == '\n'
                    || (codePoint >= 0x20 && codePoint <= 0xD7FF)
                    || (codePoint >= 0xE000 && codePoint <= 0xFFFD)
                    || (codePoint >= 0x10000 && codePoint <= 0x10FFFF)) {
                sb.appendCodePoint(codePoint);
            } else {
                sb.appendCodePoint(0xFFFD);
            }
        });
        return sb.toString();
    }
}

Save it as Toolchains.java and run java Toolchains.java > /usr/share/maven/conf/toolchains.xml

maffe commented 1 year ago

This would not be required if the toolchains plugin checked if the toolchain request can be satisfied by the JDK Maven is running on.

kent-rosenkoetter-at-nordstrom commented 1 year ago

Please prioritize this issue. Toolchain support is very important, all of the core plug-ins support it and many advanced Maven projects use toolchains.