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.artifact.DependencyResolutionRequiredException;
20 import org.apache.maven.plugin.MojoExecutionException;
21 import org.apache.maven.plugins.annotations.Mojo;
22 import org.apache.maven.plugins.annotations.Parameter;
23 import org.apache.maven.plugins.annotations.ResolutionScope;
24 import org.codehaus.gmavenplus.model.internal.Version;
25 import org.codehaus.gmavenplus.util.FileUtils;
26 import org.codehaus.gmavenplus.util.NoExitSecurityManager;
27
28 import java.io.BufferedReader;
29 import java.io.File;
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.InputStreamReader;
33 import java.io.Reader;
34 import java.lang.reflect.InvocationTargetException;
35 import java.lang.reflect.Method;
36 import java.net.MalformedURLException;
37 import java.net.URL;
38
39 import static org.codehaus.gmavenplus.util.ReflectionUtils.findConstructor;
40 import static org.codehaus.gmavenplus.util.ReflectionUtils.findMethod;
41 import static org.codehaus.gmavenplus.util.ReflectionUtils.invokeConstructor;
42 import static org.codehaus.gmavenplus.util.ReflectionUtils.invokeMethod;
43
44
45
46
47
48
49
50
51
52
53
54 @Mojo(name = "execute", requiresDependencyResolution = ResolutionScope.TEST, threadSafe = true)
55 public class ExecuteMojo extends AbstractToolsMojo {
56
57
58
59
60 protected static final Version GROOVY_4_0_0_RC_1 = new Version(4, 0, 0, "RC-1");
61
62
63
64
65 protected static final Version GROOVY_1_7_0 = new Version(1, 7, 0);
66
67
68
69
70
71 @Parameter(required = true)
72 protected String[] scripts;
73
74
75
76
77 @Parameter(defaultValue = "false")
78 protected boolean continueExecuting;
79
80
81
82
83
84
85 @Parameter(defaultValue = "${project.build.sourceEncoding}")
86 protected String sourceEncoding;
87
88
89
90
91
92
93 @Parameter(defaultValue = "false")
94 protected boolean skipScriptExecution;
95
96
97
98
99
100
101 @Override
102 public void execute() throws MojoExecutionException {
103 doExecute();
104 }
105
106
107
108
109
110
111 protected synchronized void doExecute() throws MojoExecutionException {
112 if (skipScriptExecution) {
113 getLog().info("Skipping script execution because ${skipScriptExecution} was set to true.");
114 return;
115 }
116
117 if (scripts == null || scripts.length == 0) {
118 getLog().info("No scripts specified for execution. Skipping.");
119 return;
120 }
121
122 try {
123 setupClassWrangler(project.getTestClasspathElements(), includeClasspath);
124 } catch (MalformedURLException e) {
125 throw new MojoExecutionException("Unable to add project test dependencies to classpath.", e);
126 } catch (DependencyResolutionRequiredException e) {
127 throw new MojoExecutionException("Test dependencies weren't resolved.", e);
128 }
129
130 logPluginClasspath();
131 classWrangler.logGroovyVersion(mojoExecution.getMojoDescriptor().getGoal());
132
133 try {
134 getLog().debug("Project test classpath:\n" + project.getTestClasspathElements());
135 } catch (DependencyResolutionRequiredException e) {
136 getLog().debug("Unable to log project test classpath");
137 }
138
139 if (!groovyVersionSupportsAction()) {
140 getLog().error("Your Groovy version (" + classWrangler.getGroovyVersionString() + ") doesn't support script execution. The minimum version of Groovy required is " + minGroovyVersion + ". Skipping script execution.");
141 return;
142 }
143
144 final SecurityManager defaultSecurityManager = System.getSecurityManager();
145 try {
146 if (!allowSystemExits) {
147 getLog().warn("JEP 411 deprecated Security Manager in Java 17 for removal. Therefore `allowSystemExits` is also deprecated for removal.");
148 try {
149 System.setSecurityManager(new NoExitSecurityManager());
150 } catch (UnsupportedOperationException e) {
151 getLog().warn("Attempted to use Security Manager in a JVM where it's disabled by default. You might try `-Djava.security.manager=allow` to override this.");
152 }
153 }
154
155
156 Class<?> groovyShellClass = classWrangler.getClass("groovy.lang.GroovyShell");
157
158
159 Object shell = setupShell(groovyShellClass);
160
161
162 executeScripts(groovyShellClass, shell);
163 } catch (ClassNotFoundException e) {
164 throw new MojoExecutionException("Unable to get a Groovy class from classpath (" + e.getMessage() + "). Do you have Groovy as a compile dependency in your project or the plugin?", e);
165 } catch (InvocationTargetException e) {
166 throw new MojoExecutionException("Error occurred while calling a method on a Groovy class from classpath.", e);
167 } catch (InstantiationException e) {
168 throw new MojoExecutionException("Error occurred while instantiating a Groovy class from classpath.", e);
169 } catch (IllegalAccessException e) {
170 throw new MojoExecutionException("Unable to access a method on a Groovy class from classpath.", e);
171 } finally {
172 if (!allowSystemExits) {
173 try {
174 System.setSecurityManager(defaultSecurityManager);
175 } catch (UnsupportedOperationException e) {
176 getLog().warn("Attempted to use Security Manager in a JVM where it's disabled by default. You might try `-Djava.security.manager=allow` to override this.");
177 }
178 }
179 }
180 }
181
182
183
184
185
186
187
188
189
190
191
192 protected Object setupShell(final Class<?> groovyShellClass) throws InvocationTargetException, IllegalAccessException, InstantiationException, ClassNotFoundException {
193 Object shell;
194 if (sourceEncoding != null) {
195 Class<?> compilerConfigurationClass = classWrangler.getClass("org.codehaus.groovy.control.CompilerConfiguration");
196 Object compilerConfiguration = invokeConstructor(findConstructor(compilerConfigurationClass));
197 invokeMethod(findMethod(compilerConfigurationClass, "setSourceEncoding", String.class), compilerConfiguration, sourceEncoding);
198 shell = invokeConstructor(findConstructor(groovyShellClass, ClassLoader.class, compilerConfigurationClass), classWrangler.getClassLoader(), compilerConfiguration);
199 } else {
200 shell = invokeConstructor(findConstructor(groovyShellClass, ClassLoader.class), classWrangler.getClassLoader());
201 }
202 initializeProperties();
203 Method setProperty = findMethod(groovyShellClass, "setProperty", String.class, Object.class);
204 if (bindPropertiesToSeparateVariables) {
205 for (Object k : properties.keySet()) {
206 invokeMethod(setProperty, shell, k, properties.get(k));
207 }
208 } else {
209 if (groovyOlderThan(GROOVY_4_0_0_RC_1)) {
210 invokeMethod(setProperty, shell, "properties", properties);
211 } else {
212 throw new IllegalArgumentException("properties is a read-only property in Groovy " + GROOVY_4_0_0_RC_1 + " and later.");
213 }
214 }
215
216 return shell;
217 }
218
219
220
221
222
223
224
225
226
227
228 protected void executeScripts(final Class<?> groovyShellClass, final Object shell) throws InvocationTargetException, IllegalAccessException, MojoExecutionException {
229 int scriptNum = 1;
230 for (String script : scripts) {
231 try {
232
233 try {
234
235 executeScriptFromUrl(groovyShellClass, shell, script);
236 } catch (MalformedURLException e) {
237
238 File scriptFile = new File(script);
239 if (scriptFile.isFile()) {
240 getLog().info("Running Groovy script from " + scriptFile.getCanonicalPath() + ".");
241 Method evaluateFile = findMethod(groovyShellClass, "evaluate", File.class);
242 invokeMethod(evaluateFile, shell, scriptFile);
243 } else {
244
245 Method evaluateString = findMethod(groovyShellClass, "evaluate", String.class);
246 invokeMethod(evaluateString, shell, script);
247 }
248 }
249 } catch (IOException ioe) {
250 if (continueExecuting) {
251 getLog().error("An Exception occurred while executing script " + scriptNum + ". Continuing to execute remaining scripts.", ioe);
252 } else {
253 throw new MojoExecutionException("An Exception occurred while executing script " + scriptNum + ".", ioe);
254 }
255 }
256 scriptNum++;
257 }
258 }
259
260
261
262
263
264
265
266
267
268
269
270 protected void executeScriptFromUrl(Class<?> groovyShellClass, Object shell, String script) throws IOException, InvocationTargetException, IllegalAccessException {
271 URL url = new URL(script);
272 getLog().info("Running Groovy script from " + url + ".");
273 if (groovyAtLeast(GROOVY_1_7_0)) {
274 Method evaluateUrlWithReader = findMethod(groovyShellClass, "evaluate", Reader.class);
275 BufferedReader reader = null;
276 try {
277 if (sourceEncoding != null) {
278 reader = new BufferedReader(new InputStreamReader(url.openStream(), sourceEncoding));
279 } else {
280 reader = new BufferedReader(new InputStreamReader(url.openStream()));
281 }
282 invokeMethod(evaluateUrlWithReader, shell, reader);
283 } finally {
284 FileUtils.closeQuietly(reader);
285 }
286 } else {
287 Method evaluateUrlWithStream = findMethod(groovyShellClass, "evaluate", InputStream.class);
288 InputStream inputStream = null;
289 try {
290 if (sourceEncoding != null) {
291 getLog().warn("Source encoding does not apply to Groovy versions previous to 1.7.0, ignoring.");
292 }
293 inputStream = url.openStream();
294 invokeMethod(evaluateUrlWithStream, shell, inputStream);
295 } finally {
296 FileUtils.closeQuietly(inputStream);
297 }
298 }
299 }
300
301 }