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