[
https://issues.apache.org/jira/browse/MTOOLCHAINS-49?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17821630#comment-17821630
]
ASF GitHub Bot commented on MTOOLCHAINS-49:
-------------------------------------------
elharo commented on code in PR #14:
URL:
https://github.com/apache/maven-toolchains-plugin/pull/14#discussion_r1505841944
##########
src/main/java/org/apache/maven/plugins/toolchain/jdk/GenerateJdkToolchainsXmlMojo.java:
##########
@@ -0,0 +1,75 @@
+/*
+ * 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.plugins.toolchain.jdk;
+
+import javax.inject.Inject;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.toolchain.model.PersistedToolchains;
+import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Writer;
+
+/**
+ * Run the JDK discovery mechanism and generates the toolchains XML.
+ */
+@Mojo(name = "generate-jdk-toolchains-xml", requiresProject = false)
+public class GenerateJdkToolchainsXmlMojo extends AbstractMojo {
+
+ /**
+ * The path and name pf the toolchain XML file that will be generated.
+ * If not provided, the XML will be written to the standard output.
+ */
+ @Parameter(property = "toolchain.file")
+ String file;
+
+ /**
+ * Toolchain discoverer
+ */
+ @Inject
+ ToolchainDiscoverer discoverer;
+
+ @Override
+ public void execute() throws MojoFailureException {
+ try {
+ PersistedToolchains toolchains = discoverer.discoverToolchains();
+ if (file != null) {
+ Path file = Paths.get(this.file).toAbsolutePath();
+ Files.createDirectories(file.getParent());
+ try (Writer writer = Files.newBufferedWriter(file)) {
+ new MavenToolchainsXpp3Writer().write(writer, toolchains);
+ }
+ } else {
+ StringWriter writer = new StringWriter();
+ new MavenToolchainsXpp3Writer().write(writer, toolchains);
+ System.out.println(writer);
Review Comment:
remove println.
Did you mean to write onto the writer rather than printing the writer object?
##########
src/main/java/org/apache/maven/plugins/toolchain/jdk/GenerateJdkToolchainsXmlMojo.java:
##########
@@ -0,0 +1,75 @@
+/*
+ * 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.plugins.toolchain.jdk;
+
+import javax.inject.Inject;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.toolchain.model.PersistedToolchains;
+import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Writer;
+
+/**
+ * Run the JDK discovery mechanism and generates the toolchains XML.
+ */
+@Mojo(name = "generate-jdk-toolchains-xml", requiresProject = false)
+public class GenerateJdkToolchainsXmlMojo extends AbstractMojo {
+
+ /**
+ * The path and name pf the toolchain XML file that will be generated.
+ * If not provided, the XML will be written to the standard output.
+ */
+ @Parameter(property = "toolchain.file")
+ String file;
+
+ /**
+ * Toolchain discoverer
+ */
+ @Inject
+ ToolchainDiscoverer discoverer;
+
+ @Override
+ public void execute() throws MojoFailureException {
+ try {
+ PersistedToolchains toolchains = discoverer.discoverToolchains();
+ if (file != null) {
+ Path file = Paths.get(this.file).toAbsolutePath();
+ Files.createDirectories(file.getParent());
+ try (Writer writer = Files.newBufferedWriter(file)) {
Review Comment:
add a UTF-8 charset here
##########
src/main/java/org/apache/maven/plugins/toolchain/jdk/ToolchainDiscoverer.java:
##########
@@ -0,0 +1,433 @@
+/*
+ * 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.plugins.toolchain.jdk;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.maven.toolchain.model.PersistedToolchains;
+import org.apache.maven.toolchain.model.ToolchainModel;
+import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Reader;
+import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Writer;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static
org.apache.maven.plugins.toolchain.jdk.SelectJdkToolchainMojo.TOOLCHAIN_TYPE_JDK;
+
+/**
+ * Toolchain discoverer service
+ */
+@Named
+@Singleton
+public class ToolchainDiscoverer {
+
+ public static final String JAVA = "java.";
+ public static final String VERSION = "version";
+ public static final String RUNTIME_NAME = "runtime.name";
+ public static final String RUNTIME_VERSION = "runtime.version";
+ public static final String VENDOR = "vendor";
+ public static final String VENDOR_VERSION = "vendor.version";
+ public static final String[] PROPERTIES = {VERSION, RUNTIME_NAME,
RUNTIME_VERSION, VENDOR, VENDOR_VERSION};
+
+ public static final String DISCOVERED_TOOLCHAINS_CACHE_XML =
".m2/discovered-toolchains-cache.xml";
+
+ public static final String CURRENT = "current";
+ public static final String ENV = "env";
+ public static final String LTS = "lts";
+
+ public static final String JDK_HOME = "jdkHome";
+ public static final String JAVA_HOME = "java.home";
+
+ private static final String COMMA = ",";
+ public static final String USER_HOME = "user.home";
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private Map<Path, ToolchainModel> cache;
+ private boolean cacheModified;
+
+ /**
+ * Build the model for the current JDK toolchain
+ */
+ public Optional<ToolchainModel> getCurrentJdkToolchain() {
+ Path currentJdkHome =
getCanonicalPath(Paths.get(System.getProperty(JAVA_HOME)));
+ if (hasJavaC(currentJdkHome)) {
+ // in case the current JVM is not a JDK
+ return Optional.empty();
+ }
+ ToolchainModel model = new ToolchainModel();
+ model.setType(TOOLCHAIN_TYPE_JDK);
+ Stream.of(PROPERTIES).forEach(k -> {
+ String v = System.getProperty(JAVA + k);
+ if (v != null) {
+ model.addProvide(k.substring(JAVA.length()), v);
+ }
+ });
+ model.addProvide(CURRENT, "true");
+ Xpp3Dom config = new Xpp3Dom("configuration");
+ Xpp3Dom jdkHome = new Xpp3Dom(JDK_HOME);
+ jdkHome.setValue(currentJdkHome.toString());
+ config.addChild(jdkHome);
+ model.setConfiguration(config);
+ return Optional.of(model);
+ }
+
+ public PersistedToolchains discoverToolchains() {
+ return discoverToolchains(LTS + COMMA + VERSION + COMMA + VENDOR);
+ }
+
+ /**
+ * Returns a PersistedToolchains object containing a list of discovered
toolchains,
+ * never <code>null</code>.
+ */
+ public PersistedToolchains discoverToolchains(String comparator) {
+ try {
+ Set<Path> jdks = findJdks();
+ log.info("Found " + jdks.size() + " possible jdks: " + jdks);
+ cacheModified = false;
+ readCache();
+ Map<Path, Map<String, String>> flags = new HashMap<>();
+ Path currentJdkHome =
getCanonicalPath(Paths.get(System.getProperty(JAVA_HOME)));
+ flags.computeIfAbsent(currentJdkHome, p -> new
HashMap<>()).put(CURRENT, "true");
+ // check environment variables for JAVA{xx}_HOME
+ System.getenv().entrySet().stream()
+ .filter(e -> e.getKey().startsWith("JAVA") &&
e.getKey().endsWith("_HOME"))
Review Comment:
maybe a regex including the digits?
##########
src/main/java/org/apache/maven/plugins/toolchain/jdk/ToolchainDiscoverer.java:
##########
@@ -0,0 +1,433 @@
+/*
+ * 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.plugins.toolchain.jdk;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.maven.toolchain.model.PersistedToolchains;
+import org.apache.maven.toolchain.model.ToolchainModel;
+import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Reader;
+import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Writer;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static
org.apache.maven.plugins.toolchain.jdk.SelectJdkToolchainMojo.TOOLCHAIN_TYPE_JDK;
+
+/**
+ * Toolchain discoverer service
+ */
+@Named
+@Singleton
+public class ToolchainDiscoverer {
+
+ public static final String JAVA = "java.";
+ public static final String VERSION = "version";
+ public static final String RUNTIME_NAME = "runtime.name";
+ public static final String RUNTIME_VERSION = "runtime.version";
+ public static final String VENDOR = "vendor";
+ public static final String VENDOR_VERSION = "vendor.version";
+ public static final String[] PROPERTIES = {VERSION, RUNTIME_NAME,
RUNTIME_VERSION, VENDOR, VENDOR_VERSION};
+
+ public static final String DISCOVERED_TOOLCHAINS_CACHE_XML =
".m2/discovered-toolchains-cache.xml";
+
+ public static final String CURRENT = "current";
+ public static final String ENV = "env";
+ public static final String LTS = "lts";
+
+ public static final String JDK_HOME = "jdkHome";
+ public static final String JAVA_HOME = "java.home";
+
+ private static final String COMMA = ",";
+ public static final String USER_HOME = "user.home";
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private Map<Path, ToolchainModel> cache;
+ private boolean cacheModified;
+
+ /**
+ * Build the model for the current JDK toolchain
+ */
+ public Optional<ToolchainModel> getCurrentJdkToolchain() {
+ Path currentJdkHome =
getCanonicalPath(Paths.get(System.getProperty(JAVA_HOME)));
+ if (hasJavaC(currentJdkHome)) {
+ // in case the current JVM is not a JDK
+ return Optional.empty();
+ }
+ ToolchainModel model = new ToolchainModel();
+ model.setType(TOOLCHAIN_TYPE_JDK);
+ Stream.of(PROPERTIES).forEach(k -> {
+ String v = System.getProperty(JAVA + k);
+ if (v != null) {
+ model.addProvide(k.substring(JAVA.length()), v);
+ }
+ });
+ model.addProvide(CURRENT, "true");
+ Xpp3Dom config = new Xpp3Dom("configuration");
+ Xpp3Dom jdkHome = new Xpp3Dom(JDK_HOME);
+ jdkHome.setValue(currentJdkHome.toString());
+ config.addChild(jdkHome);
+ model.setConfiguration(config);
+ return Optional.of(model);
+ }
+
+ public PersistedToolchains discoverToolchains() {
+ return discoverToolchains(LTS + COMMA + VERSION + COMMA + VENDOR);
+ }
+
+ /**
+ * Returns a PersistedToolchains object containing a list of discovered
toolchains,
+ * never <code>null</code>.
+ */
+ public PersistedToolchains discoverToolchains(String comparator) {
+ try {
+ Set<Path> jdks = findJdks();
+ log.info("Found " + jdks.size() + " possible jdks: " + jdks);
+ cacheModified = false;
+ readCache();
+ Map<Path, Map<String, String>> flags = new HashMap<>();
+ Path currentJdkHome =
getCanonicalPath(Paths.get(System.getProperty(JAVA_HOME)));
+ flags.computeIfAbsent(currentJdkHome, p -> new
HashMap<>()).put(CURRENT, "true");
+ // check environment variables for JAVA{xx}_HOME
+ System.getenv().entrySet().stream()
+ .filter(e -> e.getKey().startsWith("JAVA") &&
e.getKey().endsWith("_HOME"))
+ .forEach(e -> {
+ Path path = getCanonicalPath(Paths.get(e.getValue()));
+ Map<String, String> f = flags.computeIfAbsent(path, p
-> new HashMap<>());
+ String val = f.getOrDefault(ENV, "");
+ f.put(ENV, (val.isEmpty() ? "" : val + ",") +
e.getKey());
+ });
+
+ List<ToolchainModel> tcs = jdks.parallelStream()
+ .map(s -> {
+ ToolchainModel tc = getToolchainModel(s);
+ flags.getOrDefault(s, Collections.emptyMap())
+ .forEach((k, v) ->
tc.getProvides().setProperty(k, v));
+ String version = tc.getProvides().getProperty(VERSION);
+ if (isLts(version)) {
+ tc.getProvides().setProperty(LTS, "true");
+ }
+ return tc;
+ })
+ .sorted(getToolchainModelComparator(comparator))
+ .collect(Collectors.toList());
+ if (this.cacheModified) {
+ writeCache();
+ }
+ PersistedToolchains ps = new PersistedToolchains();
+ ps.setToolchains(tcs);
+ return ps;
+ } catch (Exception e) {
+ if (log.isDebugEnabled()) {
Review Comment:
The if block doesn't seem to do much.
More significantly I'm not sure this is the right error handling. Is it
expected that there's an error discovering toolchains? if so, no message at
all. If it's not expected, maybe always a message. What does it mean if the
toolchains fail here?
##########
src/main/java/org/apache/maven/plugins/toolchain/jdk/ToolchainDiscoverer.java:
##########
@@ -0,0 +1,433 @@
+/*
+ * 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.plugins.toolchain.jdk;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.maven.toolchain.model.PersistedToolchains;
+import org.apache.maven.toolchain.model.ToolchainModel;
+import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Reader;
+import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Writer;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static
org.apache.maven.plugins.toolchain.jdk.SelectJdkToolchainMojo.TOOLCHAIN_TYPE_JDK;
+
+/**
+ * Toolchain discoverer service
+ */
+@Named
+@Singleton
+public class ToolchainDiscoverer {
+
+ public static final String JAVA = "java.";
+ public static final String VERSION = "version";
+ public static final String RUNTIME_NAME = "runtime.name";
+ public static final String RUNTIME_VERSION = "runtime.version";
+ public static final String VENDOR = "vendor";
+ public static final String VENDOR_VERSION = "vendor.version";
+ public static final String[] PROPERTIES = {VERSION, RUNTIME_NAME,
RUNTIME_VERSION, VENDOR, VENDOR_VERSION};
+
+ public static final String DISCOVERED_TOOLCHAINS_CACHE_XML =
".m2/discovered-toolchains-cache.xml";
+
+ public static final String CURRENT = "current";
+ public static final String ENV = "env";
+ public static final String LTS = "lts";
+
+ public static final String JDK_HOME = "jdkHome";
+ public static final String JAVA_HOME = "java.home";
+
+ private static final String COMMA = ",";
+ public static final String USER_HOME = "user.home";
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private Map<Path, ToolchainModel> cache;
+ private boolean cacheModified;
+
+ /**
+ * Build the model for the current JDK toolchain
+ */
+ public Optional<ToolchainModel> getCurrentJdkToolchain() {
+ Path currentJdkHome =
getCanonicalPath(Paths.get(System.getProperty(JAVA_HOME)));
+ if (hasJavaC(currentJdkHome)) {
+ // in case the current JVM is not a JDK
+ return Optional.empty();
+ }
+ ToolchainModel model = new ToolchainModel();
+ model.setType(TOOLCHAIN_TYPE_JDK);
+ Stream.of(PROPERTIES).forEach(k -> {
+ String v = System.getProperty(JAVA + k);
+ if (v != null) {
+ model.addProvide(k.substring(JAVA.length()), v);
+ }
+ });
+ model.addProvide(CURRENT, "true");
+ Xpp3Dom config = new Xpp3Dom("configuration");
+ Xpp3Dom jdkHome = new Xpp3Dom(JDK_HOME);
+ jdkHome.setValue(currentJdkHome.toString());
+ config.addChild(jdkHome);
+ model.setConfiguration(config);
+ return Optional.of(model);
+ }
+
+ public PersistedToolchains discoverToolchains() {
+ return discoverToolchains(LTS + COMMA + VERSION + COMMA + VENDOR);
+ }
+
+ /**
+ * Returns a PersistedToolchains object containing a list of discovered
toolchains,
+ * never <code>null</code>.
+ */
+ public PersistedToolchains discoverToolchains(String comparator) {
+ try {
+ Set<Path> jdks = findJdks();
+ log.info("Found " + jdks.size() + " possible jdks: " + jdks);
+ cacheModified = false;
+ readCache();
+ Map<Path, Map<String, String>> flags = new HashMap<>();
+ Path currentJdkHome =
getCanonicalPath(Paths.get(System.getProperty(JAVA_HOME)));
+ flags.computeIfAbsent(currentJdkHome, p -> new
HashMap<>()).put(CURRENT, "true");
+ // check environment variables for JAVA{xx}_HOME
+ System.getenv().entrySet().stream()
+ .filter(e -> e.getKey().startsWith("JAVA") &&
e.getKey().endsWith("_HOME"))
+ .forEach(e -> {
+ Path path = getCanonicalPath(Paths.get(e.getValue()));
+ Map<String, String> f = flags.computeIfAbsent(path, p
-> new HashMap<>());
+ String val = f.getOrDefault(ENV, "");
+ f.put(ENV, (val.isEmpty() ? "" : val + ",") +
e.getKey());
+ });
+
+ List<ToolchainModel> tcs = jdks.parallelStream()
+ .map(s -> {
+ ToolchainModel tc = getToolchainModel(s);
+ flags.getOrDefault(s, Collections.emptyMap())
+ .forEach((k, v) ->
tc.getProvides().setProperty(k, v));
+ String version = tc.getProvides().getProperty(VERSION);
+ if (isLts(version)) {
+ tc.getProvides().setProperty(LTS, "true");
+ }
+ return tc;
+ })
+ .sorted(getToolchainModelComparator(comparator))
+ .collect(Collectors.toList());
+ if (this.cacheModified) {
+ writeCache();
+ }
+ PersistedToolchains ps = new PersistedToolchains();
+ ps.setToolchains(tcs);
+ return ps;
+ } catch (Exception e) {
+ if (log.isDebugEnabled()) {
+ log.warn("Error discovering toolchains: " + e, e);
+ } else {
+ log.warn("Error discovering toolchains (enable debug level for
more information): " + e);
+ }
+ return new PersistedToolchains();
+ }
+ }
+
+ private static boolean isLts(String version) {
+ return version.startsWith("1.8.")
+ || version.startsWith("11.")
+ || version.startsWith("17.")
+ || version.startsWith("21.")
+ || version.startsWith("25.");
+ }
+
+ private void readCache() {
+ try {
+ cache = new ConcurrentHashMap<>();
+ Path cacheFile = getCacheFile();
+ if (Files.isRegularFile(cacheFile)) {
+ try (Reader r = Files.newBufferedReader(cacheFile)) {
+ PersistedToolchains pt = new
MavenToolchainsXpp3Reader().read(r, false);
+ cache = pt.getToolchains().stream()
+ // Remove stale entries
+ .filter(tc -> {
+ // If the bin/java executable is not available
anymore, remove this TC
+ if (!hasJavaC(getJdkHome(tc))) {
+ cacheModified = false;
+ return false;
+ } else {
+ return true;
+ }
+ })
+
.collect(Collectors.toConcurrentMap(this::getJdkHome, Function.identity()));
+ }
+ }
+ } catch (IOException | XmlPullParserException e) {
+ log.warn("Error reading toolchains cache: " + e);
+ }
+ }
+
+ private void writeCache() {
+ try {
+ Path cacheFile = getCacheFile();
+ Files.createDirectories(cacheFile.getParent());
+ try (Writer w = Files.newBufferedWriter(cacheFile)) {
Review Comment:
charset
##########
src/main/java/org/apache/maven/plugins/toolchain/jdk/ToolchainDiscoverer.java:
##########
@@ -0,0 +1,433 @@
+/*
+ * 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.plugins.toolchain.jdk;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.maven.toolchain.model.PersistedToolchains;
+import org.apache.maven.toolchain.model.ToolchainModel;
+import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Reader;
+import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Writer;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static
org.apache.maven.plugins.toolchain.jdk.SelectJdkToolchainMojo.TOOLCHAIN_TYPE_JDK;
+
+/**
+ * Toolchain discoverer service
+ */
+@Named
+@Singleton
+public class ToolchainDiscoverer {
+
+ public static final String JAVA = "java.";
+ public static final String VERSION = "version";
+ public static final String RUNTIME_NAME = "runtime.name";
+ public static final String RUNTIME_VERSION = "runtime.version";
+ public static final String VENDOR = "vendor";
+ public static final String VENDOR_VERSION = "vendor.version";
+ public static final String[] PROPERTIES = {VERSION, RUNTIME_NAME,
RUNTIME_VERSION, VENDOR, VENDOR_VERSION};
+
+ public static final String DISCOVERED_TOOLCHAINS_CACHE_XML =
".m2/discovered-toolchains-cache.xml";
+
+ public static final String CURRENT = "current";
+ public static final String ENV = "env";
+ public static final String LTS = "lts";
+
+ public static final String JDK_HOME = "jdkHome";
+ public static final String JAVA_HOME = "java.home";
+
+ private static final String COMMA = ",";
+ public static final String USER_HOME = "user.home";
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private Map<Path, ToolchainModel> cache;
+ private boolean cacheModified;
+
+ /**
+ * Build the model for the current JDK toolchain
+ */
+ public Optional<ToolchainModel> getCurrentJdkToolchain() {
+ Path currentJdkHome =
getCanonicalPath(Paths.get(System.getProperty(JAVA_HOME)));
+ if (hasJavaC(currentJdkHome)) {
+ // in case the current JVM is not a JDK
+ return Optional.empty();
+ }
+ ToolchainModel model = new ToolchainModel();
+ model.setType(TOOLCHAIN_TYPE_JDK);
+ Stream.of(PROPERTIES).forEach(k -> {
+ String v = System.getProperty(JAVA + k);
+ if (v != null) {
+ model.addProvide(k.substring(JAVA.length()), v);
+ }
+ });
+ model.addProvide(CURRENT, "true");
+ Xpp3Dom config = new Xpp3Dom("configuration");
+ Xpp3Dom jdkHome = new Xpp3Dom(JDK_HOME);
+ jdkHome.setValue(currentJdkHome.toString());
+ config.addChild(jdkHome);
+ model.setConfiguration(config);
+ return Optional.of(model);
+ }
+
+ public PersistedToolchains discoverToolchains() {
+ return discoverToolchains(LTS + COMMA + VERSION + COMMA + VENDOR);
+ }
+
+ /**
+ * Returns a PersistedToolchains object containing a list of discovered
toolchains,
+ * never <code>null</code>.
+ */
+ public PersistedToolchains discoverToolchains(String comparator) {
+ try {
+ Set<Path> jdks = findJdks();
+ log.info("Found " + jdks.size() + " possible jdks: " + jdks);
+ cacheModified = false;
+ readCache();
+ Map<Path, Map<String, String>> flags = new HashMap<>();
+ Path currentJdkHome =
getCanonicalPath(Paths.get(System.getProperty(JAVA_HOME)));
+ flags.computeIfAbsent(currentJdkHome, p -> new
HashMap<>()).put(CURRENT, "true");
+ // check environment variables for JAVA{xx}_HOME
+ System.getenv().entrySet().stream()
+ .filter(e -> e.getKey().startsWith("JAVA") &&
e.getKey().endsWith("_HOME"))
+ .forEach(e -> {
+ Path path = getCanonicalPath(Paths.get(e.getValue()));
+ Map<String, String> f = flags.computeIfAbsent(path, p
-> new HashMap<>());
+ String val = f.getOrDefault(ENV, "");
+ f.put(ENV, (val.isEmpty() ? "" : val + ",") +
e.getKey());
+ });
+
+ List<ToolchainModel> tcs = jdks.parallelStream()
+ .map(s -> {
+ ToolchainModel tc = getToolchainModel(s);
+ flags.getOrDefault(s, Collections.emptyMap())
+ .forEach((k, v) ->
tc.getProvides().setProperty(k, v));
+ String version = tc.getProvides().getProperty(VERSION);
+ if (isLts(version)) {
+ tc.getProvides().setProperty(LTS, "true");
+ }
+ return tc;
+ })
+ .sorted(getToolchainModelComparator(comparator))
+ .collect(Collectors.toList());
+ if (this.cacheModified) {
+ writeCache();
+ }
+ PersistedToolchains ps = new PersistedToolchains();
+ ps.setToolchains(tcs);
+ return ps;
+ } catch (Exception e) {
+ if (log.isDebugEnabled()) {
+ log.warn("Error discovering toolchains: " + e, e);
+ } else {
+ log.warn("Error discovering toolchains (enable debug level for
more information): " + e);
+ }
+ return new PersistedToolchains();
+ }
+ }
+
+ private static boolean isLts(String version) {
+ return version.startsWith("1.8.")
+ || version.startsWith("11.")
+ || version.startsWith("17.")
+ || version.startsWith("21.")
+ || version.startsWith("25.");
+ }
+
+ private void readCache() {
+ try {
+ cache = new ConcurrentHashMap<>();
+ Path cacheFile = getCacheFile();
+ if (Files.isRegularFile(cacheFile)) {
+ try (Reader r = Files.newBufferedReader(cacheFile)) {
+ PersistedToolchains pt = new
MavenToolchainsXpp3Reader().read(r, false);
+ cache = pt.getToolchains().stream()
+ // Remove stale entries
+ .filter(tc -> {
+ // If the bin/java executable is not available
anymore, remove this TC
+ if (!hasJavaC(getJdkHome(tc))) {
+ cacheModified = false;
+ return false;
+ } else {
+ return true;
+ }
+ })
+
.collect(Collectors.toConcurrentMap(this::getJdkHome, Function.identity()));
+ }
+ }
+ } catch (IOException | XmlPullParserException e) {
+ log.warn("Error reading toolchains cache: " + e);
+ }
+ }
+
+ private void writeCache() {
+ try {
+ Path cacheFile = getCacheFile();
+ Files.createDirectories(cacheFile.getParent());
+ try (Writer w = Files.newBufferedWriter(cacheFile)) {
+ PersistedToolchains pt = new PersistedToolchains();
+ pt.setToolchains(cache.values().stream()
+ .map(tc -> {
+ ToolchainModel model = tc.clone();
+ model.getProvides().remove(CURRENT);
+ model.getProvides().remove(ENV);
+ return model;
+ })
+ .sorted(version().thenComparing(vendor()))
+ .collect(Collectors.toList()));
+ new MavenToolchainsXpp3Writer().write(w, pt);
+ }
+ } catch (IOException e) {
+ log.warn("Error writing toolchains cache: " + e);
+ }
+ }
+
+ private static Path getCacheFile() {
+ return
Paths.get(System.getProperty(USER_HOME)).resolve(DISCOVERED_TOOLCHAINS_CACHE_XML);
+ }
+
+ private Path getJdkHome(ToolchainModel toolchain) {
+ Xpp3Dom dom = (Xpp3Dom) toolchain.getConfiguration();
+ Xpp3Dom javahome = dom != null ? dom.getChild(JDK_HOME) : null;
+ String jdk = javahome != null ? javahome.getValue() : null;
+ return Paths.get(Objects.requireNonNull(jdk));
+ }
+
+ ToolchainModel getToolchainModel(Path jdk) {
+ log.debug("Computing model for " + jdk);
+
+ ToolchainModel model = cache.get(jdk);
+ if (model == null) {
+ model = doGetToolchainModel(jdk);
+ cache.put(jdk, model);
+ cacheModified = true;
+ }
+
+ return model;
+ }
+
+ ToolchainModel doGetToolchainModel(Path jdk) {
+ Path java = jdk.resolve("bin/java");
+ if (!java.toFile().canExecute()) {
+ java = jdk.resolve("bin/java.exe");
+ if (!java.toFile().canExecute()) {
+ log.debug("JDK toolchain discovered at " + jdk + " will be
ignored: unable to find java executable");
Review Comment:
Not quite accurate. It found java. It just can't execute it.
##########
src/main/java/org/apache/maven/plugins/toolchain/jdk/ToolchainDiscoverer.java:
##########
@@ -0,0 +1,433 @@
+/*
+ * 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.plugins.toolchain.jdk;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.maven.toolchain.model.PersistedToolchains;
+import org.apache.maven.toolchain.model.ToolchainModel;
+import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Reader;
+import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Writer;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static
org.apache.maven.plugins.toolchain.jdk.SelectJdkToolchainMojo.TOOLCHAIN_TYPE_JDK;
+
+/**
+ * Toolchain discoverer service
+ */
+@Named
+@Singleton
+public class ToolchainDiscoverer {
+
+ public static final String JAVA = "java.";
+ public static final String VERSION = "version";
+ public static final String RUNTIME_NAME = "runtime.name";
+ public static final String RUNTIME_VERSION = "runtime.version";
+ public static final String VENDOR = "vendor";
+ public static final String VENDOR_VERSION = "vendor.version";
+ public static final String[] PROPERTIES = {VERSION, RUNTIME_NAME,
RUNTIME_VERSION, VENDOR, VENDOR_VERSION};
+
+ public static final String DISCOVERED_TOOLCHAINS_CACHE_XML =
".m2/discovered-toolchains-cache.xml";
+
+ public static final String CURRENT = "current";
+ public static final String ENV = "env";
+ public static final String LTS = "lts";
+
+ public static final String JDK_HOME = "jdkHome";
+ public static final String JAVA_HOME = "java.home";
+
+ private static final String COMMA = ",";
+ public static final String USER_HOME = "user.home";
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private Map<Path, ToolchainModel> cache;
+ private boolean cacheModified;
+
+ /**
+ * Build the model for the current JDK toolchain
+ */
+ public Optional<ToolchainModel> getCurrentJdkToolchain() {
+ Path currentJdkHome =
getCanonicalPath(Paths.get(System.getProperty(JAVA_HOME)));
+ if (hasJavaC(currentJdkHome)) {
+ // in case the current JVM is not a JDK
+ return Optional.empty();
+ }
+ ToolchainModel model = new ToolchainModel();
+ model.setType(TOOLCHAIN_TYPE_JDK);
+ Stream.of(PROPERTIES).forEach(k -> {
+ String v = System.getProperty(JAVA + k);
+ if (v != null) {
+ model.addProvide(k.substring(JAVA.length()), v);
+ }
+ });
+ model.addProvide(CURRENT, "true");
+ Xpp3Dom config = new Xpp3Dom("configuration");
+ Xpp3Dom jdkHome = new Xpp3Dom(JDK_HOME);
+ jdkHome.setValue(currentJdkHome.toString());
+ config.addChild(jdkHome);
+ model.setConfiguration(config);
+ return Optional.of(model);
+ }
+
+ public PersistedToolchains discoverToolchains() {
+ return discoverToolchains(LTS + COMMA + VERSION + COMMA + VENDOR);
+ }
+
+ /**
+ * Returns a PersistedToolchains object containing a list of discovered
toolchains,
+ * never <code>null</code>.
+ */
+ public PersistedToolchains discoverToolchains(String comparator) {
+ try {
+ Set<Path> jdks = findJdks();
+ log.info("Found " + jdks.size() + " possible jdks: " + jdks);
+ cacheModified = false;
+ readCache();
+ Map<Path, Map<String, String>> flags = new HashMap<>();
+ Path currentJdkHome =
getCanonicalPath(Paths.get(System.getProperty(JAVA_HOME)));
+ flags.computeIfAbsent(currentJdkHome, p -> new
HashMap<>()).put(CURRENT, "true");
+ // check environment variables for JAVA{xx}_HOME
+ System.getenv().entrySet().stream()
+ .filter(e -> e.getKey().startsWith("JAVA") &&
e.getKey().endsWith("_HOME"))
+ .forEach(e -> {
+ Path path = getCanonicalPath(Paths.get(e.getValue()));
+ Map<String, String> f = flags.computeIfAbsent(path, p
-> new HashMap<>());
+ String val = f.getOrDefault(ENV, "");
+ f.put(ENV, (val.isEmpty() ? "" : val + ",") +
e.getKey());
+ });
+
+ List<ToolchainModel> tcs = jdks.parallelStream()
+ .map(s -> {
+ ToolchainModel tc = getToolchainModel(s);
+ flags.getOrDefault(s, Collections.emptyMap())
+ .forEach((k, v) ->
tc.getProvides().setProperty(k, v));
+ String version = tc.getProvides().getProperty(VERSION);
+ if (isLts(version)) {
+ tc.getProvides().setProperty(LTS, "true");
+ }
+ return tc;
+ })
+ .sorted(getToolchainModelComparator(comparator))
+ .collect(Collectors.toList());
+ if (this.cacheModified) {
+ writeCache();
+ }
+ PersistedToolchains ps = new PersistedToolchains();
+ ps.setToolchains(tcs);
+ return ps;
+ } catch (Exception e) {
+ if (log.isDebugEnabled()) {
+ log.warn("Error discovering toolchains: " + e, e);
+ } else {
+ log.warn("Error discovering toolchains (enable debug level for
more information): " + e);
+ }
+ return new PersistedToolchains();
+ }
+ }
+
+ private static boolean isLts(String version) {
+ return version.startsWith("1.8.")
+ || version.startsWith("11.")
+ || version.startsWith("17.")
+ || version.startsWith("21.")
+ || version.startsWith("25.");
+ }
+
+ private void readCache() {
+ try {
+ cache = new ConcurrentHashMap<>();
+ Path cacheFile = getCacheFile();
+ if (Files.isRegularFile(cacheFile)) {
+ try (Reader r = Files.newBufferedReader(cacheFile)) {
+ PersistedToolchains pt = new
MavenToolchainsXpp3Reader().read(r, false);
+ cache = pt.getToolchains().stream()
+ // Remove stale entries
+ .filter(tc -> {
+ // If the bin/java executable is not available
anymore, remove this TC
+ if (!hasJavaC(getJdkHome(tc))) {
+ cacheModified = false;
+ return false;
+ } else {
+ return true;
+ }
+ })
+
.collect(Collectors.toConcurrentMap(this::getJdkHome, Function.identity()));
+ }
+ }
+ } catch (IOException | XmlPullParserException e) {
+ log.warn("Error reading toolchains cache: " + e);
+ }
+ }
+
+ private void writeCache() {
+ try {
+ Path cacheFile = getCacheFile();
+ Files.createDirectories(cacheFile.getParent());
+ try (Writer w = Files.newBufferedWriter(cacheFile)) {
+ PersistedToolchains pt = new PersistedToolchains();
+ pt.setToolchains(cache.values().stream()
+ .map(tc -> {
+ ToolchainModel model = tc.clone();
+ model.getProvides().remove(CURRENT);
+ model.getProvides().remove(ENV);
+ return model;
+ })
+ .sorted(version().thenComparing(vendor()))
+ .collect(Collectors.toList()));
+ new MavenToolchainsXpp3Writer().write(w, pt);
+ }
+ } catch (IOException e) {
+ log.warn("Error writing toolchains cache: " + e);
+ }
+ }
+
+ private static Path getCacheFile() {
+ return
Paths.get(System.getProperty(USER_HOME)).resolve(DISCOVERED_TOOLCHAINS_CACHE_XML);
+ }
+
+ private Path getJdkHome(ToolchainModel toolchain) {
+ Xpp3Dom dom = (Xpp3Dom) toolchain.getConfiguration();
+ Xpp3Dom javahome = dom != null ? dom.getChild(JDK_HOME) : null;
+ String jdk = javahome != null ? javahome.getValue() : null;
+ return Paths.get(Objects.requireNonNull(jdk));
+ }
+
+ ToolchainModel getToolchainModel(Path jdk) {
+ log.debug("Computing model for " + jdk);
Review Comment:
remove
##########
src/main/java/org/apache/maven/plugins/toolchain/jdk/ToolchainDiscoverer.java:
##########
@@ -0,0 +1,433 @@
+/*
+ * 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.plugins.toolchain.jdk;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.maven.toolchain.model.PersistedToolchains;
+import org.apache.maven.toolchain.model.ToolchainModel;
+import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Reader;
+import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Writer;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static
org.apache.maven.plugins.toolchain.jdk.SelectJdkToolchainMojo.TOOLCHAIN_TYPE_JDK;
+
+/**
+ * Toolchain discoverer service
+ */
+@Named
+@Singleton
+public class ToolchainDiscoverer {
+
+ public static final String JAVA = "java.";
+ public static final String VERSION = "version";
+ public static final String RUNTIME_NAME = "runtime.name";
+ public static final String RUNTIME_VERSION = "runtime.version";
+ public static final String VENDOR = "vendor";
+ public static final String VENDOR_VERSION = "vendor.version";
+ public static final String[] PROPERTIES = {VERSION, RUNTIME_NAME,
RUNTIME_VERSION, VENDOR, VENDOR_VERSION};
+
+ public static final String DISCOVERED_TOOLCHAINS_CACHE_XML =
".m2/discovered-toolchains-cache.xml";
+
+ public static final String CURRENT = "current";
+ public static final String ENV = "env";
+ public static final String LTS = "lts";
+
+ public static final String JDK_HOME = "jdkHome";
+ public static final String JAVA_HOME = "java.home";
+
+ private static final String COMMA = ",";
+ public static final String USER_HOME = "user.home";
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private Map<Path, ToolchainModel> cache;
+ private boolean cacheModified;
+
+ /**
+ * Build the model for the current JDK toolchain
+ */
+ public Optional<ToolchainModel> getCurrentJdkToolchain() {
+ Path currentJdkHome =
getCanonicalPath(Paths.get(System.getProperty(JAVA_HOME)));
+ if (hasJavaC(currentJdkHome)) {
+ // in case the current JVM is not a JDK
+ return Optional.empty();
+ }
+ ToolchainModel model = new ToolchainModel();
+ model.setType(TOOLCHAIN_TYPE_JDK);
+ Stream.of(PROPERTIES).forEach(k -> {
+ String v = System.getProperty(JAVA + k);
+ if (v != null) {
+ model.addProvide(k.substring(JAVA.length()), v);
+ }
+ });
+ model.addProvide(CURRENT, "true");
+ Xpp3Dom config = new Xpp3Dom("configuration");
+ Xpp3Dom jdkHome = new Xpp3Dom(JDK_HOME);
+ jdkHome.setValue(currentJdkHome.toString());
+ config.addChild(jdkHome);
+ model.setConfiguration(config);
+ return Optional.of(model);
+ }
+
+ public PersistedToolchains discoverToolchains() {
+ return discoverToolchains(LTS + COMMA + VERSION + COMMA + VENDOR);
+ }
+
+ /**
+ * Returns a PersistedToolchains object containing a list of discovered
toolchains,
+ * never <code>null</code>.
+ */
+ public PersistedToolchains discoverToolchains(String comparator) {
+ try {
+ Set<Path> jdks = findJdks();
+ log.info("Found " + jdks.size() + " possible jdks: " + jdks);
+ cacheModified = false;
+ readCache();
+ Map<Path, Map<String, String>> flags = new HashMap<>();
+ Path currentJdkHome =
getCanonicalPath(Paths.get(System.getProperty(JAVA_HOME)));
+ flags.computeIfAbsent(currentJdkHome, p -> new
HashMap<>()).put(CURRENT, "true");
+ // check environment variables for JAVA{xx}_HOME
+ System.getenv().entrySet().stream()
+ .filter(e -> e.getKey().startsWith("JAVA") &&
e.getKey().endsWith("_HOME"))
+ .forEach(e -> {
+ Path path = getCanonicalPath(Paths.get(e.getValue()));
+ Map<String, String> f = flags.computeIfAbsent(path, p
-> new HashMap<>());
+ String val = f.getOrDefault(ENV, "");
+ f.put(ENV, (val.isEmpty() ? "" : val + ",") +
e.getKey());
+ });
+
+ List<ToolchainModel> tcs = jdks.parallelStream()
+ .map(s -> {
+ ToolchainModel tc = getToolchainModel(s);
+ flags.getOrDefault(s, Collections.emptyMap())
+ .forEach((k, v) ->
tc.getProvides().setProperty(k, v));
+ String version = tc.getProvides().getProperty(VERSION);
+ if (isLts(version)) {
+ tc.getProvides().setProperty(LTS, "true");
+ }
+ return tc;
+ })
+ .sorted(getToolchainModelComparator(comparator))
+ .collect(Collectors.toList());
+ if (this.cacheModified) {
+ writeCache();
+ }
+ PersistedToolchains ps = new PersistedToolchains();
+ ps.setToolchains(tcs);
+ return ps;
+ } catch (Exception e) {
+ if (log.isDebugEnabled()) {
+ log.warn("Error discovering toolchains: " + e, e);
+ } else {
+ log.warn("Error discovering toolchains (enable debug level for
more information): " + e);
+ }
+ return new PersistedToolchains();
+ }
+ }
+
+ private static boolean isLts(String version) {
+ return version.startsWith("1.8.")
+ || version.startsWith("11.")
+ || version.startsWith("17.")
+ || version.startsWith("21.")
+ || version.startsWith("25.");
+ }
+
+ private void readCache() {
+ try {
+ cache = new ConcurrentHashMap<>();
+ Path cacheFile = getCacheFile();
+ if (Files.isRegularFile(cacheFile)) {
+ try (Reader r = Files.newBufferedReader(cacheFile)) {
Review Comment:
charset
##########
src/main/java/org/apache/maven/plugins/toolchain/jdk/ToolchainDiscoverer.java:
##########
@@ -0,0 +1,433 @@
+/*
+ * 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.plugins.toolchain.jdk;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.maven.toolchain.model.PersistedToolchains;
+import org.apache.maven.toolchain.model.ToolchainModel;
+import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Reader;
+import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Writer;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static
org.apache.maven.plugins.toolchain.jdk.SelectJdkToolchainMojo.TOOLCHAIN_TYPE_JDK;
+
+/**
+ * Toolchain discoverer service
+ */
+@Named
+@Singleton
+public class ToolchainDiscoverer {
+
+ public static final String JAVA = "java.";
+ public static final String VERSION = "version";
+ public static final String RUNTIME_NAME = "runtime.name";
+ public static final String RUNTIME_VERSION = "runtime.version";
+ public static final String VENDOR = "vendor";
+ public static final String VENDOR_VERSION = "vendor.version";
+ public static final String[] PROPERTIES = {VERSION, RUNTIME_NAME,
RUNTIME_VERSION, VENDOR, VENDOR_VERSION};
+
+ public static final String DISCOVERED_TOOLCHAINS_CACHE_XML =
".m2/discovered-toolchains-cache.xml";
+
+ public static final String CURRENT = "current";
+ public static final String ENV = "env";
+ public static final String LTS = "lts";
+
+ public static final String JDK_HOME = "jdkHome";
+ public static final String JAVA_HOME = "java.home";
+
+ private static final String COMMA = ",";
+ public static final String USER_HOME = "user.home";
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private Map<Path, ToolchainModel> cache;
+ private boolean cacheModified;
+
+ /**
+ * Build the model for the current JDK toolchain
+ */
+ public Optional<ToolchainModel> getCurrentJdkToolchain() {
+ Path currentJdkHome =
getCanonicalPath(Paths.get(System.getProperty(JAVA_HOME)));
+ if (hasJavaC(currentJdkHome)) {
+ // in case the current JVM is not a JDK
+ return Optional.empty();
+ }
+ ToolchainModel model = new ToolchainModel();
+ model.setType(TOOLCHAIN_TYPE_JDK);
+ Stream.of(PROPERTIES).forEach(k -> {
+ String v = System.getProperty(JAVA + k);
+ if (v != null) {
+ model.addProvide(k.substring(JAVA.length()), v);
+ }
+ });
+ model.addProvide(CURRENT, "true");
+ Xpp3Dom config = new Xpp3Dom("configuration");
+ Xpp3Dom jdkHome = new Xpp3Dom(JDK_HOME);
+ jdkHome.setValue(currentJdkHome.toString());
+ config.addChild(jdkHome);
+ model.setConfiguration(config);
+ return Optional.of(model);
+ }
+
+ public PersistedToolchains discoverToolchains() {
+ return discoverToolchains(LTS + COMMA + VERSION + COMMA + VENDOR);
+ }
+
+ /**
+ * Returns a PersistedToolchains object containing a list of discovered
toolchains,
+ * never <code>null</code>.
+ */
+ public PersistedToolchains discoverToolchains(String comparator) {
+ try {
+ Set<Path> jdks = findJdks();
+ log.info("Found " + jdks.size() + " possible jdks: " + jdks);
+ cacheModified = false;
+ readCache();
+ Map<Path, Map<String, String>> flags = new HashMap<>();
+ Path currentJdkHome =
getCanonicalPath(Paths.get(System.getProperty(JAVA_HOME)));
+ flags.computeIfAbsent(currentJdkHome, p -> new
HashMap<>()).put(CURRENT, "true");
+ // check environment variables for JAVA{xx}_HOME
+ System.getenv().entrySet().stream()
+ .filter(e -> e.getKey().startsWith("JAVA") &&
e.getKey().endsWith("_HOME"))
+ .forEach(e -> {
+ Path path = getCanonicalPath(Paths.get(e.getValue()));
+ Map<String, String> f = flags.computeIfAbsent(path, p
-> new HashMap<>());
+ String val = f.getOrDefault(ENV, "");
+ f.put(ENV, (val.isEmpty() ? "" : val + ",") +
e.getKey());
+ });
+
+ List<ToolchainModel> tcs = jdks.parallelStream()
+ .map(s -> {
+ ToolchainModel tc = getToolchainModel(s);
+ flags.getOrDefault(s, Collections.emptyMap())
+ .forEach((k, v) ->
tc.getProvides().setProperty(k, v));
+ String version = tc.getProvides().getProperty(VERSION);
+ if (isLts(version)) {
+ tc.getProvides().setProperty(LTS, "true");
+ }
+ return tc;
+ })
+ .sorted(getToolchainModelComparator(comparator))
+ .collect(Collectors.toList());
+ if (this.cacheModified) {
+ writeCache();
+ }
+ PersistedToolchains ps = new PersistedToolchains();
+ ps.setToolchains(tcs);
+ return ps;
+ } catch (Exception e) {
+ if (log.isDebugEnabled()) {
+ log.warn("Error discovering toolchains: " + e, e);
+ } else {
+ log.warn("Error discovering toolchains (enable debug level for
more information): " + e);
+ }
+ return new PersistedToolchains();
+ }
+ }
+
+ private static boolean isLts(String version) {
+ return version.startsWith("1.8.")
+ || version.startsWith("11.")
+ || version.startsWith("17.")
+ || version.startsWith("21.")
+ || version.startsWith("25.");
+ }
+
+ private void readCache() {
+ try {
+ cache = new ConcurrentHashMap<>();
+ Path cacheFile = getCacheFile();
+ if (Files.isRegularFile(cacheFile)) {
+ try (Reader r = Files.newBufferedReader(cacheFile)) {
+ PersistedToolchains pt = new
MavenToolchainsXpp3Reader().read(r, false);
+ cache = pt.getToolchains().stream()
+ // Remove stale entries
+ .filter(tc -> {
+ // If the bin/java executable is not available
anymore, remove this TC
+ if (!hasJavaC(getJdkHome(tc))) {
+ cacheModified = false;
+ return false;
+ } else {
+ return true;
+ }
+ })
+
.collect(Collectors.toConcurrentMap(this::getJdkHome, Function.identity()));
+ }
+ }
+ } catch (IOException | XmlPullParserException e) {
+ log.warn("Error reading toolchains cache: " + e);
Review Comment:
If the cache isn't read, what's the effect? if we just read directly without
caching, then no warning should be logged. debug level at most.
How important is a cache here anyway? How long does it take to just
recompute every time?
##########
src/main/java/org/apache/maven/plugins/toolchain/jdk/ToolchainDiscoverer.java:
##########
@@ -0,0 +1,433 @@
+/*
+ * 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.plugins.toolchain.jdk;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.maven.toolchain.model.PersistedToolchains;
+import org.apache.maven.toolchain.model.ToolchainModel;
+import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Reader;
+import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Writer;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static
org.apache.maven.plugins.toolchain.jdk.SelectJdkToolchainMojo.TOOLCHAIN_TYPE_JDK;
+
+/**
+ * Toolchain discoverer service
+ */
+@Named
+@Singleton
+public class ToolchainDiscoverer {
+
+ public static final String JAVA = "java.";
+ public static final String VERSION = "version";
+ public static final String RUNTIME_NAME = "runtime.name";
+ public static final String RUNTIME_VERSION = "runtime.version";
+ public static final String VENDOR = "vendor";
+ public static final String VENDOR_VERSION = "vendor.version";
+ public static final String[] PROPERTIES = {VERSION, RUNTIME_NAME,
RUNTIME_VERSION, VENDOR, VENDOR_VERSION};
+
+ public static final String DISCOVERED_TOOLCHAINS_CACHE_XML =
".m2/discovered-toolchains-cache.xml";
+
+ public static final String CURRENT = "current";
+ public static final String ENV = "env";
+ public static final String LTS = "lts";
+
+ public static final String JDK_HOME = "jdkHome";
+ public static final String JAVA_HOME = "java.home";
+
+ private static final String COMMA = ",";
+ public static final String USER_HOME = "user.home";
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private Map<Path, ToolchainModel> cache;
+ private boolean cacheModified;
+
+ /**
+ * Build the model for the current JDK toolchain
+ */
+ public Optional<ToolchainModel> getCurrentJdkToolchain() {
+ Path currentJdkHome =
getCanonicalPath(Paths.get(System.getProperty(JAVA_HOME)));
+ if (hasJavaC(currentJdkHome)) {
+ // in case the current JVM is not a JDK
+ return Optional.empty();
+ }
+ ToolchainModel model = new ToolchainModel();
+ model.setType(TOOLCHAIN_TYPE_JDK);
+ Stream.of(PROPERTIES).forEach(k -> {
+ String v = System.getProperty(JAVA + k);
+ if (v != null) {
+ model.addProvide(k.substring(JAVA.length()), v);
+ }
+ });
+ model.addProvide(CURRENT, "true");
+ Xpp3Dom config = new Xpp3Dom("configuration");
+ Xpp3Dom jdkHome = new Xpp3Dom(JDK_HOME);
+ jdkHome.setValue(currentJdkHome.toString());
+ config.addChild(jdkHome);
+ model.setConfiguration(config);
+ return Optional.of(model);
+ }
+
+ public PersistedToolchains discoverToolchains() {
+ return discoverToolchains(LTS + COMMA + VERSION + COMMA + VENDOR);
+ }
+
+ /**
+ * Returns a PersistedToolchains object containing a list of discovered
toolchains,
+ * never <code>null</code>.
+ */
+ public PersistedToolchains discoverToolchains(String comparator) {
+ try {
+ Set<Path> jdks = findJdks();
+ log.info("Found " + jdks.size() + " possible jdks: " + jdks);
+ cacheModified = false;
+ readCache();
+ Map<Path, Map<String, String>> flags = new HashMap<>();
+ Path currentJdkHome =
getCanonicalPath(Paths.get(System.getProperty(JAVA_HOME)));
+ flags.computeIfAbsent(currentJdkHome, p -> new
HashMap<>()).put(CURRENT, "true");
+ // check environment variables for JAVA{xx}_HOME
+ System.getenv().entrySet().stream()
+ .filter(e -> e.getKey().startsWith("JAVA") &&
e.getKey().endsWith("_HOME"))
+ .forEach(e -> {
+ Path path = getCanonicalPath(Paths.get(e.getValue()));
+ Map<String, String> f = flags.computeIfAbsent(path, p
-> new HashMap<>());
+ String val = f.getOrDefault(ENV, "");
+ f.put(ENV, (val.isEmpty() ? "" : val + ",") +
e.getKey());
+ });
+
+ List<ToolchainModel> tcs = jdks.parallelStream()
+ .map(s -> {
+ ToolchainModel tc = getToolchainModel(s);
+ flags.getOrDefault(s, Collections.emptyMap())
+ .forEach((k, v) ->
tc.getProvides().setProperty(k, v));
+ String version = tc.getProvides().getProperty(VERSION);
+ if (isLts(version)) {
+ tc.getProvides().setProperty(LTS, "true");
+ }
+ return tc;
+ })
+ .sorted(getToolchainModelComparator(comparator))
+ .collect(Collectors.toList());
+ if (this.cacheModified) {
+ writeCache();
+ }
+ PersistedToolchains ps = new PersistedToolchains();
+ ps.setToolchains(tcs);
+ return ps;
+ } catch (Exception e) {
Review Comment:
can this be a more specific exception?
> Automatic discovery of JDK toolchains
> -------------------------------------
>
> Key: MTOOLCHAINS-49
> URL: https://issues.apache.org/jira/browse/MTOOLCHAINS-49
> Project: Maven Toolchains Plugin
> Issue Type: Improvement
> Reporter: Guillaume Nodet
> Assignee: Guillaume Nodet
> Priority: Major
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)