aboutsummaryrefslogtreecommitdiffstats
path: root/taskdefs
diff options
context:
space:
mode:
Diffstat (limited to 'taskdefs')
-rw-r--r--taskdefs/src/org/aspectj/tools/ant/taskdefs/Ajc11CompilerAdapter.java282
1 files changed, 122 insertions, 160 deletions
diff --git a/taskdefs/src/org/aspectj/tools/ant/taskdefs/Ajc11CompilerAdapter.java b/taskdefs/src/org/aspectj/tools/ant/taskdefs/Ajc11CompilerAdapter.java
index 15198d957..4e23c962b 100644
--- a/taskdefs/src/org/aspectj/tools/ant/taskdefs/Ajc11CompilerAdapter.java
+++ b/taskdefs/src/org/aspectj/tools/ant/taskdefs/Ajc11CompilerAdapter.java
@@ -1,190 +1,152 @@
/* *******************************************************************
- * Copyright (c) 2001-2001 Xerox Corporation,
- * 2002 Palo Alto Research Center, Incorporated (PARC).
- * All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Common Public License v1.0
- * which accompanies this distribution and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * Xerox/PARC initial implementation
+ * Copyright (c) 2003 Contributors.
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Wes Isberg initial implementation
* ******************************************************************/
package org.aspectj.tools.ant.taskdefs;
import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.types.Commandline;
-import org.apache.tools.ant.taskdefs.compilers.DefaultCompilerAdapter;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.Javac;
+import org.apache.tools.ant.taskdefs.compilers.CompilerAdapter;
+import org.aspectj.util.FileUtil;
import java.io.File;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.ListIterator;
-
-import org.aspectj.bridge.*;
-import org.aspectj.util.LangUtil;
-
+import java.io.FileFilter;
+import java.io.FileWriter;
+import java.io.IOException;
/**
- * EXPERIMENTAL - This adapts the AspectJ compiler as if it were Javac.
- * It just passes the arguments through to the compiler.
- * Limitations:
+ * Adapt ajc to javac commands.
+ * Note that the srcdirs set for javac are NOT passed on to ajc;
+ * instead, the list of source files generated is passed to ajc.
+ * <p>
+ * Javac usually prunes the source file list based on the timestamps
+ * of corresponding .class files, which is wrong for ajc which
+ * requires all the files every time. To work around this,
+ * set the global property CLEAN ("build.compiler.clean") to delete
+ * all .class files in the destination directory before compiling.
+ * This clean process only permits one compile process at a time
+ * for each destination directory because it tracks recursion by
+ * writing a tag file to the destination directory.
+ *
+ * <p><u>Warnings</u>:
* <ol>
- * <li>Users still must specify all source files to compile.</li>
- * <li>No support for non-Javac options</li>
- * <li>Javac srcdir are treated as sourceroots unless -DajcAdapterSkipRoots=...</li>
- * </ol>
+ * <li>cleaning will makes stepwise build processes fail
+ * if they depend on the results of the prior compilation being
+ * in the same directory, since this deletes <strong>all</strong>
+ * .class files.</li>
+ * <li>If no files are out of date, then the adapter is never called
+ * and thus cannot gain control to clean out the destination dir.
+ * </li>
+ * <p>
*
* @author Wes Isberg <a href="mailto:isberg@aspectj.org">isberg@aspectj.org</a>
- * @since AspectJ 1.1, Ant 1.3
+ * @since AspectJ 1.1, Ant 1.5.1
*/
-public class Ajc11CompilerAdapter extends DefaultCompilerAdapter {
- /*
- * Not sure how best to implement our functionality -- not documented.
- * Desired functionality:
- * - ability to run in-line or forked
- * - switch based only on fork="[true|false]"
- * (so classpath required to fork must be calculated)
- * - able to set memory available when forking
- * - handles .lst files on command-line by prefixing with @
- * - and/or handles compiler option -XargPrefix=...
- * - this means all AspectJ-specific options (injars/outjars...)
- * are in the .lst file?
- *
- * Implementation options:
- * - straight CompilerAdapter
- * - override DefaultCompilerAdapter methods for template processes
- * - create a new FacadeTaskHelper, supply to DefaultCompilerAdaper
- */
- public static final String SKIP_ROOTS_NAME = "ajcAdapterSkipRoots";
-
- // ------------------------------ setup
- /**
- * Adds the command line arguments specifc to the current implementation.
- */
- protected void addCurrentCompilerArgs(Commandline cmd) {
- cmd.addArguments(getJavac().getCurrentCompilerArgs());
+public class Ajc11CompilerAdapter implements CompilerAdapter {
+ /**
+ * Define this system/project property to signal that the
+ * destination directory should be cleaned
+ * and javac reinvoked
+ * to get the complete list of files every time.
+ */
+ public static final String CLEAN = "build.compiler.clean";
+
+ Javac javac;
+
+ public void setJavac(Javac javac) {
+ this.javac = javac;
}
-
- // ------------------------------ run
- /**
- * Run the compilation.
- *
- * @exception BuildException if the compilation has problems.
- */
+
public boolean execute() throws BuildException {
- Commandline cmd = setupModernJavacCommand();
-
- try {
- String[] args = cmd.getArguments();
- int result = runCompiler(args);
- return (0 == result);
- } catch (BuildException e) {
- throw e;
- } catch (AbortException x) {
- if (x.isSilent()) { // no message, just return
- return false;
- } else {
- Throwable t = x.getThrown();
- if (null == t) {
- t = x;
+ checkJavac();
+ if (recurse()) {
+ javac.execute(); // re-invokes us after recalculating file list
+ } else {
+ try {
+ AjcTask ajc = new AjcTask();
+ String err = AjcTask.setupAjc(ajc, javac, getDestDir());
+ if (null != err) {
+ throw new BuildException(err, javac.getLocation());
}
- throw new BuildException("Thrown: ", t, location);
+ ajc.execute(); // handles BuildException for failonerror, etc.
+ } finally {
+ doneRecursing();
}
- } catch (Throwable x) {
- throw new BuildException("Thrown: ", x, location);
+ }
+ return true;
+ }
+
+ /** @throws IllegalStateException if javac is not defined */
+ protected void checkJavac() {
+ if (null == javac) {
+ throw new IllegalStateException("null javac");
}
}
- // run? handle forking?
- private int runCompiler(String[] args) {
- int result = -1;
- IMessageHolder sink = new MessageHandler();
- ICommand compiler = ReflectionFactory.makeCommand(ReflectionFactory.ECLIPSE, sink);
- if ((null == compiler) || sink.hasAnyMessage(IMessage.FAIL, true)) {
- throwBuildException("loading compiler", sink);
- } else {
- args = filterArgs(args);
- if (!compiler.runCommand(args, sink)) {
- System.err.println("runCompiler args: " + Arrays.asList(args));
- throwBuildException("running compiler", sink);
- } else {
- result = 0;
- }
+ protected File getDestDir() {
+ checkJavac();
+ File destDir = javac.getDestdir();
+ if (null == destDir) {
+ destDir = new File(".");
}
- return result;
+ return destDir;
}
- /**
- * Method throwBuildException.
- * @param string
- * @param sink
- */
- private void throwBuildException(String string, IMessageHolder sink) { // XXX nicer
- if ((null != sink) && (0 < sink.numMessages(null, true))) {
- MessageUtil.print(System.err, sink, null);
+ protected File getTagFile() {
+ return new File(getDestDir(), "Ajc11CompilerAdapter.tag");
+ }
+
+ /**
+ * If property CLEAN is set, then this
+ * cleans out the dest dir of any .class files,
+ * installs a tag file, and returns true to signal a recursive call.
+ * That means this returns false if CLEAN is not set
+ * or if the tag file already exists (i.e., already recursing).
+ * The result is that javac is re-invoked after the dest dir
+ * is cleaned, so it picks up all the correct source files.
+ * (This is a costly hack to work around Javac's forcing the
+ * pruning of the file list.)
+ * @return true if javac should be re-invoked.
+ */
+ protected boolean recurse() {
+ checkJavac();
+ String cleanDirs = javac.getProject().getProperty(CLEAN);
+ if (null == cleanDirs) {
+ return false;
}
- throw new BuildException(string + ": " + sink, location);
- }
-
- /** Convert javac argument list to a form acceptable by ajc */
- protected String[] filterArgs(String[] args) {
- LinkedList argList = new LinkedList();
- argList.addAll(LangUtil.arrayAsList(args));
- ArrayList roots = new ArrayList();
- for (ListIterator iter = argList.listIterator(); iter.hasNext();) {
- String arg = (String) iter.next();
- if ("-sourcepath".equals(arg)) { // similar to -sourceroots?
- iter.remove();
- roots.add(iter.next()); // need next after remove?
- iter.remove();
- } else if ("-0".equals(arg)) { // unsupported
- System.err.println("warning: ignoring -0 argument");
- iter.remove();
- } else if ("-bootclasspath".equals(arg)) { // ajc fakes
- } else if ("-extdirs".equals(arg)) { // ajc fakes
- } else if ("-target".equals(arg)) { // -1.4 or -1.3
- iter.remove();
- String vers = (String) iter.next();
- if ("1.3".equals(vers)) {
- iter.set("-1.3");
- } else if ("1.4".equals(vers)) {
- iter.set("-1.4");
- } else { // huh?
- String s = "expecting 1.3 or 1.4 at " + vers + " in " + argList;
- throwBuildException(s, null);
- }
- }
- }
-
- if (0 < roots.size()) {
- String skipRoots = null;
- try {
- skipRoots = System.getProperty(SKIP_ROOTS_NAME);
- } catch (Throwable t) {
- // ignore SecurityException, etc.
- }
-
- if (null == skipRoots) {
- StringBuffer sb = new StringBuffer();
- boolean first = true;
- for (Iterator iter = roots.iterator(); iter.hasNext();) {
- if (!first) {
- sb.append(File.pathSeparator);
- } else {
- first = false;
- }
- sb.append((String) iter.next());
- }
- argList.add(0, "-sourceroots");
- argList.add(1, sb.toString());
- }
+ File tagFile = getTagFile();
+ if (tagFile.exists()) {
+ return false;
}
+ try {
+ File destDir = getDestDir();
+ javac.log(CLEAN + " cleaning .class files from " + destDir,
+ Project.MSG_VERBOSE);
+ FileUtil.deleteContents(destDir, FileUtil.DIRS_AND_WRITABLE_CLASSES, true);
+ FileWriter fw = new FileWriter(tagFile);
+ fw.write("Ajc11CompilerAdapter.recursing");
+ fw.close();
+ return true;
+ } catch (IOException e) {
+ return false;
+ }
+ }
- return (String[]) argList.toArray(new String[0]);
+ protected void doneRecursing() {
+ File tagFile = getTagFile();
+ if (tagFile.exists()) {
+ tagFile.delete();
+ }
}
}
+