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 package org.codehaus.groovy.ant;
47
48 import java.io.File;
49 import java.io.PrintWriter;
50 import java.io.StringWriter;
51 import java.nio.charset.Charset;
52
53 import org.apache.tools.ant.BuildException;
54 import org.apache.tools.ant.DirectoryScanner;
55 import org.apache.tools.ant.Project;
56 import org.apache.tools.ant.listener.AnsiColorLogger;
57 import org.apache.tools.ant.taskdefs.MatchingTask;
58 import org.apache.tools.ant.types.Path;
59 import org.apache.tools.ant.types.Reference;
60 import org.apache.tools.ant.util.GlobPatternMapper;
61 import org.apache.tools.ant.util.SourceFileScanner;
62 import org.codehaus.groovy.control.CompilationUnit;
63 import org.codehaus.groovy.control.CompilerConfiguration;
64 import org.codehaus.groovy.tools.ErrorReporter;
65
66
67 /***
68 * Compiles Groovy source files. This task can take the following
69 * arguments:
70 * <ul>
71 * <li>sourcedir
72 * <li>destdir
73 * <li>classpath
74 * </ul>
75 * Of these arguments, the <b>sourcedir</b> and <b>destdir</b> are required.
76 * <p>
77 * When this task executes, it will recursively scan the sourcedir and
78 * destdir looking for Groovy source files to compile. This task makes its
79 * compile decision based on timestamp.
80 *
81 * Based heavily on the Javac implementation in Ant
82 *
83 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
84 * @version $Revision: 1.14 $
85 */
86 public class Groovyc extends MatchingTask {
87
88 private CompilerConfiguration configuration = new CompilerConfiguration();
89 private Path src;
90 private File destDir;
91 private Path compileClasspath;
92 private Path compileSourcepath;
93 private String encoding;
94
95 protected boolean failOnError = true;
96 protected boolean listFiles = false;
97 protected File[] compileList = new File[0];
98
99 public static void main(String[] args) {
100 String dest = ".";
101 String src = ".";
102 boolean listFiles = false;
103 if (args.length > 0) {
104 dest = args[0];
105 }
106 if (args.length > 1) {
107 src = args[1];
108 }
109 if (args.length > 2) {
110 String flag = args[2];
111 if (flag.equalsIgnoreCase("true")) {
112 listFiles = true;
113 }
114 }
115
116 Project project = new Project();
117 project.addBuildListener(new AnsiColorLogger());
118
119 Groovyc compiler = new Groovyc();
120 compiler.setProject(project);
121 compiler.setSrcdir(new Path(project, src));
122 compiler.setDestdir(project.resolveFile(dest));
123 compiler.setListfiles(listFiles);
124 compiler.execute();
125 }
126
127 public Groovyc() {
128 }
129
130 /***
131 * Adds a path for source compilation.
132 *
133 * @return a nested src element.
134 */
135 public Path createSrc() {
136 if (src == null) {
137 src = new Path(getProject());
138 }
139 return src.createPath();
140 }
141
142 /***
143 * Recreate src.
144 *
145 * @return a nested src element.
146 */
147 protected Path recreateSrc() {
148 src = null;
149 return createSrc();
150 }
151
152 /***
153 * Set the source directories to find the source Java files.
154 * @param srcDir the source directories as a path
155 */
156 public void setSrcdir(Path srcDir) {
157 if (src == null) {
158 src = srcDir;
159 }
160 else {
161 src.append(srcDir);
162 }
163 }
164
165 /***
166 * Gets the source dirs to find the source java files.
167 * @return the source directorys as a path
168 */
169 public Path getSrcdir() {
170 return src;
171 }
172
173 /***
174 * Set the destination directory into which the Java source
175 * files should be compiled.
176 * @param destDir the destination director
177 */
178 public void setDestdir(File destDir) {
179 this.destDir = destDir;
180 }
181
182 /***
183 * Enable verbose compiling which will display which files
184 * are being compiled
185 * @param verbose
186 */
187 public void setVerbose(boolean verbose) {
188 configuration.setVerbose( verbose );
189 }
190
191 /***
192 * Gets the destination directory into which the java source files
193 * should be compiled.
194 * @return the destination directory
195 */
196 public File getDestdir() {
197 return destDir;
198 }
199
200 /***
201 * Set the sourcepath to be used for this compilation.
202 * @param sourcepath the source path
203 */
204 public void setSourcepath(Path sourcepath) {
205 if (compileSourcepath == null) {
206 compileSourcepath = sourcepath;
207 }
208 else {
209 compileSourcepath.append(sourcepath);
210 }
211 }
212
213 /***
214 * Gets the sourcepath to be used for this compilation.
215 * @return the source path
216 */
217 public Path getSourcepath() {
218 return compileSourcepath;
219 }
220
221 /***
222 * Adds a path to sourcepath.
223 * @return a sourcepath to be configured
224 */
225 public Path createSourcepath() {
226 if (compileSourcepath == null) {
227 compileSourcepath = new Path(getProject());
228 }
229 return compileSourcepath.createPath();
230 }
231
232 /***
233 * Adds a reference to a source path defined elsewhere.
234 * @param r a reference to a source path
235 */
236 public void setSourcepathRef(Reference r) {
237 createSourcepath().setRefid(r);
238 }
239
240 /***
241 * Set the classpath to be used for this compilation.
242 *
243 * @param classpath an Ant Path object containing the compilation classpath.
244 */
245 public void setClasspath(Path classpath) {
246 if (compileClasspath == null) {
247 compileClasspath = classpath;
248 }
249 else {
250 compileClasspath.append(classpath);
251 }
252 }
253
254 /***
255 * Gets the classpath to be used for this compilation.
256 * @return the class path
257 */
258 public Path getClasspath() {
259 return compileClasspath;
260 }
261
262 /***
263 * Adds a path to the classpath.
264 * @return a class path to be configured
265 */
266 public Path createClasspath() {
267 if (compileClasspath == null) {
268 compileClasspath = new Path(getProject());
269 }
270 return compileClasspath.createPath();
271 }
272
273 /***
274 * Adds a reference to a classpath defined elsewhere.
275 * @param r a reference to a classpath
276 */
277 public void setClasspathRef(Reference r) {
278 createClasspath().setRefid(r);
279 }
280
281 public String createEncoding() {
282 if (encoding == null) {
283 encoding = System.getProperty("file.encoding");
284 }
285 return encoding;
286 }
287
288 public void setEncoding(String encoding) {
289 this.encoding = encoding;
290 }
291
292 public String getEncoding() {
293 return encoding;
294 }
295
296 /***
297 * If true, list the source files being handed off to the compiler.
298 * @param list if true list the source files
299 */
300 public void setListfiles(boolean list) {
301 listFiles = list;
302 }
303
304 /***
305 * Get the listfiles flag.
306 * @return the listfiles flag
307 */
308 public boolean getListfiles() {
309 return listFiles;
310 }
311
312 /***
313 * Indicates whether the build will continue
314 * even if there are compilation errors; defaults to true.
315 * @param fail if true halt the build on failure
316 */
317 public void setFailonerror(boolean fail) {
318 failOnError = fail;
319 }
320
321 /***
322 * @ant.attribute ignore="true"
323 * @param proceed inverse of failoferror
324 */
325 public void setProceed(boolean proceed) {
326 failOnError = !proceed;
327 }
328
329 /***
330 * Gets the failonerror flag.
331 * @return the failonerror flag
332 */
333 public boolean getFailonerror() {
334 return failOnError;
335 }
336
337 /***
338 * Executes the task.
339 * @exception BuildException if an error occurs
340 */
341 public void execute() throws BuildException {
342 checkParameters();
343 resetFileLists();
344
345
346
347 String[] list = src.list();
348 for (int i = 0; i < list.length; i++) {
349 File srcDir = getProject().resolveFile(list[i]);
350 if (!srcDir.exists()) {
351 throw new BuildException("srcdir \"" + srcDir.getPath() + "\" does not exist!", getLocation());
352 }
353
354 DirectoryScanner ds = this.getDirectoryScanner(srcDir);
355 String[] files = ds.getIncludedFiles();
356
357 scanDir(srcDir, destDir != null ? destDir : srcDir, files);
358 }
359
360 compile();
361 }
362
363 /***
364 * Clear the list of files to be compiled and copied..
365 */
366 protected void resetFileLists() {
367 compileList = new File[0];
368 }
369
370 /***
371 * Scans the directory looking for source files to be compiled.
372 * The results are returned in the class variable compileList
373 *
374 * @param srcDir The source directory
375 * @param destDir The destination directory
376 * @param files An array of filenames
377 */
378 protected void scanDir(File srcDir, File destDir, String[] files) {
379 GlobPatternMapper m = new GlobPatternMapper();
380 m.setFrom("*.groovy");
381 m.setTo("*.class");
382 SourceFileScanner sfs = new SourceFileScanner(this);
383 File[] newFiles = sfs.restrictAsFiles(files, srcDir, destDir, m);
384
385 if (newFiles.length > 0) {
386 File[] newCompileList = new File[compileList.length + newFiles.length];
387 System.arraycopy(compileList, 0, newCompileList, 0, compileList.length);
388 System.arraycopy(newFiles, 0, newCompileList, compileList.length, newFiles.length);
389 compileList = newCompileList;
390 }
391 }
392
393 /***
394 * Gets the list of files to be compiled.
395 * @return the list of files as an array
396 */
397 public File[] getFileList() {
398 return compileList;
399 }
400
401 protected void checkParameters() throws BuildException {
402 if (src == null) {
403 throw new BuildException("srcdir attribute must be set!", getLocation());
404 }
405 if (src.size() == 0) {
406 throw new BuildException("srcdir attribute must be set!", getLocation());
407 }
408
409 if (destDir != null && !destDir.isDirectory()) {
410 throw new BuildException(
411 "destination directory \"" + destDir + "\" does not exist " + "or is not a directory",
412 getLocation());
413 }
414
415 if (encoding != null && !Charset.isSupported(encoding)) {
416 throw new BuildException("encoding \"\" not supported");
417 }
418 }
419
420 protected void compile() {
421
422 if (compileList.length > 0) {
423 log(
424 "Compiling "
425 + compileList.length
426 + " source file"
427 + (compileList.length == 1 ? "" : "s")
428 + (destDir != null ? " to " + destDir : ""));
429
430 if (listFiles) {
431 for (int i = 0; i < compileList.length; i++) {
432 String filename = compileList[i].getAbsolutePath();
433
434
435 log(filename);
436 System.out.println("compiling: " + filename);
437 }
438 }
439
440 try {
441 Path classpath = getClasspath();
442 if (classpath != null) {
443 configuration.setClasspath(classpath.toString());
444 }
445 configuration.setTargetDirectory(destDir);
446
447 if (encoding != null) {
448 configuration.setSourceEncoding(encoding);
449 }
450
451 CompilationUnit unit = new CompilationUnit( configuration );
452 unit.addSources( compileList );
453 unit.compile( );
454 }
455 catch (Exception e) {
456
457 StringWriter writer = new StringWriter();
458 new ErrorReporter( e, false ).write( new PrintWriter(writer) );
459 String message = writer.toString();
460
461 if (failOnError) {
462 throw new BuildException(message, e, getLocation());
463 }
464 else {
465 log(message, Project.MSG_ERR);
466 }
467
468 }
469 }
470 }
471 }