1. /*
  2. * Copyright 2000-2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. package org.apache.tools.ant.taskdefs.optional;
  18. import java.io.BufferedReader;
  19. import java.io.File;
  20. import java.io.IOException;
  21. import java.io.PrintWriter;
  22. import java.io.StringReader;
  23. import java.io.StringWriter;
  24. import java.util.Enumeration;
  25. import java.util.Hashtable;
  26. import java.util.Properties;
  27. import java.util.StringTokenizer;
  28. import java.util.Vector;
  29. import netrexx.lang.Rexx;
  30. import org.apache.tools.ant.BuildException;
  31. import org.apache.tools.ant.DirectoryScanner;
  32. import org.apache.tools.ant.Project;
  33. import org.apache.tools.ant.taskdefs.MatchingTask;
  34. import org.apache.tools.ant.types.EnumeratedAttribute;
  35. /**
  36. * Compiles NetRexx source files.
  37. * This task can take the following
  38. * arguments:
  39. * <ul>
  40. * <li>binary</li>
  41. * <li>classpath</li>
  42. * <li>comments</li>
  43. * <li>compile</li>
  44. * <li>console</li>
  45. * <li>crossref</li>
  46. * <li>decimal</li>
  47. * <li>destdir</li>
  48. * <li>diag</li>
  49. * <li>explicit</li>
  50. * <li>format</li>
  51. * <li>keep</li>
  52. * <li>logo</li>
  53. * <li>replace</li>
  54. * <li>savelog</li>
  55. * <li>srcdir</li>
  56. * <li>sourcedir</li>
  57. * <li>strictargs</li>
  58. * <li>strictassign</li>
  59. * <li>strictcase</li>
  60. * <li>strictimport</li>
  61. * <li>symbols</li>
  62. * <li>time</li>
  63. * <li>trace</li>
  64. * <li>utf8</li>
  65. * <li>verbose</li>
  66. * <li>suppressMethodArgumentNotUsed</li>
  67. * <li>suppressPrivatePropertyNotUsed</li>
  68. * <li>suppressVariableNotUsed</li>
  69. * <li>suppressExceptionNotSignalled</li>
  70. * <li>suppressDeprecation</li>
  71. * </ul>
  72. * Of these arguments, the <b>srcdir</b> argument is required.
  73. *
  74. * <p>When this task executes, it will recursively scan the srcdir
  75. * looking for NetRexx source files to compile. This task makes its
  76. * compile decision based on timestamp.
  77. * <p>Before files are compiled they and any other file in the
  78. * srcdir will be copied to the destdir allowing support files to be
  79. * located properly in the classpath. The reason for copying the source files
  80. * before the compile is that NetRexxC has only two destinations for classfiles:
  81. * <ol>
  82. * <li>The current directory, and,</li>
  83. * <li>The directory the source is in (see sourcedir option)
  84. * </ol>
  85. *
  86. */
  87. public class NetRexxC extends MatchingTask {
  88. // variables to hold arguments
  89. private boolean binary;
  90. private String classpath;
  91. private boolean comments;
  92. private boolean compact = true;// should be the default, as it integrates better in ant.
  93. private boolean compile = true;
  94. private boolean console;
  95. private boolean crossref;
  96. private boolean decimal = true;
  97. private File destDir;
  98. private boolean diag;
  99. private boolean explicit;
  100. private boolean format;
  101. private boolean keep;
  102. private boolean logo = true;
  103. private boolean replace;
  104. private boolean savelog;
  105. private File srcDir;
  106. private boolean sourcedir = true;// ?? Should this be the default for ant?
  107. private boolean strictargs;
  108. private boolean strictassign;
  109. private boolean strictcase;
  110. private boolean strictimport;
  111. private boolean strictprops;
  112. private boolean strictsignal;
  113. private boolean symbols;
  114. private boolean time;
  115. private String trace = "trace2";
  116. private boolean utf8;
  117. private String verbose = "verbose3";
  118. private boolean suppressMethodArgumentNotUsed = false;
  119. private boolean suppressPrivatePropertyNotUsed = false;
  120. private boolean suppressVariableNotUsed = false;
  121. private boolean suppressExceptionNotSignalled = false;
  122. private boolean suppressDeprecation = false;
  123. // constants for the messages to suppress by flags and their corresponding properties
  124. static final String MSG_METHOD_ARGUMENT_NOT_USED
  125. = "Warning: Method argument is not used";
  126. static final String MSG_PRIVATE_PROPERTY_NOT_USED
  127. = "Warning: Private property is defined but not used";
  128. static final String MSG_VARIABLE_NOT_USED
  129. = "Warning: Variable is set but not used";
  130. static final String MSG_EXCEPTION_NOT_SIGNALLED
  131. = "is in SIGNALS list but is not signalled within the method";
  132. static final String MSG_DEPRECATION = "has been deprecated";
  133. // other implementation variables
  134. private Vector compileList = new Vector();
  135. private Hashtable filecopyList = new Hashtable();
  136. /**
  137. * Set whether literals are treated as binary, rather than NetRexx types
  138. */
  139. public void setBinary(boolean binary) {
  140. this.binary = binary;
  141. }
  142. /** Set the classpath used for NetRexx compilation */
  143. public void setClasspath(String classpath) {
  144. this.classpath = classpath;
  145. }
  146. /**
  147. * Set whether comments are passed through to the generated java source.
  148. * Valid true values are "on" or "true". Anything else sets the flag to
  149. * false. The default value is false
  150. */
  151. public void setComments(boolean comments) {
  152. this.comments = comments;
  153. }
  154. /**
  155. * Set whether error messages come out in compact or verbose format. Valid
  156. * true values are "on" or "true". Anything else sets the flag to false.
  157. * The default value is false
  158. */
  159. public void setCompact(boolean compact) {
  160. this.compact = compact;
  161. }
  162. /**
  163. * Set whether the NetRexx compiler should compile the generated java code
  164. * Valid true values are "on" or "true". Anything else sets the flag to
  165. * false. The default value is true. Setting this flag to false, will
  166. * automatically set the keep flag to true.
  167. */
  168. public void setCompile(boolean compile) {
  169. this.compile = compile;
  170. if (!this.compile && !this.keep) {
  171. this.keep = true;
  172. }
  173. }
  174. /**
  175. * Set whether or not messages should be displayed on the 'console' Valid
  176. * true values are "on" or "true". Anything else sets the flag to false.
  177. * The default value is true.
  178. */
  179. public void setConsole(boolean console) {
  180. this.console = console;
  181. }
  182. /** Whether variable cross references are generated */
  183. public void setCrossref(boolean crossref) {
  184. this.crossref = crossref;
  185. }
  186. /**
  187. * Set whether decimal arithmetic should be used for the netrexx code.
  188. * Binary arithmetic is used when this flag is turned off. Valid true
  189. * values are "on" or "true". Anything else sets the flag to false. The
  190. * default value is true.
  191. */
  192. public void setDecimal(boolean decimal) {
  193. this.decimal = decimal;
  194. }
  195. /**
  196. * Set the destination directory into which the NetRexx source files
  197. * should be copied and then compiled.
  198. */
  199. public void setDestDir(File destDirName) {
  200. destDir = destDirName;
  201. }
  202. /**
  203. * Whether diagnostic information about the compile is generated
  204. */
  205. public void setDiag(boolean diag) {
  206. this.diag = diag;
  207. }
  208. /**
  209. * Sets whether variables must be declared explicitly before use. Valid
  210. * true values are "on" or "true". Anything else sets the flag to false.
  211. * The default value is false.
  212. */
  213. public void setExplicit(boolean explicit) {
  214. this.explicit = explicit;
  215. }
  216. /**
  217. * Whether the generated java code is formatted nicely or left to match
  218. * NetRexx line numbers for call stack debugging
  219. */
  220. public void setFormat(boolean format) {
  221. this.format = format;
  222. }
  223. /**
  224. * Whether the generated java code is produced Valid true values are "on"
  225. * or "true". Anything else sets the flag to false. The default value is
  226. * false.
  227. */
  228. public void setJava(boolean java) {
  229. log("The attribute java is currently unused.", Project.MSG_WARN);
  230. }
  231. /**
  232. * Sets whether the generated java source file should be kept after
  233. * compilation. The generated files will have an extension of .java.keep,
  234. * <b>not</b> .java Valid true values are "on" or "true". Anything else
  235. * sets the flag to false. The default value is false.
  236. */
  237. public void setKeep(boolean keep) {
  238. this.keep = keep;
  239. }
  240. /** Whether the compiler text logo is displayed when compiling */
  241. public void setLogo(boolean logo) {
  242. this.logo = logo;
  243. }
  244. /**
  245. * Whether the generated .java file should be replaced when compiling
  246. * Valid true values are "on" or "true". Anything else sets the flag to
  247. * false. The default value is false.
  248. */
  249. public void setReplace(boolean replace) {
  250. this.replace = replace;
  251. }
  252. /**
  253. * Sets whether the compiler messages will be written to NetRexxC.log as
  254. * well as to the console Valid true values are "on" or "true". Anything
  255. * else sets the flag to false. The default value is false.
  256. */
  257. public void setSavelog(boolean savelog) {
  258. this.savelog = savelog;
  259. }
  260. /**
  261. * Tells the NetRexx compiler to store the class files in the same
  262. * directory as the source files. The alternative is the working directory
  263. * Valid true values are "on" or "true". Anything else sets the flag to
  264. * false. The default value is true.
  265. */
  266. public void setSourcedir(boolean sourcedir) {
  267. this.sourcedir = sourcedir;
  268. }
  269. /** Set the source dir to find the source Java files. */
  270. public void setSrcDir(File srcDirName) {
  271. srcDir = srcDirName;
  272. }
  273. /**
  274. * Tells the NetRexx compiler that method calls always need parentheses,
  275. * even if no arguments are needed, e.g. <code>aStringVar.getBytes</code>
  276. * vs. <code>aStringVar.getBytes()</code> Valid true values are "on" or
  277. * "true". Anything else sets the flag to false. The default value is
  278. * false.
  279. */
  280. public void setStrictargs(boolean strictargs) {
  281. this.strictargs = strictargs;
  282. }
  283. /**
  284. * Tells the NetRexx compile that assignments must match exactly on type
  285. */
  286. public void setStrictassign(boolean strictassign) {
  287. this.strictassign = strictassign;
  288. }
  289. /**
  290. * Specifies whether the NetRexx compiler should be case sensitive or not
  291. */
  292. public void setStrictcase(boolean strictcase) {
  293. this.strictcase = strictcase;
  294. }
  295. /**
  296. * Sets whether classes need to be imported explicitly using an <code>import</code>
  297. * statement. By default the NetRexx compiler will import certain packages
  298. * automatically Valid true values are "on" or "true". Anything else sets
  299. * the flag to false. The default value is false.
  300. */
  301. public void setStrictimport(boolean strictimport) {
  302. this.strictimport = strictimport;
  303. }
  304. /**
  305. * Sets whether local properties need to be qualified explicitly using
  306. * <code>this</code> Valid true values are "on" or "true". Anything else
  307. * sets the flag to false. The default value is false.
  308. */
  309. public void setStrictprops(boolean strictprops) {
  310. this.strictprops = strictprops;
  311. }
  312. /**
  313. * Whether the compiler should force catching of exceptions by explicitly
  314. * named types
  315. */
  316. public void setStrictsignal(boolean strictsignal) {
  317. this.strictsignal = strictsignal;
  318. }
  319. /**
  320. * Sets whether debug symbols should be generated into the class file
  321. * Valid true values are "on" or "true". Anything else sets the flag to
  322. * false. The default value is false.
  323. */
  324. public void setSymbols(boolean symbols) {
  325. this.symbols = symbols;
  326. }
  327. /**
  328. * Asks the NetRexx compiler to print compilation times to the console
  329. * Valid true values are "on" or "true". Anything else sets the flag to
  330. * false. The default value is false.
  331. */
  332. public void setTime(boolean time) {
  333. this.time = time;
  334. }
  335. public void setTrace(TraceAttr trace) {
  336. this.trace = trace.getValue();
  337. }
  338. /**
  339. * Turns on or off tracing and directs the resultant trace output Valid
  340. * values are: "trace", "trace1", "trace2" and "notrace". "trace" and
  341. * "trace2"
  342. */
  343. public void setTrace(String trace) {
  344. TraceAttr t = new TraceAttr();
  345. t.setValue(trace);
  346. setTrace(t);
  347. }
  348. /**
  349. * Tells the NetRexx compiler that the source is in UTF8 Valid true values
  350. * are "on" or "true". Anything else sets the flag to false. The default
  351. * value is false.
  352. */
  353. public void setUtf8(boolean utf8) {
  354. this.utf8 = utf8;
  355. }
  356. /**
  357. * Whether lots of warnings and error messages should be generated
  358. */
  359. public void setVerbose(VerboseAttr verbose) {
  360. this.verbose = verbose.getValue();
  361. }
  362. /**
  363. * Whether lots of warnings and error messages should be generated
  364. */
  365. public void setVerbose(String verbose) {
  366. VerboseAttr v = new VerboseAttr();
  367. v.setValue(verbose);
  368. setVerbose(v);
  369. }
  370. /**
  371. * Whether the task should suppress the "Method argument is not used" in
  372. * strictargs-Mode, which can not be suppressed by the compiler itself.
  373. * The warning is logged as verbose message, though.
  374. */
  375. public void setSuppressMethodArgumentNotUsed(boolean suppressMethodArgumentNotUsed) {
  376. this.suppressMethodArgumentNotUsed = suppressMethodArgumentNotUsed;
  377. }
  378. /**
  379. * Whether the task should suppress the "Private property is defined but
  380. * not used" in strictargs-Mode, which can be quite annoying while
  381. * developing. The warning is logged as verbose message, though.
  382. */
  383. public void setSuppressPrivatePropertyNotUsed(boolean suppressPrivatePropertyNotUsed) {
  384. this.suppressPrivatePropertyNotUsed = suppressPrivatePropertyNotUsed;
  385. }
  386. /**
  387. * Whether the task should suppress the "Variable is set but not used" in
  388. * strictargs-Mode. Be careful with this one! The warning is logged as
  389. * verbose message, though.
  390. */
  391. public void setSuppressVariableNotUsed(boolean suppressVariableNotUsed) {
  392. this.suppressVariableNotUsed = suppressVariableNotUsed;
  393. }
  394. /**
  395. * Whether the task should suppress the "FooException is in SIGNALS list
  396. * but is not signalled within the method", which is sometimes rather
  397. * useless. The warning is logged as verbose message, though.
  398. */
  399. public void setSuppressExceptionNotSignalled(boolean suppressExceptionNotSignalled) {
  400. this.suppressExceptionNotSignalled = suppressExceptionNotSignalled;
  401. }
  402. /**
  403. * Tells whether we should filter out any deprecation-messages
  404. * of the compiler out.
  405. */
  406. public void setSuppressDeprecation(boolean suppressDeprecation) {
  407. this.suppressDeprecation = suppressDeprecation;
  408. }
  409. /**
  410. * init-Method sets defaults from Properties. That way, when ant is called
  411. * with arguments like -Dant.netrexxc.verbose=verbose5 one can easily take
  412. * control of all netrexxc-tasks.
  413. */
  414. public void init() {
  415. String p;
  416. if ((p = getProject().getProperty("ant.netrexxc.binary")) != null) {
  417. this.binary = Project.toBoolean(p);
  418. }
  419. // classpath makes no sense
  420. if ((p = getProject().getProperty("ant.netrexxc.comments")) != null) {
  421. this.comments = Project.toBoolean(p);
  422. }
  423. if ((p = getProject().getProperty("ant.netrexxc.compact")) != null) {
  424. this.compact = Project.toBoolean(p);
  425. }
  426. if ((p = getProject().getProperty("ant.netrexxc.compile")) != null) {
  427. this.compile = Project.toBoolean(p);
  428. }
  429. if ((p = getProject().getProperty("ant.netrexxc.console")) != null) {
  430. this.console = Project.toBoolean(p);
  431. }
  432. if ((p = getProject().getProperty("ant.netrexxc.crossref")) != null) {
  433. this.crossref = Project.toBoolean(p);
  434. }
  435. if ((p = getProject().getProperty("ant.netrexxc.decimal")) != null) {
  436. this.decimal = Project.toBoolean(p);
  437. // destDir
  438. }
  439. if ((p = getProject().getProperty("ant.netrexxc.diag")) != null) {
  440. this.diag = Project.toBoolean(p);
  441. }
  442. if ((p = getProject().getProperty("ant.netrexxc.explicit")) != null) {
  443. this.explicit = Project.toBoolean(p);
  444. }
  445. if ((p = getProject().getProperty("ant.netrexxc.format")) != null) {
  446. this.format = Project.toBoolean(p);
  447. }
  448. if ((p = getProject().getProperty("ant.netrexxc.keep")) != null) {
  449. this.keep = Project.toBoolean(p);
  450. }
  451. if ((p = getProject().getProperty("ant.netrexxc.logo")) != null) {
  452. this.logo = Project.toBoolean(p);
  453. }
  454. if ((p = getProject().getProperty("ant.netrexxc.replace")) != null) {
  455. this.replace = Project.toBoolean(p);
  456. }
  457. if ((p = getProject().getProperty("ant.netrexxc.savelog")) != null) {
  458. this.savelog = Project.toBoolean(p);
  459. // srcDir
  460. }
  461. if ((p = getProject().getProperty("ant.netrexxc.sourcedir")) != null) {
  462. this.sourcedir = Project.toBoolean(p);
  463. }
  464. if ((p = getProject().getProperty("ant.netrexxc.strictargs")) != null) {
  465. this.strictargs = Project.toBoolean(p);
  466. }
  467. if ((p = getProject().getProperty("ant.netrexxc.strictassign")) != null) {
  468. this.strictassign = Project.toBoolean(p);
  469. }
  470. if ((p = getProject().getProperty("ant.netrexxc.strictcase")) != null) {
  471. this.strictcase = Project.toBoolean(p);
  472. }
  473. if ((p = getProject().getProperty("ant.netrexxc.strictimport")) != null) {
  474. this.strictimport = Project.toBoolean(p);
  475. }
  476. if ((p = getProject().getProperty("ant.netrexxc.strictprops")) != null) {
  477. this.strictprops = Project.toBoolean(p);
  478. }
  479. if ((p = getProject().getProperty("ant.netrexxc.strictsignal")) != null) {
  480. this.strictsignal = Project.toBoolean(p);
  481. }
  482. if ((p = getProject().getProperty("ant.netrexxc.symbols")) != null) {
  483. this.symbols = Project.toBoolean(p);
  484. }
  485. if ((p = getProject().getProperty("ant.netrexxc.time")) != null) {
  486. this.time = Project.toBoolean(p);
  487. }
  488. if ((p = getProject().getProperty("ant.netrexxc.trace")) != null) {
  489. setTrace(p);
  490. }
  491. if ((p = getProject().getProperty("ant.netrexxc.utf8")) != null) {
  492. this.utf8 = Project.toBoolean(p);
  493. }
  494. if ((p = getProject().getProperty("ant.netrexxc.verbose")) != null) {
  495. setVerbose(p);
  496. }
  497. if ((p = getProject().getProperty("ant.netrexxc.suppressMethodArgumentNotUsed")) != null) {
  498. this.suppressMethodArgumentNotUsed = Project.toBoolean(p);
  499. }
  500. if ((p = getProject().getProperty("ant.netrexxc.suppressPrivatePropertyNotUsed")) != null) {
  501. this.suppressPrivatePropertyNotUsed = Project.toBoolean(p);
  502. }
  503. if ((p = getProject().getProperty("ant.netrexxc.suppressVariableNotUsed")) != null) {
  504. this.suppressVariableNotUsed = Project.toBoolean(p);
  505. }
  506. if ((p = getProject().getProperty("ant.netrexxc.suppressExceptionNotSignalled")) != null) {
  507. this.suppressExceptionNotSignalled = Project.toBoolean(p);
  508. }
  509. if ((p = getProject().getProperty("ant.netrexxc.suppressDeprecation")) != null) {
  510. this.suppressDeprecation = Project.toBoolean(p);
  511. }
  512. }
  513. /** Executes the task - performs the actual compiler call. */
  514. public void execute() throws BuildException {
  515. // first off, make sure that we've got a srcdir and destdir
  516. if (srcDir == null || destDir == null) {
  517. throw new BuildException("srcDir and destDir attributes must be set!");
  518. }
  519. // scan source and dest dirs to build up both copy lists and
  520. // compile lists
  521. // scanDir(srcDir, destDir);
  522. DirectoryScanner ds = getDirectoryScanner(srcDir);
  523. String[] files = ds.getIncludedFiles();
  524. scanDir(srcDir, destDir, files);
  525. // copy the source and support files
  526. copyFilesToDestination();
  527. // compile the source files
  528. if (compileList.size() > 0) {
  529. log("Compiling " + compileList.size() + " source file"
  530. + (compileList.size() == 1 ? "" : "s")
  531. + " to " + destDir);
  532. doNetRexxCompile();
  533. }
  534. }
  535. /**
  536. * Scans the directory looking for source files to be compiled and support
  537. * files to be copied.
  538. */
  539. private void scanDir(File srcDir, File destDir, String[] files) {
  540. for (int i = 0; i < files.length; i++) {
  541. File srcFile = new File(srcDir, files[i]);
  542. File destFile = new File(destDir, files[i]);
  543. String filename = files[i];
  544. // if it's a non source file, copy it if a later date than the
  545. // dest
  546. // if it's a source file, see if the destination class file
  547. // needs to be recreated via compilation
  548. if (filename.toLowerCase().endsWith(".nrx")) {
  549. File classFile =
  550. new File(destDir,
  551. filename.substring(0, filename.lastIndexOf('.')) + ".class");
  552. if (!compile || srcFile.lastModified() > classFile.lastModified()) {
  553. filecopyList.put(srcFile.getAbsolutePath(), destFile.getAbsolutePath());
  554. compileList.addElement(destFile.getAbsolutePath());
  555. }
  556. } else {
  557. if (srcFile.lastModified() > destFile.lastModified()) {
  558. filecopyList.put(srcFile.getAbsolutePath(), destFile.getAbsolutePath());
  559. }
  560. }
  561. }
  562. }
  563. /** Copy eligible files from the srcDir to destDir */
  564. private void copyFilesToDestination() {
  565. if (filecopyList.size() > 0) {
  566. log("Copying " + filecopyList.size() + " file"
  567. + (filecopyList.size() == 1 ? "" : "s")
  568. + " to " + destDir.getAbsolutePath());
  569. Enumeration e = filecopyList.keys();
  570. while (e.hasMoreElements()) {
  571. String fromFile = (String) e.nextElement();
  572. String toFile = (String) filecopyList.get(fromFile);
  573. try {
  574. getProject().copyFile(fromFile, toFile);
  575. } catch (IOException ioe) {
  576. String msg = "Failed to copy " + fromFile + " to " + toFile
  577. + " due to " + ioe.getMessage();
  578. throw new BuildException(msg, ioe);
  579. }
  580. }
  581. }
  582. }
  583. /** Performs a compile using the NetRexx 1.1.x compiler */
  584. private void doNetRexxCompile() throws BuildException {
  585. log("Using NetRexx compiler", Project.MSG_VERBOSE);
  586. String classpath = getCompileClasspath();
  587. StringBuffer compileOptions = new StringBuffer();
  588. // create an array of strings for input to the compiler: one array
  589. // comes from the compile options, the other from the compileList
  590. String[] compileOptionsArray = getCompileOptionsAsArray();
  591. String[] fileListArray = new String[compileList.size()];
  592. Enumeration e = compileList.elements();
  593. int j = 0;
  594. while (e.hasMoreElements()) {
  595. fileListArray[j] = (String) e.nextElement();
  596. j++;
  597. }
  598. // create a single array of arguments for the compiler
  599. String[] compileArgs = new String[compileOptionsArray.length + fileListArray.length];
  600. for (int i = 0; i < compileOptionsArray.length; i++) {
  601. compileArgs[i] = compileOptionsArray[i];
  602. }
  603. for (int i = 0; i < fileListArray.length; i++) {
  604. compileArgs[i + compileOptionsArray.length] = fileListArray[i];
  605. }
  606. // print nice output about what we are doing for the log
  607. compileOptions.append("Compilation args: ");
  608. for (int i = 0; i < compileOptionsArray.length; i++) {
  609. compileOptions.append(compileOptionsArray[i]);
  610. compileOptions.append(" ");
  611. }
  612. log(compileOptions.toString(), Project.MSG_VERBOSE);
  613. String eol = System.getProperty("line.separator");
  614. StringBuffer niceSourceList = new StringBuffer("Files to be compiled:" + eol);
  615. for (int i = 0; i < compileList.size(); i++) {
  616. niceSourceList.append(" ");
  617. niceSourceList.append(compileList.elementAt(i).toString());
  618. niceSourceList.append(eol);
  619. }
  620. log(niceSourceList.toString(), Project.MSG_VERBOSE);
  621. // need to set java.class.path property and restore it later
  622. // since the NetRexx compiler has no option for the classpath
  623. String currentClassPath = System.getProperty("java.class.path");
  624. Properties currentProperties = System.getProperties();
  625. currentProperties.put("java.class.path", classpath);
  626. try {
  627. StringWriter out = new StringWriter();
  628. int rc =
  629. COM.ibm.netrexx.process.NetRexxC.main(new Rexx(compileArgs), new PrintWriter(out));
  630. String sdir = srcDir.getAbsolutePath();
  631. String ddir = destDir.getAbsolutePath();
  632. boolean doReplace = !(sdir.equals(ddir));
  633. int dlen = ddir.length();
  634. String l;
  635. BufferedReader in = new BufferedReader(new StringReader(out.toString()));
  636. log("replacing destdir '" + ddir + "' through sourcedir '"
  637. + sdir + "'", Project.MSG_VERBOSE);
  638. while ((l = in.readLine()) != null) {
  639. int idx;
  640. while (doReplace && ((idx = l.indexOf(ddir)) != -1)) {
  641. // path is mentioned in the message
  642. l = (new StringBuffer(l)).replace(idx, idx + dlen, sdir).toString();
  643. }
  644. // verbose level logging for suppressed messages
  645. if (suppressMethodArgumentNotUsed
  646. && l.indexOf(MSG_METHOD_ARGUMENT_NOT_USED) != -1) {
  647. log(l, Project.MSG_VERBOSE);
  648. } else if (suppressPrivatePropertyNotUsed
  649. && l.indexOf(MSG_PRIVATE_PROPERTY_NOT_USED) != -1) {
  650. log(l, Project.MSG_VERBOSE);
  651. } else if (suppressVariableNotUsed
  652. && l.indexOf(MSG_VARIABLE_NOT_USED) != -1) {
  653. log(l, Project.MSG_VERBOSE);
  654. } else if (suppressExceptionNotSignalled
  655. && l.indexOf(MSG_EXCEPTION_NOT_SIGNALLED) != -1) {
  656. log(l, Project.MSG_VERBOSE);
  657. } else if (suppressDeprecation
  658. && l.indexOf(MSG_DEPRECATION) != -1) {
  659. log(l, Project.MSG_VERBOSE);
  660. } else if (l.indexOf("Error:") != -1) {
  661. // error level logging for compiler errors
  662. log(l, Project.MSG_ERR);
  663. } else if (l.indexOf("Warning:") != -1) {
  664. // warning for all warning messages
  665. log(l, Project.MSG_WARN);
  666. } else {
  667. log(l, Project.MSG_INFO); // info level for the rest.
  668. }
  669. }
  670. if (rc > 1) {
  671. throw new BuildException("Compile failed, messages should "
  672. + "have been provided.");
  673. }
  674. } catch (IOException ioe) {
  675. throw new BuildException("Unexpected IOException while "
  676. + "playing with Strings", ioe);
  677. } finally {
  678. // need to reset java.class.path property
  679. // since the NetRexx compiler has no option for the classpath
  680. currentProperties = System.getProperties();
  681. currentProperties.put("java.class.path", currentClassPath);
  682. }
  683. }
  684. /** Builds the compilation classpath. */
  685. private String getCompileClasspath() {
  686. StringBuffer classpath = new StringBuffer();
  687. // add dest dir to classpath so that previously compiled and
  688. // untouched classes are on classpath
  689. classpath.append(destDir.getAbsolutePath());
  690. // add our classpath to the mix
  691. if (this.classpath != null) {
  692. addExistingToClasspath(classpath, this.classpath);
  693. }
  694. // add the system classpath
  695. // addExistingToClasspath(classpath,System.getProperty("java.class.path"));
  696. return classpath.toString();
  697. }
  698. /** This */
  699. private String[] getCompileOptionsAsArray() {
  700. Vector options = new Vector();
  701. options.addElement(binary ? "-binary" : "-nobinary");
  702. options.addElement(comments ? "-comments" : "-nocomments");
  703. options.addElement(compile ? "-compile" : "-nocompile");
  704. options.addElement(compact ? "-compact" : "-nocompact");
  705. options.addElement(console ? "-console" : "-noconsole");
  706. options.addElement(crossref ? "-crossref" : "-nocrossref");
  707. options.addElement(decimal ? "-decimal" : "-nodecimal");
  708. options.addElement(diag ? "-diag" : "-nodiag");
  709. options.addElement(explicit ? "-explicit" : "-noexplicit");
  710. options.addElement(format ? "-format" : "-noformat");
  711. options.addElement(keep ? "-keep" : "-nokeep");
  712. options.addElement(logo ? "-logo" : "-nologo");
  713. options.addElement(replace ? "-replace" : "-noreplace");
  714. options.addElement(savelog ? "-savelog" : "-nosavelog");
  715. options.addElement(sourcedir ? "-sourcedir" : "-nosourcedir");
  716. options.addElement(strictargs ? "-strictargs" : "-nostrictargs");
  717. options.addElement(strictassign ? "-strictassign" : "-nostrictassign");
  718. options.addElement(strictcase ? "-strictcase" : "-nostrictcase");
  719. options.addElement(strictimport ? "-strictimport" : "-nostrictimport");
  720. options.addElement(strictprops ? "-strictprops" : "-nostrictprops");
  721. options.addElement(strictsignal ? "-strictsignal" : "-nostrictsignal");
  722. options.addElement(symbols ? "-symbols" : "-nosymbols");
  723. options.addElement(time ? "-time" : "-notime");
  724. options.addElement("-" + trace);
  725. options.addElement(utf8 ? "-utf8" : "-noutf8");
  726. options.addElement("-" + verbose);
  727. String[] results = new String[options.size()];
  728. options.copyInto(results);
  729. return results;
  730. }
  731. /**
  732. * Takes a classpath-like string, and adds each element of this string to
  733. * a new classpath, if the components exist. Components that don't exist,
  734. * aren't added. We do this, because jikes issues warnings for
  735. * non-existant files/dirs in his classpath, and these warnings are pretty
  736. * annoying.
  737. *
  738. * @param target - target classpath
  739. * @param source - source classpath to get file objects.
  740. */
  741. private void addExistingToClasspath(StringBuffer target, String source) {
  742. StringTokenizer tok = new StringTokenizer(source,
  743. System.getProperty("path.separator"), false);
  744. while (tok.hasMoreTokens()) {
  745. File f = getProject().resolveFile(tok.nextToken());
  746. if (f.exists()) {
  747. target.append(File.pathSeparator);
  748. target.append(f.getAbsolutePath());
  749. } else {
  750. log("Dropping from classpath: "
  751. + f.getAbsolutePath(), Project.MSG_VERBOSE);
  752. }
  753. }
  754. }
  755. public static class TraceAttr extends EnumeratedAttribute {
  756. public String[] getValues() {
  757. return new String[]{"trace", "trace1", "trace2", "notrace"};
  758. }
  759. }
  760. public static class VerboseAttr extends EnumeratedAttribute {
  761. public String[] getValues() {
  762. return new String[]{"verbose", "verbose0", "verbose1",
  763. "verbose2", "verbose3", "verbose4",
  764. "verbose5", "noverbose"};
  765. }
  766. }
  767. }