1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.geronimo.genesis.plugins.script;
21
22 import java.io.File;
23 import java.io.InputStream;
24 import java.net.MalformedURLException;
25 import java.net.URL;
26 import java.net.URLClassLoader;
27 import java.util.ArrayList;
28 import java.util.HashMap;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Properties;
33
34 import groovy.lang.GroovyClassLoader;
35 import groovy.lang.GroovyObject;
36 import groovy.lang.GroovyResourceLoader;
37 import groovy.lang.GroovyRuntimeException;
38
39 import org.apache.maven.artifact.Artifact;
40 import org.apache.maven.artifact.DependencyResolutionRequiredException;
41 import org.apache.maven.artifact.repository.ArtifactRepository;
42 import org.apache.maven.plugin.MojoExecutionException;
43 import org.apache.maven.project.MavenProject;
44
45 import org.apache.geronimo.genesis.MojoSupport;
46 import org.apache.geronimo.genesis.util.ArtifactItem;
47 import org.apache.geronimo.genesis.util.ExpressionParser;
48
49 /**
50 * Executes a <a href="http://groovy.codehaus.org">Groovy</a> script.
51 *
52 * @goal groovy
53 * @configurator override
54 * @requiresDependencyResolution
55 *
56 * @version $Rev: 507770 $ $Date: 2007-02-14 17:49:14 -0800 (Wed, 14 Feb 2007) $
57 */
58 public class GroovyMojo
59 extends MojoSupport
60 {
61 /**
62 * The source of the script to execute.
63 *
64 * @parameter
65 * @required
66 */
67 private CodeSource source = null;
68
69 /**
70 * Additional artifacts to add to the scripts classpath.
71 *
72 * @parameter
73 */
74 private ArtifactItem[] classpath = null;
75
76 /**
77 * Path to search for imported scripts.
78 *
79 * @parameter expression
80 */
81 private File[] scriptpath = null;
82
83 /**
84 * A set of default project properties, which the values will be used only if
85 * the project or system does not override.
86 *
87 * @parameter
88 */
89 private Map defaults;
90
91 /**
92 * A set of additional project properties.
93 *
94 * @parameter
95 */
96 private Map properties;
97
98
99
100
101
102
103
104
105
106
107 /**
108 * @parameter expression="${project}"
109 * @readonly
110 * @required
111 */
112 private MavenProject project = null;
113
114 /**
115 * @parameter expression="${localRepository}"
116 * @readonly
117 * @required
118 */
119 private ArtifactRepository artifactRepository = null;
120
121
122
123
124
125 protected MavenProject getProject() {
126 return project;
127 }
128
129 protected ArtifactRepository getArtifactRepository() {
130 return artifactRepository;
131 }
132
133
134
135
136
137 protected void doExecute() throws Exception {
138 boolean debug = log.isDebugEnabled();
139
140 Class type = loadGroovyClass(source);
141 if (type == null) {
142 throw new MojoExecutionException("Source did not evaluate to a Groovy class: " + source);
143 }
144
145 GroovyObject obj = (GroovyObject)type.newInstance();
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160 obj.setProperty("log", log);
161
162
163 MavenProject delegate = new MavenProject(project) {
164 private Properties resolvedProperties;
165
166 public Properties getProperties() {
167 if (resolvedProperties == null) {
168 resolvedProperties = resolveProperties(project.getProperties());
169 }
170 return resolvedProperties;
171 }
172 };
173
174 obj.setProperty("project", delegate);
175 obj.setProperty("pom", delegate);
176
177
178 if (debug) {
179 log.debug("Invoking run() on: " + obj);
180 }
181
182 try {
183 obj.invokeMethod("run", new Object[0]);
184 }
185 catch (GroovyRuntimeException e) {
186 if (log.isDebugEnabled()) {
187
188 log.error("Groovy script execution failure", e);
189 }
190
191 Throwable cause = e.getCause();
192 if (cause == null) {
193 cause = e;
194 }
195
196 throw new MojoExecutionException(cause.getMessage(), cause);
197 }
198 }
199
200 private Class loadGroovyClass(final CodeSource source) throws Exception {
201 assert source != null;
202
203 boolean debug = log.isDebugEnabled();
204
205
206 source.validate();
207
208 Class type;
209 GroovyClassLoader loader = createGroovyClassLoader();
210
211 if (source.getBody() != null) {
212 type = loader.parseClass(source.getBody());
213 }
214 else {
215 URL url;
216 if (source.getFile() != null) {
217 url = source.getFile().toURL();
218 }
219 else {
220 url = source.getUrl();
221 }
222 if (debug) {
223 log.debug("Loading source from: " + url);
224 }
225
226 String fileName = new File(url.getFile()).getName();
227 InputStream input = url.openConnection().getInputStream();
228 try {
229 type = loader.parseClass(input, fileName);
230 }
231 finally {
232 input.close();
233 }
234 }
235
236 return type;
237 }
238
239 private GroovyClassLoader createGroovyClassLoader() throws Exception {
240 boolean debug = log.isDebugEnabled();
241
242 ClassLoader parent = getClass().getClassLoader();
243 URL[] urls = getClasspath();
244 URLClassLoader cl = new URLClassLoader(urls, parent);
245
246
247 if (scriptpath != null) {
248 log.debug("Scriptpath:");
249 for (int i=0; i < scriptpath.length; i++) {
250 if (scriptpath[i] == null) {
251 throw new MojoExecutionException("Null element found in scriptpath at index: " + i);
252 }
253
254 if (debug) {
255 log.debug(" " + scriptpath[i]);
256 }
257 }
258 }
259
260
261
262
263
264 GroovyClassLoader loader = new GroovyClassLoader(cl);
265
266
267 loader.setResourceLoader(new GroovyResourceLoader() {
268 public URL loadGroovySource(final String classname) throws MalformedURLException {
269 return resolveGroovyScript(classname);
270 }
271 });
272
273 return loader;
274 }
275
276 private URL resolveGroovyScript(final String classname) throws MalformedURLException {
277 assert classname != null;
278
279 if (log.isDebugEnabled()) {
280 log.debug("Resolving script for class: " + classname);
281 }
282
283 String resource = classname.replace('.', '/');
284 if (!resource.startsWith("/")) {
285 resource = "/" + resource;
286 }
287 resource = resource + ".groovy";
288
289
290 if (scriptpath != null) {
291 for (int i=0; i<scriptpath.length; i++) {
292 assert scriptpath[i] != null;
293
294 File file = new File(scriptpath[i], resource);
295 if (file.exists()) {
296 return file.toURL();
297 }
298 }
299 }
300
301
302 ClassLoader cl = Thread.currentThread().getContextClassLoader();
303 URL url = cl.getResource(resource);
304 if (url == null) {
305
306 File script = source.getFile();
307 if (script != null) {
308 File file = new File(script.getParentFile(), resource);
309 if (file.exists()) {
310 return file.toURL();
311 }
312 }
313 }
314 else {
315 return url;
316 }
317
318 if (log.isDebugEnabled()) {
319 log.debug("Unable to resolve script for class: " + classname);
320 }
321
322
323 return null;
324 }
325
326 private URL[] getClasspath() throws DependencyResolutionRequiredException, MalformedURLException, MojoExecutionException {
327 List list = new ArrayList();
328
329
330 List classpathFiles = project.getCompileClasspathElements();
331 for (int i = 0; i < classpathFiles.size(); ++i) {
332 list.add(new File((String)classpathFiles.get(i)).toURL());
333 }
334
335
336 if (classpath != null) {
337 for (int i=0; i < classpath.length; i++) {
338 Artifact artifact = getArtifact(classpath[i]);
339 list.add(artifact.getFile().toURL());
340 }
341 }
342
343 URL[] urls = (URL[])list.toArray(new URL[list.size()]);
344
345
346 if (log.isDebugEnabled()) {
347 log.debug("Classpath:");
348 for (int i=0; i < urls.length; i++) {
349 log.debug(" " + urls[i]);
350 }
351 }
352
353 return urls;
354 }
355
356 private Properties resolveProperties(final Properties source) {
357 assert source != null;
358
359
360
361
362
363 Properties dprops = new Properties();
364 if (defaults != null) {
365 dprops.putAll(defaults);
366 }
367
368 Properties sprops = new Properties(dprops);
369 sprops.putAll(System.getProperties());
370
371 Properties props = new Properties(sprops);
372
373
374 if (properties != null) {
375 props.putAll(properties);
376 }
377
378
379 Map vars = new HashMap();
380 vars.put("project", project);
381
382
383 ExpressionParser parser = new ExpressionParser(vars);
384 Iterator iter = source.keySet().iterator();
385 while (iter.hasNext()) {
386 String name = (String)iter.next();
387 props.put(name, parser.parse(source.getProperty(name)));
388 }
389
390 return props;
391 }
392 }