001 package escjava.ant;
002
003 import org.apache.tools.ant.BuildException;
004 import org.apache.tools.ant.Project;
005 import org.apache.tools.ant.taskdefs.Execute;
006 import org.apache.tools.ant.taskdefs.Javac;
007 import org.apache.tools.ant.taskdefs.LogStreamHandler;
008 import org.apache.tools.ant.taskdefs.compilers.DefaultCompilerAdapter;
009 import org.apache.tools.ant.types.Commandline;
010 import org.apache.tools.ant.types.Path;
011 import org.apache.tools.ant.util.FileUtils;
012
013 import java.io.File;
014 import java.io.FileWriter;
015 import java.io.IOException;
016 import java.io.PrintWriter;
017
018 /**
019 * Define an Escj compiler adapter. This class is only a very simple
020 * wrapper and does not try to implement of the command line options
021 * of escj.
022 *
023 * @author wsargent
024 * @version $Revision: 1.3 $
025 *
026 * @since May 16, 2004
027 */
028 public class ESCJavaTask extends DefaultCompilerAdapter
029 {
030 private FileUtils fileUtils = FileUtils.newFileUtils();
031
032 /* (non-Javadoc)
033 * @see org.apache.tools.ant.taskdefs.compilers.DefaultCompilerAdapter#execute()
034 */
035 public boolean execute() throws BuildException
036 {
037 if (super.attributes == null)
038 {
039 throw new BuildException("Null attributes");
040 }
041
042 if (super.project == null)
043 {
044 throw new BuildException("Null project");
045 }
046
047 Javac javac = getJavac();
048
049 if (javac == null)
050 {
051 throw new BuildException("null javac");
052 }
053
054 super.attributes.log("Using escj compiler", 3);
055
056 Path classpath = new Path(super.project);
057
058 if (super.bootclasspath != null)
059 {
060 classpath.append(super.bootclasspath);
061 }
062
063 classpath.addExtdirs(super.extdirs);
064
065 if ((super.bootclasspath == null) || (super.bootclasspath.size() == 0))
066 {
067 super.includeJavaRuntime = true;
068 }
069
070 classpath.append(getCompileClasspath());
071
072 if (super.compileSourcepath != null)
073 {
074 classpath.append(super.compileSourcepath);
075 } else
076 {
077 classpath.append(super.src);
078 }
079
080 Commandline cmd = new Commandline();
081 String exec = javac.getExecutable();
082 cmd.setExecutable((exec != null) ? exec : "java");
083
084 String simplifyProperty = super.project.getProperty(
085 "build.compiler.simplify");
086
087 // Make sure the simplify argument comes before...
088 if (simplifyProperty != null)
089 {
090 cmd.createArgument().setValue("-Dsimplify=" + simplifyProperty);
091 }
092
093 cmd.createArgument().setValue("-classpath");
094 cmd.createArgument().setPath(classpath);
095
096 cmd.createArgument().setValue("escjava.Main");
097
098 cmd.createArgument().setValue("-classpath");
099 cmd.createArgument().setPath(classpath);
100
101 /*
102 if (super.deprecation)
103 {
104 cmd.createArgument().setValue("-deprecation");
105 }
106 */
107 /*
108 if (super.destDir != null)
109 {
110 cmd.createArgument().setValue("-d");
111 cmd.createArgument().setFile(super.destDir);
112 }
113 */
114 /*
115 if (super.encoding != null)
116 {
117 cmd.createArgument().setValue("-encoding");
118 cmd.createArgument().setValue(super.encoding);
119 }
120 */
121 /*
122 if (super.debug)
123 {
124 cmd.createArgument().setValue("-g");
125 }
126 */
127 /*
128 if (super.optimize)
129 {
130 cmd.createArgument().setValue("-O");
131 }
132 */
133 setCounterExample(cmd);
134 setDepend(cmd);
135 setEajava(cmd);
136 setEajml(cmd);
137 setEnableAssertions(cmd);
138 setLoopsafe(cmd);
139 setLoop(cmd);
140 setNoCheck(cmd);
141 setNoCautions(cmd);
142 setNoRedundancy(cmd);
143 setNoTrace(cmd);
144 setNoWarn(cmd);
145 setPxLog(cmd);
146 setPlainWarning(cmd);
147 setQuiet(cmd);
148 setRoutine(cmd);
149 setRoutineIndirect(cmd);
150 setSource(cmd);
151 setSourcePath(cmd);
152 setSuggest(cmd);
153 setSxLog(cmd);
154 setTarget(cmd);
155 setTypeCheck(cmd);
156 setUseVars(cmd);
157 setUseFcns(cmd);
158 setUseVarsForModelVars(cmd);
159 setUseFcnsForModelVars(cmd);
160 setWarn(cmd);
161 setVerbose(cmd);
162
163 // Set the -f value to use the files following.
164 cmd.createArgument().setValue("-f");
165
166 addCurrentCompilerArgs(cmd);
167
168 int firstFileName = cmd.size();
169 logAndAddFilesToCompile(cmd);
170
171 return executeExternalCompile(cmd.getCommandline(), firstFileName) == 0;
172 }
173
174 /**
175 * @param cmd
176 */
177 private void setUseFcnsForModelVars(/*@ non_null @*/ Commandline cmd) throws BuildException
178 {
179 setTextArgument(cmd, "usefcnsformodelvars", "useFcnsForModelVars");
180 }
181
182 /**
183 * @param cmd
184 */
185 private void setUseVarsForModelVars(/*@ non_null @*/ Commandline cmd) throws BuildException
186 {
187 setTextArgument(cmd, "usevarsformodelvars", "useVarsForModelVars");
188 }
189
190 /**
191 * @param cmd
192 */
193 private void setWarn(/*@ non_null @*/ Commandline cmd) throws BuildException
194 {
195 setTextArgument(cmd, "warn", "warn");
196 }
197
198 /**
199 * @param cmd
200 */
201 private void setUseFcns(/*@ non_null @*/ Commandline cmd) throws BuildException
202 {
203 setArgument(cmd, "usefcns", "useFcns");
204 }
205
206 /**
207 * @param cmd
208 */
209 private void setRoutineIndirect(/*@ non_null @*/ Commandline cmd) throws BuildException
210 {
211 setTextArgument(cmd, "routineindirect", "routineIndirect");
212 }
213
214 /**
215 * @param cmd
216 */
217 private void setPlainWarning(/*@ non_null @*/ Commandline cmd) throws BuildException
218 {
219 setArgument(cmd, "plainwarning", "plainwarning");
220 }
221
222 /**
223 * @param cmd
224 */
225 private void setRoutine(/*@ non_null @*/ Commandline cmd) throws BuildException
226 {
227 String arg = "routine";
228 setTextArgument(cmd, arg, arg);
229 }
230
231 /**
232 * @param cmd
233 */
234 private void setLoop(/*@ non_null @*/ Commandline cmd) throws BuildException
235 {
236 String arg = "loop";
237 setTextArgument(cmd, arg, arg);
238 }
239
240 /**
241 * Sets the -quiet option.
242 *
243 * @param cmd
244 */
245 private void setQuiet(/*@ non_null @*/ Commandline cmd) throws BuildException
246 {
247 String arg = "quiet";
248 setArgument(cmd, arg, arg);
249 }
250
251 private void setVerbose(/*@ non_null @*/ Commandline cmd)
252 {
253 if (super.verbose)
254 {
255 cmd.createArgument().setValue("-v");
256 }
257 }
258
259 private void setDepend(/*@ non_null @*/ Commandline cmd)
260 {
261 if (super.depend)
262 {
263 cmd.createArgument().setValue("-depend");
264 }
265 }
266
267 private void setTarget(/*@ non_null @*/ Commandline cmd)
268 {
269 if (super.target != null)
270 {
271 cmd.createArgument().setValue("-target");
272 cmd.createArgument().setValue(super.target);
273 }
274 }
275
276 private void setNoWarn(/*@ non_null @*/ Commandline cmd) throws BuildException
277 {
278 if (super.attributes == null)
279 {
280 throw new BuildException("Null attributes");
281 }
282
283 if (super.attributes.getNowarn())
284 {
285 cmd.createArgument().setValue("-nowarn");
286 }
287 }
288
289 private void setSource(/*@ non_null @*/ Commandline cmd) throws BuildException
290 {
291 if (super.attributes == null)
292 {
293 throw new BuildException("Null attributes");
294 }
295
296 if (super.attributes.getSource() != null)
297 {
298 cmd.createArgument().setValue("-source");
299 cmd.createArgument().setValue(super.attributes.getSource());
300 }
301 }
302
303 private void setSourcePath(/*@ non_null @*/ Commandline cmd) throws BuildException
304 {
305 if (super.attributes == null)
306 {
307 throw new BuildException("Null attributes");
308 }
309
310 if (super.attributes.getSourcepath() != null)
311 {
312 cmd.createArgument().setValue("-sourcepath");
313
314 Path path = super.attributes.getSourcepath();
315 String pathString = (path == null) ? null : path.toString();
316 cmd.createArgument().setValue(pathString);
317 }
318 }
319
320 private void setSxLog(/*@ non_null @*/ Commandline cmd) throws BuildException
321 {
322 setTextArgument(cmd, "sxlog", "sxLog");
323 }
324
325 private void setPxLog(/*@ non_null @*/ Commandline cmd) throws BuildException
326 {
327 setTextArgument(cmd, "pxlog", "pxLog");
328 }
329
330 private void setCounterExample(/*@ non_null @*/ Commandline cmd) throws BuildException
331 {
332 String arg = "counterexample";
333 setArgument(cmd, arg, arg);
334 }
335
336 private void setEajava(/*@ non_null @*/ Commandline cmd) throws BuildException
337 {
338 String arg = "eajava";
339 setArgument(cmd, arg, arg);
340 }
341
342 private void setEajml(/*@ non_null @*/ Commandline cmd) throws BuildException
343 {
344 String arg = "eajml";
345 setArgument(cmd, arg, arg);
346 }
347
348 private void setEnableAssertions(/*@ non_null @*/ Commandline cmd) throws BuildException
349 {
350 String arg = "enableassertions";
351 setArgument(cmd, arg, arg);
352 }
353
354 private void setUseVars(/*@ non_null @*/ Commandline cmd) throws BuildException
355 {
356 String arg = "usevars";
357 setArgument(cmd, arg, "useVars");
358 }
359
360 private void setTypeCheck(/*@ non_null @*/ Commandline cmd) throws BuildException
361 {
362 String arg = "typecheck";
363 setArgument(cmd, arg, arg);
364 }
365
366 private void setSuggest(/*@ non_null @*/ Commandline cmd) throws BuildException
367 {
368 String arg = "suggest";
369 setArgument(cmd, arg, arg);
370 }
371
372 private void setNoTrace(/*@ non_null @*/ Commandline cmd) throws BuildException
373 {
374 String arg = "notrace";
375 setArgument(cmd, arg, arg);
376 }
377
378 private void setNoRedundancy(/*@ non_null @*/ Commandline cmd) throws BuildException
379 {
380 String arg = "noredundancy";
381 setArgument(cmd, arg, arg);
382 }
383
384 private void setNoCautions(/*@ non_null @*/ Commandline cmd) throws BuildException
385 {
386 String arg = "nocautions";
387 setArgument(cmd, arg, "noCautions");
388 }
389
390 private void setNoCheck(/*@ non_null @*/ Commandline cmd) throws BuildException
391 {
392 String arg = "nocheck";
393 setArgument(cmd, arg, arg);
394 }
395
396 private void setLoopsafe(/*@ non_null @*/ Commandline cmd) throws BuildException
397 {
398 String arg = "loopsafe";
399 setArgument(cmd, arg, arg);
400 }
401
402 /**
403 * Do the compile with the specified arguments.
404 *
405 * @param args - arguments to pass to process on command line
406 * @param firstFileName - index of the first source file in args, if the
407 * index is negative, no temporary file will ever be created, but
408 * this may hit the command line length limit on your system.
409 * @param quoteFiles - if set to true, filenames containing spaces will be
410 * quoted when they appear in the external file. This is necessary
411 * when running JDK 1.4's javac and probably others.
412 *
413 * @return DOCUMENT ME!
414 *
415 * @throws BuildException DOCUMENT ME!
416 *
417 * @since Ant 1.6
418 */
419 //@ also
420 //@ requires args != null;
421 protected int executeExternalCompile(String[] args,
422 int firstFileName,
423 boolean quoteFiles)
424 {
425 String[] commandArray = null;
426 File tmpFile = null;
427
428 try
429 {
430
431 /*
432 * Many system have been reported to get into trouble with
433 * long command lines - no, not only Windows ;-).
434 *
435 * POSIX seems to define a lower limit of 4k, so use a temporary
436 * file if the total length of the command line exceeds this limit.
437 */
438 if ((Commandline.toString(args).length() > 4096) && (firstFileName >= 0))
439 {
440 PrintWriter out = null;
441
442 try
443 {
444 File userDir = getJavac().getTempdir();
445
446 if (userDir == null)
447 {
448 String userDirName = System.getProperty("user.dir");
449 userDir = new File(userDirName);
450 }
451
452 tmpFile = fileUtils.createTempFile("files", "", userDir);
453 tmpFile.deleteOnExit();
454 out = new PrintWriter(new FileWriter(tmpFile));
455
456 for (int i = firstFileName; i < args.length; i++)
457 {
458 if (quoteFiles && (args[i].indexOf(" ") > -1))
459 {
460 args[i] = args[i].replace('\\', '/');
461 out.println("\"" + args[i] + "\"");
462 } else
463 {
464 out.println(args[i]);
465 }
466 }
467
468 out.flush();
469 commandArray = new String[firstFileName + 1];
470 System.arraycopy(args, 0, commandArray, 0, firstFileName);
471 commandArray[firstFileName] = tmpFile.toString();
472 } catch (IOException e)
473 {
474 throw new BuildException("Error creating temporary file",
475 e, location);
476 } finally
477 {
478 if (out != null)
479 {
480 try
481 {
482 out.close();
483 } catch (Throwable t)
484 {
485 // ignore
486 }
487 }
488 }
489 } else
490 {
491 commandArray = args;
492 }
493
494 try
495 {
496 Execute exe = new Execute(new LogStreamHandler(attributes,
497 Project.MSG_INFO, Project.MSG_WARN));
498 exe.setAntRun(project);
499 exe.setWorkingDirectory(project.getBaseDir());
500 exe.setCommandline(commandArray);
501 exe.execute();
502
503 return exe.getExitValue();
504 } catch (IOException e)
505 {
506 throw new BuildException("Error running " + args[0] +
507 " compiler", e, location);
508 }
509 } finally
510 {
511 if (tmpFile != null)
512 {
513 tmpFile.delete();
514 }
515 }
516 }
517
518 /**
519 * Sets an argument with a text value from a property.
520 *
521 * @param cmd
522 * @param pPropertyName
523 * @param pArgumentName
524 *
525 * @throws BuildException if one of the arguments is null.
526 */
527 private void setTextArgument(/*@ non_null @*/ Commandline cmd,
528 /*@ non_null @*/ String pPropertyName,
529 /*@ non_null @*/ String pArgumentName) throws BuildException
530 {
531 if (cmd == null)
532 {
533 throw new BuildException("null cmd");
534 }
535
536 if (pPropertyName == null)
537 {
538 throw new BuildException("null pName");
539 }
540
541 if (pArgumentName == null)
542 {
543 throw new BuildException("null pArgument");
544 }
545
546 if (super.project == null)
547 {
548 throw new BuildException("null project");
549 }
550
551 String propertyValue = super.project.getProperty("build.compiler." +
552 pPropertyName);
553
554 if (propertyValue != null)
555 {
556 cmd.createArgument().setValue("-" + pArgumentName + "=" +
557 propertyValue);
558 }
559 }
560
561 /**
562 * Sets an argument on the commandline from a boolean property.
563 *
564 * @param cmd
565 * @param pPropertyName
566 * @param pArgumentName
567 *
568 * @throws BuildException DOCUMENT ME!
569 */
570 private void setArgument(/*@ non_null @*/ Commandline cmd,
571 /*@ non_null @*/ String pPropertyName,
572 /*@ non_null @*/ String pArgumentName) throws BuildException
573 {
574 if (cmd == null)
575 {
576 throw new BuildException("null cmd");
577 }
578
579 if (pPropertyName == null)
580 {
581 throw new BuildException("null pName");
582 }
583
584 if (pArgumentName == null)
585 {
586 throw new BuildException("null pArgument");
587 }
588
589 if (super.project == null)
590 {
591 throw new BuildException("null super.project");
592 }
593
594 String propertyName = super.project.getProperty("build.compiler." +
595 pPropertyName);
596
597 if ((propertyName != null) && Project.toBoolean(propertyName))
598 {
599 cmd.createArgument().setValue("-" + pArgumentName);
600 }
601 }
602 }