You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Javac.java 37 kB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package org.apache.tools.ant.taskdefs;
  19. import java.io.File;
  20. import java.io.FileOutputStream;
  21. import java.io.IOException;
  22. import java.io.OutputStream;
  23. import java.util.HashMap;
  24. import java.util.Iterator;
  25. import java.util.Map;
  26. import org.apache.tools.ant.BuildException;
  27. import org.apache.tools.ant.DirectoryScanner;
  28. import org.apache.tools.ant.MagicNames;
  29. import org.apache.tools.ant.Project;
  30. import org.apache.tools.ant.taskdefs.compilers.CompilerAdapter;
  31. import org.apache.tools.ant.taskdefs.compilers.CompilerAdapterFactory;
  32. import org.apache.tools.ant.types.Path;
  33. import org.apache.tools.ant.types.Reference;
  34. import org.apache.tools.ant.util.FileUtils;
  35. import org.apache.tools.ant.util.GlobPatternMapper;
  36. import org.apache.tools.ant.util.JavaEnvUtils;
  37. import org.apache.tools.ant.util.SourceFileScanner;
  38. import org.apache.tools.ant.util.facade.FacadeTaskHelper;
  39. /**
  40. * Compiles Java source files. This task can take the following
  41. * arguments:
  42. * <ul>
  43. * <li>sourcedir
  44. * <li>destdir
  45. * <li>deprecation
  46. * <li>classpath
  47. * <li>bootclasspath
  48. * <li>extdirs
  49. * <li>optimize
  50. * <li>debug
  51. * <li>encoding
  52. * <li>target
  53. * <li>depend
  54. * <li>verbose
  55. * <li>failonerror
  56. * <li>includeantruntime
  57. * <li>includejavaruntime
  58. * <li>source
  59. * <li>compiler
  60. * </ul>
  61. * Of these arguments, the <b>sourcedir</b> and <b>destdir</b> are required.
  62. * <p>
  63. * When this task executes, it will recursively scan the sourcedir and
  64. * destdir looking for Java source files to compile. This task makes its
  65. * compile decision based on timestamp.
  66. *
  67. *
  68. * @since Ant 1.1
  69. *
  70. * @ant.task category="java"
  71. */
  72. public class Javac extends MatchingTask {
  73. private static final String FAIL_MSG
  74. = "Compile failed; see the compiler error output for details.";
  75. private static final String JAVAC17 = "javac1.7";
  76. private static final String JAVAC16 = "javac1.6";
  77. private static final String JAVAC15 = "javac1.5";
  78. private static final String JAVAC14 = "javac1.4";
  79. private static final String JAVAC13 = "javac1.3";
  80. private static final String JAVAC12 = "javac1.2";
  81. private static final String JAVAC11 = "javac1.1";
  82. private static final String MODERN = "modern";
  83. private static final String CLASSIC = "classic";
  84. private static final String EXTJAVAC = "extJavac";
  85. private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
  86. private Path src;
  87. private File destDir;
  88. private Path compileClasspath;
  89. private Path compileSourcepath;
  90. private String encoding;
  91. private boolean debug = false;
  92. private boolean optimize = false;
  93. private boolean deprecation = false;
  94. private boolean depend = false;
  95. private boolean verbose = false;
  96. private String targetAttribute;
  97. private Path bootclasspath;
  98. private Path extdirs;
  99. private Boolean includeAntRuntime;
  100. private boolean includeJavaRuntime = false;
  101. private boolean fork = false;
  102. private String forkedExecutable = null;
  103. private boolean nowarn = false;
  104. private String memoryInitialSize;
  105. private String memoryMaximumSize;
  106. private FacadeTaskHelper facade = null;
  107. // CheckStyle:VisibilityModifier OFF - bc
  108. protected boolean failOnError = true;
  109. protected boolean listFiles = false;
  110. protected File[] compileList = new File[0];
  111. private Map/*<String,Long>*/ packageInfos = new HashMap();
  112. // CheckStyle:VisibilityModifier ON
  113. private String source;
  114. private String debugLevel;
  115. private File tmpDir;
  116. private String updatedProperty;
  117. private String errorProperty;
  118. private boolean taskSuccess = true; // assume the best
  119. private boolean includeDestClasses = true;
  120. private CompilerAdapter nestedAdapter = null;
  121. /**
  122. * Javac task for compilation of Java files.
  123. */
  124. public Javac() {
  125. facade = new FacadeTaskHelper(assumedJavaVersion());
  126. }
  127. private String assumedJavaVersion() {
  128. if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_4)) {
  129. return JAVAC14;
  130. } else if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_5)) {
  131. return JAVAC15;
  132. } else if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_6)) {
  133. return JAVAC16;
  134. } else if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_7)) {
  135. return JAVAC17;
  136. } else {
  137. return CLASSIC;
  138. }
  139. }
  140. /**
  141. * Get the value of debugLevel.
  142. * @return value of debugLevel.
  143. */
  144. public String getDebugLevel() {
  145. return debugLevel;
  146. }
  147. /**
  148. * Keyword list to be appended to the -g command-line switch.
  149. *
  150. * This will be ignored by all implementations except modern
  151. * and classic(ver >= 1.2). Legal values are none or a
  152. * comma-separated list of the following keywords: lines, vars,
  153. * and source. If debuglevel is not specified, by default, :none
  154. * will be appended to -g. If debug is not turned on, this attribute
  155. * will be ignored.
  156. *
  157. * @param v Value to assign to debugLevel.
  158. */
  159. public void setDebugLevel(String v) {
  160. this.debugLevel = v;
  161. }
  162. /**
  163. * Get the value of source.
  164. * @return value of source.
  165. */
  166. public String getSource() {
  167. return source != null
  168. ? source : getProject().getProperty(MagicNames.BUILD_JAVAC_SOURCE);
  169. }
  170. /**
  171. * Value of the -source command-line switch; will be ignored by
  172. * all implementations except modern, jikes and gcj (gcj uses
  173. * -fsource).
  174. *
  175. * <p>If you use this attribute together with jikes or gcj, you
  176. * must make sure that your version of jikes supports the -source
  177. * switch.</p>
  178. *
  179. * <p>Legal values are 1.3, 1.4, 1.5, and 5 - by default, no
  180. * -source argument will be used at all.</p>
  181. *
  182. * @param v Value to assign to source.
  183. */
  184. public void setSource(String v) {
  185. this.source = v;
  186. }
  187. /**
  188. * Adds a path for source compilation.
  189. *
  190. * @return a nested src element.
  191. */
  192. public Path createSrc() {
  193. if (src == null) {
  194. src = new Path(getProject());
  195. }
  196. return src.createPath();
  197. }
  198. /**
  199. * Recreate src.
  200. *
  201. * @return a nested src element.
  202. */
  203. protected Path recreateSrc() {
  204. src = null;
  205. return createSrc();
  206. }
  207. /**
  208. * Set the source directories to find the source Java files.
  209. * @param srcDir the source directories as a path
  210. */
  211. public void setSrcdir(Path srcDir) {
  212. if (src == null) {
  213. src = srcDir;
  214. } else {
  215. src.append(srcDir);
  216. }
  217. }
  218. /**
  219. * Gets the source dirs to find the source java files.
  220. * @return the source directories as a path
  221. */
  222. public Path getSrcdir() {
  223. return src;
  224. }
  225. /**
  226. * Set the destination directory into which the Java source
  227. * files should be compiled.
  228. * @param destDir the destination director
  229. */
  230. public void setDestdir(File destDir) {
  231. this.destDir = destDir;
  232. }
  233. /**
  234. * Gets the destination directory into which the java source files
  235. * should be compiled.
  236. * @return the destination directory
  237. */
  238. public File getDestdir() {
  239. return destDir;
  240. }
  241. /**
  242. * Set the sourcepath to be used for this compilation.
  243. * @param sourcepath the source path
  244. */
  245. public void setSourcepath(Path sourcepath) {
  246. if (compileSourcepath == null) {
  247. compileSourcepath = sourcepath;
  248. } else {
  249. compileSourcepath.append(sourcepath);
  250. }
  251. }
  252. /**
  253. * Gets the sourcepath to be used for this compilation.
  254. * @return the source path
  255. */
  256. public Path getSourcepath() {
  257. return compileSourcepath;
  258. }
  259. /**
  260. * Adds a path to sourcepath.
  261. * @return a sourcepath to be configured
  262. */
  263. public Path createSourcepath() {
  264. if (compileSourcepath == null) {
  265. compileSourcepath = new Path(getProject());
  266. }
  267. return compileSourcepath.createPath();
  268. }
  269. /**
  270. * Adds a reference to a source path defined elsewhere.
  271. * @param r a reference to a source path
  272. */
  273. public void setSourcepathRef(Reference r) {
  274. createSourcepath().setRefid(r);
  275. }
  276. /**
  277. * Set the classpath to be used for this compilation.
  278. *
  279. * @param classpath an Ant Path object containing the compilation classpath.
  280. */
  281. public void setClasspath(Path classpath) {
  282. if (compileClasspath == null) {
  283. compileClasspath = classpath;
  284. } else {
  285. compileClasspath.append(classpath);
  286. }
  287. }
  288. /**
  289. * Gets the classpath to be used for this compilation.
  290. * @return the class path
  291. */
  292. public Path getClasspath() {
  293. return compileClasspath;
  294. }
  295. /**
  296. * Adds a path to the classpath.
  297. * @return a class path to be configured
  298. */
  299. public Path createClasspath() {
  300. if (compileClasspath == null) {
  301. compileClasspath = new Path(getProject());
  302. }
  303. return compileClasspath.createPath();
  304. }
  305. /**
  306. * Adds a reference to a classpath defined elsewhere.
  307. * @param r a reference to a classpath
  308. */
  309. public void setClasspathRef(Reference r) {
  310. createClasspath().setRefid(r);
  311. }
  312. /**
  313. * Sets the bootclasspath that will be used to compile the classes
  314. * against.
  315. * @param bootclasspath a path to use as a boot class path (may be more
  316. * than one)
  317. */
  318. public void setBootclasspath(Path bootclasspath) {
  319. if (this.bootclasspath == null) {
  320. this.bootclasspath = bootclasspath;
  321. } else {
  322. this.bootclasspath.append(bootclasspath);
  323. }
  324. }
  325. /**
  326. * Gets the bootclasspath that will be used to compile the classes
  327. * against.
  328. * @return the boot path
  329. */
  330. public Path getBootclasspath() {
  331. return bootclasspath;
  332. }
  333. /**
  334. * Adds a path to the bootclasspath.
  335. * @return a path to be configured
  336. */
  337. public Path createBootclasspath() {
  338. if (bootclasspath == null) {
  339. bootclasspath = new Path(getProject());
  340. }
  341. return bootclasspath.createPath();
  342. }
  343. /**
  344. * Adds a reference to a classpath defined elsewhere.
  345. * @param r a reference to a classpath
  346. */
  347. public void setBootClasspathRef(Reference r) {
  348. createBootclasspath().setRefid(r);
  349. }
  350. /**
  351. * Sets the extension directories that will be used during the
  352. * compilation.
  353. * @param extdirs a path
  354. */
  355. public void setExtdirs(Path extdirs) {
  356. if (this.extdirs == null) {
  357. this.extdirs = extdirs;
  358. } else {
  359. this.extdirs.append(extdirs);
  360. }
  361. }
  362. /**
  363. * Gets the extension directories that will be used during the
  364. * compilation.
  365. * @return the extension directories as a path
  366. */
  367. public Path getExtdirs() {
  368. return extdirs;
  369. }
  370. /**
  371. * Adds a path to extdirs.
  372. * @return a path to be configured
  373. */
  374. public Path createExtdirs() {
  375. if (extdirs == null) {
  376. extdirs = new Path(getProject());
  377. }
  378. return extdirs.createPath();
  379. }
  380. /**
  381. * If true, list the source files being handed off to the compiler.
  382. * @param list if true list the source files
  383. */
  384. public void setListfiles(boolean list) {
  385. listFiles = list;
  386. }
  387. /**
  388. * Get the listfiles flag.
  389. * @return the listfiles flag
  390. */
  391. public boolean getListfiles() {
  392. return listFiles;
  393. }
  394. /**
  395. * Indicates whether the build will continue
  396. * even if there are compilation errors; defaults to true.
  397. * @param fail if true halt the build on failure
  398. */
  399. public void setFailonerror(boolean fail) {
  400. failOnError = fail;
  401. }
  402. /**
  403. * @ant.attribute ignore="true"
  404. * @param proceed inverse of failoferror
  405. */
  406. public void setProceed(boolean proceed) {
  407. failOnError = !proceed;
  408. }
  409. /**
  410. * Gets the failonerror flag.
  411. * @return the failonerror flag
  412. */
  413. public boolean getFailonerror() {
  414. return failOnError;
  415. }
  416. /**
  417. * Indicates whether source should be
  418. * compiled with deprecation information; defaults to off.
  419. * @param deprecation if true turn on deprecation information
  420. */
  421. public void setDeprecation(boolean deprecation) {
  422. this.deprecation = deprecation;
  423. }
  424. /**
  425. * Gets the deprecation flag.
  426. * @return the deprecation flag
  427. */
  428. public boolean getDeprecation() {
  429. return deprecation;
  430. }
  431. /**
  432. * The initial size of the memory for the underlying VM
  433. * if javac is run externally; ignored otherwise.
  434. * Defaults to the standard VM memory setting.
  435. * (Examples: 83886080, 81920k, or 80m)
  436. * @param memoryInitialSize string to pass to VM
  437. */
  438. public void setMemoryInitialSize(String memoryInitialSize) {
  439. this.memoryInitialSize = memoryInitialSize;
  440. }
  441. /**
  442. * Gets the memoryInitialSize flag.
  443. * @return the memoryInitialSize flag
  444. */
  445. public String getMemoryInitialSize() {
  446. return memoryInitialSize;
  447. }
  448. /**
  449. * The maximum size of the memory for the underlying VM
  450. * if javac is run externally; ignored otherwise.
  451. * Defaults to the standard VM memory setting.
  452. * (Examples: 83886080, 81920k, or 80m)
  453. * @param memoryMaximumSize string to pass to VM
  454. */
  455. public void setMemoryMaximumSize(String memoryMaximumSize) {
  456. this.memoryMaximumSize = memoryMaximumSize;
  457. }
  458. /**
  459. * Gets the memoryMaximumSize flag.
  460. * @return the memoryMaximumSize flag
  461. */
  462. public String getMemoryMaximumSize() {
  463. return memoryMaximumSize;
  464. }
  465. /**
  466. * Set the Java source file encoding name.
  467. * @param encoding the source file encoding
  468. */
  469. public void setEncoding(String encoding) {
  470. this.encoding = encoding;
  471. }
  472. /**
  473. * Gets the java source file encoding name.
  474. * @return the source file encoding name
  475. */
  476. public String getEncoding() {
  477. return encoding;
  478. }
  479. /**
  480. * Indicates whether source should be compiled
  481. * with debug information; defaults to off.
  482. * @param debug if true compile with debug information
  483. */
  484. public void setDebug(boolean debug) {
  485. this.debug = debug;
  486. }
  487. /**
  488. * Gets the debug flag.
  489. * @return the debug flag
  490. */
  491. public boolean getDebug() {
  492. return debug;
  493. }
  494. /**
  495. * If true, compiles with optimization enabled.
  496. * @param optimize if true compile with optimization enabled
  497. */
  498. public void setOptimize(boolean optimize) {
  499. this.optimize = optimize;
  500. }
  501. /**
  502. * Gets the optimize flag.
  503. * @return the optimize flag
  504. */
  505. public boolean getOptimize() {
  506. return optimize;
  507. }
  508. /**
  509. * Enables dependency-tracking for compilers
  510. * that support this (jikes and classic).
  511. * @param depend if true enable dependency-tracking
  512. */
  513. public void setDepend(boolean depend) {
  514. this.depend = depend;
  515. }
  516. /**
  517. * Gets the depend flag.
  518. * @return the depend flag
  519. */
  520. public boolean getDepend() {
  521. return depend;
  522. }
  523. /**
  524. * If true, asks the compiler for verbose output.
  525. * @param verbose if true, asks the compiler for verbose output
  526. */
  527. public void setVerbose(boolean verbose) {
  528. this.verbose = verbose;
  529. }
  530. /**
  531. * Gets the verbose flag.
  532. * @return the verbose flag
  533. */
  534. public boolean getVerbose() {
  535. return verbose;
  536. }
  537. /**
  538. * Sets the target VM that the classes will be compiled for. Valid
  539. * values depend on the compiler, for jdk 1.4 the valid values are
  540. * "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "5", "6" and "7".
  541. * @param target the target VM
  542. */
  543. public void setTarget(String target) {
  544. this.targetAttribute = target;
  545. }
  546. /**
  547. * Gets the target VM that the classes will be compiled for.
  548. * @return the target VM
  549. */
  550. public String getTarget() {
  551. return targetAttribute != null
  552. ? targetAttribute
  553. : getProject().getProperty(MagicNames.BUILD_JAVAC_TARGET);
  554. }
  555. /**
  556. * If true, includes Ant's own classpath in the classpath.
  557. * @param include if true, includes Ant's own classpath in the classpath
  558. */
  559. public void setIncludeantruntime(boolean include) {
  560. includeAntRuntime = Boolean.valueOf(include);
  561. }
  562. /**
  563. * Gets whether or not the ant classpath is to be included in the classpath.
  564. * @return whether or not the ant classpath is to be included in the classpath
  565. */
  566. public boolean getIncludeantruntime() {
  567. return includeAntRuntime != null ? includeAntRuntime.booleanValue() : true;
  568. }
  569. /**
  570. * If true, includes the Java runtime libraries in the classpath.
  571. * @param include if true, includes the Java runtime libraries in the classpath
  572. */
  573. public void setIncludejavaruntime(boolean include) {
  574. includeJavaRuntime = include;
  575. }
  576. /**
  577. * Gets whether or not the java runtime should be included in this
  578. * task's classpath.
  579. * @return the includejavaruntime attribute
  580. */
  581. public boolean getIncludejavaruntime() {
  582. return includeJavaRuntime;
  583. }
  584. /**
  585. * If true, forks the javac compiler.
  586. *
  587. * @param f "true|false|on|off|yes|no"
  588. */
  589. public void setFork(boolean f) {
  590. fork = f;
  591. }
  592. /**
  593. * Sets the name of the javac executable.
  594. *
  595. * <p>Ignored unless fork is true or extJavac has been specified
  596. * as the compiler.</p>
  597. * @param forkExec the name of the executable
  598. */
  599. public void setExecutable(String forkExec) {
  600. forkedExecutable = forkExec;
  601. }
  602. /**
  603. * The value of the executable attribute, if any.
  604. *
  605. * @since Ant 1.6
  606. * @return the name of the java executable
  607. */
  608. public String getExecutable() {
  609. return forkedExecutable;
  610. }
  611. /**
  612. * Is this a forked invocation of JDK's javac?
  613. * @return true if this is a forked invocation
  614. */
  615. public boolean isForkedJavac() {
  616. return fork || EXTJAVAC.equalsIgnoreCase(getCompiler());
  617. }
  618. /**
  619. * The name of the javac executable to use in fork-mode.
  620. *
  621. * <p>This is either the name specified with the executable
  622. * attribute or the full path of the javac compiler of the VM Ant
  623. * is currently running in - guessed by Ant.</p>
  624. *
  625. * <p>You should <strong>not</strong> invoke this method if you
  626. * want to get the value of the executable command - use {@link
  627. * #getExecutable getExecutable} for this.</p>
  628. * @return the name of the javac executable
  629. */
  630. public String getJavacExecutable() {
  631. if (forkedExecutable == null && isForkedJavac()) {
  632. forkedExecutable = getSystemJavac();
  633. } else if (forkedExecutable != null && !isForkedJavac()) {
  634. forkedExecutable = null;
  635. }
  636. return forkedExecutable;
  637. }
  638. /**
  639. * If true, enables the -nowarn option.
  640. * @param flag if true, enable the -nowarn option
  641. */
  642. public void setNowarn(boolean flag) {
  643. this.nowarn = flag;
  644. }
  645. /**
  646. * Should the -nowarn option be used.
  647. * @return true if the -nowarn option should be used
  648. */
  649. public boolean getNowarn() {
  650. return nowarn;
  651. }
  652. /**
  653. * Adds an implementation specific command-line argument.
  654. * @return a ImplementationSpecificArgument to be configured
  655. */
  656. public ImplementationSpecificArgument createCompilerArg() {
  657. ImplementationSpecificArgument arg =
  658. new ImplementationSpecificArgument();
  659. facade.addImplementationArgument(arg);
  660. return arg;
  661. }
  662. /**
  663. * Get the additional implementation specific command line arguments.
  664. * @return array of command line arguments, guaranteed to be non-null.
  665. */
  666. public String[] getCurrentCompilerArgs() {
  667. String chosen = facade.getExplicitChoice();
  668. try {
  669. // make sure facade knows about magic properties and fork setting
  670. String appliedCompiler = getCompiler();
  671. facade.setImplementation(appliedCompiler);
  672. String[] result = facade.getArgs();
  673. String altCompilerName = getAltCompilerName(facade.getImplementation());
  674. if (result.length == 0 && altCompilerName != null) {
  675. facade.setImplementation(altCompilerName);
  676. result = facade.getArgs();
  677. }
  678. return result;
  679. } finally {
  680. facade.setImplementation(chosen);
  681. }
  682. }
  683. private String getAltCompilerName(String anImplementation) {
  684. if (JAVAC17.equalsIgnoreCase(anImplementation)
  685. || JAVAC16.equalsIgnoreCase(anImplementation)
  686. || JAVAC15.equalsIgnoreCase(anImplementation)
  687. || JAVAC14.equalsIgnoreCase(anImplementation)
  688. || JAVAC13.equalsIgnoreCase(anImplementation)) {
  689. return MODERN;
  690. }
  691. if (JAVAC12.equalsIgnoreCase(anImplementation)
  692. || JAVAC11.equalsIgnoreCase(anImplementation)) {
  693. return CLASSIC;
  694. }
  695. if (MODERN.equalsIgnoreCase(anImplementation)) {
  696. String nextSelected = assumedJavaVersion();
  697. if (JAVAC17.equalsIgnoreCase(nextSelected)
  698. || JAVAC16.equalsIgnoreCase(nextSelected)
  699. || JAVAC15.equalsIgnoreCase(nextSelected)
  700. || JAVAC14.equalsIgnoreCase(nextSelected)
  701. || JAVAC13.equalsIgnoreCase(nextSelected)) {
  702. return nextSelected;
  703. }
  704. }
  705. if (CLASSIC.equalsIgnoreCase(anImplementation)) {
  706. return assumedJavaVersion();
  707. }
  708. if (EXTJAVAC.equalsIgnoreCase(anImplementation)) {
  709. return assumedJavaVersion();
  710. }
  711. return null;
  712. }
  713. /**
  714. * Where Ant should place temporary files.
  715. *
  716. * @since Ant 1.6
  717. * @param tmpDir the temporary directory
  718. */
  719. public void setTempdir(File tmpDir) {
  720. this.tmpDir = tmpDir;
  721. }
  722. /**
  723. * Where Ant should place temporary files.
  724. *
  725. * @since Ant 1.6
  726. * @return the temporary directory
  727. */
  728. public File getTempdir() {
  729. return tmpDir;
  730. }
  731. /**
  732. * The property to set on compilation success.
  733. * This property will not be set if the compilation
  734. * fails, or if there are no files to compile.
  735. * @param updatedProperty the property name to use.
  736. * @since Ant 1.7.1.
  737. */
  738. public void setUpdatedProperty(String updatedProperty) {
  739. this.updatedProperty = updatedProperty;
  740. }
  741. /**
  742. * The property to set on compilation failure.
  743. * This property will be set if the compilation
  744. * fails.
  745. * @param errorProperty the property name to use.
  746. * @since Ant 1.7.1.
  747. */
  748. public void setErrorProperty(String errorProperty) {
  749. this.errorProperty = errorProperty;
  750. }
  751. /**
  752. * This property controls whether to include the
  753. * destination classes directory in the classpath
  754. * given to the compiler.
  755. * The default value is "true".
  756. * @param includeDestClasses the value to use.
  757. */
  758. public void setIncludeDestClasses(boolean includeDestClasses) {
  759. this.includeDestClasses = includeDestClasses;
  760. }
  761. /**
  762. * Get the value of the includeDestClasses property.
  763. * @return the value.
  764. */
  765. public boolean isIncludeDestClasses() {
  766. return includeDestClasses;
  767. }
  768. /**
  769. * Get the result of the javac task (success or failure).
  770. * @return true if compilation succeeded, or
  771. * was not neccessary, false if the compilation failed.
  772. */
  773. public boolean getTaskSuccess() {
  774. return taskSuccess;
  775. }
  776. /**
  777. * The classpath to use when loading the compiler implementation
  778. * if it is not a built-in one.
  779. *
  780. * @since Ant 1.8.0
  781. */
  782. public Path createCompilerClasspath() {
  783. return facade.getImplementationClasspath(getProject());
  784. }
  785. /**
  786. * Set the compiler adapter explicitly.
  787. * @since Ant 1.8.0
  788. */
  789. public void add(CompilerAdapter adapter) {
  790. if (nestedAdapter != null) {
  791. throw new BuildException("Can't have more than one compiler"
  792. + " adapter");
  793. }
  794. nestedAdapter = adapter;
  795. }
  796. /**
  797. * Executes the task.
  798. * @exception BuildException if an error occurs
  799. */
  800. public void execute() throws BuildException {
  801. checkParameters();
  802. resetFileLists();
  803. // scan source directories and dest directory to build up
  804. // compile lists
  805. String[] list = src.list();
  806. for (int i = 0; i < list.length; i++) {
  807. File srcDir = getProject().resolveFile(list[i]);
  808. if (!srcDir.exists()) {
  809. throw new BuildException("srcdir \""
  810. + srcDir.getPath()
  811. + "\" does not exist!", getLocation());
  812. }
  813. DirectoryScanner ds = this.getDirectoryScanner(srcDir);
  814. String[] files = ds.getIncludedFiles();
  815. scanDir(srcDir, destDir != null ? destDir : srcDir, files);
  816. }
  817. compile();
  818. if (updatedProperty != null
  819. && taskSuccess
  820. && compileList.length != 0) {
  821. getProject().setNewProperty(updatedProperty, "true");
  822. }
  823. }
  824. /**
  825. * Clear the list of files to be compiled and copied..
  826. */
  827. protected void resetFileLists() {
  828. compileList = new File[0];
  829. packageInfos = new HashMap();
  830. }
  831. /**
  832. * Scans the directory looking for source files to be compiled.
  833. * The results are returned in the class variable compileList
  834. *
  835. * @param srcDir The source directory
  836. * @param destDir The destination directory
  837. * @param files An array of filenames
  838. */
  839. protected void scanDir(File srcDir, File destDir, String[] files) {
  840. GlobPatternMapper m = new GlobPatternMapper();
  841. m.setFrom("*.java");
  842. m.setTo("*.class");
  843. SourceFileScanner sfs = new SourceFileScanner(this);
  844. File[] newFiles = sfs.restrictAsFiles(files, srcDir, destDir, m);
  845. if (newFiles.length > 0) {
  846. lookForPackageInfos(srcDir, newFiles);
  847. File[] newCompileList
  848. = new File[compileList.length + newFiles.length];
  849. System.arraycopy(compileList, 0, newCompileList, 0,
  850. compileList.length);
  851. System.arraycopy(newFiles, 0, newCompileList,
  852. compileList.length, newFiles.length);
  853. compileList = newCompileList;
  854. }
  855. }
  856. /**
  857. * Gets the list of files to be compiled.
  858. * @return the list of files as an array
  859. */
  860. public File[] getFileList() {
  861. return compileList;
  862. }
  863. /**
  864. * Is the compiler implementation a jdk compiler
  865. *
  866. * @param compilerImpl the name of the compiler implementation
  867. * @return true if compilerImpl is "modern", "classic",
  868. * "javac1.1", "javac1.2", "javac1.3", "javac1.4", "javac1.5" or
  869. * "javac1.6".
  870. */
  871. protected boolean isJdkCompiler(String compilerImpl) {
  872. return MODERN.equals(compilerImpl)
  873. || CLASSIC.equals(compilerImpl)
  874. || JAVAC17.equals(compilerImpl)
  875. || JAVAC16.equals(compilerImpl)
  876. || JAVAC15.equals(compilerImpl)
  877. || JAVAC14.equals(compilerImpl)
  878. || JAVAC13.equals(compilerImpl)
  879. || JAVAC12.equals(compilerImpl)
  880. || JAVAC11.equals(compilerImpl);
  881. }
  882. /**
  883. * @return the executable name of the java compiler
  884. */
  885. protected String getSystemJavac() {
  886. return JavaEnvUtils.getJdkExecutable("javac");
  887. }
  888. /**
  889. * Choose the implementation for this particular task.
  890. * @param compiler the name of the compiler
  891. * @since Ant 1.5
  892. */
  893. public void setCompiler(String compiler) {
  894. facade.setImplementation(compiler);
  895. }
  896. /**
  897. * The implementation for this particular task.
  898. *
  899. * <p>Defaults to the build.compiler property but can be overridden
  900. * via the compiler and fork attributes.</p>
  901. *
  902. * <p>If fork has been set to true, the result will be extJavac
  903. * and not classic or java1.2 - no matter what the compiler
  904. * attribute looks like.</p>
  905. *
  906. * @see #getCompilerVersion
  907. * @return the compiler.
  908. * @since Ant 1.5
  909. */
  910. public String getCompiler() {
  911. String compilerImpl = getCompilerVersion();
  912. if (fork) {
  913. if (isJdkCompiler(compilerImpl)) {
  914. compilerImpl = EXTJAVAC;
  915. } else {
  916. log("Since compiler setting isn't classic or modern, "
  917. + "ignoring fork setting.", Project.MSG_WARN);
  918. }
  919. }
  920. return compilerImpl;
  921. }
  922. /**
  923. * The implementation for this particular task.
  924. *
  925. * <p>Defaults to the build.compiler property but can be overridden
  926. * via the compiler attribute.</p>
  927. *
  928. * <p>This method does not take the fork attribute into
  929. * account.</p>
  930. *
  931. * @see #getCompiler
  932. * @return the compiler.
  933. *
  934. * @since Ant 1.5
  935. */
  936. public String getCompilerVersion() {
  937. facade.setMagicValue(getProject().getProperty("build.compiler"));
  938. return facade.getImplementation();
  939. }
  940. /**
  941. * Check that all required attributes have been set and nothing
  942. * silly has been entered.
  943. *
  944. * @since Ant 1.5
  945. * @exception BuildException if an error occurs
  946. */
  947. protected void checkParameters() throws BuildException {
  948. if (src == null) {
  949. throw new BuildException("srcdir attribute must be set!",
  950. getLocation());
  951. }
  952. if (src.size() == 0) {
  953. throw new BuildException("srcdir attribute must be set!",
  954. getLocation());
  955. }
  956. if (destDir != null && !destDir.isDirectory()) {
  957. throw new BuildException("destination directory \""
  958. + destDir
  959. + "\" does not exist "
  960. + "or is not a directory", getLocation());
  961. }
  962. if (includeAntRuntime == null && getProject().getProperty("build.sysclasspath") == null) {
  963. log(getLocation() + "warning: 'includeantruntime' was not set, " +
  964. "defaulting to build.sysclasspath=last; set to false for repeatable builds",
  965. Project.MSG_WARN);
  966. }
  967. }
  968. /**
  969. * Perform the compilation.
  970. *
  971. * @since Ant 1.5
  972. */
  973. protected void compile() {
  974. String compilerImpl = getCompiler();
  975. if (compileList.length > 0) {
  976. log("Compiling " + compileList.length + " source file"
  977. + (compileList.length == 1 ? "" : "s")
  978. + (destDir != null ? " to " + destDir : ""));
  979. if (listFiles) {
  980. for (int i = 0; i < compileList.length; i++) {
  981. String filename = compileList[i].getAbsolutePath();
  982. log(filename);
  983. }
  984. }
  985. CompilerAdapter adapter =
  986. nestedAdapter != null ? nestedAdapter :
  987. CompilerAdapterFactory.getCompiler(compilerImpl, this,
  988. createCompilerClasspath());
  989. // now we need to populate the compiler adapter
  990. adapter.setJavac(this);
  991. // finally, lets execute the compiler!!
  992. if (adapter.execute()) {
  993. // Success
  994. try {
  995. generateMissingPackageInfoClasses();
  996. } catch (IOException x) {
  997. // Should this be made a nonfatal warning?
  998. throw new BuildException(x, getLocation());
  999. }
  1000. } else {
  1001. // Fail path
  1002. this.taskSuccess = false;
  1003. if (errorProperty != null) {
  1004. getProject().setNewProperty(
  1005. errorProperty, "true");
  1006. }
  1007. if (failOnError) {
  1008. throw new BuildException(FAIL_MSG, getLocation());
  1009. } else {
  1010. log(FAIL_MSG, Project.MSG_ERR);
  1011. }
  1012. }
  1013. }
  1014. }
  1015. /**
  1016. * Adds an "compiler" attribute to Commandline$Attribute used to
  1017. * filter command line attributes based on the current
  1018. * implementation.
  1019. */
  1020. public class ImplementationSpecificArgument extends
  1021. org.apache.tools.ant.util.facade.ImplementationSpecificArgument {
  1022. /**
  1023. * @param impl the name of the compiler
  1024. */
  1025. public void setCompiler(String impl) {
  1026. super.setImplementation(impl);
  1027. }
  1028. }
  1029. private void lookForPackageInfos(File srcDir, File[] newFiles) {
  1030. for (int i = 0; i < newFiles.length; i++) {
  1031. File f = newFiles[i];
  1032. if (!f.getName().equals("package-info.java")) {
  1033. continue;
  1034. }
  1035. String path = FILE_UTILS.removeLeadingPath(srcDir, f).
  1036. replace(File.separatorChar, '/');
  1037. String suffix = "/package-info.java";
  1038. if (!path.endsWith(suffix)) {
  1039. log("anomalous package-info.java path: " + path, Project.MSG_WARN);
  1040. continue;
  1041. }
  1042. String pkg = path.substring(0, path.length() - suffix.length());
  1043. packageInfos.put(pkg, new Long(f.lastModified()));
  1044. }
  1045. }
  1046. /**
  1047. * Ensure that every {@code package-info.java} produced a {@code package-info.class}.
  1048. * Otherwise this task's up-to-date tracking mechanisms do not work.
  1049. * @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=43114">Bug #43114</a>
  1050. */
  1051. private void generateMissingPackageInfoClasses() throws IOException {
  1052. for (Iterator i = packageInfos.entrySet().iterator(); i.hasNext(); ) {
  1053. Map.Entry entry = (Map.Entry) i.next();
  1054. String pkg = (String) entry.getKey();
  1055. Long sourceLastMod = (Long) entry.getValue();
  1056. File pkgBinDir = new File(destDir, pkg.replace('/', File.separatorChar));
  1057. pkgBinDir.mkdirs();
  1058. File pkgInfoClass = new File(pkgBinDir, "package-info.class");
  1059. if (pkgInfoClass.isFile() && pkgInfoClass.lastModified() >= sourceLastMod.longValue()) {
  1060. continue;
  1061. }
  1062. log("Creating empty " + pkgInfoClass);
  1063. OutputStream os = new FileOutputStream(pkgInfoClass);
  1064. try {
  1065. os.write(PACKAGE_INFO_CLASS_HEADER);
  1066. byte[] name = pkg.getBytes("UTF-8");
  1067. int length = name.length + /* "/package-info" */ 13;
  1068. os.write((byte) length / 256);
  1069. os.write((byte) length % 256);
  1070. os.write(name);
  1071. os.write(PACKAGE_INFO_CLASS_FOOTER);
  1072. } finally {
  1073. os.close();
  1074. }
  1075. }
  1076. }
  1077. private static final byte[] PACKAGE_INFO_CLASS_HEADER = {
  1078. (byte) 0xca, (byte) 0xfe, (byte) 0xba, (byte) 0xbe, 0x00, 0x00, 0x00,
  1079. 0x31, 0x00, 0x07, 0x07, 0x00, 0x05, 0x07, 0x00, 0x06, 0x01, 0x00, 0x0a,
  1080. 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x01, 0x00,
  1081. 0x11, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x2d, 0x69, 0x6e, 0x66,
  1082. 0x6f, 0x2e, 0x6a, 0x61, 0x76, 0x61, 0x01
  1083. };
  1084. private static final byte[] PACKAGE_INFO_CLASS_FOOTER = {
  1085. 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x2d, 0x69, 0x6e, 0x66,
  1086. 0x6f, 0x01, 0x00, 0x10, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61, 0x6e,
  1087. 0x67, 0x2f, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x02, 0x00, 0x00, 0x01,
  1088. 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03,
  1089. 0x00, 0x00, 0x00, 0x02, 0x00, 0x04
  1090. };
  1091. }