diff options
author | aclement <aclement> | 2009-01-31 04:33:22 +0000 |
---|---|---|
committer | aclement <aclement> | 2009-01-31 04:33:22 +0000 |
commit | 1da1f7cdaca36e258045ef29660abaa13c84ebed (patch) | |
tree | e4cfadd34fe2c3c927616f6a0a900c4b6ad57b7e /taskdefs/src | |
parent | c04eccb2aad5c0f427b123d4c5712ba0317f4695 (diff) | |
download | aspectj-1da1f7cdaca36e258045ef29660abaa13c84ebed.tar.gz aspectj-1da1f7cdaca36e258045ef29660abaa13c84ebed.zip |
261808: fix
Diffstat (limited to 'taskdefs/src')
-rw-r--r-- | taskdefs/src/org/aspectj/tools/ant/taskdefs/AjcTask.java | 3949 |
1 files changed, 1923 insertions, 2026 deletions
diff --git a/taskdefs/src/org/aspectj/tools/ant/taskdefs/AjcTask.java b/taskdefs/src/org/aspectj/tools/ant/taskdefs/AjcTask.java index 794335ae3..e22fc9a85 100644 --- a/taskdefs/src/org/aspectj/tools/ant/taskdefs/AjcTask.java +++ b/taskdefs/src/org/aspectj/tools/ant/taskdefs/AjcTask.java @@ -13,7 +13,6 @@ * Wes Isberg 2003-2004 changes * ******************************************************************/ - package org.aspectj.tools.ant.taskdefs; import java.io.File; @@ -61,2089 +60,1987 @@ import org.aspectj.tools.ajc.Main; import org.aspectj.util.FileUtil; import org.aspectj.util.LangUtil; - /** - * This runs the AspectJ 1.1 compiler, - * supporting all the command-line options. - * In 1.1.1, ajc copies resources from input jars, - * but you can copy resources from the source directories - * using sourceRootCopyFilter. - * When not forking, things will be copied as needed - * for each iterative compile, - * but when forking things are only copied at the - * completion of a successful compile. + * This runs the AspectJ 1.1 compiler, supporting all the command-line options. In 1.1.1, ajc copies resources from input jars, but + * you can copy resources from the source directories using sourceRootCopyFilter. When not forking, things will be copied as needed + * for each iterative compile, but when forking things are only copied at the completion of a successful compile. * <p> - * See the development environment guide for - * usage documentation. + * See the development environment guide for usage documentation. * * @since AspectJ 1.1, Ant 1.5 */ public class AjcTask extends MatchingTask { - /* - * This task mainly converts ant specification for ajc, - * verbosely ignoring improper input. - * It also has some special features for non-obvious clients: - * (1) Javac compiler adapter supported in - * <code>setupAjc(AjcTask, Javac, File)</code> - * and - * <code>readArguments(String[])</code>; - * (2) testing is supported by - * (a) permitting the same specification to be re-run - * with added flags (settings once made cannot be - * removed); and - * (b) permitting recycling the task with - * <code>reset()</code> (untested). - * - * The parts that do more than convert ant specs are - * (a) code for forking; - * (b) code for copying resources. - * - * If you maintain/upgrade this task, keep in mind: - * (1) changes to the semantics of ajc (new options, new - * values permitted, etc.) will have to be reflected here. - * (2) the clients: - * the iajc ant script, Javac compiler adapter, - * maven clients of iajc, and testing code. - */ - - // XXX move static methods after static initializer - /** - * This method extracts javac arguments to ajc, - * and add arguments to make ajc behave more like javac - * in copying resources. - * <p> - * Pass ajc-specific options using compilerarg sub-element: - * <pre> - * <javac srcdir="src"> - * <compilerarg compiler="..." line="-argfile src/args.lst"/> - * <javac> - * </pre> - * Some javac arguments are not supported in this component (yet): - * <pre> - * String memoryInitialSize; - * boolean includeAntRuntime = true; - * boolean includeJavaRuntime = false; - * </pre> - * Other javac arguments are not supported in ajc 1.1: - * <pre> - * boolean optimize; - * String forkedExecutable; - * FacadeTaskHelper facade; - * boolean depend; - * String debugLevel; - * Path compileSourcepath; - * </pre> - * @param javac the Javac command to implement (not null) - * @param ajc the AjcTask to adapt (not null) - * @param destDir the File class destination directory (may be null) - * @return null if no error, or String error otherwise - */ - public String setupAjc(Javac javac) { - if (null == javac) { - return "null javac"; - } - AjcTask ajc = this; - // no null checks b/c AjcTask handles null input gracefully - ajc.setProject(javac.getProject()); - ajc.setLocation(javac.getLocation()); - ajc.setTaskName("javac-iajc"); - - ajc.setDebug(javac.getDebug()); - ajc.setDeprecation(javac.getDeprecation()); - ajc.setFailonerror(javac.getFailonerror()); - final boolean fork = javac.isForkedJavac(); - ajc.setFork(fork); - if (fork) { - ajc.setMaxmem(javac.getMemoryMaximumSize()); - } - ajc.setNowarn(javac.getNowarn()); - ajc.setListFileArgs(javac.getListfiles()); - ajc.setVerbose(javac.getVerbose()); - ajc.setTarget(javac.getTarget()); - ajc.setSource(javac.getSource()); - ajc.setEncoding(javac.getEncoding()); - File javacDestDir = javac.getDestdir(); - if (null != javacDestDir) { - ajc.setDestdir(javacDestDir); - // filter requires dest dir - // mimic Javac task's behavior in copying resources, - ajc.setSourceRootCopyFilter("**/CVS/*,**/*.java,**/*.aj"); - } - ajc.setBootclasspath(javac.getBootclasspath()); - ajc.setExtdirs(javac.getExtdirs()); - ajc.setClasspath(javac.getClasspath()); - // ignore srcDir -- all files picked up in recalculated file list -// ajc.setSrcDir(javac.getSrcdir()); - ajc.addFiles(javac.getFileList()); - // arguments can override the filter, add to paths, override options - ajc.readArguments(javac.getCurrentCompilerArgs()); - - return null; - } - - /** - * Find aspectjtools.jar on the task or system classpath. - * Accept <code>aspectj{-}tools{...}.jar</code> - * mainly to support build systems using maven-style - * re-naming - * (e.g., <code>aspectj-tools-1.1.0.jar</code>. - * Note that we search the task classpath first, - * though an entry on the system classpath would be loaded first, - * because it seems more correct as the more specific one. - * @return readable File for aspectjtools.jar, or null if not found. - */ - public static File findAspectjtoolsJar() { - File result = null; - ClassLoader loader = AjcTask.class.getClassLoader(); - if (loader instanceof AntClassLoader) { - AntClassLoader taskLoader = (AntClassLoader) loader; - String cp = taskLoader.getClasspath(); - String[] cps = LangUtil.splitClasspath(cp); - for (int i = 0; (i < cps.length) && (null == result); i++) { - result = isAspectjtoolsjar(cps[i]); - } - } - if (null == result) { - final Path classpath = Path.systemClasspath; - final String[] paths = classpath.list(); - for (int i = 0; (i < paths.length) && (null == result); i++) { - result = isAspectjtoolsjar(paths[i]); - } - } - return (null == result? null : result.getAbsoluteFile()); - } - - /** @return File if readable jar with aspectj tools name, or null */ - private static File isAspectjtoolsjar(String path) { - if (null == path) { - return null; - } - final String prefix = "aspectj"; - final String infix = "tools"; - final String altInfix = "-tools"; - final String suffix = ".jar"; - final int prefixLength = 7; // prefix.length(); - final int minLength = 16; - // prefixLength + infix.length() + suffix.length(); - if (!path.endsWith(suffix)) { - return null; - } - int loc = path.lastIndexOf(prefix); - if ((-1 != loc) && ((loc + minLength) <= path.length())) { - String rest = path.substring(loc+prefixLength); - if (-1 != rest.indexOf(File.pathSeparator)) { - return null; - } - if (rest.startsWith(infix) - || rest.startsWith(altInfix)) { - File result = new File(path); - if (result.canRead() && result.isFile()) { - return result; - } - } - } - return null; - } - - /** - * Maximum length (in chars) of command line - * before converting to an argfile when forking - */ - private static final int MAX_COMMANDLINE = 4096; - - private static final File DEFAULT_DESTDIR = new File(".") { - public String toString() { - return "(no destination dir specified)"; - } - }; - - /** do not throw BuildException on fail/abort message with usage */ - private static final String USAGE_SUBSTRING = "AspectJ-specific options"; - - /** valid -X[...] options other than -Xlint variants */ - private static final List VALID_XOPTIONS; + /* + * This task mainly converts ant specification for ajc, verbosely ignoring improper input. It also has some special features for + * non-obvious clients: (1) Javac compiler adapter supported in <code>setupAjc(AjcTask, Javac, File)</code> and + * <code>readArguments(String[])</code>; (2) testing is supported by (a) permitting the same specification to be re-run with + * added flags (settings once made cannot be removed); and (b) permitting recycling the task with <code>reset()</code> + * (untested). + * + * The parts that do more than convert ant specs are (a) code for forking; (b) code for copying resources. + * + * If you maintain/upgrade this task, keep in mind: (1) changes to the semantics of ajc (new options, new values permitted, + * etc.) will have to be reflected here. (2) the clients: the iajc ant script, Javac compiler adapter, maven clients of iajc, + * and testing code. + */ + + // XXX move static methods after static initializer + /** + * This method extracts javac arguments to ajc, and add arguments to make ajc behave more like javac in copying resources. + * <p> + * Pass ajc-specific options using compilerarg sub-element: + * + * <pre> + * <javac srcdir="src"> + * <compilerarg compiler="..." line="-argfile src/args.lst"/> + * <javac> + * </pre> + * + * Some javac arguments are not supported in this component (yet): + * + * <pre> + * String memoryInitialSize; + * boolean includeAntRuntime = true; + * boolean includeJavaRuntime = false; + * </pre> + * + * Other javac arguments are not supported in ajc 1.1: + * + * <pre> + * boolean optimize; + * String forkedExecutable; + * FacadeTaskHelper facade; + * boolean depend; + * String debugLevel; + * Path compileSourcepath; + * </pre> + * + * @param javac the Javac command to implement (not null) + * @param ajc the AjcTask to adapt (not null) + * @param destDir the File class destination directory (may be null) + * @return null if no error, or String error otherwise + */ + public String setupAjc(Javac javac) { + if (null == javac) { + return "null javac"; + } + AjcTask ajc = this; + // no null checks b/c AjcTask handles null input gracefully + ajc.setProject(javac.getProject()); + ajc.setLocation(javac.getLocation()); + ajc.setTaskName("javac-iajc"); + + ajc.setDebug(javac.getDebug()); + ajc.setDeprecation(javac.getDeprecation()); + ajc.setFailonerror(javac.getFailonerror()); + final boolean fork = javac.isForkedJavac(); + ajc.setFork(fork); + if (fork) { + ajc.setMaxmem(javac.getMemoryMaximumSize()); + } + ajc.setNowarn(javac.getNowarn()); + ajc.setListFileArgs(javac.getListfiles()); + ajc.setVerbose(javac.getVerbose()); + ajc.setTarget(javac.getTarget()); + ajc.setSource(javac.getSource()); + ajc.setEncoding(javac.getEncoding()); + File javacDestDir = javac.getDestdir(); + if (null != javacDestDir) { + ajc.setDestdir(javacDestDir); + // filter requires dest dir + // mimic Javac task's behavior in copying resources, + ajc.setSourceRootCopyFilter("**/CVS/*,**/*.java,**/*.aj"); + } + ajc.setBootclasspath(javac.getBootclasspath()); + ajc.setExtdirs(javac.getExtdirs()); + ajc.setClasspath(javac.getClasspath()); + // ignore srcDir -- all files picked up in recalculated file list + // ajc.setSrcDir(javac.getSrcdir()); + ajc.addFiles(javac.getFileList()); + // arguments can override the filter, add to paths, override options + ajc.readArguments(javac.getCurrentCompilerArgs()); + + return null; + } + + /** + * Find aspectjtools.jar on the task or system classpath. Accept <code>aspectj{-}tools{...}.jar</code> mainly to support build + * systems using maven-style re-naming (e.g., <code>aspectj-tools-1.1.0.jar</code>. Note that we search the task classpath + * first, though an entry on the system classpath would be loaded first, because it seems more correct as the more specific one. + * + * @return readable File for aspectjtools.jar, or null if not found. + */ + public static File findAspectjtoolsJar() { + File result = null; + ClassLoader loader = AjcTask.class.getClassLoader(); + if (loader instanceof AntClassLoader) { + AntClassLoader taskLoader = (AntClassLoader) loader; + String cp = taskLoader.getClasspath(); + String[] cps = LangUtil.splitClasspath(cp); + for (int i = 0; (i < cps.length) && (null == result); i++) { + result = isAspectjtoolsjar(cps[i]); + } + } + if (null == result) { + final Path classpath = Path.systemClasspath; + final String[] paths = classpath.list(); + for (int i = 0; (i < paths.length) && (null == result); i++) { + result = isAspectjtoolsjar(paths[i]); + } + } + return (null == result ? null : result.getAbsoluteFile()); + } + + /** @return File if readable jar with aspectj tools name, or null */ + private static File isAspectjtoolsjar(String path) { + if (null == path) { + return null; + } + final String prefix = "aspectj"; + final String infix = "tools"; + final String altInfix = "-tools"; + final String suffix = ".jar"; + final int prefixLength = 7; // prefix.length(); + final int minLength = 16; + // prefixLength + infix.length() + suffix.length(); + if (!path.endsWith(suffix)) { + return null; + } + int loc = path.lastIndexOf(prefix); + if ((-1 != loc) && ((loc + minLength) <= path.length())) { + String rest = path.substring(loc + prefixLength); + if (-1 != rest.indexOf(File.pathSeparator)) { + return null; + } + if (rest.startsWith(infix) || rest.startsWith(altInfix)) { + File result = new File(path); + if (result.canRead() && result.isFile()) { + return result; + } + } + } + return null; + } + + /** + * Maximum length (in chars) of command line before converting to an argfile when forking + */ + private static final int MAX_COMMANDLINE = 4096; + + private static final File DEFAULT_DESTDIR = new File(".") { + public String toString() { + return "(no destination dir specified)"; + } + }; + + /** do not throw BuildException on fail/abort message with usage */ + private static final String USAGE_SUBSTRING = "AspectJ-specific options"; + + /** valid -X[...] options other than -Xlint variants */ + private static final List VALID_XOPTIONS; /** valid warning (-warn:[...]) variants */ - private static final List VALID_WARNINGS; - + private static final List VALID_WARNINGS; + /** valid debugging (-g:[...]) variants */ - private static final List VALID_DEBUG; + private static final List VALID_DEBUG; - /** + /** * -Xlint variants (error, warning, ignore) - * @see org.aspectj.weaver.Lint + * + * @see org.aspectj.weaver.Lint */ - private static final List VALID_XLINT; - - public static final String COMMAND_EDITOR_NAME - = AjcTask.class.getName() + ".COMMAND_EDITOR"; - - static final String[] TARGET_INPUTS = new String [] - { "1.1", "1.2", "1.3", "1.4", "1.5", "1.6" }; - static final String[] SOURCE_INPUTS = new String [] - { "1.3", "1.4", "1.5", "1.6" }; - static final String[] COMPLIANCE_INPUTS = new String [] - { "-1.3", "-1.4", "-1.5", "-1.6" }; - - private static final ICommandEditor COMMAND_EDITOR; - - static { - // many now deprecated: reweavable* - String[] xs = new String[] - { "serializableAspects", "incrementalFile", "lazyTjp", - "reweavable", "reweavable:compress", "notReweavable", "noInline", - "terminateAfterCompilation","hasMember", - "ajruntimetarget:1.2", "ajruntimetarget:1.5", - "addSerialVersionUID" - - //, "targetNearSource", "OcodeSize", - }; - VALID_XOPTIONS = Collections.unmodifiableList(Arrays.asList(xs)); - - xs = new String[] - { "constructorName", "packageDefaultMethod", "deprecation", - "maskedCatchBlocks", "unusedLocals", "unusedArguments", - "unusedImports", "syntheticAccess", "assertIdentifier", - "allDeprecation","allJavadoc","charConcat","conditionAssign", - - "emptyBlock", - "fieldHiding", - "finally", - "indirectStatic", - "intfNonInherited", - "javadoc", - "localHiding", - "nls", - "noEffectAssign", - "pkgDefaultMethod", - "semicolon", - "unqualifiedField", - "unusedPrivate", - "unusedThrown", - "uselessTypeCheck", - "specialParamHiding", - "staticReceiver", - "syntheticAccess", - "none" }; - VALID_WARNINGS = Collections.unmodifiableList(Arrays.asList(xs)); - - xs = new String[] {"none", "lines", "vars", "source" }; - VALID_DEBUG = Collections.unmodifiableList(Arrays.asList(xs)); - - - xs = new String[] { "error", "warning", "ignore"}; - VALID_XLINT = Collections.unmodifiableList(Arrays.asList(xs)); - - ICommandEditor editor = null; - try { - String editorClassName = System.getProperty(COMMAND_EDITOR_NAME); - if (null != editorClassName) { - ClassLoader cl = AjcTask.class.getClassLoader(); - Class editorClass = cl.loadClass(editorClassName); - editor = (ICommandEditor) editorClass.newInstance(); - } - } catch (Throwable t) { - System.err.println("Warning: unable to load command editor"); - t.printStackTrace(System.err); - } - COMMAND_EDITOR = editor; - } + private static final List VALID_XLINT; + + public static final String COMMAND_EDITOR_NAME = AjcTask.class.getName() + ".COMMAND_EDITOR"; + + static final String[] TARGET_INPUTS = new String[] { "1.1", "1.2", "1.3", "1.4", "1.5", "1.6" }; + static final String[] SOURCE_INPUTS = new String[] { "1.3", "1.4", "1.5", "1.6" }; + static final String[] COMPLIANCE_INPUTS = new String[] { "-1.3", "-1.4", "-1.5", "-1.6" }; + + private static final ICommandEditor COMMAND_EDITOR; + + static { + // many now deprecated: reweavable* + String[] xs = new String[] { "serializableAspects", "incrementalFile", "lazyTjp", "reweavable", "reweavable:compress", + "notReweavable", "noInline", "terminateAfterCompilation", "hasMember", "ajruntimetarget:1.2", + "ajruntimetarget:1.5", "addSerialVersionUID" + + // , "targetNearSource", "OcodeSize", + }; + VALID_XOPTIONS = Collections.unmodifiableList(Arrays.asList(xs)); + + xs = new String[] { "constructorName", "packageDefaultMethod", "deprecation", "maskedCatchBlocks", "unusedLocals", + "unusedArguments", "unusedImports", "syntheticAccess", "assertIdentifier", "allDeprecation", "allJavadoc", + "charConcat", "conditionAssign", + + "emptyBlock", "fieldHiding", "finally", "indirectStatic", "intfNonInherited", "javadoc", "localHiding", "nls", + "noEffectAssign", "pkgDefaultMethod", "semicolon", "unqualifiedField", "unusedPrivate", "unusedThrown", + "uselessTypeCheck", "specialParamHiding", "staticReceiver", "syntheticAccess", "none" }; + VALID_WARNINGS = Collections.unmodifiableList(Arrays.asList(xs)); + + xs = new String[] { "none", "lines", "vars", "source" }; + VALID_DEBUG = Collections.unmodifiableList(Arrays.asList(xs)); + + xs = new String[] { "error", "warning", "ignore" }; + VALID_XLINT = Collections.unmodifiableList(Arrays.asList(xs)); + + ICommandEditor editor = null; + try { + String editorClassName = System.getProperty(COMMAND_EDITOR_NAME); + if (null != editorClassName) { + ClassLoader cl = AjcTask.class.getClassLoader(); + Class editorClass = cl.loadClass(editorClassName); + editor = (ICommandEditor) editorClass.newInstance(); + } + } catch (Throwable t) { + System.err.println("Warning: unable to load command editor"); + t.printStackTrace(System.err); + } + COMMAND_EDITOR = editor; + } // ---------------------------- state and Ant interface thereto - private boolean verbose; - private boolean listFileArgs; - private boolean failonerror; - private boolean fork; - private String maxMem; - private TaskLogger logger; - + private boolean verbose; + private boolean listFileArgs; + private boolean failonerror; + private boolean fork; + private String maxMem; + private TaskLogger logger; + // ------- single entries dumped into cmd - protected GuardedCommand cmd; - + protected GuardedCommand cmd; + // ------- lists resolved in addListArgs() at execute() time - private Path srcdir; - private Path injars; - private Path inpath; - private Path classpath; - private Path bootclasspath; - private Path forkclasspath; - private Path extdirs; - private Path aspectpath; - private Path argfiles; - private List ignored; - private Path sourceRoots; - private File xweaveDir; - private String xdoneSignal; - - // ----- added by adapter - integrate better? - private List /* File */ adapterFiles; - private String[] adapterArguments; - - private IMessageHolder messageHolder; - private ICommandEditor commandEditor; - - // -------- resource-copying - /** true if copying injar non-.class files to the output jar */ - private boolean copyInjars; - private boolean copyInpath; - - /** non-null if copying all source root files but the filtered ones */ - private String sourceRootCopyFilter; - - /** non-null if copying all inpath dir files but the filtered ones */ - private String inpathDirCopyFilter; - - /** directory sink for classes */ - private File destDir; - - /** zip file sink for classes */ - private File outjar; - - /** track whether we've supplied any temp outjar */ - private boolean outjarFixedup; - - /** - * When possibly copying resources to the output jar, - * pass ajc a fake output jar to copy from, - * so we don't change the modification time of the output jar - * when copying injars/inpath into the actual outjar. - */ - private File tmpOutjar; - - private boolean executing; - - /** non-null only while executing in same vm */ - private Main main; - - /** true only when executing in other vm */ - private boolean executingInOtherVM; - - /** true if -incremental */ - private boolean inIncrementalMode; - - /** true if -XincrementalFile (i.e, setTagFile)*/ - private boolean inIncrementalFileMode; - - /** log command in non-verbose mode */ - private boolean logCommand; - - /** used when forking */ - private CommandlineJava javaCmd = new CommandlineJava(); - - // also note MatchingTask grabs source files... - - public AjcTask() { - reset(); - } + private Path srcdir; + private Path injars; + private Path inpath; + private Path classpath; + private Path bootclasspath; + private Path forkclasspath; + private Path extdirs; + private Path aspectpath; + private Path argfiles; + private List ignored; + private Path sourceRoots; + private File xweaveDir; + private String xdoneSignal; + + // ----- added by adapter - integrate better? + private List /* File */adapterFiles; + private String[] adapterArguments; + + private IMessageHolder messageHolder; + private ICommandEditor commandEditor; + + // -------- resource-copying + /** true if copying injar non-.class files to the output jar */ + private boolean copyInjars; + private boolean copyInpath; + + /** non-null if copying all source root files but the filtered ones */ + private String sourceRootCopyFilter; + + /** non-null if copying all inpath dir files but the filtered ones */ + private String inpathDirCopyFilter; + + /** directory sink for classes */ + private File destDir; + + /** zip file sink for classes */ + private File outjar; + + /** track whether we've supplied any temp outjar */ + private boolean outjarFixedup; + + /** + * When possibly copying resources to the output jar, pass ajc a fake output jar to copy from, so we don't change the + * modification time of the output jar when copying injars/inpath into the actual outjar. + */ + private File tmpOutjar; + + private boolean executing; + + /** non-null only while executing in same vm */ + private Main main; + + /** true only when executing in other vm */ + private boolean executingInOtherVM; + + /** true if -incremental */ + private boolean inIncrementalMode; + + /** true if -XincrementalFile (i.e, setTagFile) */ + private boolean inIncrementalFileMode; + + /** log command in non-verbose mode */ + private boolean logCommand; + + /** used when forking */ + private CommandlineJava javaCmd = new CommandlineJava(); + + // also note MatchingTask grabs source files... + + public AjcTask() { + reset(); + } /** to use this same Task more than once (testing) */ - public void reset() { // XXX possible to reset MatchingTask? - // need declare for "all fields initialized in ..." - adapterArguments = null; - adapterFiles = new ArrayList(); - argfiles = null; - executing = false; - aspectpath = null; - bootclasspath = null; - classpath = null; - cmd = new GuardedCommand(); - copyInjars = false; - copyInpath = false; - destDir = DEFAULT_DESTDIR; - executing = false; - executingInOtherVM = false; - extdirs = null; - failonerror = true; // non-standard default - forkclasspath = null; - inIncrementalMode = false; - inIncrementalFileMode = false; - ignored = new ArrayList(); - injars = null; - inpath = null; - listFileArgs = false; - maxMem = null; - messageHolder = null; - outjar = null; - sourceRootCopyFilter = null; - inpathDirCopyFilter = null; - sourceRoots = null; - srcdir = null; - tmpOutjar = null; - verbose = false; - xweaveDir = null; - xdoneSignal = null; - logCommand = false; - javaCmd = new CommandlineJava(); - } - - protected void ignore(String ignored) { - this.ignored.add(ignored + " at " + getLocation()); - } - - //---------------------- option values - - // used by entries with internal commas - protected String validCommaList(String list, List valid, String label) { - return validCommaList(list, valid, label, valid.size()); - } - - protected String validCommaList(String list, List valid, String label, int max) { - StringBuffer result = new StringBuffer(); - StringTokenizer st = new StringTokenizer(list, ","); + public void reset() { // XXX possible to reset MatchingTask? + // need declare for "all fields initialized in ..." + adapterArguments = null; + adapterFiles = new ArrayList(); + argfiles = null; + executing = false; + aspectpath = null; + bootclasspath = null; + classpath = null; + cmd = new GuardedCommand(); + copyInjars = false; + copyInpath = false; + destDir = DEFAULT_DESTDIR; + executing = false; + executingInOtherVM = false; + extdirs = null; + failonerror = true; // non-standard default + forkclasspath = null; + inIncrementalMode = false; + inIncrementalFileMode = false; + ignored = new ArrayList(); + injars = null; + inpath = null; + listFileArgs = false; + maxMem = null; + messageHolder = null; + outjar = null; + sourceRootCopyFilter = null; + inpathDirCopyFilter = null; + sourceRoots = null; + srcdir = null; + tmpOutjar = null; + verbose = false; + xweaveDir = null; + xdoneSignal = null; + logCommand = false; + javaCmd = new CommandlineJava(); + } + + protected void ignore(String ignored) { + this.ignored.add(ignored + " at " + getLocation()); + } + + // ---------------------- option values + + // used by entries with internal commas + protected String validCommaList(String list, List valid, String label) { + return validCommaList(list, valid, label, valid.size()); + } + + protected String validCommaList(String list, List valid, String label, int max) { + StringBuffer result = new StringBuffer(); + StringTokenizer st = new StringTokenizer(list, ","); int num = 0; - while (st.hasMoreTokens()) { + while (st.hasMoreTokens()) { String token = st.nextToken().trim(); num++; if (num > max) { - ignore("too many entries for -" - + label - + ": " - + token); + ignore("too many entries for -" + label + ": " + token); break; } if (!valid.contains(token)) { - ignore("bad commaList entry for -" - + label - + ": " - + token); + ignore("bad commaList entry for -" + label + ": " + token); } else { if (0 < result.length()) { result.append(","); } result.append(token); } - } - return (0 == result.length() ? null : result.toString()); - } - - public void setIncremental(boolean incremental) { - cmd.addFlag("-incremental", incremental); - inIncrementalMode = incremental; - } - - public void setLogCommand(boolean logCommand) { - this.logCommand = logCommand; - } - - public void setHelp(boolean help) { - cmd.addFlag("-help", help); - } - - public void setVersion(boolean version) { - cmd.addFlag("-version", version); - } - - public void setXTerminateAfterCompilation(boolean b) { - cmd.addFlag("-XterminateAfterCompilation", b); - } - - public void setXReweavable(boolean reweavable) { - cmd.addFlag("-Xreweavable",reweavable); - } - - - public void setXJoinpoints(String optionalJoinpoints) { - cmd.addFlag("-Xjoinpoints:"+optionalJoinpoints,true); - } - - public void setCheckRuntimeVersion(boolean b) { - cmd.addFlag("-checkRuntimeVersion:"+b,true); - } - - public void setXNoWeave(boolean b) { - if (logger!=null) logger.warning("the noweave option is no longer required and is being ignored"); - } - - public void setNoWeave(boolean b) { - if (logger!=null) logger.warning("the noweave option is no longer required and is being ignored"); - } - - public void setXNotReweavable(boolean notReweavable) { - cmd.addFlag("-XnotReweavable",notReweavable); - } - - public void setXaddSerialVersionUID(boolean addUID) { - cmd.addFlag("-XaddSerialVersionUID",addUID); - } - - public void setXNoInline(boolean noInline) { - cmd.addFlag("-XnoInline",noInline); - } - - public void setShowWeaveInfo(boolean showweaveinfo) { - cmd.addFlag("-showWeaveInfo",showweaveinfo); - } - - public void setNowarn(boolean nowarn) { - cmd.addFlag("-nowarn", nowarn); - } - - public void setDeprecation(boolean deprecation) { - cmd.addFlag("-deprecation", deprecation); - } - - public void setWarn(String warnings) { - warnings = validCommaList(warnings, VALID_WARNINGS, "warn"); - cmd.addFlag("-warn:" + warnings, (null != warnings)); - } - - public void setDebug(boolean debug) { - cmd.addFlag("-g", debug); - } - - public void setDebugLevel(String level) { - level = validCommaList(level, VALID_DEBUG, "g"); - cmd.addFlag("-g:" + level, (null != level)); - } - - public void setEmacssym(boolean emacssym) { - cmd.addFlag("-emacssym", emacssym); - } - - public void setCrossrefs(boolean on) { - cmd.addFlag("-crossrefs", on); - } - - /** - * -Xlint - set default level of -Xlint messages to warning - * (same as </code>-Xlint:warning</code>) + } + return (0 == result.length() ? null : result.toString()); + } + + public void setIncremental(boolean incremental) { + cmd.addFlag("-incremental", incremental); + inIncrementalMode = incremental; + } + + public void setLogCommand(boolean logCommand) { + this.logCommand = logCommand; + } + + public void setHelp(boolean help) { + cmd.addFlag("-help", help); + } + + public void setVersion(boolean version) { + cmd.addFlag("-version", version); + } + + public void setXTerminateAfterCompilation(boolean b) { + cmd.addFlag("-XterminateAfterCompilation", b); + } + + public void setXReweavable(boolean reweavable) { + cmd.addFlag("-Xreweavable", reweavable); + } + + public void setXJoinpoints(String optionalJoinpoints) { + cmd.addFlag("-Xjoinpoints:" + optionalJoinpoints, true); + } + + public void setCheckRuntimeVersion(boolean b) { + cmd.addFlag("-checkRuntimeVersion:" + b, true); + } + + public void setXNoWeave(boolean b) { + if (logger != null) + logger.warning("the noweave option is no longer required and is being ignored"); + } + + public void setNoWeave(boolean b) { + if (logger != null) + logger.warning("the noweave option is no longer required and is being ignored"); + } + + public void setXNotReweavable(boolean notReweavable) { + cmd.addFlag("-XnotReweavable", notReweavable); + } + + public void setXaddSerialVersionUID(boolean addUID) { + cmd.addFlag("-XaddSerialVersionUID", addUID); + } + + public void setXNoInline(boolean noInline) { + cmd.addFlag("-XnoInline", noInline); + } + + public void setShowWeaveInfo(boolean showweaveinfo) { + cmd.addFlag("-showWeaveInfo", showweaveinfo); + } + + public void setNowarn(boolean nowarn) { + cmd.addFlag("-nowarn", nowarn); + } + + public void setDeprecation(boolean deprecation) { + cmd.addFlag("-deprecation", deprecation); + } + + public void setWarn(String warnings) { + warnings = validCommaList(warnings, VALID_WARNINGS, "warn"); + cmd.addFlag("-warn:" + warnings, (null != warnings)); + } + + public void setDebug(boolean debug) { + cmd.addFlag("-g", debug); + } + + public void setDebugLevel(String level) { + level = validCommaList(level, VALID_DEBUG, "g"); + cmd.addFlag("-g:" + level, (null != level)); + } + + public void setEmacssym(boolean emacssym) { + cmd.addFlag("-emacssym", emacssym); + } + + public void setCrossrefs(boolean on) { + cmd.addFlag("-crossrefs", on); + } + + /** + * -Xlint - set default level of -Xlint messages to warning (same as </code>-Xlint:warning</code>) */ public void setXlintwarnings(boolean xlintwarnings) { - cmd.addFlag("-Xlint", xlintwarnings); + cmd.addFlag("-Xlint", xlintwarnings); } - - /** -Xlint:{error|warning|info} - set default level for -Xlint messages - * @param xlint the String with one of error, warning, ignored + + /** + * -Xlint:{error|warning|info} - set default level for -Xlint messages + * + * @param xlint the String with one of error, warning, ignored */ - public void setXlint(String xlint) { - xlint = validCommaList(xlint, VALID_XLINT, "Xlint", 1); - cmd.addFlag("-Xlint:" + xlint, (null != xlint)); - } - - /** - * -Xlintfile {lint.properties} - enable or disable specific forms - * of -Xlint messages based on a lint properties file - * (default is - * <code>org/aspectj/weaver/XLintDefault.properties</code>) + public void setXlint(String xlint) { + xlint = validCommaList(xlint, VALID_XLINT, "Xlint", 1); + cmd.addFlag("-Xlint:" + xlint, (null != xlint)); + } + + /** + * -Xlintfile {lint.properties} - enable or disable specific forms of -Xlint messages based on a lint properties file (default + * is <code>org/aspectj/weaver/XLintDefault.properties</code>) + * * @param xlintFile the File with lint properties */ - public void setXlintfile(File xlintFile) { - cmd.addFlagged("-Xlintfile", xlintFile.getAbsolutePath()); - } - - public void setPreserveAllLocals(boolean preserveAllLocals) { - cmd.addFlag("-preserveAllLocals", preserveAllLocals); - } - - public void setNoImportError(boolean noImportError) { - cmd.addFlag("-warn:-unusedImport", noImportError); - } - - public void setEncoding(String encoding) { - cmd.addFlagged("-encoding", encoding); - } - - public void setLog(File file) { - cmd.addFlagged("-log", file.getAbsolutePath()); - } - - public void setProceedOnError(boolean proceedOnError) { - cmd.addFlag("-proceedOnError", proceedOnError); - } - - public void setVerbose(boolean verbose) { - cmd.addFlag("-verbose", verbose); - this.verbose = verbose; - } - - public void setListFileArgs(boolean listFileArgs) { - this.listFileArgs = listFileArgs; - } - - public void setReferenceInfo(boolean referenceInfo) { - cmd.addFlag("-referenceInfo", referenceInfo); - } - - public void setTime(boolean time) { - cmd.addFlag("-time", time); - } - - public void setNoExit(boolean noExit) { - cmd.addFlag("-noExit", noExit); - } - - public void setFailonerror(boolean failonerror) { - this.failonerror = failonerror; - } - - /** - * @return true if fork was set - */ - public boolean isForked() { - return fork; - } - - public void setFork(boolean fork) { - this.fork = fork; - } - - public void setMaxmem(String maxMem) { - this.maxMem = maxMem; - } - - /** support for nested <jvmarg> elements */ - public Commandline.Argument createJvmarg() { - return this.javaCmd.createVmArgument(); - } + public void setXlintfile(File xlintFile) { + cmd.addFlagged("-Xlintfile", xlintFile.getAbsolutePath()); + } + + public void setPreserveAllLocals(boolean preserveAllLocals) { + cmd.addFlag("-preserveAllLocals", preserveAllLocals); + } + + public void setNoImportError(boolean noImportError) { + cmd.addFlag("-warn:-unusedImport", noImportError); + } + + public void setEncoding(String encoding) { + cmd.addFlagged("-encoding", encoding); + } + + public void setLog(File file) { + cmd.addFlagged("-log", file.getAbsolutePath()); + } + + public void setProceedOnError(boolean proceedOnError) { + cmd.addFlag("-proceedOnError", proceedOnError); + } + + public void setVerbose(boolean verbose) { + cmd.addFlag("-verbose", verbose); + this.verbose = verbose; + } + + public void setListFileArgs(boolean listFileArgs) { + this.listFileArgs = listFileArgs; + } + + public void setReferenceInfo(boolean referenceInfo) { + cmd.addFlag("-referenceInfo", referenceInfo); + } + + public void setTime(boolean time) { + cmd.addFlag("-time", time); + } + + public void setNoExit(boolean noExit) { + cmd.addFlag("-noExit", noExit); + } + + public void setFailonerror(boolean failonerror) { + this.failonerror = failonerror; + } + + /** + * @return true if fork was set + */ + public boolean isForked() { + return fork; + } + + public void setFork(boolean fork) { + this.fork = fork; + } + + public void setMaxmem(String maxMem) { + this.maxMem = maxMem; + } + + /** support for nested <jvmarg> elements */ + public Commandline.Argument createJvmarg() { + return this.javaCmd.createVmArgument(); + } // ---------------- - public void setTagFile(File file) { - inIncrementalMode = true; - cmd.addFlagged(Main.CommandController.TAG_FILE_OPTION, - file.getAbsolutePath()); - inIncrementalFileMode = true; - } - - public void setOutjar(File file) { - if (DEFAULT_DESTDIR != destDir) { - String e = "specifying both output jar (" - + file - + ") and destination dir (" - + destDir - + ")"; - throw new BuildException(e); - } - outjar = file; - outjarFixedup = false; - tmpOutjar = null; - } - - public void setOutxml(boolean outxml) { - cmd.addFlag("-outxml",outxml); - } - - public void setOutxmlfile(String name) { - cmd.addFlagged("-outxmlfile", name); - } - - public void setDestdir(File dir) { - if (null != outjar) { - String e = "specifying both output jar (" - + outjar - + ") and destination dir (" - + dir - + ")"; - throw new BuildException(e); - } - cmd.addFlagged("-d", dir.getAbsolutePath()); - destDir = dir; - } - - /** - * @param input a String in TARGET_INPUTS - */ - public void setTarget(String input) { - String ignore = cmd.addOption("-target", TARGET_INPUTS, input); - if (null != ignore) { - ignore(ignore); - } - } - - /** - * Language compliance level. - * If not set explicitly, eclipse default holds. - * @param input a String in COMPLIANCE_INPUTS - */ - public void setCompliance(String input) { - String ignore = cmd.addOption(null, COMPLIANCE_INPUTS, input); - if (null != ignore) { - ignore(ignore); - } - } - - /** - * Source compliance level. - * If not set explicitly, eclipse default holds. - * @param input a String in SOURCE_INPUTS - */ - public void setSource(String input) { - String ignore = cmd.addOption("-source", SOURCE_INPUTS, input); - if (null != ignore) { - ignore(ignore); - } - } - /** - * Flag to copy all non-.class contents of injars - * to outjar after compile completes. - * Requires both injars and outjar. - * @param doCopy - */ - public void setCopyInjars(boolean doCopy){ - ignore("copyInJars"); - log("copyInjars not required since 1.1.1.\n", Project.MSG_WARN); - //this.copyInjars = doCopy; - } - - - /** - * Option to copy all files from - * all source root directories - * except those specified here. - * If this is specified and sourceroots are specified, - * then this will copy all files except - * those specified in the filter pattern. - * Requires sourceroots. - * - * @param filter a String acceptable as an excludes - * filter for an Ant Zip fileset. - */ - public void setSourceRootCopyFilter(String filter){ - this.sourceRootCopyFilter = filter; - } - /** - * Option to copy all files from - * all inpath directories - * except the files specified here. - * If this is specified and inpath directories are specified, - * then this will copy all files except - * those specified in the filter pattern. - * Requires inpath. - * If the input does not contain "**\/*.class", then - * this prepends it, to avoid overwriting woven classes - * with unwoven input. - * @param filter a String acceptable as an excludes - * filter for an Ant Zip fileset. - */ - public void setInpathDirCopyFilter(String filter){ - if (null != filter) { - if (-1 == filter.indexOf("**/*.class")) { - filter = "**/*.class," + filter; - } - } - this.inpathDirCopyFilter = filter; - } - - public void setX(String input) { // ajc-only eajc-also docDone - StringTokenizer tokens = new StringTokenizer(input, ",", false); - while (tokens.hasMoreTokens()) { - String token = tokens.nextToken().trim(); - if (1 < token.length()) { - // new special case: allow -Xset:anything - if (VALID_XOPTIONS.contains(token) || token.indexOf("set:")==0 || - token.indexOf("joinpoints:")==0) { - cmd.addFlag("-X" + token, true); - } else { - ignore("-X" + token); - } - } - } - } - - public void setXDoneSignal(String doneSignal) { - this.xdoneSignal = doneSignal; - } - - /** direct API for testing */ - public void setMessageHolder(IMessageHolder holder) { - this.messageHolder = holder; - } - - /** - * Setup custom message handling. - * @param className the String fully-qualified-name of a class - * reachable from this object's class loader, - * implementing IMessageHolder, and - * having a public no-argument constructor. - * @throws BuildException if unable to create instance of className - */ - public void setMessageHolderClass(String className) { - try { - Class mclass = Class.forName(className); - IMessageHolder holder = (IMessageHolder) mclass.newInstance(); - setMessageHolder(holder); - } catch (Throwable t) { - String m = "unable to instantiate message holder: " + className; - throw new BuildException(m, t); - } - } - - /** direct API for testing */ - public void setCommandEditor(ICommandEditor editor) { - this.commandEditor = editor; - } - - /** - * Setup command-line filter. - * To do this staticly, define the environment variable - * <code>org.aspectj.tools.ant.taskdefs.AjcTask.COMMAND_EDITOR</code> - * with the <code>className</code> parameter. - * @param className the String fully-qualified-name of a class - * reachable from this object's class loader, - * implementing ICommandEditor, and - * having a public no-argument constructor. - * @throws BuildException if unable to create instance of className - */ - public void setCommandEditorClass(String className) { // skip Ant interface? - try { - Class mclass = Class.forName(className); - setCommandEditor((ICommandEditor) mclass.newInstance()); - } catch (Throwable t) { - String m = "unable to instantiate command editor: " + className; - throw new BuildException(m, t); - } - } - //---------------------- Path lists - - /** - * Add path elements to source path and return result. - * Elements are added even if they do not exist. - * @param source the Path to add to - may be null - * @param toAdd the Path to add - may be null - * @return the (never-null) Path that results - */ - protected Path incPath(Path source, Path toAdd) { - if (null == source) { - source = new Path(project); - } - if (null != toAdd) { - source.append(toAdd); - } - return source; - } - - public void setSourcerootsref(Reference ref) { - createSourceRoots().setRefid(ref); - } - - public void setSourceRoots(Path roots) { - sourceRoots = incPath(sourceRoots, roots); - } - - public Path createSourceRoots() { - if (sourceRoots == null) { - sourceRoots = new Path(project); - } - return sourceRoots.createPath(); - } - - public void setXWeaveDir(File file) { - if ((null != file) && file.isDirectory() - && file.canRead()) { - xweaveDir = file; - } - } - - public void setInjarsref(Reference ref) { - createInjars().setRefid(ref); - } - - public void setInpathref(Reference ref) { - createInpath().setRefid(ref); - } - - public void setInjars(Path path) { - injars = incPath(injars, path); - } - - public void setInpath(Path path) { - inpath = incPath(inpath,path); - } - - public Path createInjars() { - if (injars == null) { - injars = new Path(project); - } - return injars.createPath(); - } - - public Path createInpath() { - if (inpath == null) { - inpath = new Path(project); - } - return inpath.createPath(); - } - - public void setClasspath(Path path) { - classpath = incPath(classpath, path); - } - - public void setClasspathref(Reference classpathref) { - createClasspath().setRefid(classpathref); - } - - public Path createClasspath() { - if (classpath == null) { - classpath = new Path(project); - } - return classpath.createPath(); - } - - public void setBootclasspath(Path path) { - bootclasspath = incPath(bootclasspath, path); - } - - public void setBootclasspathref(Reference bootclasspathref) { - createBootclasspath().setRefid(bootclasspathref); - } - - public Path createBootclasspath() { - if (bootclasspath == null) { - bootclasspath = new Path(project); - } - return bootclasspath.createPath(); - } - - public void setForkclasspath(Path path) { - forkclasspath = incPath(forkclasspath, path); - } - - public void setForkclasspathref(Reference forkclasspathref) { - createForkclasspath().setRefid(forkclasspathref); - } - - public Path createForkclasspath() { - if (forkclasspath == null) { - forkclasspath = new Path(project); - } - return forkclasspath.createPath(); - } - - public void setExtdirs(Path path) { - extdirs = incPath(extdirs, path); - } - - public void setExtdirsref(Reference ref) { - createExtdirs().setRefid(ref); - } - - public Path createExtdirs() { - if (extdirs == null) { - extdirs = new Path(project); - } - return extdirs.createPath(); - } - - - public void setAspectpathref(Reference ref) { - createAspectpath().setRefid(ref); - } - - public void setAspectpath(Path path) { - aspectpath = incPath(aspectpath, path); - } - - public Path createAspectpath() { - if (aspectpath == null) { - aspectpath = new Path(project); - } - return aspectpath.createPath(); - } - - public void setSrcDir(Path path) { - srcdir = incPath(srcdir, path); - } - - public Path createSrc() { - return createSrcdir(); - } - - public Path createSrcdir() { - if (srcdir == null) { - srcdir = new Path(project); - } - return srcdir.createPath(); - } - - /** @return true if in incremental mode (command-line or file) */ - public boolean isInIncrementalMode() { - return inIncrementalMode; - } - - /** @return true if in incremental file mode */ - public boolean isInIncrementalFileMode() { - return inIncrementalFileMode; - } - - public void setArgfilesref(Reference ref) { - createArgfiles().setRefid(ref); - } - - public void setArgfiles(Path path) { // ajc-only eajc-also docDone - argfiles = incPath(argfiles, path); - } - - public Path createArgfiles() { - if (argfiles == null) { - argfiles = new Path(project); - } - return argfiles.createPath(); - } - - // ------------------------------ run - - /** - * Compile using ajc per settings. - * @exception BuildException if the compilation has problems - * or if there were compiler errors and failonerror is true. - */ - public void execute() throws BuildException { - this.logger = new TaskLogger(this); - if (executing) { - throw new IllegalStateException("already executing"); - } else { - executing = true; - } - setupOptions(); - verifyOptions(); - try { - String[] args = makeCommand(); - if (logCommand) { - log("ajc " + Arrays.asList(args)); - } else { - logVerbose("ajc " + Arrays.asList(args)); - } - if (!fork) { - executeInSameVM(args); - } else { // when forking, Adapter handles failonerror - executeInOtherVM(args); - } - } catch (BuildException e) { - throw e; - } catch (Throwable x) { - this.logger.error(Main.renderExceptionForUser(x)); - throw new BuildException("IGNORE -- See " - + LangUtil.unqualifiedClassName(x) - + " rendered to ant logger"); - } finally { - executing = false; - if (null != tmpOutjar) { - tmpOutjar.delete(); - } - } - } - - /** - * Halt processing. - * This tells main in the same vm to quit. - * It fails when running in forked mode. - * @return true if not in forked mode - * and main has quit or been told to quit - */ - public boolean quit() { - if (executingInOtherVM) { - return false; - } - Main me = main; - if (null != me) { - me.quit(); - } - return true; - } - - // package-private for testing - String[] makeCommand() { - ArrayList result = new ArrayList(); - if (0 < ignored.size()) { - for (Iterator iter = ignored.iterator(); iter.hasNext();) { - logVerbose("ignored: " + iter.next()); - } - } - // when copying resources, use temp jar for class output - // then copy temp jar contents and resources to output jar - if ((null != outjar) && !outjarFixedup) { - if (copyInjars || copyInpath || (null != sourceRootCopyFilter) - || (null != inpathDirCopyFilter)) { - String path = outjar.getAbsolutePath(); - int len = FileUtil.zipSuffixLength(path); - path = path.substring(0, path.length()-len) + ".tmp.jar"; - tmpOutjar = new File(path); - } - if (null == tmpOutjar) { - cmd.addFlagged("-outjar", outjar.getAbsolutePath()); - } else { - cmd.addFlagged("-outjar", tmpOutjar.getAbsolutePath()); - } - outjarFixedup = true; - } - - result.addAll(cmd.extractArguments()); - addListArgs(result); - - String[] command = (String[]) result.toArray(new String[0]); - if (null != commandEditor) { - command = commandEditor.editCommand(command); - } else if (null != COMMAND_EDITOR) { - command = COMMAND_EDITOR.editCommand(command); - } - return command; - } - - /** - * Create any pseudo-options required to implement - * some of the macro options - * @throws BuildException if options conflict - */ - protected void setupOptions() { - if (null != xweaveDir) { - if (DEFAULT_DESTDIR != destDir) { - throw new BuildException("weaveDir forces destdir"); - } - if (null != outjar) { - throw new BuildException("weaveDir forces outjar"); - } - if (null != injars) { - throw new BuildException("weaveDir incompatible with injars now"); - } - if (null != inpath) { - throw new BuildException("weaveDir incompatible with inpath now"); - } - - File injar = zipDirectory(xweaveDir); - setInjars(new Path(getProject(), injar.getAbsolutePath())); - setDestdir(xweaveDir); - } - } - - protected File zipDirectory(File dir) { - File tempDir = new File("."); - try { - tempDir = File.createTempFile("AjcTest", ".tmp"); - tempDir.mkdirs(); - tempDir.deleteOnExit(); // XXX remove zip explicitly.. - } catch (IOException e) { - // ignore - } -// File result = new File(tempDir, - String filename = "AjcTask-" - + System.currentTimeMillis() - + ".zip"; - File result = new File(filename); - Zip zip = new Zip(); - zip.setProject(getProject()); - zip.setDestFile(result); - zip.setTaskName(getTaskName() + " - zip"); - FileSet fileset = new FileSet(); - fileset.setDir(dir); - zip.addFileset(fileset); - zip.execute(); - Delete delete = new Delete(); - delete.setProject(getProject()); - delete.setTaskName(getTaskName() + " - delete"); - delete.setDir(dir); - delete.execute(); - Mkdir mkdir = new Mkdir(); - mkdir.setProject(getProject()); - mkdir.setTaskName(getTaskName() + " - mkdir"); - mkdir.setDir(dir); - mkdir.execute(); - return result; - } - - /** - * @throw BuildException if options conflict - */ - protected void verifyOptions() { - StringBuffer sb = new StringBuffer(); - if (fork && isInIncrementalMode() && !isInIncrementalFileMode()) { - sb.append("can fork incremental only using tag file.\n"); - } - if (((null != inpathDirCopyFilter) || (null != sourceRootCopyFilter)) - && (null == outjar) && (DEFAULT_DESTDIR == destDir)) { - final String REQ = " requires dest dir or output jar.\n"; - if (null == inpathDirCopyFilter) { - sb.append("sourceRootCopyFilter"); - } else if (null == sourceRootCopyFilter) { - sb.append("inpathDirCopyFilter"); - } else { - sb.append("sourceRootCopyFilter and inpathDirCopyFilter"); - } - sb.append(REQ); - } - if (0 < sb.length()) { - throw new BuildException(sb.toString()); - } - } - - /** - * Run the compile in the same VM by - * loading the compiler (Main), - * setting up any message holders, - * doing the compile, - * and converting abort/failure and error messages - * to BuildException, as appropriate. - * @throws BuildException if abort or failure messages - * or if errors and failonerror. - * - */ - protected void executeInSameVM(String[] args) { - if (null != maxMem) { - log("maxMem ignored unless forked: " + maxMem, Project.MSG_WARN); - } - IMessageHolder holder = messageHolder; - int numPreviousErrors; - if (null == holder) { - MessageHandler mhandler = new MessageHandler(true); + public void setTagFile(File file) { + inIncrementalMode = true; + cmd.addFlagged(Main.CommandController.TAG_FILE_OPTION, file.getAbsolutePath()); + inIncrementalFileMode = true; + } + + public void setOutjar(File file) { + if (DEFAULT_DESTDIR != destDir) { + String e = "specifying both output jar (" + file + ") and destination dir (" + destDir + ")"; + throw new BuildException(e); + } + outjar = file; + outjarFixedup = false; + tmpOutjar = null; + } + + public void setOutxml(boolean outxml) { + cmd.addFlag("-outxml", outxml); + } + + public void setOutxmlfile(String name) { + cmd.addFlagged("-outxmlfile", name); + } + + public void setDestdir(File dir) { + if (null != outjar) { + String e = "specifying both output jar (" + outjar + ") and destination dir (" + dir + ")"; + throw new BuildException(e); + } + cmd.addFlagged("-d", dir.getAbsolutePath()); + destDir = dir; + } + + /** + * @param input a String in TARGET_INPUTS + */ + public void setTarget(String input) { + String ignore = cmd.addOption("-target", TARGET_INPUTS, input); + if (null != ignore) { + ignore(ignore); + } + } + + /** + * Language compliance level. If not set explicitly, eclipse default holds. + * + * @param input a String in COMPLIANCE_INPUTS + */ + public void setCompliance(String input) { + String ignore = cmd.addOption(null, COMPLIANCE_INPUTS, input); + if (null != ignore) { + ignore(ignore); + } + } + + /** + * Source compliance level. If not set explicitly, eclipse default holds. + * + * @param input a String in SOURCE_INPUTS + */ + public void setSource(String input) { + String ignore = cmd.addOption("-source", SOURCE_INPUTS, input); + if (null != ignore) { + ignore(ignore); + } + } + + /** + * Flag to copy all non-.class contents of injars to outjar after compile completes. Requires both injars and outjar. + * + * @param doCopy + */ + public void setCopyInjars(boolean doCopy) { + ignore("copyInJars"); + log("copyInjars not required since 1.1.1.\n", Project.MSG_WARN); + // this.copyInjars = doCopy; + } + + /** + * Option to copy all files from all source root directories except those specified here. If this is specified and sourceroots + * are specified, then this will copy all files except those specified in the filter pattern. Requires sourceroots. + * + * @param filter a String acceptable as an excludes filter for an Ant Zip fileset. + */ + public void setSourceRootCopyFilter(String filter) { + this.sourceRootCopyFilter = filter; + } + + /** + * Option to copy all files from all inpath directories except the files specified here. If this is specified and inpath + * directories are specified, then this will copy all files except those specified in the filter pattern. Requires inpath. If + * the input does not contain "**\/*.class", then this prepends it, to avoid overwriting woven classes with unwoven input. + * + * @param filter a String acceptable as an excludes filter for an Ant Zip fileset. + */ + public void setInpathDirCopyFilter(String filter) { + if (null != filter) { + if (-1 == filter.indexOf("**/*.class")) { + filter = "**/*.class," + filter; + } + } + this.inpathDirCopyFilter = filter; + } + + public void setX(String input) { // ajc-only eajc-also docDone + StringTokenizer tokens = new StringTokenizer(input, ",", false); + while (tokens.hasMoreTokens()) { + String token = tokens.nextToken().trim(); + if (1 < token.length()) { + // new special case: allow -Xset:anything + if (VALID_XOPTIONS.contains(token) || token.indexOf("set:") == 0 || token.indexOf("joinpoints:") == 0) { + cmd.addFlag("-X" + token, true); + } else { + ignore("-X" + token); + } + } + } + } + + public void setXDoneSignal(String doneSignal) { + this.xdoneSignal = doneSignal; + } + + /** direct API for testing */ + public void setMessageHolder(IMessageHolder holder) { + this.messageHolder = holder; + } + + /** + * Setup custom message handling. + * + * @param className the String fully-qualified-name of a class reachable from this object's class loader, implementing + * IMessageHolder, and having a public no-argument constructor. + * @throws BuildException if unable to create instance of className + */ + public void setMessageHolderClass(String className) { + try { + Class mclass = Class.forName(className); + IMessageHolder holder = (IMessageHolder) mclass.newInstance(); + setMessageHolder(holder); + } catch (Throwable t) { + String m = "unable to instantiate message holder: " + className; + throw new BuildException(m, t); + } + } + + /** direct API for testing */ + public void setCommandEditor(ICommandEditor editor) { + this.commandEditor = editor; + } + + /** + * Setup command-line filter. To do this staticly, define the environment variable + * <code>org.aspectj.tools.ant.taskdefs.AjcTask.COMMAND_EDITOR</code> with the <code>className</code> parameter. + * + * @param className the String fully-qualified-name of a class reachable from this object's class loader, implementing + * ICommandEditor, and having a public no-argument constructor. + * @throws BuildException if unable to create instance of className + */ + public void setCommandEditorClass(String className) { // skip Ant interface? + try { + Class mclass = Class.forName(className); + setCommandEditor((ICommandEditor) mclass.newInstance()); + } catch (Throwable t) { + String m = "unable to instantiate command editor: " + className; + throw new BuildException(m, t); + } + } + + // ---------------------- Path lists + + /** + * Add path elements to source path and return result. Elements are added even if they do not exist. + * + * @param source the Path to add to - may be null + * @param toAdd the Path to add - may be null + * @return the (never-null) Path that results + */ + protected Path incPath(Path source, Path toAdd) { + if (null == source) { + source = new Path(project); + } + if (null != toAdd) { + source.append(toAdd); + } + return source; + } + + public void setSourcerootsref(Reference ref) { + createSourceRoots().setRefid(ref); + } + + public void setSourceRoots(Path roots) { + sourceRoots = incPath(sourceRoots, roots); + } + + public Path createSourceRoots() { + if (sourceRoots == null) { + sourceRoots = new Path(project); + } + return sourceRoots.createPath(); + } + + public void setXWeaveDir(File file) { + if ((null != file) && file.isDirectory() && file.canRead()) { + xweaveDir = file; + } + } + + public void setInjarsref(Reference ref) { + createInjars().setRefid(ref); + } + + public void setInpathref(Reference ref) { + createInpath().setRefid(ref); + } + + public void setInjars(Path path) { + injars = incPath(injars, path); + } + + public void setInpath(Path path) { + inpath = incPath(inpath, path); + } + + public Path createInjars() { + if (injars == null) { + injars = new Path(project); + } + return injars.createPath(); + } + + public Path createInpath() { + if (inpath == null) { + inpath = new Path(project); + } + return inpath.createPath(); + } + + public void setClasspath(Path path) { + classpath = incPath(classpath, path); + } + + public void setClasspathref(Reference classpathref) { + createClasspath().setRefid(classpathref); + } + + public Path createClasspath() { + if (classpath == null) { + classpath = new Path(project); + } + return classpath.createPath(); + } + + public void setBootclasspath(Path path) { + bootclasspath = incPath(bootclasspath, path); + } + + public void setBootclasspathref(Reference bootclasspathref) { + createBootclasspath().setRefid(bootclasspathref); + } + + public Path createBootclasspath() { + if (bootclasspath == null) { + bootclasspath = new Path(project); + } + return bootclasspath.createPath(); + } + + public void setForkclasspath(Path path) { + forkclasspath = incPath(forkclasspath, path); + } + + public void setForkclasspathref(Reference forkclasspathref) { + createForkclasspath().setRefid(forkclasspathref); + } + + public Path createForkclasspath() { + if (forkclasspath == null) { + forkclasspath = new Path(project); + } + return forkclasspath.createPath(); + } + + public void setExtdirs(Path path) { + extdirs = incPath(extdirs, path); + } + + public void setExtdirsref(Reference ref) { + createExtdirs().setRefid(ref); + } + + public Path createExtdirs() { + if (extdirs == null) { + extdirs = new Path(project); + } + return extdirs.createPath(); + } + + public void setAspectpathref(Reference ref) { + createAspectpath().setRefid(ref); + } + + public void setAspectpath(Path path) { + aspectpath = incPath(aspectpath, path); + } + + public Path createAspectpath() { + if (aspectpath == null) { + aspectpath = new Path(project); + } + return aspectpath.createPath(); + } + + public void setSrcDir(Path path) { + srcdir = incPath(srcdir, path); + } + + public Path createSrc() { + return createSrcdir(); + } + + public Path createSrcdir() { + if (srcdir == null) { + srcdir = new Path(project); + } + return srcdir.createPath(); + } + + /** @return true if in incremental mode (command-line or file) */ + public boolean isInIncrementalMode() { + return inIncrementalMode; + } + + /** @return true if in incremental file mode */ + public boolean isInIncrementalFileMode() { + return inIncrementalFileMode; + } + + public void setArgfilesref(Reference ref) { + createArgfiles().setRefid(ref); + } + + public void setArgfiles(Path path) { // ajc-only eajc-also docDone + argfiles = incPath(argfiles, path); + } + + public Path createArgfiles() { + if (argfiles == null) { + argfiles = new Path(project); + } + return argfiles.createPath(); + } + + // ------------------------------ run + + /** + * Compile using ajc per settings. + * + * @exception BuildException if the compilation has problems or if there were compiler errors and failonerror is true. + */ + public void execute() throws BuildException { + this.logger = new TaskLogger(this); + if (executing) { + throw new IllegalStateException("already executing"); + } else { + executing = true; + } + setupOptions(); + verifyOptions(); + try { + String[] args = makeCommand(); + if (logCommand) { + log("ajc " + Arrays.asList(args)); + } else { + logVerbose("ajc " + Arrays.asList(args)); + } + if (!fork) { + executeInSameVM(args); + } else { // when forking, Adapter handles failonerror + executeInOtherVM(args); + } + } catch (BuildException e) { + throw e; + } catch (Throwable x) { + this.logger.error(Main.renderExceptionForUser(x)); + throw new BuildException("IGNORE -- See " + LangUtil.unqualifiedClassName(x) + " rendered to ant logger"); + } finally { + executing = false; + if (null != tmpOutjar) { + tmpOutjar.delete(); + } + } + } + + /** + * Halt processing. This tells main in the same vm to quit. It fails when running in forked mode. + * + * @return true if not in forked mode and main has quit or been told to quit + */ + public boolean quit() { + if (executingInOtherVM) { + return false; + } + Main me = main; + if (null != me) { + me.quit(); + } + return true; + } + + // package-private for testing + String[] makeCommand() { + ArrayList result = new ArrayList(); + if (0 < ignored.size()) { + for (Iterator iter = ignored.iterator(); iter.hasNext();) { + logVerbose("ignored: " + iter.next()); + } + } + // when copying resources, use temp jar for class output + // then copy temp jar contents and resources to output jar + if ((null != outjar) && !outjarFixedup) { + if (copyInjars || copyInpath || (null != sourceRootCopyFilter) || (null != inpathDirCopyFilter)) { + String path = outjar.getAbsolutePath(); + int len = FileUtil.zipSuffixLength(path); + path = path.substring(0, path.length() - len) + ".tmp.jar"; + tmpOutjar = new File(path); + } + if (null == tmpOutjar) { + cmd.addFlagged("-outjar", outjar.getAbsolutePath()); + } else { + cmd.addFlagged("-outjar", tmpOutjar.getAbsolutePath()); + } + outjarFixedup = true; + } + + result.addAll(cmd.extractArguments()); + addListArgs(result); + + String[] command = (String[]) result.toArray(new String[0]); + if (null != commandEditor) { + command = commandEditor.editCommand(command); + } else if (null != COMMAND_EDITOR) { + command = COMMAND_EDITOR.editCommand(command); + } + return command; + } + + /** + * Create any pseudo-options required to implement some of the macro options + * + * @throws BuildException if options conflict + */ + protected void setupOptions() { + if (null != xweaveDir) { + if (DEFAULT_DESTDIR != destDir) { + throw new BuildException("weaveDir forces destdir"); + } + if (null != outjar) { + throw new BuildException("weaveDir forces outjar"); + } + if (null != injars) { + throw new BuildException("weaveDir incompatible with injars now"); + } + if (null != inpath) { + throw new BuildException("weaveDir incompatible with inpath now"); + } + + File injar = zipDirectory(xweaveDir); + setInjars(new Path(getProject(), injar.getAbsolutePath())); + setDestdir(xweaveDir); + } + } + + protected File zipDirectory(File dir) { + File tempDir = new File("."); + try { + tempDir = File.createTempFile("AjcTest", ".tmp"); + tempDir.mkdirs(); + tempDir.deleteOnExit(); // XXX remove zip explicitly.. + } catch (IOException e) { + // ignore + } + // File result = new File(tempDir, + String filename = "AjcTask-" + System.currentTimeMillis() + ".zip"; + File result = new File(filename); + Zip zip = new Zip(); + zip.setProject(getProject()); + zip.setDestFile(result); + zip.setTaskName(getTaskName() + " - zip"); + FileSet fileset = new FileSet(); + fileset.setDir(dir); + zip.addFileset(fileset); + zip.execute(); + Delete delete = new Delete(); + delete.setProject(getProject()); + delete.setTaskName(getTaskName() + " - delete"); + delete.setDir(dir); + delete.execute(); + Mkdir mkdir = new Mkdir(); + mkdir.setProject(getProject()); + mkdir.setTaskName(getTaskName() + " - mkdir"); + mkdir.setDir(dir); + mkdir.execute(); + return result; + } + + /** + * @throw BuildException if options conflict + */ + protected void verifyOptions() { + StringBuffer sb = new StringBuffer(); + if (fork && isInIncrementalMode() && !isInIncrementalFileMode()) { + sb.append("can fork incremental only using tag file.\n"); + } + if (((null != inpathDirCopyFilter) || (null != sourceRootCopyFilter)) && (null == outjar) && (DEFAULT_DESTDIR == destDir)) { + final String REQ = " requires dest dir or output jar.\n"; + if (null == inpathDirCopyFilter) { + sb.append("sourceRootCopyFilter"); + } else if (null == sourceRootCopyFilter) { + sb.append("inpathDirCopyFilter"); + } else { + sb.append("sourceRootCopyFilter and inpathDirCopyFilter"); + } + sb.append(REQ); + } + if (0 < sb.length()) { + throw new BuildException(sb.toString()); + } + } + + /** + * Run the compile in the same VM by loading the compiler (Main), setting up any message holders, doing the compile, and + * converting abort/failure and error messages to BuildException, as appropriate. + * + * @throws BuildException if abort or failure messages or if errors and failonerror. + * + */ + protected void executeInSameVM(String[] args) { + if (null != maxMem) { + log("maxMem ignored unless forked: " + maxMem, Project.MSG_WARN); + } + IMessageHolder holder = messageHolder; + int numPreviousErrors; + if (null == holder) { + MessageHandler mhandler = new MessageHandler(true); final IMessageHandler delegate; - delegate = new AntMessageHandler(this.logger,this.verbose, false); - mhandler.setInterceptor(delegate); - holder = mhandler; - numPreviousErrors = 0; - } else { - numPreviousErrors = holder.numMessages(IMessage.ERROR, true); - } - { - Main newmain = new Main(); - newmain.setHolder(holder); - newmain.setCompletionRunner(new Runnable() { - public void run() { - doCompletionTasks(); - } - }); - if (null != main) { - MessageUtil.fail(holder, "still running prior main"); - return; - } - main = newmain; - } - main.runMain(args, false); - if (failonerror) { - int errs = holder.numMessages(IMessage.ERROR, false); - errs -= numPreviousErrors; - if (0 < errs) { - String m = errs + " errors"; - MessageUtil.print(System.err, holder, "", MessageUtil.MESSAGE_ALL, MessageUtil.PICK_ERROR, true); - throw new BuildException(m); - } - } - // Throw BuildException if there are any fail or abort - // messages. - // The BuildException message text has a list of class names - // for the exceptions found in the messages, or the - // number of fail/abort messages found if there were - // no exceptions for any of the fail/abort messages. - // The interceptor message handler should have already - // printed the messages, including any stack traces. - // HACK: this ignores the Usage message - { - IMessage[] fails = holder.getMessages(IMessage.FAIL, true); - if (!LangUtil.isEmpty(fails)) { - StringBuffer sb = new StringBuffer(); - String prefix = "fail due to "; - int numThrown = 0; - for (int i = 0; i < fails.length; i++) { - String message = fails[i].getMessage(); - if (LangUtil.isEmpty(message)) { - message = "<no message>"; - } else if (-1 != message.indexOf(USAGE_SUBSTRING)) { - continue; - } - Throwable t = fails[i].getThrown(); - if (null != t) { - numThrown++; - sb.append(prefix); - sb.append(LangUtil.unqualifiedClassName(t.getClass())); - String thrownMessage = t.getMessage(); - if (!LangUtil.isEmpty(thrownMessage)) { - sb.append(" \"" + thrownMessage + "\""); - } - } - sb.append("\"" + message + "\""); - prefix = ", "; - } - if (0 < sb.length()) { - sb.append(" (" + numThrown + " exceptions)"); - throw new BuildException(sb.toString()); - } - } - } - } - - /** - * Execute in a separate VM. - * Differences from normal same-VM execution: - * <ul> - * <li>ignores any message holder {class} set</li> - * <li>No resource-copying between interative runs</li> - * <li>failonerror fails when process interface fails - * to return negative values</li> - * </ul> - * @param args String[] of the complete compiler command to execute - * - * @see DefaultCompilerAdapter#executeExternalCompile(String[], int) - * @throws BuildException if ajc aborts (negative value) - * or if failonerror and there were compile errors. - */ - protected void executeInOtherVM(String[] args) { - javaCmd.setClassname(org.aspectj.tools.ajc.Main.class.getName()); - - final Path vmClasspath = javaCmd.createClasspath(getProject()); - { - File aspectjtools = null; - int vmClasspathSize = vmClasspath.size(); - if ((null != forkclasspath) - && (0 != forkclasspath.size())) { - vmClasspath.addExisting(forkclasspath); - } else { - aspectjtools = findAspectjtoolsJar(); - if (null != aspectjtools) { - vmClasspath.createPathElement().setLocation(aspectjtools); - } - } - int newVmClasspathSize = vmClasspath.size(); - if (vmClasspathSize == newVmClasspathSize) { - String m = "unable to find aspectjtools to fork - "; - if (null != aspectjtools) { - m += "tried " + aspectjtools.toString(); - } else if (null != forkclasspath) { - m += "tried " + forkclasspath.toString(); - } else { - m += "define forkclasspath or put aspectjtools on classpath"; - } - throw new BuildException(m); - } - } - if (null != maxMem) { - javaCmd.setMaxmemory(maxMem); - } - File tempFile = null; - int numArgs = args.length; - args = GuardedCommand.limitTo(args, MAX_COMMANDLINE, getLocation()); - - if (args.length != numArgs) { - tempFile = new File(args[1]); - } - try { - boolean setMessageHolderOnForking = (this.messageHolder != null); - String[] javaArgs = javaCmd.getCommandline(); - String[] both = new String[javaArgs.length + args.length + (setMessageHolderOnForking ? 2 : 0)]; - System.arraycopy(javaArgs,0,both,0,javaArgs.length); - System.arraycopy(args,0,both,javaArgs.length,args.length); - if (setMessageHolderOnForking) { - both[both.length - 2] = "-messageHolder"; - both[both.length - 1] = this.messageHolder.getClass().getName(); - } - // try to use javaw instead on windows - if (both[0].endsWith("java.exe")) { - String path = both[0]; - path = path.substring(0, path.length()-4); - path = path + "w.exe"; - File javaw = new File(path); - if (javaw.canRead() && javaw.isFile()) { - both[0] = path; - } - } - logVerbose("forking " + Arrays.asList(both)); - int result = execInOtherVM(both); - if (0 > result) { - throw new BuildException("failure[" + result + "] running ajc"); - } else if (failonerror && (0 < result)) { - throw new BuildException("compile errors: " + result); - } - // when forking, do completion only at end and when successful - doCompletionTasks(); - } finally { - if (null != tempFile) { - tempFile.delete(); - } - } - } - - /** - * Execute in another process using the same JDK - * and the base directory of the project. XXX correct? - * @param args - * @return - */ - protected int execInOtherVM(String[] args) { - try { - - Project project = getProject(); - PumpStreamHandler handler = new LogStreamHandler(this, - verbose ? Project.MSG_VERBOSE : Project.MSG_INFO, - Project.MSG_WARN); - -// replace above two lines with what follows as an aid to debugging when running the unit tests.... -// LogStreamHandler handler = new LogStreamHandler(this, -// Project.MSG_INFO, Project.MSG_WARN) { -// -// ByteArrayOutputStream baos = new ByteArrayOutputStream(); -// /* (non-Javadoc) -// * @see org.apache.tools.ant.taskdefs.PumpStreamHandler#createProcessOutputPump(java.io.InputStream, java.io.OutputStream) -// */ -// protected void createProcessErrorPump(InputStream is, -// OutputStream os) { -// super.createProcessErrorPump(is, baos); -// } -// -// /* (non-Javadoc) -// * @see org.apache.tools.ant.taskdefs.LogStreamHandler#stop() -// */ -// public void stop() { -// byte[] written = baos.toByteArray(); -// System.err.print(new String(written)); -// super.stop(); -// } -// }; + delegate = new AntMessageHandler(this.logger, this.verbose, false); + mhandler.setInterceptor(delegate); + holder = mhandler; + numPreviousErrors = 0; + } else { + numPreviousErrors = holder.numMessages(IMessage.ERROR, true); + } + { + Main newmain = new Main(); + newmain.setHolder(holder); + newmain.setCompletionRunner(new Runnable() { + public void run() { + doCompletionTasks(); + } + }); + if (null != main) { + MessageUtil.fail(holder, "still running prior main"); + return; + } + main = newmain; + } + main.runMain(args, false); + if (failonerror) { + int errs = holder.numMessages(IMessage.ERROR, false); + errs -= numPreviousErrors; + if (0 < errs) { + String m = errs + " errors"; + MessageUtil.print(System.err, holder, "", MessageUtil.MESSAGE_ALL, MessageUtil.PICK_ERROR, true); + throw new BuildException(m); + } + } + // Throw BuildException if there are any fail or abort + // messages. + // The BuildException message text has a list of class names + // for the exceptions found in the messages, or the + // number of fail/abort messages found if there were + // no exceptions for any of the fail/abort messages. + // The interceptor message handler should have already + // printed the messages, including any stack traces. + // HACK: this ignores the Usage message + { + IMessage[] fails = holder.getMessages(IMessage.FAIL, true); + if (!LangUtil.isEmpty(fails)) { + StringBuffer sb = new StringBuffer(); + String prefix = "fail due to "; + int numThrown = 0; + for (int i = 0; i < fails.length; i++) { + String message = fails[i].getMessage(); + if (LangUtil.isEmpty(message)) { + message = "<no message>"; + } else if (-1 != message.indexOf(USAGE_SUBSTRING)) { + continue; + } + Throwable t = fails[i].getThrown(); + if (null != t) { + numThrown++; + sb.append(prefix); + sb.append(LangUtil.unqualifiedClassName(t.getClass())); + String thrownMessage = t.getMessage(); + if (!LangUtil.isEmpty(thrownMessage)) { + sb.append(" \"" + thrownMessage + "\""); + } + } + sb.append("\"" + message + "\""); + prefix = ", "; + } + if (0 < sb.length()) { + sb.append(" (" + numThrown + " exceptions)"); + throw new BuildException(sb.toString()); + } + } + } + } + + /** + * Execute in a separate VM. Differences from normal same-VM execution: + * <ul> + * <li>ignores any message holder {class} set</li> + * <li>No resource-copying between interative runs</li> + * <li>failonerror fails when process interface fails to return negative values</li> + * </ul> + * + * @param args String[] of the complete compiler command to execute + * + * @see DefaultCompilerAdapter#executeExternalCompile(String[], int) + * @throws BuildException if ajc aborts (negative value) or if failonerror and there were compile errors. + */ + protected void executeInOtherVM(String[] args) { + javaCmd.setClassname(org.aspectj.tools.ajc.Main.class.getName()); + + final Path vmClasspath = javaCmd.createClasspath(getProject()); + { + File aspectjtools = null; + int vmClasspathSize = vmClasspath.size(); + if ((null != forkclasspath) && (0 != forkclasspath.size())) { + vmClasspath.addExisting(forkclasspath); + } else { + aspectjtools = findAspectjtoolsJar(); + if (null != aspectjtools) { + vmClasspath.createPathElement().setLocation(aspectjtools); + } + } + int newVmClasspathSize = vmClasspath.size(); + if (vmClasspathSize == newVmClasspathSize) { + String m = "unable to find aspectjtools to fork - "; + if (null != aspectjtools) { + m += "tried " + aspectjtools.toString(); + } else if (null != forkclasspath) { + m += "tried " + forkclasspath.toString(); + } else { + m += "define forkclasspath or put aspectjtools on classpath"; + } + throw new BuildException(m); + } + } + if (null != maxMem) { + javaCmd.setMaxmemory(maxMem); + } + File tempFile = null; + int numArgs = args.length; + args = GuardedCommand.limitTo(args, MAX_COMMANDLINE, getLocation()); + + if (args.length != numArgs) { + tempFile = new File(args[1]); + } + try { + boolean setMessageHolderOnForking = (this.messageHolder != null); + String[] javaArgs = javaCmd.getCommandline(); + String[] both = new String[javaArgs.length + args.length + (setMessageHolderOnForking ? 2 : 0)]; + System.arraycopy(javaArgs, 0, both, 0, javaArgs.length); + System.arraycopy(args, 0, both, javaArgs.length, args.length); + if (setMessageHolderOnForking) { + both[both.length - 2] = "-messageHolder"; + both[both.length - 1] = this.messageHolder.getClass().getName(); + } + // try to use javaw instead on windows + if (both[0].endsWith("java.exe")) { + String path = both[0]; + path = path.substring(0, path.length() - 4); + path = path + "w.exe"; + File javaw = new File(path); + if (javaw.canRead() && javaw.isFile()) { + both[0] = path; + } + } + logVerbose("forking " + Arrays.asList(both)); + int result = execInOtherVM(both); + if (0 > result) { + throw new BuildException("failure[" + result + "] running ajc"); + } else if (failonerror && (0 < result)) { + throw new BuildException("compile errors: " + result); + } + // when forking, do completion only at end and when successful + doCompletionTasks(); + } finally { + if (null != tempFile) { + tempFile.delete(); + } + } + } + + /** + * Execute in another process using the same JDK and the base directory of the project. XXX correct? + * + * @param args + * @return + */ + protected int execInOtherVM(String[] args) { + try { + + Project project = getProject(); + PumpStreamHandler handler = new LogStreamHandler(this, verbose ? Project.MSG_VERBOSE : Project.MSG_INFO, + Project.MSG_WARN); + + // replace above two lines with what follows as an aid to debugging when running the unit tests.... + // LogStreamHandler handler = new LogStreamHandler(this, + // Project.MSG_INFO, Project.MSG_WARN) { + // + // ByteArrayOutputStream baos = new ByteArrayOutputStream(); + // /* (non-Javadoc) + // * @see org.apache.tools.ant.taskdefs.PumpStreamHandler#createProcessOutputPump(java.io.InputStream, + // java.io.OutputStream) + // */ + // protected void createProcessErrorPump(InputStream is, + // OutputStream os) { + // super.createProcessErrorPump(is, baos); + // } + // + // /* (non-Javadoc) + // * @see org.apache.tools.ant.taskdefs.LogStreamHandler#stop() + // */ + // public void stop() { + // byte[] written = baos.toByteArray(); + // System.err.print(new String(written)); + // super.stop(); + // } + // }; Execute exe = new Execute(handler); - exe.setAntRun(project); - exe.setWorkingDirectory(project.getBaseDir()); - exe.setCommandline(args); - try { - if (executingInOtherVM) { - String s = "already running in other vm?"; - throw new BuildException(s, location); - } - executingInOtherVM = true; - exe.execute(); - } finally { - executingInOtherVM = false; - } - return exe.getExitValue(); - } catch (IOException e) { - String m = "Error executing command " + Arrays.asList(args); - throw new BuildException(m, e, location); - } - } - - // ------------------------------ setup and reporting - /** @return null if path null or empty, String rendition otherwise */ - protected static void addFlaggedPath(String flag, Path path, List list) { - if (!LangUtil.isEmpty(flag) - && ((null != path) && (0 < path.size()))) { - list.add(flag); - list.add(path.toString()); - } - } - - /** - * Add to list any path or plural arguments. - */ - protected void addListArgs(List list) throws BuildException { - addFlaggedPath("-classpath", classpath, list); - addFlaggedPath("-bootclasspath", bootclasspath, list); - addFlaggedPath("-extdirs", extdirs, list); - addFlaggedPath("-aspectpath", aspectpath, list); - addFlaggedPath("-injars", injars, list); - addFlaggedPath("-inpath", inpath, list); - addFlaggedPath("-sourceroots", sourceRoots, list); - - if (argfiles != null) { - String[] files = argfiles.list(); - for (int i = 0; i < files.length; i++) { - File argfile = project.resolveFile(files[i]); - if (check(argfile, files[i], false, location)) { - list.add("-argfile"); - list.add(argfile.getAbsolutePath()); - } - } - } - if (srcdir != null) { - // todo: ignore any srcdir if any argfiles and no explicit includes - String[] dirs = srcdir.list(); - for (int i = 0; i < dirs.length; i++) { - File dir = project.resolveFile(dirs[i]); - check(dir, dirs[i], true, location); - // relies on compiler to prune non-source files - String[] files = getDirectoryScanner(dir).getIncludedFiles(); - for (int j = 0; j < files.length; j++) { - File file = new File(dir, files[j]); - if (FileUtil.hasSourceSuffix(file)) { - list.add(file.getAbsolutePath()); - } - } - } - } - if (0 < adapterFiles.size()) { - for (Iterator iter = adapterFiles.iterator(); iter.hasNext();) { - File file = (File) iter.next(); - if (file.canRead() && FileUtil.hasSourceSuffix(file)) { - list.add(file.getAbsolutePath()); - } else { - this.logger.warning("skipping file: " + file); - } - } - } - } - - /** - * Throw BuildException unless file is valid. - * @param file the File to check - * @param name the symbolic name to print on error - * @param isDir if true, verify file is a directory - * @param loc the Location used to create sensible BuildException - * @return - * @throws BuildException unless file valid - */ - protected final boolean check(File file, String name, - boolean isDir, Location loc) { - loc = loc != null ? loc : location; - if (file == null) { - throw new BuildException(name + " is null!", loc); - } - if (!file.exists()) { - throw new BuildException(file + " doesn't exist!", loc); - } - if (isDir ^ file.isDirectory()) { - String e = file + " should" + (isDir ? "" : "n't") + - " be a directory!"; - throw new BuildException(e, loc); - } - return true; - } - - /** - * Called when compile or incremental compile is completing, - * this completes the output jar or directory - * by copying resources if requested. - * Note: this is a callback run synchronously by the compiler. - * That means exceptions thrown here are caught by Main.run(..) - * and passed to the message handler. - */ - protected void doCompletionTasks() { - if (!executing) { - throw new IllegalStateException("should be executing"); - } - if (null != outjar) { - completeOutjar(); - } else { - completeDestdir(); - } - if (null != xdoneSignal) { - MessageUtil.info(messageHolder, xdoneSignal); - } - } - - /** - * Complete the destination directory - * by copying resources from the source root directories - * (if the filter is specified) - * and non-.class files from the input jars - * (if XCopyInjars is enabled). - */ - private void completeDestdir() { - if (!copyInjars && (null == sourceRootCopyFilter) - && (null == inpathDirCopyFilter)) { - return; - } else if ((destDir == DEFAULT_DESTDIR) - || !destDir.canWrite()) { - String s = "unable to copy resources to destDir: " + destDir; - throw new BuildException(s); - } - final Project project = getProject(); - if (copyInjars) { // XXXX remove as unused since 1.1.1 - if (null != inpath) { - log("copyInjars does not support inpath.\n", Project.MSG_WARN); - } - String taskName = getTaskName() + " - unzip"; - String[] paths = injars.list(); - if (!LangUtil.isEmpty(paths)) { - PatternSet patternSet = new PatternSet(); - patternSet.setProject(project); - patternSet.setIncludes("**/*"); - patternSet.setExcludes("**/*.class"); - for (int i = 0; i < paths.length; i++) { - Expand unzip = new Expand(); - unzip.setProject(project); - unzip.setTaskName(taskName); - unzip.setDest(destDir); - unzip.setSrc(new File(paths[i])); - unzip.addPatternset(patternSet); - unzip.execute(); - } - } - } - if ((null != sourceRootCopyFilter) && (null != sourceRoots)) { - String[] paths = sourceRoots.list(); - if (!LangUtil.isEmpty(paths)) { - Copy copy = new Copy(); - copy.setProject(project); - copy.setTodir(destDir); - for (int i = 0; i < paths.length; i++) { - FileSet fileSet = new FileSet(); - fileSet.setDir(new File(paths[i])); - fileSet.setIncludes("**/*"); - fileSet.setExcludes(sourceRootCopyFilter); - copy.addFileset(fileSet); - } - copy.execute(); - } - } - if ((null != inpathDirCopyFilter) && (null != inpath)) { - String[] paths = inpath.list(); - if (!LangUtil.isEmpty(paths)) { - Copy copy = new Copy(); - copy.setProject(project); - copy.setTodir(destDir); - boolean gotDir = false; - for (int i = 0; i < paths.length; i++) { - File inpathDir = new File(paths[i]); - if (inpathDir.isDirectory() && inpathDir.canRead()) { - if (!gotDir) { - gotDir = true; - } - FileSet fileSet = new FileSet(); - fileSet.setDir(inpathDir); - fileSet.setIncludes("**/*"); - fileSet.setExcludes(inpathDirCopyFilter); - copy.addFileset(fileSet); - } - } - if (gotDir) { - copy.execute(); - } - } - } - } - - /** - * Complete the output jar - * by copying resources from the source root directories - * if the filter is specified. - * and non-.class files from the input jars if enabled. - */ - private void completeOutjar() { - if (((null == tmpOutjar) || !tmpOutjar.canRead()) - || (!copyInjars && (null == sourceRootCopyFilter) - && (null == inpathDirCopyFilter))) { - return; - } - Zip zip = new Zip(); - Project project = getProject(); - zip.setProject(project); - zip.setTaskName(getTaskName() + " - zip"); - zip.setDestFile(outjar); - ZipFileSet zipfileset = new ZipFileSet(); - zipfileset.setProject(project); - zipfileset.setSrc(tmpOutjar); - zipfileset.setIncludes("**/*.class"); - zip.addZipfileset(zipfileset); - if (copyInjars) { - String[] paths = injars.list(); - if (!LangUtil.isEmpty(paths)) { - for (int i = 0; i < paths.length; i++) { - File jarFile = new File(paths[i]); - zipfileset = new ZipFileSet(); - zipfileset.setProject(project); - zipfileset.setSrc(jarFile); - zipfileset.setIncludes("**/*"); - zipfileset.setExcludes("**/*.class"); - zip.addZipfileset(zipfileset); - } - } - } - if ((null != sourceRootCopyFilter) && (null != sourceRoots)) { - String[] paths = sourceRoots.list(); - if (!LangUtil.isEmpty(paths)) { - for (int i = 0; i < paths.length; i++) { - File srcRoot = new File(paths[i]); - FileSet fileset = new FileSet(); - fileset.setProject(project); - fileset.setDir(srcRoot); - fileset.setIncludes("**/*"); - fileset.setExcludes(sourceRootCopyFilter); - zip.addFileset(fileset); - } - } - } - if ((null != inpathDirCopyFilter) && (null != inpath)) { - String[] paths = inpath.list(); - if (!LangUtil.isEmpty(paths)) { - for (int i = 0; i < paths.length; i++) { - File inpathDir = new File(paths[i]); - if (inpathDir.isDirectory() && inpathDir.canRead()) { - FileSet fileset = new FileSet(); - fileset.setProject(project); - fileset.setDir(inpathDir); - fileset.setIncludes("**/*"); - fileset.setExcludes(inpathDirCopyFilter); - zip.addFileset(fileset); - } - } - } - } - zip.execute(); - } - - // -------------------------- compiler adapter interface extras - - /** - * Add specified source files. - */ - void addFiles(File[] paths) { - for (int i = 0; i < paths.length; i++) { - addFile(paths[i]); - } - } - /** - * Add specified source file. - */ - void addFile(File path) { - if (null != path) { - adapterFiles.add(path); - } - } - - /** - * Read arguments in as if from a command line, - * mainly to support compiler adapter compilerarg subelement. - * - * @param args the String[] of arguments to read - */ - public void readArguments(String[] args) { // XXX slow, stupid, unmaintainable - if ((null == args) || (0 == args.length)) { - return; - } - /** String[] wrapper with increment, error reporting */ - class Args { - final String[] args; - int index = 0; - Args(String[] args) { - this.args = args; // not null or empty - } - boolean hasNext() { - return index < args.length; - } - String next() { - String err = null; - if (!hasNext()) { - err = "need arg for flag " + args[args.length-1]; - } else { - String s = args[index++]; - if (null == s) { - err = "null value"; - } else { - s = s.trim(); - if (0 == s.trim().length()) { - err = "no value"; - } else { - return s; - } - } - } - err += " at [" + index + "] of " + Arrays.asList(args); - throw new BuildException(err); - } - } // class Args - - Args in = new Args(args); - String flag; - while (in.hasNext()) { - flag = in.next(); - if ("-1.3".equals(flag)) { - setCompliance(flag); - } else if ("-1.4".equals(flag)) { - setCompliance(flag); - } else if ("-1.5".equals(flag)) { - setCompliance("1.5"); - } else if ("-argfile".equals(flag)) { - setArgfiles(new Path(project, in.next())); - } else if ("-aspectpath".equals(flag)) { - setAspectpath(new Path(project, in.next())); - } else if ("-classpath".equals(flag)) { - setClasspath(new Path(project, in.next())); - } else if ("-extdirs".equals(flag)) { - setExtdirs(new Path(project, in.next())); - } else if ("-Xcopyinjars".equals(flag)) { - setCopyInjars(true); // ignored - will be flagged by setter - } else if ("-g".equals(flag)) { - setDebug(true); - } else if (flag.startsWith("-g:")) { - setDebugLevel(flag.substring(2)); - } else if ("-deprecation".equals(flag)) { - setDeprecation(true); - } else if ("-d".equals(flag)) { - setDestdir(new File(in.next())); - } else if ("-crossrefs".equals(flag)) { - setCrossrefs(true); - } else if ("-emacssym".equals(flag)) { - setEmacssym(true); - } else if ("-encoding".equals(flag)) { - setEncoding(in.next()); - } else if ("-Xfailonerror".equals(flag)) { - setFailonerror(true); - } else if ("-fork".equals(flag)) { - setFork(true); - } else if ("-forkclasspath".equals(flag)) { - setForkclasspath(new Path(project, in.next())); - } else if ("-help".equals(flag)) { - setHelp(true); - } else if ("-incremental".equals(flag)) { - setIncremental(true); - } else if ("-injars".equals(flag)) { - setInjars(new Path(project, in.next())); - } else if ("-inpath".equals(flag)) { - setInpath(new Path(project,in.next())); - } else if ("-Xlistfileargs".equals(flag)) { - setListFileArgs(true); - } else if ("-Xmaxmem".equals(flag)) { - setMaxmem(in.next()); - } else if ("-Xmessageholderclass".equals(flag)) { - setMessageHolderClass(in.next()); - } else if ("-noexit".equals(flag)) { - setNoExit(true); - } else if ("-noimport".equals(flag)) { - setNoExit(true); - } else if ("-noExit".equals(flag)) { - setNoExit(true); - } else if ("-noImportError".equals(flag)) { - setNoImportError(true); - } else if ("-noWarn".equals(flag)) { - setNowarn(true); - } else if ("-noexit".equals(flag)) { - setNoExit(true); - } else if ("-outjar".equals(flag)) { - setOutjar(new File(in.next())); - } else if ("-outxml".equals(flag)) { - setOutxml(true); - } else if ("-outxmlfile".equals(flag)) { - setOutxmlfile(in.next()); - } else if ("-preserveAllLocals".equals(flag)) { - setPreserveAllLocals(true); - } else if ("-proceedOnError".equals(flag)) { - setProceedOnError(true); - } else if ("-referenceInfo".equals(flag)) { - setReferenceInfo(true); - } else if ("-source".equals(flag)) { - setSource(in.next()); - } else if ("-Xsourcerootcopyfilter".equals(flag)) { - setSourceRootCopyFilter(in.next()); - } else if ("-sourceroots".equals(flag)) { - setSourceRoots(new Path(project, in.next())); - } else if ("-Xsrcdir".equals(flag)) { - setSrcDir(new Path(project, in.next())); - } else if ("-Xtagfile".equals(flag)) { - setTagFile(new File(in.next())); - } else if ("-target".equals(flag)) { - setTarget(in.next()); - } else if ("-time".equals(flag)) { - setTime(true); - } else if ("-time".equals(flag)) { - setTime(true); - } else if ("-verbose".equals(flag)) { - setVerbose(true); - } else if ("-showWeaveInfo".equals(flag)) { - setShowWeaveInfo(true); - } else if ("-version".equals(flag)) { - setVersion(true); - } else if ("-warn".equals(flag)) { - setWarn(in.next()); - } else if (flag.startsWith("-warn:")) { - setWarn(flag.substring(6)); - } else if ("-Xlint".equals(flag)) { - setXlintwarnings(true); - } else if (flag.startsWith("-Xlint:")) { - setXlint(flag.substring(7)); - } else if ("-Xlintfile".equals(flag)) { - setXlintfile(new File(in.next())); - } else if ("-XterminateAfterCompilation".equals(flag)) { - setXTerminateAfterCompilation(true); - } else if ("-Xreweavable".equals(flag)) { - setXReweavable(true); - } else if ("-XnotReweavable".equals(flag)) { - setXNotReweavable(true); - } else if (flag.startsWith("@")) { - File file = new File(flag.substring(1)); - if (file.canRead()) { - setArgfiles(new Path(project, file.getPath())); - } else { - ignore(flag); - } - } else { - File file = new File(flag); - if (file.isFile() - && file.canRead() - && FileUtil.hasSourceSuffix(file)) { - addFile(file); - } else { - ignore(flag); - } - } - } - - } - - protected void logVerbose(String text) { - if (this.verbose) { - this.logger.info(text); - } else { - this.logger.verbose(text); - } - } -/** - * Commandline wrapper that - * only permits addition of non-empty values - * and converts to argfile form if necessary. - */ -public static class GuardedCommand { - Commandline command; - //int size; - - static boolean isEmpty(String s) { - return ((null == s) || (0 == s.trim().length())); - } - - GuardedCommand() { - command = new Commandline(); - } - - void addFlag(String flag, boolean doAdd) { - if (doAdd && !isEmpty(flag)) { - command.createArgument().setValue(flag); - //size += 1 + flag.length(); - } - } - - /** @return null if added or ignoreString otherwise */ - String addOption(String prefix, String[] validOptions, String input) { - if (isEmpty(input)) { - return null; - } - for (int i = 0; i < validOptions.length; i++) { - if (input.equals(validOptions[i])) { - if (isEmpty(prefix)) { - addFlag(input, true); - } else { - addFlagged(prefix, input); - } - return null; + exe.setAntRun(project); + exe.setWorkingDirectory(project.getBaseDir()); + exe.setCommandline(args); + try { + if (executingInOtherVM) { + String s = "already running in other vm?"; + throw new BuildException(s, location); + } + executingInOtherVM = true; + exe.execute(); + } finally { + executingInOtherVM = false; } + return exe.getExitValue(); + } catch (IOException e) { + String m = "Error executing command " + Arrays.asList(args); + throw new BuildException(m, e, location); } - return (null == prefix ? input : prefix + " " + input); - } - - void addFlagged(String flag, String argument) { - if (!isEmpty(flag) && !isEmpty(argument)) { - command.addArguments(new String[] {flag, argument}); - //size += 1 + flag.length() + argument.length(); - } - } - -// private void addFile(File file) { -// if (null != file) { -// String path = file.getAbsolutePath(); -// addFlag(path, true); -// } -// } - - List extractArguments() { - ArrayList result = new ArrayList(); - String[] cmds = command.getArguments(); - if (!LangUtil.isEmpty(cmds)) { - result.addAll(Arrays.asList(cmds)); - } - return result; - } - - /** - * Adjust args for size if necessary by creating - * an argument file, which should be deleted by the client - * after the compiler run has completed. - * @param max the int maximum length of the command line (in char) - * @return the temp File for the arguments (if generated), - * for deletion when done. - * @throws IllegalArgumentException if max is negative - */ - static String[] limitTo(String[] args, int max, - Location location) { - if (max < 0) { - throw new IllegalArgumentException("negative max: " + max); - } - // sigh - have to count anyway for now - int size = 0; - for (int i = 0; (i < args.length) && (size < max); i++) { - size += 1 + (null == args[i] ? 0 : args[i].length()); - } - if (size <= max) { - return args; - } - File tmpFile = null; - PrintWriter out = null; - // adapted from DefaultCompilerAdapter.executeExternalCompile - try { - String userDirName = System.getProperty("user.dir"); - File userDir = new File(userDirName); - tmpFile = File.createTempFile("argfile", "", userDir); - out = new PrintWriter(new FileWriter(tmpFile)); - for (int i = 0; i < args.length; i++) { - out.println(args[i]); - } - out.flush(); - return new String[] {"-argfile", tmpFile.getAbsolutePath()}; - } catch (IOException e) { - throw new BuildException("Error creating temporary file", - e, location); - } finally { - if (out != null) { - try {out.close();} catch (Throwable t) {} - } - } - } -} + } -private static class AntMessageHandler implements IMessageHandler { + // ------------------------------ setup and reporting + /** @return null if path null or empty, String rendition otherwise */ + protected static void addFlaggedPath(String flag, Path path, List list) { + if (!LangUtil.isEmpty(flag) && ((null != path) && (0 < path.size()))) { + list.add(flag); + list.add(path.toString()); + } + } - private TaskLogger logger; - private final boolean taskLevelVerbose; - private final boolean handledMessage; - - public AntMessageHandler(TaskLogger logger, boolean taskVerbose, boolean handledMessage) { - this.logger = logger; - this.taskLevelVerbose = taskVerbose; - this.handledMessage = handledMessage; - } - - /* (non-Javadoc) - * @see org.aspectj.bridge.IMessageHandler#handleMessage(org.aspectj.bridge.IMessage) + /** + * Add to list any path or plural arguments. */ - public boolean handleMessage(IMessage message) throws AbortException { - Kind messageKind = message.getKind(); - String messageText = message.toString(); - if (messageKind == IMessage.ABORT) { - this.logger.error(messageText); - } else if (messageKind == IMessage.DEBUG) { - this.logger.debug(messageText); - } else if (messageKind == IMessage.ERROR) { - this.logger.error(messageText); - } else if (messageKind == IMessage.FAIL){ - this.logger.error(messageText); - } else if (messageKind == IMessage.INFO) { - if (this.taskLevelVerbose) { - this.logger.info(messageText); + protected void addListArgs(List list) throws BuildException { + addFlaggedPath("-classpath", classpath, list); + addFlaggedPath("-bootclasspath", bootclasspath, list); + addFlaggedPath("-extdirs", extdirs, list); + addFlaggedPath("-aspectpath", aspectpath, list); + addFlaggedPath("-injars", injars, list); + addFlaggedPath("-inpath", inpath, list); + addFlaggedPath("-sourceroots", sourceRoots, list); + + if (argfiles != null) { + String[] files = argfiles.list(); + for (int i = 0; i < files.length; i++) { + File argfile = project.resolveFile(files[i]); + if (check(argfile, files[i], false, location)) { + list.add("-argfile"); + list.add(argfile.getAbsolutePath()); + } } - else { - this.logger.verbose(messageText); + } + if (srcdir != null) { + // todo: ignore any srcdir if any argfiles and no explicit includes + String[] dirs = srcdir.list(); + for (int i = 0; i < dirs.length; i++) { + File dir = project.resolveFile(dirs[i]); + check(dir, dirs[i], true, location); + // relies on compiler to prune non-source files + String[] files = getDirectoryScanner(dir).getIncludedFiles(); + for (int j = 0; j < files.length; j++) { + File file = new File(dir, files[j]); + if (FileUtil.hasSourceSuffix(file)) { + if (!list.contains(file.getAbsolutePath())) { + list.add(file.getAbsolutePath()); + } + } + } } - } else if (messageKind == IMessage.WARNING) { - this.logger.warning(messageText); - } else if (messageKind == IMessage.WEAVEINFO) { - this.logger.info(messageText); - } else if (messageKind == IMessage.TASKTAG) { - // ignore + } + if (0 < adapterFiles.size()) { + for (Iterator iter = adapterFiles.iterator(); iter.hasNext();) { + File file = (File) iter.next(); + if (file.canRead() && FileUtil.hasSourceSuffix(file)) { + list.add(file.getAbsolutePath()); + } else { + this.logger.warning("skipping file: " + file); + } + } + } + } + + /** + * Throw BuildException unless file is valid. + * + * @param file the File to check + * @param name the symbolic name to print on error + * @param isDir if true, verify file is a directory + * @param loc the Location used to create sensible BuildException + * @return + * @throws BuildException unless file valid + */ + protected final boolean check(File file, String name, boolean isDir, Location loc) { + loc = loc != null ? loc : location; + if (file == null) { + throw new BuildException(name + " is null!", loc); + } + if (!file.exists()) { + throw new BuildException(file + " doesn't exist!", loc); + } + if (isDir ^ file.isDirectory()) { + String e = file + " should" + (isDir ? "" : "n't") + " be a directory!"; + throw new BuildException(e, loc); + } + return true; + } + + /** + * Called when compile or incremental compile is completing, this completes the output jar or directory by copying resources if + * requested. Note: this is a callback run synchronously by the compiler. That means exceptions thrown here are caught by + * Main.run(..) and passed to the message handler. + */ + protected void doCompletionTasks() { + if (!executing) { + throw new IllegalStateException("should be executing"); + } + if (null != outjar) { + completeOutjar(); } else { - throw new BuildException("Unknown message kind from AspectJ compiler: " + messageKind.toString()); + completeDestdir(); + } + if (null != xdoneSignal) { + MessageUtil.info(messageHolder, xdoneSignal); } - return handledMessage; } - /* (non-Javadoc) - * @see org.aspectj.bridge.IMessageHandler#isIgnoring(org.aspectj.bridge.IMessage.Kind) + /** + * Complete the destination directory by copying resources from the source root directories (if the filter is specified) and + * non-.class files from the input jars (if XCopyInjars is enabled). */ - public boolean isIgnoring(Kind kind) { - return false; + private void completeDestdir() { + if (!copyInjars && (null == sourceRootCopyFilter) && (null == inpathDirCopyFilter)) { + return; + } else if ((destDir == DEFAULT_DESTDIR) || !destDir.canWrite()) { + String s = "unable to copy resources to destDir: " + destDir; + throw new BuildException(s); + } + final Project project = getProject(); + if (copyInjars) { // XXXX remove as unused since 1.1.1 + if (null != inpath) { + log("copyInjars does not support inpath.\n", Project.MSG_WARN); + } + String taskName = getTaskName() + " - unzip"; + String[] paths = injars.list(); + if (!LangUtil.isEmpty(paths)) { + PatternSet patternSet = new PatternSet(); + patternSet.setProject(project); + patternSet.setIncludes("**/*"); + patternSet.setExcludes("**/*.class"); + for (int i = 0; i < paths.length; i++) { + Expand unzip = new Expand(); + unzip.setProject(project); + unzip.setTaskName(taskName); + unzip.setDest(destDir); + unzip.setSrc(new File(paths[i])); + unzip.addPatternset(patternSet); + unzip.execute(); + } + } + } + if ((null != sourceRootCopyFilter) && (null != sourceRoots)) { + String[] paths = sourceRoots.list(); + if (!LangUtil.isEmpty(paths)) { + Copy copy = new Copy(); + copy.setProject(project); + copy.setTodir(destDir); + for (int i = 0; i < paths.length; i++) { + FileSet fileSet = new FileSet(); + fileSet.setDir(new File(paths[i])); + fileSet.setIncludes("**/*"); + fileSet.setExcludes(sourceRootCopyFilter); + copy.addFileset(fileSet); + } + copy.execute(); + } + } + if ((null != inpathDirCopyFilter) && (null != inpath)) { + String[] paths = inpath.list(); + if (!LangUtil.isEmpty(paths)) { + Copy copy = new Copy(); + copy.setProject(project); + copy.setTodir(destDir); + boolean gotDir = false; + for (int i = 0; i < paths.length; i++) { + File inpathDir = new File(paths[i]); + if (inpathDir.isDirectory() && inpathDir.canRead()) { + if (!gotDir) { + gotDir = true; + } + FileSet fileSet = new FileSet(); + fileSet.setDir(inpathDir); + fileSet.setIncludes("**/*"); + fileSet.setExcludes(inpathDirCopyFilter); + copy.addFileset(fileSet); + } + } + if (gotDir) { + copy.execute(); + } + } + } } - /* (non-Javadoc) - * @see org.aspectj.bridge.IMessageHandler#dontIgnore(org.aspectj.bridge.IMessage.Kind) + /** + * Complete the output jar by copying resources from the source root directories if the filter is specified. and non-.class + * files from the input jars if enabled. */ - public void dontIgnore(Kind kind) { + private void completeOutjar() { + if (((null == tmpOutjar) || !tmpOutjar.canRead()) + || (!copyInjars && (null == sourceRootCopyFilter) && (null == inpathDirCopyFilter))) { + return; + } + Zip zip = new Zip(); + Project project = getProject(); + zip.setProject(project); + zip.setTaskName(getTaskName() + " - zip"); + zip.setDestFile(outjar); + ZipFileSet zipfileset = new ZipFileSet(); + zipfileset.setProject(project); + zipfileset.setSrc(tmpOutjar); + zipfileset.setIncludes("**/*.class"); + zip.addZipfileset(zipfileset); + if (copyInjars) { + String[] paths = injars.list(); + if (!LangUtil.isEmpty(paths)) { + for (int i = 0; i < paths.length; i++) { + File jarFile = new File(paths[i]); + zipfileset = new ZipFileSet(); + zipfileset.setProject(project); + zipfileset.setSrc(jarFile); + zipfileset.setIncludes("**/*"); + zipfileset.setExcludes("**/*.class"); + zip.addZipfileset(zipfileset); + } + } + } + if ((null != sourceRootCopyFilter) && (null != sourceRoots)) { + String[] paths = sourceRoots.list(); + if (!LangUtil.isEmpty(paths)) { + for (int i = 0; i < paths.length; i++) { + File srcRoot = new File(paths[i]); + FileSet fileset = new FileSet(); + fileset.setProject(project); + fileset.setDir(srcRoot); + fileset.setIncludes("**/*"); + fileset.setExcludes(sourceRootCopyFilter); + zip.addFileset(fileset); + } + } + } + if ((null != inpathDirCopyFilter) && (null != inpath)) { + String[] paths = inpath.list(); + if (!LangUtil.isEmpty(paths)) { + for (int i = 0; i < paths.length; i++) { + File inpathDir = new File(paths[i]); + if (inpathDir.isDirectory() && inpathDir.canRead()) { + FileSet fileset = new FileSet(); + fileset.setProject(project); + fileset.setDir(inpathDir); + fileset.setIncludes("**/*"); + fileset.setExcludes(inpathDirCopyFilter); + zip.addFileset(fileset); + } + } + } + } + zip.execute(); } - /* (non-Javadoc) - * @see org.aspectj.bridge.IMessageHandler#ignore(org.aspectj.bridge.IMessage.Kind) + // -------------------------- compiler adapter interface extras + + /** + * Add specified source files. */ - public void ignore(Kind kind) { + void addFiles(File[] paths) { + for (int i = 0; i < paths.length; i++) { + addFile(paths[i]); + } } - -} -} + /** + * Add specified source file. + */ + void addFile(File path) { + if (null != path) { + adapterFiles.add(path); + } + } + + /** + * Read arguments in as if from a command line, mainly to support compiler adapter compilerarg subelement. + * + * @param args the String[] of arguments to read + */ + public void readArguments(String[] args) { // XXX slow, stupid, unmaintainable + if ((null == args) || (0 == args.length)) { + return; + } + /** String[] wrapper with increment, error reporting */ + class Args { + final String[] args; + int index = 0; + + Args(String[] args) { + this.args = args; // not null or empty + } + + boolean hasNext() { + return index < args.length; + } + + String next() { + String err = null; + if (!hasNext()) { + err = "need arg for flag " + args[args.length - 1]; + } else { + String s = args[index++]; + if (null == s) { + err = "null value"; + } else { + s = s.trim(); + if (0 == s.trim().length()) { + err = "no value"; + } else { + return s; + } + } + } + err += " at [" + index + "] of " + Arrays.asList(args); + throw new BuildException(err); + } + } // class Args + + Args in = new Args(args); + String flag; + while (in.hasNext()) { + flag = in.next(); + if ("-1.3".equals(flag)) { + setCompliance(flag); + } else if ("-1.4".equals(flag)) { + setCompliance(flag); + } else if ("-1.5".equals(flag)) { + setCompliance("1.5"); + } else if ("-argfile".equals(flag)) { + setArgfiles(new Path(project, in.next())); + } else if ("-aspectpath".equals(flag)) { + setAspectpath(new Path(project, in.next())); + } else if ("-classpath".equals(flag)) { + setClasspath(new Path(project, in.next())); + } else if ("-extdirs".equals(flag)) { + setExtdirs(new Path(project, in.next())); + } else if ("-Xcopyinjars".equals(flag)) { + setCopyInjars(true); // ignored - will be flagged by setter + } else if ("-g".equals(flag)) { + setDebug(true); + } else if (flag.startsWith("-g:")) { + setDebugLevel(flag.substring(2)); + } else if ("-deprecation".equals(flag)) { + setDeprecation(true); + } else if ("-d".equals(flag)) { + setDestdir(new File(in.next())); + } else if ("-crossrefs".equals(flag)) { + setCrossrefs(true); + } else if ("-emacssym".equals(flag)) { + setEmacssym(true); + } else if ("-encoding".equals(flag)) { + setEncoding(in.next()); + } else if ("-Xfailonerror".equals(flag)) { + setFailonerror(true); + } else if ("-fork".equals(flag)) { + setFork(true); + } else if ("-forkclasspath".equals(flag)) { + setForkclasspath(new Path(project, in.next())); + } else if ("-help".equals(flag)) { + setHelp(true); + } else if ("-incremental".equals(flag)) { + setIncremental(true); + } else if ("-injars".equals(flag)) { + setInjars(new Path(project, in.next())); + } else if ("-inpath".equals(flag)) { + setInpath(new Path(project, in.next())); + } else if ("-Xlistfileargs".equals(flag)) { + setListFileArgs(true); + } else if ("-Xmaxmem".equals(flag)) { + setMaxmem(in.next()); + } else if ("-Xmessageholderclass".equals(flag)) { + setMessageHolderClass(in.next()); + } else if ("-noexit".equals(flag)) { + setNoExit(true); + } else if ("-noimport".equals(flag)) { + setNoExit(true); + } else if ("-noExit".equals(flag)) { + setNoExit(true); + } else if ("-noImportError".equals(flag)) { + setNoImportError(true); + } else if ("-noWarn".equals(flag)) { + setNowarn(true); + } else if ("-noexit".equals(flag)) { + setNoExit(true); + } else if ("-outjar".equals(flag)) { + setOutjar(new File(in.next())); + } else if ("-outxml".equals(flag)) { + setOutxml(true); + } else if ("-outxmlfile".equals(flag)) { + setOutxmlfile(in.next()); + } else if ("-preserveAllLocals".equals(flag)) { + setPreserveAllLocals(true); + } else if ("-proceedOnError".equals(flag)) { + setProceedOnError(true); + } else if ("-referenceInfo".equals(flag)) { + setReferenceInfo(true); + } else if ("-source".equals(flag)) { + setSource(in.next()); + } else if ("-Xsourcerootcopyfilter".equals(flag)) { + setSourceRootCopyFilter(in.next()); + } else if ("-sourceroots".equals(flag)) { + setSourceRoots(new Path(project, in.next())); + } else if ("-Xsrcdir".equals(flag)) { + setSrcDir(new Path(project, in.next())); + } else if ("-Xtagfile".equals(flag)) { + setTagFile(new File(in.next())); + } else if ("-target".equals(flag)) { + setTarget(in.next()); + } else if ("-time".equals(flag)) { + setTime(true); + } else if ("-time".equals(flag)) { + setTime(true); + } else if ("-verbose".equals(flag)) { + setVerbose(true); + } else if ("-showWeaveInfo".equals(flag)) { + setShowWeaveInfo(true); + } else if ("-version".equals(flag)) { + setVersion(true); + } else if ("-warn".equals(flag)) { + setWarn(in.next()); + } else if (flag.startsWith("-warn:")) { + setWarn(flag.substring(6)); + } else if ("-Xlint".equals(flag)) { + setXlintwarnings(true); + } else if (flag.startsWith("-Xlint:")) { + setXlint(flag.substring(7)); + } else if ("-Xlintfile".equals(flag)) { + setXlintfile(new File(in.next())); + } else if ("-XterminateAfterCompilation".equals(flag)) { + setXTerminateAfterCompilation(true); + } else if ("-Xreweavable".equals(flag)) { + setXReweavable(true); + } else if ("-XnotReweavable".equals(flag)) { + setXNotReweavable(true); + } else if (flag.startsWith("@")) { + File file = new File(flag.substring(1)); + if (file.canRead()) { + setArgfiles(new Path(project, file.getPath())); + } else { + ignore(flag); + } + } else { + File file = new File(flag); + if (file.isFile() && file.canRead() && FileUtil.hasSourceSuffix(file)) { + addFile(file); + } else { + ignore(flag); + } + } + } + + } + + protected void logVerbose(String text) { + if (this.verbose) { + this.logger.info(text); + } else { + this.logger.verbose(text); + } + } + + /** + * Commandline wrapper that only permits addition of non-empty values and converts to argfile form if necessary. + */ + public static class GuardedCommand { + Commandline command; + + // int size; + + static boolean isEmpty(String s) { + return ((null == s) || (0 == s.trim().length())); + } + + GuardedCommand() { + command = new Commandline(); + } + + void addFlag(String flag, boolean doAdd) { + if (doAdd && !isEmpty(flag)) { + command.createArgument().setValue(flag); + // size += 1 + flag.length(); + } + } + + /** @return null if added or ignoreString otherwise */ + String addOption(String prefix, String[] validOptions, String input) { + if (isEmpty(input)) { + return null; + } + for (int i = 0; i < validOptions.length; i++) { + if (input.equals(validOptions[i])) { + if (isEmpty(prefix)) { + addFlag(input, true); + } else { + addFlagged(prefix, input); + } + return null; + } + } + return (null == prefix ? input : prefix + " " + input); + } + + void addFlagged(String flag, String argument) { + if (!isEmpty(flag) && !isEmpty(argument)) { + command.addArguments(new String[] { flag, argument }); + // size += 1 + flag.length() + argument.length(); + } + } + + // private void addFile(File file) { + // if (null != file) { + // String path = file.getAbsolutePath(); + // addFlag(path, true); + // } + // } + + List extractArguments() { + ArrayList result = new ArrayList(); + String[] cmds = command.getArguments(); + if (!LangUtil.isEmpty(cmds)) { + result.addAll(Arrays.asList(cmds)); + } + return result; + } + + /** + * Adjust args for size if necessary by creating an argument file, which should be deleted by the client after the compiler + * run has completed. + * + * @param max the int maximum length of the command line (in char) + * @return the temp File for the arguments (if generated), for deletion when done. + * @throws IllegalArgumentException if max is negative + */ + static String[] limitTo(String[] args, int max, Location location) { + if (max < 0) { + throw new IllegalArgumentException("negative max: " + max); + } + // sigh - have to count anyway for now + int size = 0; + for (int i = 0; (i < args.length) && (size < max); i++) { + size += 1 + (null == args[i] ? 0 : args[i].length()); + } + if (size <= max) { + return args; + } + File tmpFile = null; + PrintWriter out = null; + // adapted from DefaultCompilerAdapter.executeExternalCompile + try { + String userDirName = System.getProperty("user.dir"); + File userDir = new File(userDirName); + tmpFile = File.createTempFile("argfile", "", userDir); + out = new PrintWriter(new FileWriter(tmpFile)); + for (int i = 0; i < args.length; i++) { + out.println(args[i]); + } + out.flush(); + return new String[] { "-argfile", tmpFile.getAbsolutePath() }; + } catch (IOException e) { + throw new BuildException("Error creating temporary file", e, location); + } finally { + if (out != null) { + try { + out.close(); + } catch (Throwable t) { + } + } + } + } + } + + private static class AntMessageHandler implements IMessageHandler { + + private TaskLogger logger; + private final boolean taskLevelVerbose; + private final boolean handledMessage; + + public AntMessageHandler(TaskLogger logger, boolean taskVerbose, boolean handledMessage) { + this.logger = logger; + this.taskLevelVerbose = taskVerbose; + this.handledMessage = handledMessage; + } + + /* + * (non-Javadoc) + * + * @see org.aspectj.bridge.IMessageHandler#handleMessage(org.aspectj.bridge.IMessage) + */ + public boolean handleMessage(IMessage message) throws AbortException { + Kind messageKind = message.getKind(); + String messageText = message.toString(); + if (messageKind == IMessage.ABORT) { + this.logger.error(messageText); + } else if (messageKind == IMessage.DEBUG) { + this.logger.debug(messageText); + } else if (messageKind == IMessage.ERROR) { + this.logger.error(messageText); + } else if (messageKind == IMessage.FAIL) { + this.logger.error(messageText); + } else if (messageKind == IMessage.INFO) { + if (this.taskLevelVerbose) { + this.logger.info(messageText); + } else { + this.logger.verbose(messageText); + } + } else if (messageKind == IMessage.WARNING) { + this.logger.warning(messageText); + } else if (messageKind == IMessage.WEAVEINFO) { + this.logger.info(messageText); + } else if (messageKind == IMessage.TASKTAG) { + // ignore + } else { + throw new BuildException("Unknown message kind from AspectJ compiler: " + messageKind.toString()); + } + return handledMessage; + } + + /* + * (non-Javadoc) + * + * @see org.aspectj.bridge.IMessageHandler#isIgnoring(org.aspectj.bridge.IMessage.Kind) + */ + public boolean isIgnoring(Kind kind) { + return false; + } + + /* + * (non-Javadoc) + * + * @see org.aspectj.bridge.IMessageHandler#dontIgnore(org.aspectj.bridge.IMessage.Kind) + */ + public void dontIgnore(Kind kind) { + } + + /* + * (non-Javadoc) + * + * @see org.aspectj.bridge.IMessageHandler#ignore(org.aspectj.bridge.IMessage.Kind) + */ + public void ignore(Kind kind) { + } + + } +} |