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