1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugins.jlink;
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 import java.io.File;
41 import java.util.List;
42 import java.util.NoSuchElementException;
43 import java.util.Optional;
44 import java.util.stream.Collectors;
45
46 import org.apache.maven.plugin.MojoExecutionException;
47 import org.apache.maven.plugin.logging.Log;
48 import org.apache.maven.shared.utils.cli.CommandLineException;
49 import org.apache.maven.shared.utils.cli.CommandLineUtils;
50 import org.apache.maven.shared.utils.cli.Commandline;
51 import org.apache.maven.toolchain.Toolchain;
52
53 abstract class AbstractJLinkToolchainExecutor extends AbstractJLinkExecutor {
54 private final Toolchain toolchain;
55
56 AbstractJLinkToolchainExecutor(Toolchain toolchain, Log log) {
57 super(log);
58 this.toolchain = toolchain;
59 }
60
61 protected Optional<Toolchain> getToolchain() {
62 return Optional.ofNullable(this.toolchain);
63 }
64
65
66
67
68
69
70 @Override
71 public int executeJlink(List<String> jlinkArgs) throws MojoExecutionException {
72 File jlinkExecutable = getJlinkExecutable();
73 getLog().info("Toolchain in maven-jlink-plugin: jlink [ " + jlinkExecutable + " ]");
74 Commandline cmd = createJLinkCommandLine(jlinkExecutable, jlinkArgs);
75
76 return executeCommand(cmd);
77 }
78
79 private File getJlinkExecutable() {
80 return new File(getJLinkExecutable());
81 }
82
83 @Override
84 public Optional<File> getJmodsFolder( File sourceJdkModules) {
85
86 File jLinkParent = getJlinkExecutable().getParentFile().getParentFile();
87 File jmodsFolder;
88 if (sourceJdkModules != null && sourceJdkModules.isDirectory()) {
89 jmodsFolder = new File(sourceJdkModules, JMODS);
90 } else {
91 jmodsFolder = new File(jLinkParent, JMODS);
92 }
93
94 getLog().debug(" Parent: " + jLinkParent.getAbsolutePath());
95 getLog().debug(" jmodsFolder: " + jmodsFolder.getAbsolutePath());
96
97 return Optional.of(jmodsFolder);
98 }
99
100 static Commandline createJLinkCommandLine(File jlinkExecutable, List<String> jlinkArgs) {
101 Commandline cmd = new Commandline();
102
103
104
105 cmd.getShell().setQuotedArgumentsEnabled(false);
106
107 String jlinkArgsStr = jlinkArgs.stream().map(arg -> "\"" + arg + "\"").collect(Collectors.joining(" "));
108 cmd.setExecutable(jlinkExecutable.getAbsolutePath() + " " + jlinkArgsStr);
109 return cmd;
110 }
111
112 private String getJLinkExecutable() {
113 Optional<Toolchain> toolchain = getToolchain();
114
115 if (!toolchain.isPresent()) {
116 getLog().error("Either JDK9+ or a toolchain "
117 + "pointing to a JDK9+ containing a jlink binary is required.");
118 getLog().info("See https://maven.apache.org/guides/mini/guide-using-toolchains.html "
119 + "for mor information.");
120 throw new IllegalStateException("Running on JDK8 and no toolchain found.");
121 }
122
123 String jLinkExecutable =
124 toolchain.orElseThrow(NoSuchElementException::new).findTool("jlink");
125
126 if (jLinkExecutable.isEmpty()) {
127 throw new IllegalStateException(
128 "The jlink executable '" + jLinkExecutable + "' doesn't exist or is not a file.");
129 }
130
131
132 String jLinkCommand = "jlink" + (isOSWindows() ? ".exe" : "");
133
134 File jLinkExe = new File(jLinkExecutable);
135
136 if (jLinkExe.isDirectory()) {
137 jLinkExe = new File(jLinkExe, jLinkCommand);
138 }
139
140 if (isOSWindows() && jLinkExe.getName().indexOf('.') < 0) {
141 jLinkExe = new File(jLinkExe.getPath() + ".exe");
142 }
143
144 if (!jLinkExe.isFile()) {
145 throw new IllegalStateException("The jlink executable '" + jLinkExe + "' doesn't exist or is not a file.");
146 }
147 return jLinkExe.getAbsolutePath();
148 }
149
150 private int executeCommand(Commandline cmd) throws MojoExecutionException {
151 if (getLog().isDebugEnabled()) {
152
153 getLog().debug(CommandLineUtils.toString(cmd.getCommandline()));
154 }
155
156 CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer();
157 CommandLineUtils.StringStreamConsumer out = new CommandLineUtils.StringStreamConsumer();
158 try {
159 int exitCode = CommandLineUtils.executeCommandLine(cmd, out, err);
160
161 String output = out.getOutput().trim();
162 output = output.isEmpty() ? null : '\n' + output;
163
164 if (exitCode != 0) {
165
166 if (output != null && !output.isEmpty()) {
167
168
169 for (String outputLine : output.split("\n")) {
170 getLog().error(outputLine);
171 }
172 }
173
174 StringBuilder msg = new StringBuilder("\nExit code: ");
175 msg.append(exitCode);
176 if (!err.getOutput().trim().isEmpty()) {
177 msg.append(" - ").append(err.getOutput());
178 }
179 msg.append('\n');
180 msg.append("Command line was: ").append(cmd).append('\n').append('\n');
181
182 throw new MojoExecutionException(msg.toString());
183 }
184
185 if (output != null && !output.isEmpty()) {
186
187 for (String outputLine : output.split("\n")) {
188 getLog().info(outputLine);
189 }
190 }
191
192 return exitCode;
193 } catch (CommandLineException e) {
194 throw new MojoExecutionException("Unable to execute jlink command: " + e.getMessage(), e);
195 }
196 }
197
198 private static boolean isOSWindows() {
199 try {
200 String osName = System.getProperty("os.name");
201 if (osName == null) {
202 return false;
203 }
204 return osName.startsWith("Windows");
205 } catch (final SecurityException ex) {
206
207 return false;
208 }
209 }
210 }