1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugins.jar;
20
21 import javax.inject.Named;
22 import javax.inject.Singleton;
23
24 import java.io.BufferedReader;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.InputStreamReader;
28 import java.io.UncheckedIOException;
29 import java.nio.file.Path;
30 import java.nio.file.Paths;
31 import java.util.HashMap;
32 import java.util.Map;
33 import java.util.Optional;
34
35 import org.apache.maven.toolchain.Toolchain;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39
40
41
42 @Named
43 @Singleton
44 class ToolchainsJdkSpecification {
45
46 private final Logger logger = LoggerFactory.getLogger(ToolchainsJdkSpecification.class);
47
48 private final Map<Path, String> cache = new HashMap<>();
49
50 public synchronized Optional<String> getJDKSpecification(Toolchain toolchain) {
51 Optional<Path> javacPath = getJavacPath(toolchain);
52 return javacPath.map(path -> cache.computeIfAbsent(path, this::getSpecForPath));
53 }
54
55 private Optional<Path> getJavacPath(Toolchain toolchain) {
56 return Optional.ofNullable(toolchain.findTool("javac")).map(Paths::get).map(this::getCanonicalPath);
57 }
58
59 private Path getCanonicalPath(Path path) {
60 try {
61 return path.toRealPath();
62 } catch (IOException e) {
63 if (path.getParent() != null) {
64 return getCanonicalPath(path.getParent()).resolve(path.getFileName());
65 } else {
66 throw new UncheckedIOException(e);
67 }
68 }
69 }
70
71 private String getSpecForPath(Path path) {
72 try {
73 ProcessBuilder processBuilder = new ProcessBuilder(path.toString(), "-version");
74 processBuilder.redirectErrorStream(true);
75 Process process = processBuilder.start();
76 String version = readOutput(process.getInputStream()).trim();
77 process.waitFor();
78
79 if (version.startsWith("javac ")) {
80 version = version.substring(6);
81 if (version.startsWith("1.")) {
82 version = version.substring(0, 3);
83 } else {
84 version = version.substring(0, 2);
85 }
86 return version;
87 } else {
88 logger.warn("Unrecognized output from {}: {}", processBuilder.command(), version);
89 }
90 } catch (IndexOutOfBoundsException | IOException e) {
91 logger.warn("Failed to execute: {} - {}", path, e.getMessage());
92 } catch (InterruptedException e) {
93 Thread.currentThread().interrupt();
94 }
95
96 return null;
97 }
98
99 private String readOutput(InputStream inputstream) throws IOException {
100 BufferedReader br = new BufferedReader(new InputStreamReader(inputstream));
101
102 StringBuilder output = new StringBuilder();
103 String line;
104 while ((line = br.readLine()) != null) {
105 output.append(line + System.lineSeparator());
106 }
107
108 return output.toString();
109 }
110 }