1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 package org.codehaus.groovy.ant;
48
49 import groovy.lang.GroovyShell;
50 import groovy.lang.Script;
51 import groovy.lang.Binding;
52 import groovy.util.AntBuilder;
53
54 import java.io.BufferedOutputStream;
55 import java.io.BufferedReader;
56 import java.io.File;
57 import java.io.FileOutputStream;
58 import java.io.FileReader;
59 import java.io.IOException;
60 import java.io.PrintStream;
61 import java.io.Reader;
62 import java.io.StringWriter;
63 import java.io.PrintWriter;
64 import java.lang.reflect.Field;
65 import java.util.Hashtable;
66 import java.util.Vector;
67
68 import org.apache.tools.ant.BuildException;
69 import org.apache.tools.ant.DirectoryScanner;
70 import org.apache.tools.ant.Project;
71 import org.apache.tools.ant.Task;
72 import org.apache.tools.ant.types.FileSet;
73 import org.apache.tools.ant.types.Path;
74 import org.apache.tools.ant.types.Reference;
75 import org.codehaus.groovy.control.CompilationFailedException;
76 import org.codehaus.groovy.control.CompilerConfiguration;
77 import org.codehaus.groovy.runtime.InvokerHelper;
78 import org.codehaus.groovy.tools.ErrorReporter;
79
80 /***
81 * Executes a series of Groovy statements.
82 *
83 * <p>Statements can
84 * either be read in from a text file using the <i>src</i> attribute or from
85 * between the enclosing groovy tags.</p>
86 *
87 *
88 * Based heavily on SQLExec.java which is part of apache-ant
89 * http://cvs.apache.org/viewcvs.cgi/ant/src/main/org/apache/tools/ant/taskdefs/SQLExec.java?rev=MAIN
90 *
91 * Copyright 2000-2005 The Apache Software Foundation
92 *
93 * Licensed under the Apache License, Version 2.0 (the "License");
94 * you may not use this file except in compliance with the License.
95 * You may obtain a copy of the License at
96 *
97 * http://www.apache.org/licenses/LICENSE-2.0
98 *
99 * Unless required by applicable law or agreed to in writing, software
100 * distributed under the License is distributed on an "AS IS" BASIS,
101 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
102 * See the License for the specific language governing permissions and
103 * limitations under the License.
104 *
105 *
106 */
107 public class Groovy extends Task {
108 /***
109 * files to load
110 */
111 private Vector filesets = new Vector();
112
113 /***
114 * input file
115 */
116 private File srcFile = null;
117
118 /***
119 * input command
120 */
121 private String command = "";
122
123 /***
124 * Print results.
125 */
126 private boolean print = false;
127
128 /***
129 * Results Output file.
130 */
131 private File output = null;
132
133 /***
134 * Append to an existing file or overwrite it?
135 */
136 private boolean append = false;
137
138 /***
139 * Used for caching loaders / driver. This is to avoid
140 * getting an OutOfMemoryError when calling this task
141 * multiple times in a row.
142 */
143 private static Hashtable loaderMap = new Hashtable(3);
144
145 private Path classpath;
146
147 /***
148 * User name.
149 */
150 private String userId = null;
151
152 /***
153 * Groovy Version needed for this collection of statements.
154 **/
155 private String version = null;
156
157 /***
158 * Compiler configuration.
159 *
160 * Used to specify the debug output to print stacktraces in case something fails.
161 * TODO: Could probably be reused to specify the encoding of the files to load or other properties.
162 */
163 private CompilerConfiguration configuration = new CompilerConfiguration();
164
165 /***
166 * Enable compiler to report stack trace information if a problem occurs
167 * during compilation.
168 * @param stacktrace
169 */
170 public void setStacktrace(boolean stacktrace) {
171 configuration.setDebug(stacktrace);
172 }
173
174
175 /***
176 * Set the name of the file to be run.
177 * Required unless statements are enclosed in the build file
178 */
179 public void setSrc(File srcFile) {
180 this.srcFile = srcFile;
181 }
182
183 /***
184 * Set an inline command to execute.
185 * NB: Properties are not expanded in this text.
186 */
187 public void addText(String txt) {
188 log("addText('"+txt+"')", Project.MSG_VERBOSE);
189 this.command += txt;
190 }
191
192 /***
193 * Adds a set of files (nested fileset attribute).
194 */
195 public void addFileset(FileSet set) {
196 filesets.addElement(set);
197 }
198
199 /***
200 * Print results from the statements;
201 * optional, default false
202 */
203 public void setPrint(boolean print) {
204 this.print = print;
205 }
206
207 /***
208 * Set the output file;
209 * optional, defaults to the Ant log.
210 */
211 public void setOutput(File output) {
212 this.output = output;
213 }
214
215 /***
216 * whether output should be appended to or overwrite
217 * an existing file. Defaults to false.
218 *
219 * @since Ant 1.5
220 */
221 public void setAppend(boolean append) {
222 this.append = append;
223 }
224
225
226 /***
227 * Sets the classpath for loading.
228 * @param classpath The classpath to set
229 */
230 public void setClasspath(Path classpath) {
231 this.classpath = classpath;
232 }
233
234 /***
235 * Add a path to the classpath for loading.
236 */
237 public Path createClasspath() {
238 if (this.classpath == null) {
239 this.classpath = new Path(getProject());
240 }
241 return this.classpath.createPath();
242 }
243
244 /***
245 * Set the classpath for loading
246 * using the classpath reference.
247 */
248 public void setClasspathRef(Reference r) {
249 createClasspath().setRefid(r);
250 }
251
252 /***
253 * Sets the version string, execute task only if
254 * groovy version match; optional.
255 * @param version The version to set
256 */
257 public void setVersion(String version) {
258 this.version = version;
259 }
260
261
262 protected static Hashtable getLoaderMap() {
263 return loaderMap;
264 }
265
266
267
268
269 /***
270 * Gets the classpath.
271 * @return Returns a Path
272 */
273 public Path getClasspath() {
274 return classpath;
275 }
276
277 /***
278 * Gets the userId.
279 * @return Returns a String
280 */
281 public String getUserId() {
282 return userId;
283 }
284
285 /***
286 * Set the user name for the connection; required.
287 * @param userId The userId to set
288 */
289 public void setUserid(String userId) {
290 this.userId = userId;
291 }
292
293 /***
294 * Gets the version.
295 * @return Returns a String
296 */
297 public String getVersion() {
298 return version;
299 }
300
301 /***
302 * Load the file and then execute it
303 */
304 public void execute() throws BuildException {
305 log("execute()", Project.MSG_VERBOSE);
306
307 command = command.trim();
308
309 try {
310 if (srcFile == null && command.length() == 0
311 && filesets.isEmpty()) {
312 throw new BuildException("Source file does not exist!", getLocation());
313 }
314
315 if (srcFile != null && !srcFile.exists()) {
316 throw new BuildException("Source file does not exist!", getLocation());
317 }
318
319
320 for (int i = 0; i < filesets.size(); i++) {
321 FileSet fs = (FileSet) filesets.elementAt(i);
322 DirectoryScanner ds = fs.getDirectoryScanner(getProject());
323 File srcDir = fs.getDir(getProject());
324
325 String[] srcFiles = ds.getIncludedFiles();
326 }
327
328 try {
329 PrintStream out = System.out;
330 try {
331 if (output != null) {
332 log("Opening PrintStream to output file " + output,
333 Project.MSG_VERBOSE);
334 out = new PrintStream(
335 new BufferedOutputStream(
336 new FileOutputStream(output
337 .getAbsolutePath(),
338 append)));
339 }
340
341
342
343 if (command == null || command.trim().length() == 0) {
344 command = getText(new BufferedReader(new FileReader(srcFile)));
345 }
346
347
348 if (command != null) {
349 execGroovy(command,out);
350 } else {
351 throw new BuildException("Source file does not exist!", getLocation());
352 }
353
354 } finally {
355 if (out != null && out != System.out) {
356 out.close();
357 }
358 }
359 } catch (IOException e) {
360 throw new BuildException(e, getLocation());
361 }
362
363 log("statements executed successfully");
364 } finally{}
365 }
366
367
368 private static String getText(BufferedReader reader) throws IOException {
369 StringBuffer answer = new StringBuffer();
370
371 char[] charBuffer = new char[4096];
372 int nbCharRead = 0;
373 while ((nbCharRead = reader.read(charBuffer)) != -1) {
374
375 answer.append(charBuffer, 0, nbCharRead);
376 }
377 reader.close();
378 return answer.toString();
379 }
380
381
382 /***
383 * read in lines and execute them
384 */
385 protected void runStatements(Reader reader, PrintStream out)
386 throws IOException {
387 log("runStatements()", Project.MSG_VERBOSE);
388
389 StringBuffer txt = new StringBuffer();
390 String line = "";
391
392 BufferedReader in = new BufferedReader(reader);
393
394 while ((line = in.readLine()) != null) {
395 line = getProject().replaceProperties(line);
396
397 if (line.indexOf("--") >= 0) {
398 txt.append("\n");
399 }
400 }
401
402 if (!txt.equals("")) {
403 execGroovy(txt.toString(), out);
404 }
405 }
406
407
408 /***
409 * Exec the statement.
410 */
411 protected void execGroovy(String txt, PrintStream out) {
412 log("execGroovy()", Project.MSG_VERBOSE);
413
414
415 if ("".equals(txt.trim())) {
416 return;
417 }
418
419 log("Groovy: " + txt, Project.MSG_VERBOSE);
420
421
422 GroovyShell groovy = null;
423 Object mavenPom = null;
424 Project project = getProject();
425
426 if ("org.apache.commons.grant.GrantProject".equals(project.getClass().getName())) {
427 try {
428 Object propsHandler = project.getClass().getMethod("getPropsHandler", new Class[0]).invoke(project, new Object[0]);
429 Field contextField = propsHandler.getClass().getDeclaredField("context");
430 contextField.setAccessible(true);
431 Object context = contextField.get(propsHandler);
432 mavenPom = InvokerHelper.invokeMethod(context, "getProject", new Object[0]);
433 }
434 catch (Exception e) {
435 throw new BuildException("Impossible to retrieve Maven's Ant project: " + e.getMessage(), getLocation());
436 }
437
438 Thread.currentThread().setContextClassLoader(GroovyShell.class.getClassLoader());
439
440
441 groovy = new GroovyShell(mavenPom.getClass().getClassLoader(), new Binding(), configuration);
442 } else {
443 groovy = new GroovyShell(GroovyShell.class.getClassLoader(), new Binding(), configuration);
444 }
445 try {
446 Script script = groovy.parse(txt);
447 script.setProperty("ant", new AntBuilder(project));
448 script.setProperty("project", project);
449 script.setProperty("properties", new AntProjectPropertiesDelegate(project));
450 script.setProperty("target", getOwningTarget());
451 script.setProperty("task", this);
452 if(mavenPom != null) {
453 script.setProperty("pom", mavenPom);
454 }
455 script.run();
456 } catch (CompilationFailedException e) {
457 StringWriter writer = new StringWriter();
458 new ErrorReporter( e, false ).write( new PrintWriter(writer) );
459 String message = writer.toString();
460 throw new BuildException("Script Failed: "+ message, getLocation());
461 }
462 }
463
464 /***
465 * print any results in the statement.
466 */
467 protected void printResults(PrintStream out) {
468 log("printResults()", Project.MSG_VERBOSE);
469 StringBuffer line = new StringBuffer();
470 out.println(line);
471 line = new StringBuffer();
472 out.println();
473 }
474 }