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 final SecurityManager sm = System.getSecurityManager();
141 try {
142 if (!allowSystemExits) {
143 System.setSecurityManager(new NoExitSecurityManager());
144 }
145
146
147 Class<?> groovyShellClass = classWrangler.getClass("groovy.lang.GroovyShell");
148
149
150 Object shell = setupShell(groovyShellClass);
151
152
153 executeScripts(groovyShellClass, shell);
154 } catch (ClassNotFoundException e) {
155 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);
156 } catch (InvocationTargetException e) {
157 throw new MojoExecutionException("Error occurred while calling a method on a Groovy class from classpath.", e);
158 } catch (InstantiationException e) {
159 throw new MojoExecutionException("Error occurred while instantiating a Groovy class from classpath.", e);
160 } catch (IllegalAccessException e) {
161 throw new MojoExecutionException("Unable to access a method on a Groovy class from classpath.", e);
162 } finally {
163 if (!allowSystemExits) {
164 System.setSecurityManager(sm);
165 }
166 }
167 } else {
168 getLog().error("Your Groovy version (" + classWrangler.getGroovyVersionString() + ") doesn't support script execution. The minimum version of Groovy required is " + minGroovyVersion + ". Skipping script execution.");
169 }
170 }
171
172
173
174
175
176
177
178
179
180
181
182 protected Object setupShell(final Class<?> groovyShellClass) throws InvocationTargetException, IllegalAccessException, InstantiationException, ClassNotFoundException {
183 Object shell;
184 if (sourceEncoding != null) {
185 Class<?> compilerConfigurationClass = classWrangler.getClass("org.codehaus.groovy.control.CompilerConfiguration");
186 Object compilerConfiguration = invokeConstructor(findConstructor(compilerConfigurationClass));
187 invokeMethod(findMethod(compilerConfigurationClass, "setSourceEncoding", String.class), compilerConfiguration, sourceEncoding);
188 shell = invokeConstructor(findConstructor(groovyShellClass, ClassLoader.class, compilerConfigurationClass), classWrangler.getClassLoader(), compilerConfiguration);
189 } else {
190 shell = invokeConstructor(findConstructor(groovyShellClass, ClassLoader.class), classWrangler.getClassLoader());
191 }
192 initializeProperties();
193 Method setProperty = findMethod(groovyShellClass, "setProperty", String.class, Object.class);
194 if (bindPropertiesToSeparateVariables) {
195 for (Object k : properties.keySet()) {
196 invokeMethod(setProperty, shell, k, properties.get(k));
197 }
198 } else {
199 if (groovyOlderThan(GROOVY_4_0_0_RC_1)) {
200 invokeMethod(setProperty, shell, "properties", properties);
201 } else {
202 throw new IllegalArgumentException("properties is a read-only property in Groovy " + GROOVY_4_0_0_RC_1 + " and later.");
203 }
204 }
205
206 return shell;
207 }
208
209
210
211
212
213
214
215
216
217
218 protected void executeScripts(final Class<?> groovyShellClass, final Object shell) throws InvocationTargetException, IllegalAccessException, MojoExecutionException {
219 int scriptNum = 1;
220 for (String script : scripts) {
221 try {
222
223 try {
224
225 executeScriptFromUrl(groovyShellClass, shell, script);
226 } catch (MalformedURLException e) {
227
228 File scriptFile = new File(script);
229 if (scriptFile.isFile()) {
230 getLog().info("Running Groovy script from " + scriptFile.getCanonicalPath() + ".");
231 Method evaluateFile = findMethod(groovyShellClass, "evaluate", File.class);
232 invokeMethod(evaluateFile, shell, scriptFile);
233 } else {
234
235 Method evaluateString = findMethod(groovyShellClass, "evaluate", String.class);
236 invokeMethod(evaluateString, shell, script);
237 }
238 }
239 } catch (IOException ioe) {
240 if (continueExecuting) {
241 getLog().error("An Exception occurred while executing script " + scriptNum + ". Continuing to execute remaining scripts.", ioe);
242 } else {
243 throw new MojoExecutionException("An Exception occurred while executing script " + scriptNum + ".", ioe);
244 }
245 }
246 scriptNum++;
247 }
248 }
249
250
251
252
253
254
255
256
257
258
259
260 protected void executeScriptFromUrl(Class<?> groovyShellClass, Object shell, String script) throws IOException, InvocationTargetException, IllegalAccessException {
261 URL url = new URL(script);
262 getLog().info("Running Groovy script from " + url + ".");
263 if (groovyAtLeast(GROOVY_1_7_0)) {
264 Method evaluateUrlWithReader = findMethod(groovyShellClass, "evaluate", Reader.class);
265 BufferedReader reader = null;
266 try {
267 if (sourceEncoding != null) {
268 reader = new BufferedReader(new InputStreamReader(url.openStream(), sourceEncoding));
269 } else {
270 reader = new BufferedReader(new InputStreamReader(url.openStream()));
271 }
272 invokeMethod(evaluateUrlWithReader, shell, reader);
273 } finally {
274 FileUtils.closeQuietly(reader);
275 }
276 } else {
277 Method evaluateUrlWithStream = findMethod(groovyShellClass, "evaluate", InputStream.class);
278 InputStream inputStream = null;
279 try {
280 if (sourceEncoding != null) {
281 getLog().warn("Source encoding does not apply to Groovy versions previous to 1.7.0, ignoring.");
282 }
283 inputStream = url.openStream();
284 invokeMethod(evaluateUrlWithStream, shell, inputStream);
285 } finally {
286 FileUtils.closeQuietly(inputStream);
287 }
288 }
289 }
290
291 }