0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: *
0017: */
0018:
0019: package org.apache.tools.ant.taskdefs;
0020:
0021: import java.io.File;
0022:
0023: import org.apache.tools.ant.BuildException;
0024: import org.apache.tools.ant.DirectoryScanner;
0025: import org.apache.tools.ant.MagicNames;
0026: import org.apache.tools.ant.Project;
0027: import org.apache.tools.ant.taskdefs.compilers.CompilerAdapter;
0028: import org.apache.tools.ant.taskdefs.compilers.CompilerAdapterFactory;
0029: import org.apache.tools.ant.types.Path;
0030: import org.apache.tools.ant.types.Reference;
0031: import org.apache.tools.ant.util.GlobPatternMapper;
0032: import org.apache.tools.ant.util.JavaEnvUtils;
0033: import org.apache.tools.ant.util.SourceFileScanner;
0034: import org.apache.tools.ant.util.facade.FacadeTaskHelper;
0035:
0036: /**
0037: * Compiles Java source files. This task can take the following
0038: * arguments:
0039: * <ul>
0040: * <li>sourcedir
0041: * <li>destdir
0042: * <li>deprecation
0043: * <li>classpath
0044: * <li>bootclasspath
0045: * <li>extdirs
0046: * <li>optimize
0047: * <li>debug
0048: * <li>encoding
0049: * <li>target
0050: * <li>depend
0051: * <li>verbose
0052: * <li>failonerror
0053: * <li>includeantruntime
0054: * <li>includejavaruntime
0055: * <li>source
0056: * <li>compiler
0057: * </ul>
0058: * Of these arguments, the <b>sourcedir</b> and <b>destdir</b> are required.
0059: * <p>
0060: * When this task executes, it will recursively scan the sourcedir and
0061: * destdir looking for Java source files to compile. This task makes its
0062: * compile decision based on timestamp.
0063: *
0064: *
0065: * @since Ant 1.1
0066: *
0067: * @ant.task category="java"
0068: */
0069:
0070: public class Javac extends MatchingTask {
0071:
0072: private static final String FAIL_MSG = "Compile failed; see the compiler error output for details.";
0073:
0074: private static final String JAVAC16 = "javac1.6";
0075: private static final String JAVAC15 = "javac1.5";
0076: private static final String JAVAC14 = "javac1.4";
0077: private static final String JAVAC13 = "javac1.3";
0078: private static final String JAVAC12 = "javac1.2";
0079: private static final String JAVAC11 = "javac1.1";
0080: private static final String MODERN = "modern";
0081: private static final String CLASSIC = "classic";
0082: private static final String EXTJAVAC = "extJavac";
0083:
0084: private Path src;
0085: private File destDir;
0086: private Path compileClasspath;
0087: private Path compileSourcepath;
0088: private String encoding;
0089: private boolean debug = false;
0090: private boolean optimize = false;
0091: private boolean deprecation = false;
0092: private boolean depend = false;
0093: private boolean verbose = false;
0094: private String targetAttribute;
0095: private Path bootclasspath;
0096: private Path extdirs;
0097: private boolean includeAntRuntime = true;
0098: private boolean includeJavaRuntime = false;
0099: private boolean fork = false;
0100: private String forkedExecutable = null;
0101: private boolean nowarn = false;
0102: private String memoryInitialSize;
0103: private String memoryMaximumSize;
0104: private FacadeTaskHelper facade = null;
0105:
0106: // CheckStyle:VisibilityModifier OFF - bc
0107: protected boolean failOnError = true;
0108: protected boolean listFiles = false;
0109: protected File[] compileList = new File[0];
0110: // CheckStyle:VisibilityModifier ON
0111:
0112: private String source;
0113: private String debugLevel;
0114: private File tmpDir;
0115:
0116: /**
0117: * Javac task for compilation of Java files.
0118: */
0119: public Javac() {
0120: facade = new FacadeTaskHelper(assumedJavaVersion());
0121: }
0122:
0123: private String assumedJavaVersion() {
0124: if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_2)) {
0125: return JAVAC12;
0126: } else if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_3)) {
0127: return JAVAC13;
0128: } else if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_4)) {
0129: return JAVAC14;
0130: } else if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_5)) {
0131: return JAVAC15;
0132: } else if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_6)) {
0133: return JAVAC16;
0134: } else {
0135: return CLASSIC;
0136: }
0137: }
0138:
0139: /**
0140: * Get the value of debugLevel.
0141: * @return value of debugLevel.
0142: */
0143: public String getDebugLevel() {
0144: return debugLevel;
0145: }
0146:
0147: /**
0148: * Keyword list to be appended to the -g command-line switch.
0149: *
0150: * This will be ignored by all implementations except modern
0151: * and classic(ver >= 1.2). Legal values are none or a
0152: * comma-separated list of the following keywords: lines, vars,
0153: * and source. If debuglevel is not specified, by default, :none
0154: * will be appended to -g. If debug is not turned on, this attribute
0155: * will be ignored.
0156: *
0157: * @param v Value to assign to debugLevel.
0158: */
0159: public void setDebugLevel(String v) {
0160: this .debugLevel = v;
0161: }
0162:
0163: /**
0164: * Get the value of source.
0165: * @return value of source.
0166: */
0167: public String getSource() {
0168: return source != null ? source : getProject().getProperty(
0169: MagicNames.BUILD_JAVAC_SOURCE);
0170: }
0171:
0172: /**
0173: * Value of the -source command-line switch; will be ignored
0174: * by all implementations except modern and jikes.
0175: *
0176: * If you use this attribute together with jikes, you must make
0177: * sure that your version of jikes supports the -source switch.
0178: * Legal values are 1.3, 1.4, 1.5, and 5 - by default, no
0179: * -source argument will be used at all.
0180: *
0181: * @param v Value to assign to source.
0182: */
0183: public void setSource(String v) {
0184: this .source = v;
0185: }
0186:
0187: /**
0188: * Adds a path for source compilation.
0189: *
0190: * @return a nested src element.
0191: */
0192: public Path createSrc() {
0193: if (src == null) {
0194: src = new Path(getProject());
0195: }
0196: return src.createPath();
0197: }
0198:
0199: /**
0200: * Recreate src.
0201: *
0202: * @return a nested src element.
0203: */
0204: protected Path recreateSrc() {
0205: src = null;
0206: return createSrc();
0207: }
0208:
0209: /**
0210: * Set the source directories to find the source Java files.
0211: * @param srcDir the source directories as a path
0212: */
0213: public void setSrcdir(Path srcDir) {
0214: if (src == null) {
0215: src = srcDir;
0216: } else {
0217: src.append(srcDir);
0218: }
0219: }
0220:
0221: /**
0222: * Gets the source dirs to find the source java files.
0223: * @return the source directories as a path
0224: */
0225: public Path getSrcdir() {
0226: return src;
0227: }
0228:
0229: /**
0230: * Set the destination directory into which the Java source
0231: * files should be compiled.
0232: * @param destDir the destination director
0233: */
0234: public void setDestdir(File destDir) {
0235: this .destDir = destDir;
0236: }
0237:
0238: /**
0239: * Gets the destination directory into which the java source files
0240: * should be compiled.
0241: * @return the destination directory
0242: */
0243: public File getDestdir() {
0244: return destDir;
0245: }
0246:
0247: /**
0248: * Set the sourcepath to be used for this compilation.
0249: * @param sourcepath the source path
0250: */
0251: public void setSourcepath(Path sourcepath) {
0252: if (compileSourcepath == null) {
0253: compileSourcepath = sourcepath;
0254: } else {
0255: compileSourcepath.append(sourcepath);
0256: }
0257: }
0258:
0259: /**
0260: * Gets the sourcepath to be used for this compilation.
0261: * @return the source path
0262: */
0263: public Path getSourcepath() {
0264: return compileSourcepath;
0265: }
0266:
0267: /**
0268: * Adds a path to sourcepath.
0269: * @return a sourcepath to be configured
0270: */
0271: public Path createSourcepath() {
0272: if (compileSourcepath == null) {
0273: compileSourcepath = new Path(getProject());
0274: }
0275: return compileSourcepath.createPath();
0276: }
0277:
0278: /**
0279: * Adds a reference to a source path defined elsewhere.
0280: * @param r a reference to a source path
0281: */
0282: public void setSourcepathRef(Reference r) {
0283: createSourcepath().setRefid(r);
0284: }
0285:
0286: /**
0287: * Set the classpath to be used for this compilation.
0288: *
0289: * @param classpath an Ant Path object containing the compilation classpath.
0290: */
0291: public void setClasspath(Path classpath) {
0292: if (compileClasspath == null) {
0293: compileClasspath = classpath;
0294: } else {
0295: compileClasspath.append(classpath);
0296: }
0297: }
0298:
0299: /**
0300: * Gets the classpath to be used for this compilation.
0301: * @return the class path
0302: */
0303: public Path getClasspath() {
0304: return compileClasspath;
0305: }
0306:
0307: /**
0308: * Adds a path to the classpath.
0309: * @return a class path to be configured
0310: */
0311: public Path createClasspath() {
0312: if (compileClasspath == null) {
0313: compileClasspath = new Path(getProject());
0314: }
0315: return compileClasspath.createPath();
0316: }
0317:
0318: /**
0319: * Adds a reference to a classpath defined elsewhere.
0320: * @param r a reference to a classpath
0321: */
0322: public void setClasspathRef(Reference r) {
0323: createClasspath().setRefid(r);
0324: }
0325:
0326: /**
0327: * Sets the bootclasspath that will be used to compile the classes
0328: * against.
0329: * @param bootclasspath a path to use as a boot class path (may be more
0330: * than one)
0331: */
0332: public void setBootclasspath(Path bootclasspath) {
0333: if (this .bootclasspath == null) {
0334: this .bootclasspath = bootclasspath;
0335: } else {
0336: this .bootclasspath.append(bootclasspath);
0337: }
0338: }
0339:
0340: /**
0341: * Gets the bootclasspath that will be used to compile the classes
0342: * against.
0343: * @return the boot path
0344: */
0345: public Path getBootclasspath() {
0346: return bootclasspath;
0347: }
0348:
0349: /**
0350: * Adds a path to the bootclasspath.
0351: * @return a path to be configured
0352: */
0353: public Path createBootclasspath() {
0354: if (bootclasspath == null) {
0355: bootclasspath = new Path(getProject());
0356: }
0357: return bootclasspath.createPath();
0358: }
0359:
0360: /**
0361: * Adds a reference to a classpath defined elsewhere.
0362: * @param r a reference to a classpath
0363: */
0364: public void setBootClasspathRef(Reference r) {
0365: createBootclasspath().setRefid(r);
0366: }
0367:
0368: /**
0369: * Sets the extension directories that will be used during the
0370: * compilation.
0371: * @param extdirs a path
0372: */
0373: public void setExtdirs(Path extdirs) {
0374: if (this .extdirs == null) {
0375: this .extdirs = extdirs;
0376: } else {
0377: this .extdirs.append(extdirs);
0378: }
0379: }
0380:
0381: /**
0382: * Gets the extension directories that will be used during the
0383: * compilation.
0384: * @return the extension directories as a path
0385: */
0386: public Path getExtdirs() {
0387: return extdirs;
0388: }
0389:
0390: /**
0391: * Adds a path to extdirs.
0392: * @return a path to be configured
0393: */
0394: public Path createExtdirs() {
0395: if (extdirs == null) {
0396: extdirs = new Path(getProject());
0397: }
0398: return extdirs.createPath();
0399: }
0400:
0401: /**
0402: * If true, list the source files being handed off to the compiler.
0403: * @param list if true list the source files
0404: */
0405: public void setListfiles(boolean list) {
0406: listFiles = list;
0407: }
0408:
0409: /**
0410: * Get the listfiles flag.
0411: * @return the listfiles flag
0412: */
0413: public boolean getListfiles() {
0414: return listFiles;
0415: }
0416:
0417: /**
0418: * Indicates whether the build will continue
0419: * even if there are compilation errors; defaults to true.
0420: * @param fail if true halt the build on failure
0421: */
0422: public void setFailonerror(boolean fail) {
0423: failOnError = fail;
0424: }
0425:
0426: /**
0427: * @ant.attribute ignore="true"
0428: * @param proceed inverse of failoferror
0429: */
0430: public void setProceed(boolean proceed) {
0431: failOnError = !proceed;
0432: }
0433:
0434: /**
0435: * Gets the failonerror flag.
0436: * @return the failonerror flag
0437: */
0438: public boolean getFailonerror() {
0439: return failOnError;
0440: }
0441:
0442: /**
0443: * Indicates whether source should be
0444: * compiled with deprecation information; defaults to off.
0445: * @param deprecation if true turn on deprecation information
0446: */
0447: public void setDeprecation(boolean deprecation) {
0448: this .deprecation = deprecation;
0449: }
0450:
0451: /**
0452: * Gets the deprecation flag.
0453: * @return the deprecation flag
0454: */
0455: public boolean getDeprecation() {
0456: return deprecation;
0457: }
0458:
0459: /**
0460: * The initial size of the memory for the underlying VM
0461: * if javac is run externally; ignored otherwise.
0462: * Defaults to the standard VM memory setting.
0463: * (Examples: 83886080, 81920k, or 80m)
0464: * @param memoryInitialSize string to pass to VM
0465: */
0466: public void setMemoryInitialSize(String memoryInitialSize) {
0467: this .memoryInitialSize = memoryInitialSize;
0468: }
0469:
0470: /**
0471: * Gets the memoryInitialSize flag.
0472: * @return the memoryInitialSize flag
0473: */
0474: public String getMemoryInitialSize() {
0475: return memoryInitialSize;
0476: }
0477:
0478: /**
0479: * The maximum size of the memory for the underlying VM
0480: * if javac is run externally; ignored otherwise.
0481: * Defaults to the standard VM memory setting.
0482: * (Examples: 83886080, 81920k, or 80m)
0483: * @param memoryMaximumSize string to pass to VM
0484: */
0485: public void setMemoryMaximumSize(String memoryMaximumSize) {
0486: this .memoryMaximumSize = memoryMaximumSize;
0487: }
0488:
0489: /**
0490: * Gets the memoryMaximumSize flag.
0491: * @return the memoryMaximumSize flag
0492: */
0493: public String getMemoryMaximumSize() {
0494: return memoryMaximumSize;
0495: }
0496:
0497: /**
0498: * Set the Java source file encoding name.
0499: * @param encoding the source file encoding
0500: */
0501: public void setEncoding(String encoding) {
0502: this .encoding = encoding;
0503: }
0504:
0505: /**
0506: * Gets the java source file encoding name.
0507: * @return the source file encoding name
0508: */
0509: public String getEncoding() {
0510: return encoding;
0511: }
0512:
0513: /**
0514: * Indicates whether source should be compiled
0515: * with debug information; defaults to off.
0516: * @param debug if true compile with debug information
0517: */
0518: public void setDebug(boolean debug) {
0519: this .debug = debug;
0520: }
0521:
0522: /**
0523: * Gets the debug flag.
0524: * @return the debug flag
0525: */
0526: public boolean getDebug() {
0527: return debug;
0528: }
0529:
0530: /**
0531: * If true, compiles with optimization enabled.
0532: * @param optimize if true compile with optimization enabled
0533: */
0534: public void setOptimize(boolean optimize) {
0535: this .optimize = optimize;
0536: }
0537:
0538: /**
0539: * Gets the optimize flag.
0540: * @return the optimize flag
0541: */
0542: public boolean getOptimize() {
0543: return optimize;
0544: }
0545:
0546: /**
0547: * Enables dependency-tracking for compilers
0548: * that support this (jikes and classic).
0549: * @param depend if true enable dependency-tracking
0550: */
0551: public void setDepend(boolean depend) {
0552: this .depend = depend;
0553: }
0554:
0555: /**
0556: * Gets the depend flag.
0557: * @return the depend flag
0558: */
0559: public boolean getDepend() {
0560: return depend;
0561: }
0562:
0563: /**
0564: * If true, asks the compiler for verbose output.
0565: * @param verbose if true, asks the compiler for verbose output
0566: */
0567: public void setVerbose(boolean verbose) {
0568: this .verbose = verbose;
0569: }
0570:
0571: /**
0572: * Gets the verbose flag.
0573: * @return the verbose flag
0574: */
0575: public boolean getVerbose() {
0576: return verbose;
0577: }
0578:
0579: /**
0580: * Sets the target VM that the classes will be compiled for. Valid
0581: * values depend on the compiler, for jdk 1.4 the valid values are
0582: * "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "5" and "6".
0583: * @param target the target VM
0584: */
0585: public void setTarget(String target) {
0586: this .targetAttribute = target;
0587: }
0588:
0589: /**
0590: * Gets the target VM that the classes will be compiled for.
0591: * @return the target VM
0592: */
0593: public String getTarget() {
0594: return targetAttribute != null ? targetAttribute : getProject()
0595: .getProperty(MagicNames.BUILD_JAVAC_TARGET);
0596: }
0597:
0598: /**
0599: * If true, includes Ant's own classpath in the classpath.
0600: * @param include if true, includes Ant's own classpath in the classpath
0601: */
0602: public void setIncludeantruntime(boolean include) {
0603: includeAntRuntime = include;
0604: }
0605:
0606: /**
0607: * Gets whether or not the ant classpath is to be included in the classpath.
0608: * @return whether or not the ant classpath is to be included in the classpath
0609: */
0610: public boolean getIncludeantruntime() {
0611: return includeAntRuntime;
0612: }
0613:
0614: /**
0615: * If true, includes the Java runtime libraries in the classpath.
0616: * @param include if true, includes the Java runtime libraries in the classpath
0617: */
0618: public void setIncludejavaruntime(boolean include) {
0619: includeJavaRuntime = include;
0620: }
0621:
0622: /**
0623: * Gets whether or not the java runtime should be included in this
0624: * task's classpath.
0625: * @return the includejavaruntime attribute
0626: */
0627: public boolean getIncludejavaruntime() {
0628: return includeJavaRuntime;
0629: }
0630:
0631: /**
0632: * If true, forks the javac compiler.
0633: *
0634: * @param f "true|false|on|off|yes|no"
0635: */
0636: public void setFork(boolean f) {
0637: fork = f;
0638: }
0639:
0640: /**
0641: * Sets the name of the javac executable.
0642: *
0643: * <p>Ignored unless fork is true or extJavac has been specified
0644: * as the compiler.</p>
0645: * @param forkExec the name of the executable
0646: */
0647: public void setExecutable(String forkExec) {
0648: forkedExecutable = forkExec;
0649: }
0650:
0651: /**
0652: * The value of the executable attribute, if any.
0653: *
0654: * @since Ant 1.6
0655: * @return the name of the java executable
0656: */
0657: public String getExecutable() {
0658: return forkedExecutable;
0659: }
0660:
0661: /**
0662: * Is this a forked invocation of JDK's javac?
0663: * @return true if this is a forked invocation
0664: */
0665: public boolean isForkedJavac() {
0666: return fork || "extJavac".equals(getCompiler());
0667: }
0668:
0669: /**
0670: * The name of the javac executable to use in fork-mode.
0671: *
0672: * <p>This is either the name specified with the executable
0673: * attribute or the full path of the javac compiler of the VM Ant
0674: * is currently running in - guessed by Ant.</p>
0675: *
0676: * <p>You should <strong>not</strong> invoke this method if you
0677: * want to get the value of the executable command - use {@link
0678: * #getExecutable getExecutable} for this.</p>
0679: * @return the name of the javac executable
0680: */
0681: public String getJavacExecutable() {
0682: if (forkedExecutable == null && isForkedJavac()) {
0683: forkedExecutable = getSystemJavac();
0684: } else if (forkedExecutable != null && !isForkedJavac()) {
0685: forkedExecutable = null;
0686: }
0687: return forkedExecutable;
0688: }
0689:
0690: /**
0691: * If true, enables the -nowarn option.
0692: * @param flag if true, enable the -nowarn option
0693: */
0694: public void setNowarn(boolean flag) {
0695: this .nowarn = flag;
0696: }
0697:
0698: /**
0699: * Should the -nowarn option be used.
0700: * @return true if the -nowarn option should be used
0701: */
0702: public boolean getNowarn() {
0703: return nowarn;
0704: }
0705:
0706: /**
0707: * Adds an implementation specific command-line argument.
0708: * @return a ImplementationSpecificArgument to be configured
0709: */
0710: public ImplementationSpecificArgument createCompilerArg() {
0711: ImplementationSpecificArgument arg = new ImplementationSpecificArgument();
0712: facade.addImplementationArgument(arg);
0713: return arg;
0714: }
0715:
0716: /**
0717: * Get the additional implementation specific command line arguments.
0718: * @return array of command line arguments, guaranteed to be non-null.
0719: */
0720: public String[] getCurrentCompilerArgs() {
0721: String chosen = facade.getExplicitChoice();
0722: try {
0723: // make sure facade knows about magic properties and fork setting
0724: String appliedCompiler = getCompiler();
0725: facade.setImplementation(appliedCompiler);
0726:
0727: String[] result = facade.getArgs();
0728:
0729: String altCompilerName = getAltCompilerName(facade
0730: .getImplementation());
0731:
0732: if (result.length == 0 && altCompilerName != null) {
0733: facade.setImplementation(altCompilerName);
0734: result = facade.getArgs();
0735: }
0736:
0737: return result;
0738:
0739: } finally {
0740: facade.setImplementation(chosen);
0741: }
0742: }
0743:
0744: private String getAltCompilerName(String anImplementation) {
0745: if (JAVAC16.equalsIgnoreCase(anImplementation)
0746: || JAVAC15.equalsIgnoreCase(anImplementation)
0747: || JAVAC14.equalsIgnoreCase(anImplementation)
0748: || JAVAC13.equalsIgnoreCase(anImplementation)) {
0749: return MODERN;
0750: }
0751: if (JAVAC12.equalsIgnoreCase(anImplementation)
0752: || JAVAC11.equalsIgnoreCase(anImplementation)) {
0753: return CLASSIC;
0754: }
0755: if (MODERN.equalsIgnoreCase(anImplementation)) {
0756: String nextSelected = assumedJavaVersion();
0757: if (JAVAC16.equalsIgnoreCase(nextSelected)
0758: || JAVAC15.equalsIgnoreCase(nextSelected)
0759: || JAVAC14.equalsIgnoreCase(nextSelected)
0760: || JAVAC13.equalsIgnoreCase(nextSelected)) {
0761: return nextSelected;
0762: }
0763: }
0764: if (CLASSIC.equals(anImplementation)) {
0765: return assumedJavaVersion();
0766: }
0767: if (EXTJAVAC.equalsIgnoreCase(anImplementation)) {
0768: return assumedJavaVersion();
0769: }
0770: return null;
0771: }
0772:
0773: /**
0774: * Where Ant should place temporary files.
0775: *
0776: * @since Ant 1.6
0777: * @param tmpDir the temporary directory
0778: */
0779: public void setTempdir(File tmpDir) {
0780: this .tmpDir = tmpDir;
0781: }
0782:
0783: /**
0784: * Where Ant should place temporary files.
0785: *
0786: * @since Ant 1.6
0787: * @return the temporary directory
0788: */
0789: public File getTempdir() {
0790: return tmpDir;
0791: }
0792:
0793: /**
0794: * Executes the task.
0795: * @exception BuildException if an error occurs
0796: */
0797: public void execute() throws BuildException {
0798: checkParameters();
0799: resetFileLists();
0800:
0801: // scan source directories and dest directory to build up
0802: // compile lists
0803: String[] list = src.list();
0804: for (int i = 0; i < list.length; i++) {
0805: File srcDir = getProject().resolveFile(list[i]);
0806: if (!srcDir.exists()) {
0807: throw new BuildException("srcdir \"" + srcDir.getPath()
0808: + "\" does not exist!", getLocation());
0809: }
0810:
0811: DirectoryScanner ds = this .getDirectoryScanner(srcDir);
0812: String[] files = ds.getIncludedFiles();
0813:
0814: scanDir(srcDir, destDir != null ? destDir : srcDir, files);
0815: }
0816:
0817: compile();
0818: }
0819:
0820: /**
0821: * Clear the list of files to be compiled and copied..
0822: */
0823: protected void resetFileLists() {
0824: compileList = new File[0];
0825: }
0826:
0827: /**
0828: * Scans the directory looking for source files to be compiled.
0829: * The results are returned in the class variable compileList
0830: *
0831: * @param srcDir The source directory
0832: * @param destDir The destination directory
0833: * @param files An array of filenames
0834: */
0835: protected void scanDir(File srcDir, File destDir, String[] files) {
0836: GlobPatternMapper m = new GlobPatternMapper();
0837: m.setFrom("*.java");
0838: m.setTo("*.class");
0839: SourceFileScanner sfs = new SourceFileScanner(this );
0840: File[] newFiles = sfs
0841: .restrictAsFiles(files, srcDir, destDir, m);
0842:
0843: if (newFiles.length > 0) {
0844: File[] newCompileList = new File[compileList.length
0845: + newFiles.length];
0846: System.arraycopy(compileList, 0, newCompileList, 0,
0847: compileList.length);
0848: System.arraycopy(newFiles, 0, newCompileList,
0849: compileList.length, newFiles.length);
0850: compileList = newCompileList;
0851: }
0852: }
0853:
0854: /**
0855: * Gets the list of files to be compiled.
0856: * @return the list of files as an array
0857: */
0858: public File[] getFileList() {
0859: return compileList;
0860: }
0861:
0862: /**
0863: * Is the compiler implementation a jdk compiler
0864: *
0865: * @param compilerImpl the name of the compiler implementation
0866: * @return true if compilerImpl is "modern", "classic",
0867: * "javac1.1", "javac1.2", "javac1.3", "javac1.4", "javac1.5" or
0868: * "javac1.6".
0869: */
0870: protected boolean isJdkCompiler(String compilerImpl) {
0871: return MODERN.equals(compilerImpl)
0872: || CLASSIC.equals(compilerImpl)
0873: || JAVAC16.equals(compilerImpl)
0874: || JAVAC15.equals(compilerImpl)
0875: || JAVAC14.equals(compilerImpl)
0876: || JAVAC13.equals(compilerImpl)
0877: || JAVAC12.equals(compilerImpl)
0878: || JAVAC11.equals(compilerImpl);
0879: }
0880:
0881: /**
0882: * @return the executable name of the java compiler
0883: */
0884: protected String getSystemJavac() {
0885: return JavaEnvUtils.getJdkExecutable("javac");
0886: }
0887:
0888: /**
0889: * Choose the implementation for this particular task.
0890: * @param compiler the name of the compiler
0891: * @since Ant 1.5
0892: */
0893: public void setCompiler(String compiler) {
0894: facade.setImplementation(compiler);
0895: }
0896:
0897: /**
0898: * The implementation for this particular task.
0899: *
0900: * <p>Defaults to the build.compiler property but can be overridden
0901: * via the compiler and fork attributes.</p>
0902: *
0903: * <p>If fork has been set to true, the result will be extJavac
0904: * and not classic or java1.2 - no matter what the compiler
0905: * attribute looks like.</p>
0906: *
0907: * @see #getCompilerVersion
0908: * @return the compiler.
0909: * @since Ant 1.5
0910: */
0911: public String getCompiler() {
0912: String compilerImpl = getCompilerVersion();
0913: if (fork) {
0914: if (isJdkCompiler(compilerImpl)) {
0915: compilerImpl = "extJavac";
0916: } else {
0917: log("Since compiler setting isn't classic or modern,"
0918: + "ignoring fork setting.", Project.MSG_WARN);
0919: }
0920: }
0921: return compilerImpl;
0922: }
0923:
0924: /**
0925: * The implementation for this particular task.
0926: *
0927: * <p>Defaults to the build.compiler property but can be overridden
0928: * via the compiler attribute.</p>
0929: *
0930: * <p>This method does not take the fork attribute into
0931: * account.</p>
0932: *
0933: * @see #getCompiler
0934: * @return the compiler.
0935: *
0936: * @since Ant 1.5
0937: */
0938: public String getCompilerVersion() {
0939: facade
0940: .setMagicValue(getProject().getProperty(
0941: "build.compiler"));
0942: return facade.getImplementation();
0943: }
0944:
0945: /**
0946: * Check that all required attributes have been set and nothing
0947: * silly has been entered.
0948: *
0949: * @since Ant 1.5
0950: * @exception BuildException if an error occurs
0951: */
0952: protected void checkParameters() throws BuildException {
0953: if (src == null) {
0954: throw new BuildException("srcdir attribute must be set!",
0955: getLocation());
0956: }
0957: if (src.size() == 0) {
0958: throw new BuildException("srcdir attribute must be set!",
0959: getLocation());
0960: }
0961:
0962: if (destDir != null && !destDir.isDirectory()) {
0963: throw new BuildException("destination directory \""
0964: + destDir + "\" does not exist "
0965: + "or is not a directory", getLocation());
0966: }
0967: }
0968:
0969: /**
0970: * Perform the compilation.
0971: *
0972: * @since Ant 1.5
0973: */
0974: protected void compile() {
0975: String compilerImpl = getCompiler();
0976:
0977: if (compileList.length > 0) {
0978: log("Compiling " + compileList.length + " source file"
0979: + (compileList.length == 1 ? "" : "s")
0980: + (destDir != null ? " to " + destDir : ""));
0981:
0982: if (listFiles) {
0983: for (int i = 0; i < compileList.length; i++) {
0984: String filename = compileList[i].getAbsolutePath();
0985: log(filename);
0986: }
0987: }
0988:
0989: CompilerAdapter adapter = CompilerAdapterFactory
0990: .getCompiler(compilerImpl, this );
0991:
0992: // now we need to populate the compiler adapter
0993: adapter.setJavac(this );
0994:
0995: // finally, lets execute the compiler!!
0996: if (!adapter.execute()) {
0997: if (failOnError) {
0998: throw new BuildException(FAIL_MSG, getLocation());
0999: } else {
1000: log(FAIL_MSG, Project.MSG_ERR);
1001: }
1002: }
1003: }
1004: }
1005:
1006: /**
1007: * Adds an "compiler" attribute to Commandline$Attribute used to
1008: * filter command line attributes based on the current
1009: * implementation.
1010: */
1011: public class ImplementationSpecificArgument
1012: extends
1013: org.apache.tools.ant.util.facade.ImplementationSpecificArgument {
1014:
1015: /**
1016: * @param impl the name of the compiler
1017: */
1018: public void setCompiler(String impl) {
1019: super.setImplementation(impl);
1020: }
1021: }
1022:
1023: }
|