diff options
author | wisberg <wisberg> | 2002-12-23 19:41:48 +0000 |
---|---|---|
committer | wisberg <wisberg> | 2002-12-23 19:41:48 +0000 |
commit | 9441d053abb841472dc2833417f6c495ccfa1190 (patch) | |
tree | ddc7fc67737142bb89799ce8f6db131853194a78 /build | |
parent | e4e1027f57344200c4e89f3d3daeb4c72ba2221d (diff) | |
download | aspectj-9441d053abb841472dc2833417f6c495ccfa1190.tar.gz aspectj-9441d053abb841472dc2833417f6c495ccfa1190.zip |
fixing version-handling.
build-properties.xml has actual version,
Version.java is generated,
and "DEVELOPMENT" is default.
Diffstat (limited to 'build')
-rw-r--r-- | build/build-properties.xml | 31 | ||||
-rw-r--r-- | build/build.xml | 28 | ||||
-rw-r--r-- | build/lib/BridgeVersion.java.txt | 22 | ||||
-rw-r--r-- | build/readme-build-module.html | 103 | ||||
-rw-r--r-- | build/src/org/aspectj/internal/tools/ant/taskdefs/AntBuilder.java | 102 | ||||
-rw-r--r-- | build/src/org/aspectj/internal/tools/ant/taskdefs/BuildModule.java | 1 | ||||
-rw-r--r-- | build/src/org/aspectj/internal/tools/ant/taskdefs/VersionUptodate.java | 145 | ||||
-rw-r--r-- | build/src/org/aspectj/internal/tools/ant/taskdefs/taskdefs.properties | 1 | ||||
-rw-r--r-- | build/src/org/aspectj/internal/tools/build/BuildSpec.java | 253 | ||||
-rw-r--r-- | build/src/org/aspectj/internal/tools/build/Builder.java | 906 |
10 files changed, 970 insertions, 622 deletions
diff --git a/build/build-properties.xml b/build/build-properties.xml index 64fab94a1..e85eed177 100644 --- a/build/build-properties.xml +++ b/build/build-properties.xml @@ -17,11 +17,18 @@ <target name="init-properties" unless="aspectj.modules.build.dir"> - <!-- change version manually --> - <property name="build.version" value="1.1b2"/> + <!-- + Changing version: + - base should always be 1.1 (used for manifests, other version-parsing code) + - Others should be DEVELOPMENT unless testing/doing release builds, when + they should be (e.g.,) 1.1b3 or 1.1beta3 + - Changing version here causes org/aspectj/bridge/Version.java to be updated + - also change org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/messages.properties + --> + <property name="build.version" value="DEVELOPMENT"/> <property name="build.version.base" value="1.1"/> - <property name="build.version.long" value="1.1beta2"/> - <property name="build.version.short" value="1.1b2"/> + <property name="build.version.long" value="DEVELOPMENT"/> + <property name="build.version.short" value="DEVELOPMENT"/> <!-- formats comply with SimpleDateFormat --> <property name="build.time.format" value="MM/dd/yy 'at' hh:mm:ss z"/> @@ -35,10 +42,9 @@ timezone="PST"/> </tstamp> + <property name="company.name" value="aspectj.org"/> <property name="copyright.allRights.from1998" value="Copyright (c) 1998-2001 Xerox Corporation, 2002 Palo Alto Research Center, Incorporated. All rights reserved." /> - <!-- XXX interim hack --> - <property name="aspectj.home.url" value="http://aspectj.org" /> <!-- callers define basedir as dir of build file? --> <property name="aspectj.modules.dir" @@ -85,12 +91,12 @@ unless="init-taskdefs.done" > <fail unless="aspectj.build.jar.available" message="unable to find aspectj.build.jar: ${aspectj.build.jar}"/> + <!-- run directly from classes in bin when debugging. <taskdef resource="org/aspectj/internal/tools/ant/taskdefs/taskdefs.properties" classpath="${aspectj.build.jar}"/> - <!-- when debugging, etc. + --> <taskdef resource="org/aspectj/internal/tools/ant/taskdefs/taskdefs.properties" classpath="${aspectj.modules.dir}/build/bin"/> - --> <property name="init-taskdefs.done" value="done"/> </target> @@ -108,8 +114,11 @@ <target name="init-filters" depends="init-properties" unless="init-filters.done" > - <!-- change version manually --> - <!-- see also org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/messages.properties --> + + <!-- build.version and build.date used in filters throughout, and + build.version.base used in filtering manifest, but + others used mainly for installer-resources/properties.txt --> + <filter token="build.version" value="${build.version}"/> <filter token="build.version.base" value="${build.version.base}"/> <filter token="build.version.long" value="${build.version.long}"/> @@ -119,6 +128,7 @@ <filter token="build.date.format" value="${build.date.format}"/> <filter token="build.date" value="${build.date}"/> <filter token="build.time" value="${build.time}"/> + <filter token="company.name" value="${company.name}"/> <filter token="copyright.allRights.from1998" value="${copyright.allRights.from1998}" /> <property name="init-filters.done" value="done"/> @@ -145,7 +155,6 @@ aspectj.modules.dir = ${aspectj.modules.dir} aj.build.dir = ${aj.build.dir} aj.results.dir = ${aj.results.dir} - release.build = ${release.build} ant.home = ${ant.home} java.home = ${java.home} </echo> diff --git a/build/build.xml b/build/build.xml index 0382c4428..015493d91 100644 --- a/build/build.xml +++ b/build/build.xml @@ -49,8 +49,20 @@ </target> - <target name="init-version" depends="init,init-filters" - unless="init.version.done" if="release.build" > <!-- unless=version.uptodate --> + <target name="version-uptodate" depends="init,init-taskdefs" + unless="version-uptodate.done"> + <versionuptodate + version="${build.version}" + versionSourceFile="${aspectj.modules.dir}/bridge/src/org/aspectj/bridge/Version.java" + versionTagFile="${aj.temp.dir}/versionUptodate"/> + + <available file="${aj.temp.dir}/versionUptodate" + property="version.uptodate"/> + <property name="version-uptodate.done" value="done"/> + </target> + + <target name="init-version" depends="init,init-filters,version-uptodate" + unless="version.uptodate"> <antcall target="init-filters"/> <copy file="${aspectj.modules.dir}/build/lib/BridgeVersion.java.txt" tofile="${aspectj.modules.dir}/bridge/src/org/aspectj/bridge/Version.java" @@ -216,6 +228,12 @@ inheritAll="false"/> <!-- true? --> </target> + <target name="runtime" depends="init"> + <antcall target="build-module-all"> + <param name="module.name" value="runtime"/> + </antcall> + </target> + <!-- ===================================================================== --> <!-- boilerplate antcalls --> <!-- ===================================================================== --> @@ -227,6 +245,12 @@ </antcall> </target> + <target name="any-module-all" depends="init"> + <antcall target="build-module-all"> + <param name="module.name" value="${module.name}"/> + </antcall> + </target> + <target name="any-product" depends="init"> <antcall target="build-product"> <param name="product.name" value="${product.name}"/> diff --git a/build/lib/BridgeVersion.java.txt b/build/lib/BridgeVersion.java.txt index 95d41d201..4d82a700b 100644 --- a/build/lib/BridgeVersion.java.txt +++ b/build/lib/BridgeVersion.java.txt @@ -20,14 +20,18 @@ import java.util.Date; /** release-specific version information */ public class Version { + // generated from build/lib/BridgeVersion.java + /** default version value for development version */ public static final String DEVELOPMENT = "DEVELOPMENT"; + // VersionUptodate.java depends on this value /** default time value for development version */ public static final long NOTIME = 0L; /** set by build script */ public static final String text = "@build.version@"; + // VersionUptodate.java scans for "static final String text = " /** * Time text set by build script using SIMPLE_DATE_FORMAT. @@ -58,6 +62,24 @@ public class Version { } time = foundTime; } + + /** + * Test whether the version is as specified by any first argument. + * Emit text to System.err on failure + * @param args String[] with first argument equal to Version.text + * @see Version#text + */ + public static void main(String[] args) { + if ((null != args) && (0 < args.length)) { + if (!Version.text.equals(args[0])) { + System.err.println("version expected: \"" + + args[0] + + "\" actual=\"" + + Version.text + + "\""); + } + } + } } diff --git a/build/readme-build-module.html b/build/readme-build-module.html index e056ba6f6..bca0d78a5 100644 --- a/build/readme-build-module.html +++ b/build/readme-build-module.html @@ -6,12 +6,11 @@ This build module contains taskdefs and resources for doing builds and checking source licenses. +<h3>Usage</h3> +<h4>Running the build</h4> To do a build, use Ant to run <a href="build.xml">build.xml</a> from this directory. To run Ant, use <a href="../lib/ant">../lib/ant</a> -scripts and libraries. In particular, when running Ant from eclipse, -do not use the default Eclipse Ant classpath; remove those jars and -add all the libraries in <a href="../lib/ant/lib">../lib/ant/lib</a> -as well as in <a href="../lib/junit">../lib/junit</a>. +scripts and libraries. Consider defining the following flag properties: <p> <table cellpadding="1" border="1"> @@ -20,17 +19,63 @@ Consider defining the following flag properties: <tr><td>check.build.jar </td><td>fail if build.jar is out of date </td></tr> -<tr><td>release.build - </td><td>regenerate org/aspectj/bridge/Version.java - </td></tr> -</table> +</table> +<p> + +<u>Release builds</u>: Release builds differ only in running +from a clean, up-to-date tree and with correct build version values +in <a href="build-properties.xml">build-properties.xml</a>, which +will update org.aspectj.bridge.Version. +See below for more details on how the version is updated. +<p> + +<h4>Updating module dependencies and file locations</h4> +Because the BuildModule taskdef extracts dependencies from the Eclipse +<code>.classpath</code> file, there is no need to update build scripts when +adding or removing modules or changing their dependencies, so long +as they are all in the base modules directory (usually the base of +the eclipse workspace. +All required libraries are checked into the <code>lib</code> module. + +<p>The BuildModule taskdef makes some assumptions about the naming, +position, and contents of module directories and files. +Understand those (documented in +<a href="src/org/aspectj/internal/tools/ant/taskdefs/BuildModule.java"> + BuildModule.java</a>) before using non-standard module directories. + +<p> +<h4>Running builds or built jars under Eclipse</h4> +When running Ant from eclipse, +do not use the default Eclipse Ant classpath; remove those jars and +add all the libraries in <a href="../lib/ant/lib">../lib/ant/lib</a> +as well as in <a href="../lib/junit">../lib/junit</a>. +<p> +<u>warning</u>: Jar files do not seem to be closed properly when running under eclipse. +This affects build products (e.g., installers) which are run under eclipse +(e.g., by opening with the "default system editor") and libraries used +when compiling under Javac (if not zip products or input). This problem +presents as files not being writable, i.e., deleted or modified. +You might get no notice of the problem when +deleting with quiet="on". (The alternative to that is to create any +directories being deleted before deleting them). <p> +Currently BuildModule taskdefs fork the Javac command to work around +this problem, but the Zip commands do not work around it. + +If under Eclipse, you get strange behavior with Ant builds, clear +out everything and build from the command line. In some cases, you +have to exit Eclipse before files can be deleted. (*sigh*) + + +<h3>Development</h3> +<h4>BuildModule task</h4> The <a href="src/org/aspectj/internal/tools/ant/taskdefs/BuildModule.java"> BuildModule</a> taskdef implements an integrated module or product build. -<u>Module builds</u> are based on the Eclipse .classpath file, and can produce +<u>Module builds</u> are based on the Eclipse <code>.classpath</code> +file, and can produce a jar with the module classes, with two variations: (a) include only the module classes, or assemble the jar complete with all antecedent modules and libraries; and (b) compile the module(s) without any @@ -47,27 +92,37 @@ and a <code>dist</code> directory containing all files belonging in the distribution, including 0-length placeholders for the module build results. +<h4>Build notes</h4> <p> -Top-level temporary build directories are prefixed "aj-", +<u>Directory names</u>: Top-level temporary build directories are prefixed "aj-", so you can safely destroy any such directory or ignore it in CVS or the Eclipse package explorer. By default the build script -puts them at the same level as other modules. -<p> -<u>Updating this module</u>: +puts them at the same level as other modules. Property names follow +a similar convention; those prefixed "aj-" may be deleted at will, while +"aspectj-" names are source directories which should never be deleted. -Because the BuildModule taskdef extracts dependencies from the Eclipse -.classpath file, there is no need to update build scripts when -adding or removing modules or changing their dependencies, so long -as they are all in the base modules directory (usually the base of -the eclipse workspace. -All required libraries are checked into the <code>lib</code> module. +<p> +<u>Version synchronization</u>: +Developers use the default "DEVELOPMENT" version unless doing or testing +release builds. -<p>The BuildModule taskdef makes some assumptions about the naming, -position, and contents of module directories and files. -Understand those (documented in -<a href="src/org/aspectj/internal/tools/ant/taskdefs/BuildModule.java"> - BuildModule.java</a>) before using non-standard module directories. +The build version is set in +<a href="build-properties.xml">build-properties.xml</a> and tracked in +<a href="../bridge/src/org/aspectj/bridge/Version.java"> + ../bridge/src/org/aspectj/bridge/Version.java</a> +which the <a href="build.xml">build.xml</a> <code>init-version</code> task +generates from a template +<a href="lib/BridgeVersion.java.txt">lib/BridgeVersion.java.txt</a> +using copy filters to set the build version and date. +To avoid updating <code>Version.java</code> whenever +<code>build-properties.xml</code> changes, a task +<a href="src/org/aspectj/internal/tools/ant/taskdefs/VersionUptodate.java"> + src/org/aspectj/internal/tools/ant/taskdefs/VersionUptodate.java</a> +determines whether Version.java has the same version by scanning the source file. +(Do not change the lines flagged in the template without also +changing the scanning code in the task.) +<p> <hr> </body> diff --git a/build/src/org/aspectj/internal/tools/ant/taskdefs/AntBuilder.java b/build/src/org/aspectj/internal/tools/ant/taskdefs/AntBuilder.java index 0aaaac880..06b2f1738 100644 --- a/build/src/org/aspectj/internal/tools/ant/taskdefs/AntBuilder.java +++ b/build/src/org/aspectj/internal/tools/ant/taskdefs/AntBuilder.java @@ -16,7 +16,6 @@ import org.apache.tools.ant.Project; import org.apache.tools.ant.Target; import org.apache.tools.ant.Task; import org.apache.tools.ant.taskdefs.Copy; -import org.apache.tools.ant.taskdefs.Filter; import org.apache.tools.ant.taskdefs.Javac; import org.apache.tools.ant.taskdefs.Zip; import org.apache.tools.ant.types.FileSet; @@ -34,11 +33,9 @@ import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.List; -import java.util.Properties; /** * Implement Builder in Ant. @@ -116,6 +113,7 @@ public class AntBuilder extends Builder { } protected final Project project; + protected boolean filterSetup; protected AntBuilder(Project project, File tempDir, boolean useEclipseCompiles, Messager handler) { @@ -123,6 +121,7 @@ public class AntBuilder extends Builder { this.project = project; Util.iaxIfNull(project, "project"); } + protected boolean copyFile(File fromFile, File toFile, boolean filter) { Copy copy = makeCopyTask(filter); copy.setFile(fromFile); @@ -131,58 +130,54 @@ public class AntBuilder extends Builder { return true; } + /** + * @see org.aspectj.internal.tools.ant.taskdefs.Builder#copyFiles(File, File, String, String, boolean) + */ + protected boolean copyFiles( + File fromDir, + File toDir, + String includes, + String excludes, + boolean filter) { + Copy copy = makeCopyTask(filter); + copy.setTodir(toDir); + FileSet fileset = new FileSet(); + fileset.setDir(fromDir); + if (null != includes) { + fileset.setIncludes(includes); + } + if (null != excludes) { + fileset.setExcludes(excludes); + } + copy.addFileset(fileset); + executeTask(copy); + + return false; + } + protected void copyFileset(File toDir, FileSet fileSet, boolean filter) { Copy copy = makeCopyTask(filter); copy.addFileset(fileSet); copy.setTodir(toDir); executeTask(copy); } - + /** filter if FILTER_ON, use filters */ protected Copy makeCopyTask(boolean filter) { Copy copy = new Copy(); copy.setProject(project); if (FILTER_ON == filter) { copy.setFiltering(true); - setupFilters(); } return copy; } - - /** lazily and manually generate properties */ - protected Properties getFilterProperties() { // - if (filterProps == null) { - long time = System.currentTimeMillis(); - String version = null; // unknown - system? - filterProps = BuildSpec.getFilterProperties(time, version); - } - return filterProps; - } - - protected void setupFilters() { - if (!filterSetup) { // XXX check Ant - is this static? - Properties props = getFilterProperties(); - for (Enumeration enum = props.keys(); enum.hasMoreElements();) { - String token = (String) enum.nextElement(); - String value = props.getProperty(token); - Filter filter = new Filter(); - filter.setProject(project); - filter.setToken(token); - filter.setValue(value); - if (!executeTask(filter)) { - return; - } - } - filterSetup = true; - } - } - + protected boolean compile(Module module, File classesDir, List errors) { // XXX test whether build.compiler property takes effect automatically // I suspect it requires the proper adapter setup. - Javac javac = new Javac(); + Javac javac = new Javac(); javac.setProject(project); - + javac.setTaskName("javac"); // -- source paths Path path = new Path(project); for (Iterator iter = module.getSrcDirs().iterator(); iter.hasNext();) { @@ -274,16 +269,16 @@ public class AntBuilder extends Builder { zipfileset.setProject(project); zipfileset.setSrc(mergeJar); zipfileset.setIncludes("**/*"); - zipfileset.setExcludes("META-INF/*"); // XXXFileLiteral - zipfileset.setExcludes("meta-inf/*"); + zipfileset.setExcludes("META-INF/manifest.mf"); // XXXFileLiteral + zipfileset.setExcludes("meta-inf/manifest.MF"); + zipfileset.setExcludes("META-INF/MANIFEST.mf"); + zipfileset.setExcludes("meta-inf/MANIFEST.MF"); zip.addZipfileset(zipfileset); } } // merge classes; put any meta-inf/manifest.mf here File metaInfDir = new File(classesDir, "META-INF"); - if (metaInfDir.canWrite()) { - Util.deleteContents(metaInfDir); // XXX only delete manifest - } + Util.deleteContents(metaInfDir); // -- manifest File manifest = new File(module.moduleDir, module.name + ".mf.txt"); // XXXFileLiteral @@ -408,31 +403,6 @@ public class AntBuilder extends Builder { return false; } - /** - * @see org.aspectj.internal.tools.ant.taskdefs.Builder#copyFiles(File, File, String, String, boolean) - */ - protected boolean copyFiles( - File fromDir, - File toDir, - String includes, - String excludes, - boolean filter) { - Copy copy = makeCopyTask(filter); - copy.setTodir(toDir); - FileSet fileset = new FileSet(); - fileset.setDir(fromDir); - if (null != includes) { - fileset.setIncludes(includes); - } - if (null != excludes) { - fileset.setExcludes(excludes); - } - copy.addFileset(fileset); - executeTask(copy); - - return false; - } - /** task.execute() and any advice */ protected boolean executeTask(Task task) { if (!buildingEnabled) { diff --git a/build/src/org/aspectj/internal/tools/ant/taskdefs/BuildModule.java b/build/src/org/aspectj/internal/tools/ant/taskdefs/BuildModule.java index 5853559c9..9e29b8138 100644 --- a/build/src/org/aspectj/internal/tools/ant/taskdefs/BuildModule.java +++ b/build/src/org/aspectj/internal/tools/ant/taskdefs/BuildModule.java @@ -47,7 +47,6 @@ public class BuildModule extends Task { // quickie hack... public BuildModule() { buildSpec = new BuildSpec(); - buildSpec.version = BuildSpec.BUILD_VERSION_DEFAULT; } public void setModuledir(Path moduleDir) { diff --git a/build/src/org/aspectj/internal/tools/ant/taskdefs/VersionUptodate.java b/build/src/org/aspectj/internal/tools/ant/taskdefs/VersionUptodate.java new file mode 100644 index 000000000..a2ac09ff3 --- /dev/null +++ b/build/src/org/aspectj/internal/tools/ant/taskdefs/VersionUptodate.java @@ -0,0 +1,145 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * ******************************************************************/ + +package org.aspectj.internal.tools.ant.taskdefs; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; + +/** + * Check if version source file has the specified build version, + * and ensure a tag file reflects whether it does or not. + */ +public class VersionUptodate extends Task { + public VersionUptodate() {} + + private String buildVersion; + private File versionSource; + private File versionTagFile; + + /** + * @param buildVersion String expected as Version.text - required + */ + public void setVersion(String buildVersion) { + this.buildVersion = buildVersion; + } + + /** + * @param versionSource the File Version.java containing text constant + * - required + */ + public void setVersionSourceFile(File versionSource) { + this.versionSource = versionSource; + } + + /** + * @param versionTagFile the File whose existence signals that the version + * is uptodate after this task executes - required. + */ + public void setVersionTagFile(File versionTagFile) { + this.versionTagFile = versionTagFile; + } + + /** + * If the Version.java source file contains the correct + * build version, then create the output tag file, + * else delete it if it exists. + * @throws BuildException if tagFile not creatable and version is incorrect + * or if version is correct and tagFile cannot be deleted. + */ + public void execute() throws BuildException { + if (null == buildVersion) { + throw new BuildException("require buildVersion"); + } + if ((null == versionSource) || !versionSource.canRead()){ + throw new BuildException("require versionSource"); + } + if (null == versionTagFile){ + throw new BuildException("require versionTagFile"); + } + if (sameVersion(versionSource, buildVersion)) { + if (!versionTagFile.exists()) { + createFile(versionTagFile, buildVersion); + } + } else if (null == versionTagFile) { + throw new BuildException("no tag file, and version out of date"); + } else if (versionTagFile.exists()) { + if (!versionTagFile.delete()) { + throw new BuildException("version out of date, but cannot delete " + versionTagFile); + } + } + } + + /** + * Detect whether version is correct in Java sources. + * @param versionSource + * @param buildVersion + * @return boolean + */ + private boolean sameVersion(File versionSource, String buildVersion) { + // XXX build and load instead of scanning? + FileReader fileReader = null; + try { + fileReader = new FileReader(versionSource); + BufferedReader reader = new BufferedReader(fileReader); + String line; + while (null != (line = reader.readLine())) { + int loc = line.indexOf("static final String text = "); + if (-1 != loc) { + return (-1 != line.indexOf(buildVersion , loc)); + } + } + return false; + } catch (IOException e) { + return false; + } finally { + if (null != fileReader) { + try { + fileReader.close(); + } catch (IOException e) { + } + } + } + } + + /** + * Create file with contents + */ + private void createFile(File versionTagFile, String contents) { + FileWriter writer = null; + try { + writer = new FileWriter(versionTagFile); + char[] buf = new char[contents.length()]; + contents.getChars(0, buf.length, buf, 0); + writer.write(contents); + } catch (IOException e) { + throw new BuildException("writing " + versionTagFile, e); + } finally { + if (null != writer) { + try { + writer.close(); + } catch (IOException e){ + // ignore + } + } + } + } + +} + diff --git a/build/src/org/aspectj/internal/tools/ant/taskdefs/taskdefs.properties b/build/src/org/aspectj/internal/tools/ant/taskdefs/taskdefs.properties index 37da66e9e..884077a85 100644 --- a/build/src/org/aspectj/internal/tools/ant/taskdefs/taskdefs.properties +++ b/build/src/org/aspectj/internal/tools/ant/taskdefs/taskdefs.properties @@ -1,6 +1,7 @@ ajinstaller=org.aspectj.internal.tools.ant.taskdefs.AJInstaller ajpush=org.aspectj.internal.tools.ant.taskdefs.AJPush ajbuild=org.aspectj.internal.tools.ant.taskdefs.BuildModule +versionuptodate=org.aspectj.internal.tools.ant.taskdefs.VersionUptodate checklics=org.aspectj.internal.tools.ant.taskdefs.Checklics stripnonbodyhtml=org.aspectj.internal.tools.ant.taskdefs.StripNonBodyHtml diff --git a/build/src/org/aspectj/internal/tools/build/BuildSpec.java b/build/src/org/aspectj/internal/tools/build/BuildSpec.java index f40ff6b06..f5b53c72b 100644 --- a/build/src/org/aspectj/internal/tools/build/BuildSpec.java +++ b/build/src/org/aspectj/internal/tools/build/BuildSpec.java @@ -17,7 +17,10 @@ package org.aspectj.internal.tools.build; import java.io.File; import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Collections; import java.util.Date; +import java.util.List; import java.util.Properties; /** @@ -27,107 +30,124 @@ import java.util.Properties; * Static state has much of the Ant build properties (move?) */ public class BuildSpec { - public static final String baseDir_NAME = "aspectj.modules.dir"; - public static final String stagingDir_NAME = "aj.staging.dir"; - public static final String jarDir_NAME = "aj.jar.dir"; - public static final String tempDir_NAME = "aj.temp.dir"; - public static final String distDir_NAME = "aj.dist.dir"; - - /** name of a system property for reading the build version */ - public static final String SYSTEM_BUILD_VERSION_KEY = "aspectj.build.version"; - - /** value of the build.version if build version not defined */ - public static final String BUILD_VERSION_DEFAULT = "DEVELOPMENT"; - - /** name of a filter property for the normal build version */ - public static final String BUILD_VERSION_NAME = "build.version"; - - /** name of a filter property for the company */ - public static final String COMPANY_NAME = "company.name"; - - /** default value of of a filter property for the company */ - public static final String COMPANY_NAME_DEFAULT = "aspectj.org"; - - /** name of a filter property for the base build version (no alpha, etc.) */ - public static final String BUILD_VERSION_BASE_NAME = "build.version.base"; - - /** copyright property name */ - public static final String COPYRIGHT_NAME = "copyright.allRights.from1998"; - - /** overall copyright */ - public static final String COPYRIGHT = - "Copyright (c) 1998-2001 Xerox Corporation, " - + "2002 Palo Alto Research Center, Incorporated. All rights reserved."; - - /** name of a filter property for the long build version (alpha) */ - public static final String BUILD_VERSION_LONG_NAME = "build.version.long"; - - /** name of a filter property for the short build version (alpha -> a, etc.) */ - public static final String BUILD_VERSION_SHORT_NAME = "build.version.short"; - - /** name of a filter property for the build time */ - public static final String BUILD_TIME_NAME = "build.time"; - - /** name of a filter property for the build date */ - public static final String BUILD_DATE_NAME = "build.date"; - - /** lazily and manually generate properties */ - public static Properties getFilterProperties(long time, String longVersion) { - if (time < 1) { - time = System.currentTimeMillis(); - } - if ((null == longVersion) || (0 == longVersion.length())) { - longVersion = System.getProperty( - BuildSpec.SYSTEM_BUILD_VERSION_KEY, - BuildSpec.BUILD_VERSION_DEFAULT); - } - Properties filterProps = new Properties(); - - // build time and date XXX set in build script? - String timeString = time+"L"; - // XXX wrong date format - use Version.java template format? - String date = new SimpleDateFormat("MMMM d, yyyy").format(new Date()); - filterProps.setProperty(BUILD_TIME_NAME, timeString); - filterProps.setProperty(BUILD_DATE_NAME, date); - - // build version, short build version, and base build version - // 1.1alpha1, 1.1a1, and 1.1 - String key = BuildSpec.BUILD_VERSION_NAME; - String value = longVersion; - value = value.trim(); - filterProps.setProperty(key, value); - - key = BuildSpec.BUILD_VERSION_LONG_NAME; - filterProps.setProperty(key, value); - - if (!BuildSpec.BUILD_VERSION_DEFAULT.equals(value)) { - value = Util.shortVersion(value); - } - key = BuildSpec.BUILD_VERSION_SHORT_NAME; - filterProps.setProperty(key, value); - - key = BuildSpec.BUILD_VERSION_BASE_NAME; - if (!BuildSpec.BUILD_VERSION_DEFAULT.equals(value)) { - int MAX = value.length(); - for (int i = 0; i < MAX; i++) { - char c = value.charAt(i); - if ((c != '.') && ((c < '0') || (c > '9'))) { - value = value.substring(0,i); - break; - } - } - } - filterProps.setProperty(key, value); - - // company name, copyright XXX fix company name - key = BuildSpec.COMPANY_NAME; - value = System.getProperty(key, BuildSpec.COMPANY_NAME_DEFAULT); - filterProps.setProperty(key, value); - filterProps.setProperty(BuildSpec.COPYRIGHT_NAME, BuildSpec.COPYRIGHT); - - return filterProps; - } + public static final String DEFAULT_VERSION = "DEVELOPMENT"; +// public static final String baseDir_NAME = "aspectj.modules.dir"; +// public static final String stagingDir_NAME = "aj.staging.dir"; +// public static final String jarDir_NAME = "aj.jar.dir"; +// public static final String tempDir_NAME = "aj.temp.dir"; +// public static final String distDir_NAME = "aj.dist.dir"; +// /** name of a system property for reading the build version */ +// public static final String SYSTEM_BUILD_VERSION_KEY = "aspectj.build.version"; +// +// /** value of the build.version if build version not defined */ +// public static final String BUILD_VERSION_DEFAULT = "DEVELOPMENT"; +// +// /** name of a filter property for the normal build version */ +// public static final String BUILD_VERSION_NAME = "build.version"; +// +// /** name of a filter property for the company */ +// public static final String COMPANY_NAME = "company.name"; +// +// /** default value of of a filter property for the company */ +// public static final String COMPANY_NAME_DEFAULT = "aspectj.org"; +// +// /** name of a filter property for the base build version (no alpha, etc.) */ +// public static final String BUILD_VERSION_BASE_NAME = "build.version.base"; +// +// /** copyright property name */ +// public static final String COPYRIGHT_NAME = "copyright.allRights.from1998"; +// +// /** overall copyright */ +// public static final String COPYRIGHT = +// "Copyright (c) 1998-2001 Xerox Corporation, " +// + "2002 Palo Alto Research Center, Incorporated. All rights reserved."; +// +// /** name of a filter property for the long build version (alpha) */ +// public static final String BUILD_VERSION_LONG_NAME = "build.version.long"; +// +// /** name of a filter property for the short build version (alpha -> a, etc.) */ +// public static final String BUILD_VERSION_SHORT_NAME = "build.version.short"; +// +// /** name of a filter property for the build time */ +// public static final String BUILD_TIME_NAME = "build.time"; +// +// /** name of a filter property for the build date */ +// public static final String BUILD_DATE_NAME = "build.date"; +// +// /* default value of build date format by convention tracks +// * build-properties.xml build.date.format. +// */ +// public static final String BUILD_DATE_FORMAT = "EEEE MMM d, yyyy"; +// +// /** unmodifiable List of String keys to build properties */ +// public static final List PROPERTY_NAMES; +// static { +// String[] names = new String[] +// { BUILD_VERSION_NAME, COMPANY_NAME, BUILD_VERSION_BASE_NAME, +// COPYRIGHT_NAME, BUILD_VERSION_LONG_NAME, +// BUILD_VERSION_SHORT_NAME, BUILD_TIME_NAME, +// BUILD_DATE_NAME +// }; +// PROPERTY_NAMES = Collections.unmodifiableList(Arrays.asList(names)); +// } +// +// /** lazily and manually generate properties */ +// public static Properties getBuildProperties(long time, String longVersion) { +// if (time < 1) { +// time = System.currentTimeMillis(); +// } +// if ((null == longVersion) || (0 == longVersion.length())) { +// longVersion = System.getProperty( +// BuildSpec.SYSTEM_BUILD_VERSION_KEY, +// BuildSpec.BUILD_VERSION_DEFAULT); +// } +// Properties filterProps = new Properties(); +// +// // build time and date XXX set in build script? +// String timeString = time+"L"; +// String date = new SimpleDateFormat("MMMM d, yyyy").format(new Date()); +// filterProps.setProperty(BUILD_TIME_NAME, timeString); +// filterProps.setProperty(BUILD_DATE_NAME, date); +// +// // build version, short build version, and base build version +// // 1.1alpha1, 1.1a1, and 1.1 +// String key = BuildSpec.BUILD_VERSION_NAME; +// String value = longVersion; +// value = value.trim(); +// filterProps.setProperty(key, value); +// +// key = BuildSpec.BUILD_VERSION_LONG_NAME; +// filterProps.setProperty(key, value); +// +// if (!BuildSpec.BUILD_VERSION_DEFAULT.equals(value)) { +// value = Util.shortVersion(value); +// } +// key = BuildSpec.BUILD_VERSION_SHORT_NAME; +// filterProps.setProperty(key, value); +// +// key = BuildSpec.BUILD_VERSION_BASE_NAME; +// if (!BuildSpec.BUILD_VERSION_DEFAULT.equals(value)) { +// int MAX = value.length(); +// for (int i = 0; i < MAX; i++) { +// char c = value.charAt(i); +// if ((c != '.') && ((c < '0') || (c > '9'))) { +// value = value.substring(0,i); +// break; +// } +// } +// } +// filterProps.setProperty(key, value); +// +// // company name, copyright XXX fix company name +// key = BuildSpec.COMPANY_NAME; +// value = System.getProperty(key, BuildSpec.COMPANY_NAME_DEFAULT); +// filterProps.setProperty(key, value); +// filterProps.setProperty(BuildSpec.COPYRIGHT_NAME, BuildSpec.COPYRIGHT); +// +// return filterProps; +// } +// // shared public File baseDir; public File moduleDir; @@ -141,6 +161,7 @@ public class BuildSpec { public boolean assembleAll; public boolean failonerror; public boolean verbose; + private Properties buildProperties; // building products public File productDir; @@ -149,6 +170,38 @@ public class BuildSpec { // building modules public String module; + public BuildSpec() { + version = DEFAULT_VERSION; + } + +// /** +// * Generate and cache build properties. +// * @return Properties +// */ +// public Properties getBuildProperties() { +// if (null == buildProperties) { +// long time = System.currentTimeMillis(); +// buildProperties = BuildSpec.getBuildProperties(time, version); +// } else if (null != version) { // check if version is out of sync +// String versionValue = buildProperties.getProperty(BUILD_VERSION_NAME); +// if (!version.equals(versionValue)) { +// // XXX ok, now what - reset? alert? +// } +// } +// return buildProperties; +// } + + public boolean isProduct() { + return (Util.canReadDir(productDir)); + } + + public boolean isModule() { + return (!isProduct() && Util.canReadDir(moduleDir)); + } + + public boolean isValid() { + return (isProduct() || isModule()); + } public String toString() { // XXX better if (null != productDir) { diff --git a/build/src/org/aspectj/internal/tools/build/Builder.java b/build/src/org/aspectj/internal/tools/build/Builder.java index 19c2ecb4b..9798ce320 100644 --- a/build/src/org/aspectj/internal/tools/build/Builder.java +++ b/build/src/org/aspectj/internal/tools/build/Builder.java @@ -11,7 +11,6 @@ * Xerox/PARC initial implementation * ******************************************************************/ - package org.aspectj.internal.tools.build; import org.apache.tools.ant.BuildException; @@ -74,424 +73,495 @@ import java.util.Properties; * Written to compile standalone. Refactor if using utils, bridge, etc. */ public abstract class Builder { - - /** - * This has only weak forms for build instructions needed: - * - resource pattern - * - compiler selection and control - * - * Both assumed and generated paths are scattered; - * see XXXNameLiteral and XXXFileLiteral. - */ - - public static final String RESOURCE_PATTERN - = "**/*.txt,**/*.rsc,**/*.gif,**/*.properties"; - - public static final String BINARY_SOURCE_PATTERN - = "**/*.rsc,**/*.gif,**/*.jar,**/*.zip"; - - public static final String ALL_PATTERN = "**/*"; - - /** enable copy filter semantics */ - protected static final boolean FILTER_ON = true; - - /** disable copy filter semantics */ - protected static final boolean FILTER_OFF = false; - - protected final Messager handler; - protected boolean buildingEnabled; - - private final File tempDir; - private final ArrayList tempFiles; - private final boolean useEclipseCompiles; - - protected boolean verbose; - protected Properties filterProps; - protected boolean filterSetup; - - - protected Builder(File tempDir, boolean useEclipseCompiles, - Messager handler) { - Util.iaxIfNull(handler, "handler"); - this.useEclipseCompiles = useEclipseCompiles; - this.handler = handler; - this.tempFiles = new ArrayList(); - if ((null == tempDir) || !tempDir.canWrite() || !tempDir.isDirectory()) { - this.tempDir = Util.makeTempDir("Builder"); - } else { - this.tempDir = tempDir; - } - buildingEnabled = true; - } - - /** tell builder to stop or that it's ok to run */ - public void setBuildingEnabled(boolean enabled) { - buildingEnabled = enabled; - // XXX support user cancels in eclipse... - } - - public void setVerbose(boolean verbose) { - this.verbose = verbose; - } - - public boolean build(BuildSpec buildSpec) { - if (!buildingEnabled) { - return false; - } - - if (null == buildSpec.productDir) { // ensure module properties - // derive moduleDir from baseDir + module - if (null == buildSpec.moduleDir) { - if (null == buildSpec.baseDir) { - throw new BuildException("require baseDir or moduleDir"); - } else if (null == buildSpec.module) { - throw new BuildException("require module with baseDir"); - } else { - if (null == buildSpec.baseDir) { - buildSpec.baseDir = new File("."); // user.home? - } - buildSpec.moduleDir = new File(buildSpec.baseDir, buildSpec.module); - } - } else if (null == buildSpec.baseDir) { // derive baseDir from moduleDir parent - buildSpec.baseDir = buildSpec.moduleDir.getParentFile(); // rule: base is parent - if (null == buildSpec.baseDir) { - buildSpec.baseDir = new File("."); // user.home? - } - } - Util.iaxIfNotCanReadDir(buildSpec.moduleDir, "moduleDir"); - - if (null == buildSpec.module) { // derive module name from directory - buildSpec.module = buildSpec.moduleDir.getName(); - if (null == buildSpec.module) { - throw new BuildException("no name, even from " + buildSpec.moduleDir); - } - } - } - - if (null != buildSpec.productDir) { - return buildProduct(buildSpec); - } - if (buildSpec.trimTesting && (-1 != buildSpec.module.indexOf("testing"))) { // XXXNameLiteral - String warning = "Warning - cannot trimTesting for testing modules: "; - handler.log(warning + buildSpec.module); - } - Messager handler = new Messager(); - Modules modules = new Modules(buildSpec.baseDir, buildSpec.jarDir, buildSpec.trimTesting, handler); - - final Module moduleToBuild = modules.getModule(buildSpec.module); - ArrayList errors = new ArrayList(); - try { - return buildAll( - moduleToBuild, - errors, - buildSpec.rebuild, - buildSpec.assembleAll); - } finally { - if (0 < errors.size()) { - String label = "error building " + buildSpec + ": "; - for (Iterator iter = errors.iterator(); iter.hasNext();) { - handler.error(label + iter.next()); - } - } - } - } - - /** - * Clean up any temporary files, etc. after build completes - */ - public boolean cleanup() { - boolean noErr = true; - for (ListIterator iter = tempFiles.listIterator(); iter.hasNext();) { + + /** + * This has only weak forms for build instructions needed: + * - resource pattern + * - compiler selection and control + * + * Both assumed and generated paths are scattered; + * see XXXNameLiteral and XXXFileLiteral. + * + * Builder is supposed to be thread-safe, but currently caches build + * properties to tunnel for filters. hmm. + */ + + public static final String RESOURCE_PATTERN = + "**/*.txt,**/*.rsc,**/*.gif,**/*.properties"; + + public static final String BINARY_SOURCE_PATTERN = + "**/*.rsc,**/*.gif,**/*.jar,**/*.zip"; + + public static final String ALL_PATTERN = "**/*"; + + /** enable copy filter semantics */ + protected static final boolean FILTER_ON = true; + + /** disable copy filter semantics */ + protected static final boolean FILTER_OFF = false; + + protected final Messager handler; + protected boolean buildingEnabled; + + private final File tempDir; + private final ArrayList tempFiles; + private final boolean useEclipseCompiles; + + protected boolean verbose; + + protected Builder( + File tempDir, + boolean useEclipseCompiles, + Messager handler) { + Util.iaxIfNull(handler, "handler"); + this.useEclipseCompiles = useEclipseCompiles; + this.handler = handler; + this.tempFiles = new ArrayList(); + if ((null == tempDir) + || !tempDir.canWrite() + || !tempDir.isDirectory()) { + this.tempDir = Util.makeTempDir("Builder"); + } else { + this.tempDir = tempDir; + } + buildingEnabled = true; + } + + /** tell builder to stop or that it's ok to run */ + public void setBuildingEnabled(boolean enabled) { + buildingEnabled = enabled; + } + + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + public boolean build(BuildSpec buildSpec) { + if (!buildingEnabled) { + return false; + } + if (null == buildSpec.productDir) { // ensure module properties + // derive moduleDir from baseDir + module + if (null == buildSpec.moduleDir) { + if (null == buildSpec.baseDir) { + throw new BuildException("require baseDir or moduleDir"); + } else if (null == buildSpec.module) { + throw new BuildException("require module with baseDir"); + } else { + if (null == buildSpec.baseDir) { + buildSpec.baseDir = new File("."); // user.home? + } + buildSpec.moduleDir = + new File(buildSpec.baseDir, buildSpec.module); + } + } else if (null == buildSpec.baseDir) { + // derive baseDir from moduleDir parent + buildSpec.baseDir = buildSpec.moduleDir.getParentFile(); + // rule: base is parent + if (null == buildSpec.baseDir) { + buildSpec.baseDir = new File("."); // user.home? + } + handler.log("Builder using derived baseDir: " + + buildSpec.baseDir); + } + Util.iaxIfNotCanReadDir(buildSpec.moduleDir, "moduleDir"); + + if (null == buildSpec.module) { + // derive module name from directory + buildSpec.module = buildSpec.moduleDir.getName(); + if (null == buildSpec.module) { + throw new BuildException( + "no name, even from " + buildSpec.moduleDir); + } + } + } + + if (null != buildSpec.productDir) { + return buildProduct(buildSpec); + } + if (buildSpec.trimTesting + && (-1 != buildSpec.module.indexOf("testing"))) { // XXXNameLiteral + String warning = + "Warning - cannot trimTesting for testing modules: "; + handler.log(warning + buildSpec.module); + } + Messager handler = new Messager(); + Modules modules = + new Modules( + buildSpec.baseDir, + buildSpec.jarDir, + buildSpec.trimTesting, + handler); + + final Module moduleToBuild = modules.getModule(buildSpec.module); + ArrayList errors = new ArrayList(); + try { + return buildAll( + moduleToBuild, + errors, + buildSpec.rebuild, + buildSpec.assembleAll); + } finally { + if (0 < errors.size()) { + String label = "error building " + buildSpec + ": "; + for (Iterator iter = errors.iterator(); iter.hasNext();) { + handler.error(label + iter.next()); + } + } + } + } + + /** + * Clean up any temporary files, etc. after build completes + */ + public boolean cleanup() { + boolean noErr = true; + for (ListIterator iter = tempFiles.listIterator(); + iter.hasNext(); + ) { File file = (File) iter.next(); - if (!Util.deleteContents(file) || !file.delete()) { - if (noErr) { - noErr = false; - } - handler.log("unable to clean up " + file); - } + if (!Util.deleteContents(file) || !file.delete()) { + if (noErr) { + noErr = false; + } + handler.log("unable to clean up " + file); + } } - return noErr; - } - - /** - * Build a module with all antecedants. - * @param module the Module to build - * @param errors the List sink for errors, if any - * @return false after successful build, when module jar should exist - */ - protected boolean buildAll(Module module, List errors, boolean rebuild, boolean assembleAll) { - String[] buildList = getAntecedantModuleNames(module, rebuild); - if ((null != buildList) && (0 < buildList.length)) { - final Modules modules = module.getModules(); - final Messager handler = this.handler; - final boolean log = (verbose && (null != handler)); - final boolean verbose = this.verbose; - if (log) { - handler.log("modules to build: " + Arrays.asList(buildList)); - } - for (int i = 0; i < buildList.length; i++) { - - if (!buildingEnabled) { - return false; - } - String modName = buildList[i]; - if (log) { - handler.log("building " + modName); - } - Module next = modules.getModule(modName); - if (!buildOnly(next, errors)) { - return false; - } - } - } - if (assembleAll && !assembleAll(module, handler)) { - return false; - } - return true; - } - - /** - * Build a module but no antecedants. - * @param module the Module to build - * @param errors the List sink for errors, if any - * @return false after successful build, when module jar should exist - */ - protected boolean buildOnly(Module module, List errors) { - if (!buildingEnabled) { - return false; - } - File classesDir = useEclipseCompiles - ? new File(module.moduleDir, "bin") // XXXFileLiteral - : new File(tempDir, "classes-" + System.currentTimeMillis()); - if (verbose) { - handler.log("buildOnly " + module); - } - try { - return (useEclipseCompiles || compile(module, classesDir, errors)) - && assemble(module, classesDir, errors); - } finally { - if (!useEclipseCompiles - && (!Util.deleteContents(classesDir) || !classesDir.delete())) { - errors.add("unable to delete " + classesDir); - } - } - } - - /** - * Register temporary file or directory to be deleted when - * the build is complete, even if an Exception is thrown. - */ - protected void addTempFile(File tempFile) { - if (null != tempFile) { - tempFiles.add(tempFile); - } - } - /** - * Build product by discovering any modules to build, - * building those, assembling the product distribution, - * and optionally creating an installer for it. - * @return true on success - */ - protected boolean buildProduct(BuildSpec buildSpec) - throws BuildException { - Util.iaxIfNull(buildSpec, "buildSpec"); - // XXX if installer and not out of date, do not rebuild unless rebuild set - - if (!buildSpec.trimTesting) { - buildSpec.trimTesting = true; - handler.log("testing trimmed for " + buildSpec); - } - Util.iaxIfNotCanReadDir(buildSpec.productDir, "productDir"); - Util.iaxIfNotCanReadDir(buildSpec.baseDir, "baseDir"); - Util.iaxIfNotCanWriteDir(buildSpec.distDir, "distDir"); - - // ---- discover modules to build, and build them - Modules modules = new Modules( - buildSpec.baseDir, - buildSpec.jarDir, - buildSpec.trimTesting, - handler); - ProductModule[] productModules = discoverModules(buildSpec.productDir, modules); - for (int i = 0; i < productModules.length; i++) { - if (buildSpec.verbose) { - handler.log("building product module " + productModules[i]); - } - if (!buildProductModule(productModules[i])) { - return false; - } - } - if (buildSpec.verbose) { - handler.log("assembling product module for " + buildSpec); - } - - // ---- assemble product distribution - final String productName = buildSpec.productDir.getName(); - final File targDir = new File(buildSpec.distDir, productName); - final String targDirPath = targDir.getPath(); - if (targDir.canWrite()) { - Util.deleteContents(targDir); - } - - if (!targDir.canWrite() && !targDir.mkdirs()) { - if (buildSpec.verbose) { - handler.log("unable to create " + targDir); - } - return false; - } - // filter-copy everything but the binaries - File distDir = new File(buildSpec.productDir, "dist"); // XXXFileLiteral - String excludes = Builder.BINARY_SOURCE_PATTERN; - String includes = Builder.ALL_PATTERN; - if (!copyFiles(distDir, targDir, includes, excludes, FILTER_ON)) { - return false; - } - - // copy binaries (but not module flag files) - excludes = null; - { - StringBuffer buf = new StringBuffer(); - for (int i = 0; i < productModules.length; i++) { - if (0 < buf.length()) { - buf.append(","); - } - buf.append(productModules[i].relativePath); - } - if (0 < buf.length()) { - excludes = buf.toString(); - } - } - includes = Builder.BINARY_SOURCE_PATTERN; - if (!copyFiles(distDir, targDir, includes, excludes, FILTER_OFF)) { - return false; - } - - // copy binaries associated with module flag files - for (int i = 0; i < productModules.length; i++) { - ProductModule product = productModules[i]; - String targPath = targDirPath + "/" + product.relativePath; - File jarFile = (product.assembleAll - ? product.module.getAssembledJar() - : product.module.getModuleJar() ); - copyFile(jarFile, new File(targPath), FILTER_OFF); - } - handler.log("created product in " + targDir); - - // ---- create installer - if (buildSpec.createInstaller) { - return buildInstaller(buildSpec, targDirPath); - } else { - return true; - } - } - - protected boolean buildProductModule(ProductModule module) { - boolean noRebuild = false; - ArrayList errors = new ArrayList(); - try { - return buildAll(module.module, errors, noRebuild, module.assembleAll); - } finally { - for (Iterator iter = errors.iterator(); iter.hasNext();) { - handler.error("error building " + module + ": " + iter.next()); - } - } - } - - /** - * Discover any modules that might need to be built - * in order to assemble the product distribution. - * This interprets empty .jar files as module deliverables. - */ - protected ProductModule[] discoverModules(File productDir, Modules modules) { - final ArrayList found = new ArrayList(); - FileFilter filter = new FileFilter() { - public boolean accept(File file) { - if ((null != file) - && file.canRead() - && file.getPath().endsWith(".jar") // XXXFileLiteral - && (0l == file.length())) { - found.add(file); - } - return true; - } - }; - Util.visitFiles(productDir, filter); - ArrayList results = new ArrayList(); - for (Iterator iter = found.iterator(); iter.hasNext();) { - File file = (File) iter.next(); - String jarName = moduleAliasFor(file.getName().toLowerCase()); - if (jarName.endsWith(".jar") || jarName.endsWith(".zip")) { // XXXFileLiteral - jarName = jarName.substring(0, jarName.length()-4); - } else { - handler.log("can only replace .[jar|zip]: " + file); // XXX error? - } - boolean assembleAll = jarName.endsWith("-all"); // XXXFileLiteral - String name = (!assembleAll ? jarName : jarName.substring(0, jarName.length()-4)); - Module module = modules.getModule(name); - if (null == module) { - handler.log("unable to find module for " + file); - } else { - results.add(new ProductModule(productDir, file, module, assembleAll)); - } - } - return (ProductModule[]) results.toArray(new ProductModule[0]); - } - - /** - * Map delivered-jar name to created-module name - * @param jarName the String (lowercased) of the jar/zip to map - */ - protected String moduleAliasFor(String jarName) { - if ("aspectjtools.jar".equals(jarName)) { // XXXFileLiteral - return "ajbrowser-all.jar"; - } else if ("aspectjrt.jar".equals(jarName)) { - return "runtime.jar"; - } else { - return jarName; - } - } - - /** - * @return String[] names of modules to build for this module - */ - abstract protected String[] getAntecedantModuleNames(Module toBuild, boolean rebuild); - - /** - * Compile module classes to classesDir, saving String errors. - */ - abstract protected boolean compile(Module module, File classesDir, List errors); - - /** - * Assemble the module distribution from the classesDir, saving String errors. - */ - abstract protected boolean assemble(Module module, File classesDir, List errors); - - /** - * Assemble the module distribution from the classesDir and all antecendants, - * saving String errors. - */ - abstract protected boolean assembleAll(Module module, Messager handler); - - /** - * Generate the installer for this product to targDirPath - */ - abstract protected boolean buildInstaller(BuildSpec buildSpec, String targDirPath); - - /** - * Copy fromFile to toFile, optionally filtering contents - */ - abstract protected boolean copyFile(File fromFile, File toFile, boolean filter); - - /** - * Copy toDir any fromDir included files without any exluded files, - * optionally filtering contents. - * @param fromDir File dir to read from - error if not readable - * @param toDir File dir to write to - error if not writable - * @param included String Ant pattern of included files (if null, include all) - * @param excluded String Ant pattern of excluded files (if null, exclude none) - * @param filter if FILTER_ON, then filter file contents using global token/value pairs - */ - abstract protected boolean copyFiles(File fromDir, File toDir, String included, String excluded, boolean filter); -} - + return noErr; + } + + /** + * Build a module with all antecedants. + * @param module the Module to build + * @param errors the List sink for errors, if any + * @return false after successful build, when module jar should exist + */ + protected boolean buildAll( + Module module, + List errors, + boolean rebuild, + boolean assembleAll) { + String[] buildList = getAntecedantModuleNames(module, rebuild); + if ((null != buildList) && (0 < buildList.length)) { + final Modules modules = module.getModules(); + final Messager handler = this.handler; + final boolean log = (verbose && (null != handler)); + final boolean verbose = this.verbose; + if (log) { + handler.log( + "modules to build: " + Arrays.asList(buildList)); + } + for (int i = 0; i < buildList.length; i++) { + + if (!buildingEnabled) { + return false; + } + String modName = buildList[i]; + if (log) { + handler.log("building " + modName); + } + Module next = modules.getModule(modName); + if (!buildOnly(next, errors)) { + return false; + } + } + } + if (assembleAll && !assembleAll(module, handler)) { + return false; + } + return true; + } + + /** + * Build a module but no antecedants. + * @param module the Module to build + * @param errors the List sink for errors, if any + * @return false after successful build, when module jar should exist + */ + protected boolean buildOnly(Module module, List errors) { + if (!buildingEnabled) { + return false; + } + File classesDir = + useEclipseCompiles + ? new File(module.moduleDir, "bin") // FileLiteral + : new File(tempDir, "classes-" + System.currentTimeMillis()); + if (verbose) { + handler.log("buildOnly " + module); + } + try { + return ( + useEclipseCompiles || compile(module, classesDir, errors)) + && assemble(module, classesDir, errors); + } finally { + if (!useEclipseCompiles + && (!Util.deleteContents(classesDir) + || !classesDir.delete())) { + errors.add("unable to delete " + classesDir); + } + } + } + /** + * Register temporary file or directory to be deleted when + * the build is complete, even if an Exception is thrown. + */ + protected void addTempFile(File tempFile) { + if (null != tempFile) { + tempFiles.add(tempFile); + } + } + /** + * Build product by discovering any modules to build, + * building those, assembling the product distribution, + * and optionally creating an installer for it. + * @return true on success + */ + protected boolean buildProduct(BuildSpec buildSpec) + throws BuildException { + Util.iaxIfNull(buildSpec, "buildSpec"); + // XXX if installer and not out of date, do not rebuild unless rebuild set + + if (!buildSpec.trimTesting) { + buildSpec.trimTesting = true; + handler.log("testing trimmed for " + buildSpec); + } + Util.iaxIfNotCanReadDir(buildSpec.productDir, "productDir"); + Util.iaxIfNotCanReadDir(buildSpec.baseDir, "baseDir"); + Util.iaxIfNotCanWriteDir(buildSpec.distDir, "distDir"); + + // ---- discover modules to build, and build them + Modules modules = + new Modules( + buildSpec.baseDir, + buildSpec.jarDir, + buildSpec.trimTesting, + handler); + ProductModule[] productModules = + discoverModules(buildSpec.productDir, modules); + for (int i = 0; i < productModules.length; i++) { + if (buildSpec.verbose) { + handler.log( + "building product module " + productModules[i]); + } + if (!buildProductModule(productModules[i])) { + return false; + } + } + if (buildSpec.verbose) { + handler.log("assembling product module for " + buildSpec); + } + + // ---- assemble product distribution + final String productName = buildSpec.productDir.getName(); + final File targDir = new File(buildSpec.distDir, productName); + final String targDirPath = targDir.getPath(); + if (targDir.canWrite()) { + Util.deleteContents(targDir); + } + + if (!targDir.canWrite() && !targDir.mkdirs()) { + if (buildSpec.verbose) { + handler.log("unable to create " + targDir); + } + return false; + } + // filter-copy everything but the binaries + File distDir = new File(buildSpec.productDir, "dist"); + // XXXFileLiteral + String excludes = Builder.BINARY_SOURCE_PATTERN; + String includes = Builder.ALL_PATTERN; + if (!copyFiles(distDir, targDir, includes, excludes, FILTER_ON)) { + return false; + } + + // copy binaries (but not module flag files) + excludes = null; + { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < productModules.length; i++) { + if (0 < buf.length()) { + buf.append(","); + } + buf.append(productModules[i].relativePath); + } + if (0 < buf.length()) { + excludes = buf.toString(); + } + } + includes = Builder.BINARY_SOURCE_PATTERN; + if (!copyFiles(distDir, + targDir, + includes, + excludes, + FILTER_OFF)) { + return false; + } + + // copy binaries associated with module flag files + for (int i = 0; i < productModules.length; i++) { + ProductModule product = productModules[i]; + String targPath = targDirPath + "/" + product.relativePath; + File jarFile = + (product.assembleAll + ? product.module.getAssembledJar() + : product.module.getModuleJar()); + copyFile(jarFile, new File(targPath), FILTER_OFF); + } + handler.log("created product in " + targDir); + // ---- create installer + if (buildSpec.createInstaller) { + return buildInstaller(buildSpec, targDirPath); + } else { + return true; + } + } + + protected boolean buildProductModule(ProductModule module) { + boolean noRebuild = false; + ArrayList errors = new ArrayList(); + try { + return buildAll( + module.module, + errors, + noRebuild, + module.assembleAll); + } finally { + for (Iterator iter = errors.iterator(); iter.hasNext();) { + handler.error( + "error building " + module + ": " + iter.next()); + } + } + } + + /** + * Discover any modules that might need to be built + * in order to assemble the product distribution. + * This interprets empty .jar files as module deliverables. + */ + protected ProductModule[] discoverModules( + File productDir, + Modules modules) { + final ArrayList found = new ArrayList(); + FileFilter filter = new FileFilter() {// empty jar files + public boolean accept(File file) { + if ((null != file) + && file.canRead() + && file.getPath().endsWith( + ".jar") // XXXFileLiteral + && (0l == file.length())) { + found.add(file); + } + return true; + } + }; + Util.visitFiles(productDir, filter); + ArrayList results = new ArrayList(); + for (Iterator iter = found.iterator(); iter.hasNext();) { + File file = (File) iter.next(); + String jarName = moduleAliasFor(file.getName().toLowerCase()); + if (jarName.endsWith(".jar") + || jarName.endsWith(".zip")) { // XXXFileLiteral + jarName = jarName.substring(0, jarName.length() - 4); + } else { + handler.log("can only replace .[jar|zip]: " + file); + // XXX error? + } + boolean assembleAll = jarName.endsWith("-all"); + // XXXFileLiteral + String name = + (!assembleAll + ? jarName + : jarName.substring(0, jarName.length() - 4)); + Module module = modules.getModule(name); + if (null == module) { + handler.log("unable to find module for " + file); + } else { + results.add( + new ProductModule( + productDir, + file, + module, + assembleAll)); + } + } + return (ProductModule[]) results.toArray(new ProductModule[0]); + } + + /** + * Map delivered-jar name to created-module name + * @param jarName the String (lowercased) of the jar/zip to map + */ + protected String moduleAliasFor(String jarName) { + if ("aspectjtools.jar".equals(jarName)) { // XXXFileLiteral + return "ajbrowser-all.jar"; + } else if ("aspectjrt.jar".equals(jarName)) { + return "runtime.jar"; + } else { + return jarName; + } + } + + /** + * @return String[] names of modules to build for this module + */ + abstract protected String[] getAntecedantModuleNames( + Module toBuild, + boolean rebuild); + + /** + * Compile module classes to classesDir, saving String errors. + */ + abstract protected boolean compile( + Module module, + File classesDir, + List errors); + + /** + * Assemble the module distribution from the classesDir, saving String errors. + */ + abstract protected boolean assemble( + Module module, + File classesDir, + List errors); + + /** + * Assemble the module distribution from the classesDir and all antecendants, + * saving String errors. + */ + abstract protected boolean assembleAll( + Module module, + Messager handler); + + /** + * Generate the installer for this product to targDirPath + */ + abstract protected boolean buildInstaller( + BuildSpec buildSpec, + String targDirPath); + + /** + * Copy fromFile to toFile, optionally filtering contents + */ + abstract protected boolean copyFile( + File fromFile, + File toFile, + boolean filter); + + /** + * Copy toDir any fromDir included files without any exluded files, + * optionally filtering contents. + * @param fromDir File dir to read from - error if not readable + * @param toDir File dir to write to - error if not writable + * @param included String Ant pattern of included files (if null, include all) + * @param excluded String Ant pattern of excluded files (if null, exclude none) + * @param filter if FILTER_ON, then filter file contents using global token/value pairs + */ + abstract protected boolean copyFiles( + File fromDir, + File toDir, + String included, + String excluded, + boolean filter); +} |