1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.codehaus.gmavenplus.mojo;
18
19 import org.apache.maven.plugins.annotations.Parameter;
20 import org.codehaus.gmavenplus.model.IncludeClasspath;
21 import org.codehaus.gmavenplus.model.internal.Version;
22 import org.codehaus.gmavenplus.util.GroovyCompiler;
23
24 import java.io.File;
25 import java.lang.reflect.InvocationTargetException;
26 import java.net.MalformedURLException;
27 import java.util.List;
28 import java.util.Set;
29
30
31
32
33
34
35
36 public abstract class AbstractGenerateStubsMojo extends AbstractGroovyStubSourcesMojo {
37
38
39
40
41 protected static final Version GROOVY_1_8_2 = new Version(1, 8, 2);
42
43
44
45
46 @Parameter(defaultValue = "${project.build.sourceEncoding}")
47 protected String sourceEncoding;
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96 @Parameter(property = "maven.compiler.target", defaultValue = "1.8")
97 protected String targetBytecode;
98
99
100
101
102
103
104 @Parameter(property = "skipBytecodeCheck", defaultValue = "false")
105 protected boolean skipBytecodeCheck;
106
107
108
109
110 @Parameter(defaultValue = "false")
111 protected boolean debug;
112
113
114
115
116 @Parameter(defaultValue = "false")
117 protected boolean verbose;
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132 @Parameter(defaultValue = "1")
133 protected int warningLevel;
134
135
136
137
138 @Parameter(defaultValue = "0")
139 protected int tolerance;
140
141
142
143
144
145
146
147
148
149
150
151
152 @Parameter(defaultValue = "PROJECT_ONLY")
153 protected IncludeClasspath includeClasspath;
154
155
156
157
158 @javax.inject.Inject
159 protected org.apache.maven.toolchain.ToolchainManager toolchainManager;
160
161
162
163
164 @Parameter(defaultValue = "${session}", readonly = true, required = true)
165 protected org.apache.maven.execution.MavenSession session;
166
167
168
169
170
171
172 @Parameter(property = "fork", defaultValue = "false")
173 protected boolean fork;
174
175
176
177
178
179
180
181
182
183
184
185
186
187 protected synchronized void doStubGeneration(final Set<File> stubSources, final List<?> classpath, final File outputDirectory) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException, MalformedURLException {
188 if (stubSources == null || stubSources.isEmpty()) {
189 getLog().info("No sources specified for stub generation. Skipping.");
190 return;
191 }
192
193 org.codehaus.gmavenplus.model.GroovyStubConfiguration configuration = new org.codehaus.gmavenplus.model.GroovyStubConfiguration(stubSources, classpath, outputDirectory);
194 configuration.setIncludeClasspath(includeClasspath);
195 configuration.setSkipBytecodeCheck(skipBytecodeCheck);
196 configuration.setDebug(debug);
197 configuration.setVerbose(verbose);
198 configuration.setWarningLevel(warningLevel);
199 configuration.setTolerance(tolerance);
200 configuration.setSourceEncoding(sourceEncoding);
201 configuration.setTargetBytecode(targetBytecode);
202
203 org.apache.maven.toolchain.Toolchain toolchain = toolchainManager.getToolchainFromBuildContext("jdk", session);
204 if (toolchain != null) {
205 getLog().info("Toolchain in gmavenplus-plugin: " + toolchain);
206 performForkedStubGeneration(configuration, toolchain.findTool("java"));
207 } else if (fork) {
208 String javaExecutable = getJavaExecutable();
209 getLog().info("Forking stub generation using " + javaExecutable);
210 performForkedStubGeneration(configuration, javaExecutable);
211 } else {
212 performInProcessStubGeneration(configuration, classpath);
213 }
214 }
215
216 protected void performInProcessStubGeneration(org.codehaus.gmavenplus.model.GroovyStubConfiguration configuration, List<?> classpath) throws MalformedURLException, ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException {
217 setupClassWrangler(classpath, includeClasspath);
218 logPluginClasspath();
219 classWrangler.logGroovyVersion(mojoExecution.getMojoDescriptor().getGoal());
220
221
222
223 GroovyCompiler compiler = new GroovyCompiler(classWrangler, getLog());
224 compiler.generateStubs(configuration);
225 }
226
227 protected void performForkedStubGeneration(org.codehaus.gmavenplus.model.GroovyStubConfiguration configuration, String javaExecutable) throws InvocationTargetException {
228 try {
229
230 File configFile = File.createTempFile("groovy-stub-config", ".ser");
231 configFile.deleteOnExit();
232 try (java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream(java.nio.file.Files.newOutputStream(configFile.toPath()))) {
233 oos.writeObject(configuration);
234 }
235
236
237 String forkClasspath = buildForkClasspath();
238
239 List<String> command = new java.util.ArrayList<>();
240 command.add(javaExecutable);
241 command.add("-cp");
242 command.add(forkClasspath);
243 command.add("org.codehaus.gmavenplus.util.ForkedGroovyCompiler");
244 command.add(configFile.getAbsolutePath());
245
246 ProcessBuilder pb = new ProcessBuilder(command);
247 pb.inheritIO();
248 Process process = pb.start();
249 int exitCode = process.waitFor();
250
251 if (exitCode != 0) {
252 throw new InvocationTargetException(new RuntimeException("Forked stub generation failed with exit code " + exitCode));
253 }
254
255 } catch (java.io.IOException | InterruptedException e) {
256 throw new InvocationTargetException(e);
257 }
258 }
259
260 protected String buildForkClasspath() {
261 StringBuilder cp = new StringBuilder();
262
263 cp.append(pluginDescriptor.getPluginArtifact().getFile().getAbsolutePath());
264
265
266 for (org.apache.maven.artifact.Artifact artifact : pluginDescriptor.getArtifacts()) {
267 cp.append(File.pathSeparator);
268 cp.append(artifact.getFile().getAbsolutePath());
269 }
270
271
272 try {
273 Class<?> logClass = org.apache.maven.plugin.logging.Log.class;
274 java.security.CodeSource codeSource = logClass.getProtectionDomain().getCodeSource();
275 if (codeSource != null) {
276 String logJar = new File(codeSource.getLocation().toURI()).getAbsolutePath();
277 cp.append(File.pathSeparator).append(logJar);
278 }
279 } catch (Exception e) {
280 getLog().warn("Could not find maven-plugin-api jar to add to fork classpath", e);
281 }
282
283 return cp.toString();
284 }
285
286
287
288
289
290
291 protected void logGeneratedStubs(File outputDirectory) {
292 Set<File> stubs = getStubs(outputDirectory);
293 getLog().info("Generated " + stubs.size() + " stub" + (stubs.size() != 1 ? "s" : "") + ".");
294 }
295
296
297
298
299
300
301
302
303
304 protected void resetStubModifiedDates(final Set<File> stubs) {
305 for (File stub : stubs) {
306 boolean success = stub.setLastModified(0L);
307 if (!success) {
308 getLog().warn("Unable to set modified time on stub " + stub.getAbsolutePath() + ".");
309 }
310 }
311 }
312
313
314
315
316 }