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

Save This Page
Home » apache-ant-1.7.1-src » org.apache.tools » ant » taskdefs » [javadoc | source]