<?xml version="1.0"?>

<!--
 !   TOPCAT build file
 !
 !   This file describes how to build and install {Package}
 !   from a source and binary release. {Package} is an application
 !   package, i.e. provides user-level commands and interfaces, as
 !   well as a programming API.
 !
 !   The main targets are:
 !
 !      build            -> compiles the source code
 !      clean            -> cleans up build and dist products
 !      deinstall        -> undo the install target
 !      dist             -> creates the local binary distribution
 !      export           -> creates the full distribution archives
 !      export-runonly   -> creates the runonly distribution archives
 !      export-source    -> creates the source distribution archives
 !      install          -> installs the distribution
 !      install-runonly  -> installs a runonly distribution
 !      jars             -> creates the package jar file(s)
 !      javadocs         -> creates the package API documentation
 !      javadoc-sources  -> make source files for release API documention
 !      test             -> runs JUnit test cases
 !
 !   Targets specific to TOPCAT:
 !      build-standalone -> builds topcat-full.jar, topcat-lite.jar
 !      docs-pdf         -> builds sun253.pdf
 !
 !   Authors:
 !      Peter W. Draper (17-SEP-2002)
 !
 !   Version:
 !      $Id$
 !
 !-->

<project name="Build file for TOPCAT" default="build" basedir=".">

  <!-- If either or both of these files exist then any properties
   !   contained within them will override those defined here.  -->
  <property file="${user.home}/.stardev.properties"/>
  <property file=".properties"/>

  <!-- Properties will also be set for all environment variables
   !   (PATH becomes "env.PATH"), generally not a good
   !   idea as names are OS dependent -->
  <property environment="env"/>

  <!--
   !  =================
   !  Global Properties
   !  =================
   !-->

  <!-- Directory for the Starlink installation (usually /star/java)-->
  <property name="star.dir" value="${basedir}/../../"/>

  <!-- Directory to install into (install target, usually /star/java)-->
  <property name="star.install" value="${star.dir}"/>

  <!-- Directory that contains the Starlink jar tree -->
  <property name="star.jar.dir" value="${star.dir}/lib"/>

  <!-- Directory that contains the locally built sources (usually
   !   /star/java/source for full distribution) -->
  <property name="star.build.dir" value="${basedir}/../"/>

  <!-- Directory that any archives should be placed into. The local
   !   directory by default -->
  <property name="star.archive.dir" value="${basedir}"/>

  <!-- URL and package-list for linking against full Java docs -->
  <property name="javaapi.url" value="https://docs.oracle.com/javase/8/docs/api/"/>
  <property name="javaapi.lis" value="${star.build.dir}/src/docs/javaapi/"/>

  <!--
   !  ================
   !  Local Properties
   !  ================
   !-->

  <!-- Define the package name and current versions -->
  <property name="Name" value="TOPCAT"/>
  <property name="name" value="topcat"/>
  <property name="version" value="4.8"/>

  <!-- The Java package name -->
  <property name="package.name" value="uk.ac.starlink.topcat"/>

  <!-- Compilation options -->
  <property name="debug" value="true"/>
  <property name="deprecation" value="false"/>
  <property name="optimize" value="true"/>
  <property name="source.version" value="1.8"/>

  <!-- Extra task options, if any -->
  <property name="chmod.fail" value="false"/>

  <!-- JUnit test options -->
  <property name="junit.fork" value="false"/>
  <property name="junit.filtertrace" value="on"/>
  <property name="junit.summary" value="no"/>
  <property name="junit.assertions" value="-enableassertions"/>

  <!-- Directory containing the package source -->
  <property name="src.dir" value="${basedir}/src"/>

  <!-- Directory containing the java source (top of the namespace)-->
  <property name="java.dir" value="${src.dir}/main"/>

  <!-- Directory containing miscellaneous docs -->
  <property name="user.doc" value="sun253"/>
  <property name="src.docs" value="${src.dir}/docs"/>
  <property name="xdoc.etc" value="${star.dir}/etc/xdoc"/>
  <property name="gbin.docs" value="${star.dir}/docs/gbin"/>

  <!-- Directory containing any script required to execute or setup package-->
  <property name="script.dir" value="${src.dir}/script"/>

  <!-- Directory containing any third-party jars that should be
   !   distributed (normally these would belong in a proper package)-->
  <property name="src.jars.dir" value="${src.dir}/lib"/>

  <!-- Directory containing any JNI source code -->
  <property name="src.jni.dir" value="${src.dir}/jni"/>

  <!-- Directory for demo data -->
  <property name="src.etc" value="${src.dir}/etc"/>

  <!-- Directories for JUnit test cases and related files -->
  <property name="tests.dir" value="${src.dir}/testcases"/>
  <property name="tests.etc.dir" value="${src.dir}/etc/testcases"/>

  <!-- File types that should not be passed through a filterchain when
   !   copying -->
  <property name="unfiltered.files"
            value="**/*.gif,**/*.png,**/*.jpg,**/*.ico"/>

  <!-- Directories to receive the various build components -->
  <property name="build.dir" value="${basedir}/build"/>
  <property name="build.classes" value="${build.dir}/classes"/>
  <property name="build.javadocs" value="${build.dir}/javadocs"/>
  <property name="build.docs" value="${build.dir}/docs"/>
  <property name="build.etc" value="${build.dir}/etc"/>
  <property name="build.java" value="${build.dir}/java"/>
  <property name="build.tests" value="${build.dir}/testcases"/>
  <property name="build.tests.javadocs" value="${build.dir}/javadocs.test/"/>

  <!-- Distribution directories, these are created in the current
   !   directory, unless dist.dir is redefined. Files that will be
   !   installed under a package name prefixed directory should be
   !   placed in the ".pkg" variants. Note some build components may
   !   be placed directly here for efficiency-->
  <property name="dist.dir" value="${basedir}"/>
  <property name="dist.bin" value="${dist.dir}/bin"/>
  <property name="dist.lib" value="${dist.dir}/lib"/>
  <property name="dist.src" value="${dist.dir}/src"/>
  <property name="dist.docs" value="${dist.dir}/docs"/>
  <property name="dist.etc" value="${dist.dir}/etc"/>
  <property name="dist.osx" value="${dist.dir}/osx-${name}"/>
  <property name="dist.osx.bin"
            value="${dist.osx}/${Name}.app/Contents/Resources/bin"/>
  <property name="dist.osx.docs"
            value="${dist.osx}/${Name}.app/Contents/Resources/docs"/>
  <property name="dist.dmgfile" value="${dist.dir}/${name}-full.dmg"/>

  <property name="dist.bin.pkg" value="${dist.bin}"/>
  <property name="dist.lib.pkg" value="${dist.lib}/${name}"/>
  <property name="dist.docs.pkg" value="${dist.docs}/${name}"/>
  <property name="dist.etc.pkg" value="${dist.etc}/${name}"/>
  <property name="dist.javadocs" value="${dist.docs}/${name}/javadocs"/>

  <!-- Version for zipped/tarred export files. -->
  <property name="dist.version" value="${name}-${version}"/>

  <!-- File for logging the files that are copied by the install target -->
  <property name="install.log" value=".${name}.install"/>
  <property name="install.overwrite" value="true"/>

  <!-- Local webstart properties. Note this needs a local keystore,
   !   assumed to be called keystore in $star.build.dir, .. by
   !   default. -->
  <property name="webstart.codebase" 
           value="http://starlink.jach.hawaii.edu/starjava/lib"/>
  <property name="webstart.alias" value="Starlink-UK"/>
  <property name="webstart.keystore" value="${star.build.dir}/keystore"/>
  <property name="webstart.keypass" value="Vroomfondel"/>
  <property name="webstart.storepass" value="Majikthise"/>
  <property name="webstart.starlink_logo" value="starlink_logo_med.gif"/>
  <property name="home.page" value="http://www.starlink.ac.uk/${name}/"/>

  <!-- Directory containing plot2 example graphics in the TTOOLS package. -->
  <property name="plot2.figdir"
            value="${star.build.dir}/ttools/src/docs/examp"/>

  <!-- Add any local ANT tasks that are required (these should be
   !   moved to ANT if useful beyond the needs of this package) -->

  <!--
   !   =========
   !   CLASSPATH
   !   =========
   !-->

  <!-- Name all the jar files that we directly depend on. These will be
   !   used to produce a full CLASSPATH that is equivalent to that
   !   generated when these are referenced as optional bundled packages.
   !   It's best to have a classpath (rather than use the extension
   !   mechanism) during development as this allows us to compile
   !   without having to work these dependencies out anyway (may
   !   be fixed in Java1.5) plus we can execute against locally built
   !   class files in preference to installed ones (an extra user-define
   !   defined CLASSPATH can also be used as needed).
   !-->
  <extclasspath id="installed.classpath">

    <!-- Table -->
    <pathelement location="${star.jar.dir}/table/table.jar"/>

    <!-- TTOOLS -->
    <pathelement location="${star.jar.dir}/ttools/ttools.jar"/>

    <!-- Help -->
    <pathelement location="${star.jar.dir}/help/jhall.jar"/>

    <!-- Util -->
    <pathelement location="${star.jar.dir}/util/util.jar"/>

  </extclasspath>

  <!-- Generate the local build classpath. This is the most difficult
   !   part of handling the classpath. The local classes will be in
   !   the "build/classes" part of each package, plus third party
   !   packages will have their jar files in the "dist" directories.
   !   Having the third party jars not installed means that building a
   !   classpath based on their manifest class-paths will not resolve
   !   all references (these may be to other third party jars, that
   !   are normally resolved using relative URLs). The way that this
   !   is resolved is simply to locate all "build/classes" directories
   !   and all jar files in the "dist" parts and just add these all
   !   to the classpath. Known third party dependencies are added
   !   after the "build/classes" directories using the "extclasspath"
   !   type, just so that they will be referred to first. If this
   !   doesn't work as expected add the additional classes/jars to
   !   the extra classpath.
   !-->
  <extclasspath id="built.jarpath">
    <pathelement location="${star.build.jar}/util/lib/util/util.jar"/>
    <pathelement location="${star.build.jar}/table/lib/table/table.jar"/>
    <pathelement location="${star.build.jar}/ttools/lib/ttools/ttools.jar"/>
    <pathelement location="${star.build.jar}/help/lib/help/jhall.jar"/>
  </extclasspath>

  <!-- "Local" third party jars. Normally these will be kept in their
   !   own third party package, but may be kept here temporarily, say
   !   if there are version conflicts that cannot be addressed.
   !   They are installed with the package jar files and should be
   !   entered into the main jar file manifest.
   !-->
  <path id="package.jars">
     <fileset dir="${src.jars.dir}">
        <include name="*.jar"/>
     </fileset>
  </path>

  <path id="built.classpath">

    <!-- Local third party jars -->
    <path refid="package.jars"/>

    <!-- All locally built classes -->
    <dirset dir="${star.build.dir}">
      <include name="*/build/classes"/>
    </dirset>

    <!-- Directly dependent third party jars -->
    <path refid="built.jarpath"/>

    <!-- Finally add all "dist" jar files to make sure everything is
     !   resolved, including relative URLs out of the local package -->
    <fileset dir="${star.build.dir}">
      <include name="*/lib/*/*.jar"/>
    </fileset>

    <!-- Note in passing a more elegant way to resolve these jars
     !   would be to extend <extclasspath> to go looking for dependent
     !   jars using an additional URL resolving mechanism-->

  </path>

  <!-- Extra user-defined classpath. This is set by the property
   !   "extra.class.path" (which can be defined locally using say
   !   -Dextra.class.path=$CLASSPATH on the command line or by setting
   !   the property in either of the properties files.-->
  <property name="extra.class.path" value=""/>
  <path id="local.classpath" path="${extra.class.path}"/>

  <!-- Unification of all classpaths using extra, built, installed order-->
  <path id="classpath">
    <path refid="local.classpath"/>
    <path refid="built.classpath"/>
    <path refid="installed.classpath"/>
  </path>

  <!-- JUnit tests classpath, add tests.dir and tests.etc.dir so that
   !   resources may be located there -->
  <path id="tests-classpath">
    <pathelement location="${build.classes}"/>
    <pathelement location="${build.tests}"/>
    <pathelement location="${tests.dir}"/>
    <pathelement location="${tests.etc.dir}"/>
    <pathelement location="${star.jar.dir}/xdoc/xdoc.jar"/>
    <path refid="classpath"/>
  </path>

  <!-- Need installed JNIAST for javadoc fun and games - this seems to do it
   !   (though maybe means the main classpath is broken??) -->
  <path id="docs-classpath">
    <path refid="installed.classpath"/>
    <path refid="classpath"/>
  </path>

  <!-- Turn this path into a string which is passed to the tests -->
  <property name="tests-classpath.value" refid="tests-classpath"/>

  <!--
   !    ============
   !    Library path
   !    ============
   !    Used by test targets for locating native libraries.
   !-->
  <path id="tests-libpath.id">
    <pathelement path="${java.library.path}"/>
    <pathelement location="${star.jar.dir}/${os.arch}"/>
  </path>
  <property name="tests-libpath" refid="tests-libpath.id"/>

  <!--
   !    =========================================
   !    Check availability of direct dependencies
   !    =========================================
   !    (could also use this to check optional elements).
   !
   ! If any of the required dependencies are not present then
   ! this throws a <fail> and exits the build.
   !-->
  <target name="check_packages"
          unless="runonly.install">

    <!-- UTIL -->
    <available property="util.present"
               classpathref="classpath"
               classname="uk.ac.starlink.util.DataSource"/>
    <fail message="No UTIL available" unless="util.present"/>

    <!-- TABLE -->
    <available property="table.present"
               classpathref="classpath"
               classname="uk.ac.starlink.table.StarTable"/>
    <fail message="No TABLE available" unless="table.present"/>

    <!-- HELP -->
    <available property="help.present"
               classpathref="classpath"
               classname="javax.help.JHelp"/>
    <fail message="No HELP available" unless="help.present"/>

    <!-- Need JUnit for testcases, not essential -->
    <available property="junit.present"
               classpathref="classpath"
               classname="junit.framework.TestCase"/>

  </target>

  <!--
   !   =================
   !   Prepare the build
   !   =================
   !
   !  Do any jobs that are required before any other target can proceed.
   !-->
  <target name="prepare">

    <tstamp>
      <format property="year" pattern="yyyy"/>
    </tstamp>

    <!-- Human-readable copyright string -->
    <property name="copyright.string"
              value="Copyright &#169; 2003-${year} CCLRC: Council for the Central Laboratory of the Research Councils.  All Rights Reserved."/>

    <!-- This is a filterchain that can be used to copy-edit files
     !   that require the package version, current date and/or time -->
    <filterchain id="filters">
      <replacetokens>
        <token key="VERSION" value="${version}"/>
        <token key="DATE" value="${TODAY}"/>
        <token key="TIME" value="${TSTAMP}"/>
      </replacetokens>
    </filterchain>

  </target>


  <!--
   !   ==============
   !   Build the code
   !   ==============
   !
   !  The results of the compilation are placed in the build.classes
   !  directory. Other files that are also needed in the classes tree
   !  (i.e. resources like images and property files) should also be
   !  copied into place here. 
   !-->
  <target name="build"
          depends="prepare, check_packages"
          unless="runonly.install"
          description="-> compiles the source code">

    <mkdir dir="${build.classes}"/>
    <javac srcdir="${java.dir}"
           destdir="${build.classes}"
           debug="${debug}"
           deprecation="${deprecation}"
           source="${source.version}"
           optimize="${optimize}">
      <compilerarg value="-Xlint:all,-path,-serial"/>

      <classpath refid="classpath"/>

      <!-- Exclude any files in the source tree that should not be
       !   compiled -->
      <exclude name="**/{Retired1.java}"/>
      <exclude name="**/{Retired2.java}"/>
      <exclude name="**/*.html"/>
      <exclude name="**/*.properties*"/>
    </javac>

    <!-- Copy extra files that should live with packages classes
     !   (i.e. are discovered using "getResource()"). -->
    <copy todir="${build.classes}">
      <fileset dir="${src.dir}/resources"/>
    </copy>
    <copy todir="${build.classes}/uk/ac/starlink/topcat">
      <fileset dir="${src.docs}" includes="figures/*"/>
    </copy>
    <copy todir="${build.classes}/uk/ac/starlink/topcat/figures">
      <fileset dir="${plot2.figdir}"
               includesfile="${plot2.figdir}/plot2-figs.lis"/>
    </copy>

    <!-- Write some required PNGs to the images directory programatically. -->
    <java classname="uk.ac.starlink.topcat.ResourceIcon"
          failonerror="yes"
          dir="${build.classes}/uk/ac/starlink/topcat/images/"
          fork="yes">
      <sysproperty key="java.awt.headless" value="true"/>
      <classpath refid="classpath"/>
      <arg value="-writepngs"/>
    </java>

    <!-- Version string. -->
    <echo file="${build.classes}/uk/ac/starlink/topcat/version-string"
          message="${version}"/>

    <!-- Local third party jars, if any. Copy straight into
     !   distribution directories to save on unnecessary copies and to
     !   make these available for resolution by other locally built
     !   packages that are using this one -->
    <mkdir dir="${dist.lib.pkg}"/>
    <copy todir="${dist.lib.pkg}">
       <fileset dir="${src.jars.dir}"/>
    </copy>

    <!-- Call target to do time-consuming build of additional components;
     !   first check that they are not already in place. -->
    <condition property="extras.built">
      <and>
        <uptodate targetfile="${build.javadocs}/uk/ac/starlink/topcat/func">
          <srcfiles dir="${java.dir}/uk/ac/starlink/topcat/func/"/>
        </uptodate>
        <uptodate targetfile="${build.etc}/demo">
          <srcfiles dir="${src.etc}/demo"/>
        </uptodate>
      </and>
    </condition>
    <antcall target="build-extras"/>

  </target>

  <!-- Sub-target to perform time-consuming build of additional components
   !   in build phase; unless attribute allows it to be skipped. -->
  <target name="build-extras" unless="extras.built">

    <!-- Construct HTML documentation for the JEL-accessible classes.
     !   This is built using Javadoc, and is available from the MethodWindow
     !   method browser. -->
    <javadoc doclet="uk.ac.starlink.ttools.build.HtmlDoclet"
             docletpathref="classpath"
             failonerror="true"
             public="true"
             destdir="${build.javadocs}"
             sourcepath="${java.dir}"
             packagenames="uk.ac.starlink.topcat.func"
             classpathref="classpath"
             source="${source.version}"/>

     <antcall target="build_demo"/>
  </target>

  <!--
   !   ==========================
   !   Build standalone jar files
   !   ==========================
   !
   !  Builds jar files which can be used on their own, without needing any
   !  other jars to be present.  Two of them are built: topcat-lite.jar
   !  which contains enough classes to do most things but not support for
   !  peripheral items like MySpace access etc.
   !-->
  <target name="build-standalone"
          depends="install"
          description="-> builds a standalone jar file">

    <!-- Build temporary zip file containing things not in the input jars
     !   which ought to be included in the standalone jars. -->
    <exec outputproperty="gitversion"
          logerror="true"
          executable="${star.dir}/bin/gitversion"/>
    <echo message="${gitversion}"
          file="${build.classes}/uk/ac/starlink/topcat/revision-string"/>
    <mkdir dir="${build.classes}/uk/ac/starlink/ttools"/>
    <echo message="${gitversion}"
          file="${build.classes}/uk/ac/starlink/ttools/revision-string"/>

    <zip destfile="${dist.lib.pkg}/extras.zip">
      <fileset dir="${star.bin}" includes="topcat stilts"/>
      <fileset dir="${star.dir}/source/src/etc" includes="LICENCE.txt"/>
      <fileset dir="${star.etc}/ttools" includes="stilts.py"/>
      <fileset dir="${build.classes}">
        <include name="uk/ac/starlink/topcat/revision-string"/>
        <include name="uk/ac/starlink/ttools/revision-string"/>
      </fileset>
    </zip>
    <delete file="${build.classes}/uk/ac/starlink/topcat/revision-string"/>
    <delete file="${build.classes}/uk/ac/starlink/ttools/revision-string"/>

    <!-- Build topcat-lite.jar - minimal standalone which does basic things. -->
    <java classname="uk.ac.starlink.util.SuperJar" failonerror="yes">
      <classpath refid="classpath"/>
      <arg value="-oj"/><arg value="${dist.lib.pkg}/topcat-lite.jar"/>
      <arg value="-xjar"/><arg value="array.jar"/>
      <arg value="-xjar"/><arg value="astrogrid.jar"/>
      <arg value="-xjar"/><arg value="axis.jar"/>
      <arg value="-xjar"/><arg value="hds.jar"/>
      <arg value="-xjar"/><arg value="hdx.jar"/>
      <arg value="-xjar"/><arg value="jaiutil.jar"/>
      <arg value="-xjar"/><arg value="jniast.jar"/>
      <arg value="-xjar"/><arg value="junit.jar"/>
      <arg value="-xjar"/><arg value="ndx.jar"/>
      <arg value="-xjar"/><arg value="sog.jar"/>
      <arg value="-xjar"/><arg value="soapserver.jar"/>
      <arg value="-xjar"/><arg value="srb.jar"/>
      <arg value="-xent"/><arg value="COPYING.txt"/>
      <arg value="-xent"/><arg value="README.txt"/>
      <arg value="-xent"/><arg value="package cache/"/>
      <arg value="${star.lib.pkg}/topcat.jar"/>
      <arg value="${dist.lib.pkg}/extras.zip"/>
    </java>

    <java classname="uk.ac.starlink.util.SuperJar" failonerror="yes">
      <classpath refid="classpath"/>
      <arg value="-oj"/><arg value="${dist.lib.pkg}/topcat-full.jar"/>
      <arg value="-xjar"/><arg value="junit.jar"/>
      <arg value="-xjar"/><arg value="log4j.jar"/>
      <arg value="-xjar"/><arg value="log4j-core.jar"/>
      <arg value="-xjar"/><arg value="jsky/jel.jar"/>
      <arg value="-xjar"/><arg value="gsi-classes.jar"/>
      <arg value="-xent"/><arg value="COPYING.txt"/>
      <arg value="-xent"/><arg value="README.txt"/>
      <arg value="-xent"/><arg value="package cache/"/>
      <arg value="${star.lib.pkg}/topcat.jar"/>
      <arg value="${dist.lib.pkg}/extras.zip"/>
    </java>

    <delete file="${dist.lib.pkg}/extras.zip"/>
  </target>

  <!--
   !   ===================
   !   Construct demo data
   !   ===================
   !-->
  <target name="build_demo">
    <property name="src.demo" value="${src.etc}/demo"/>
    <property name="build.demo" 
              value="${build.etc}/demo/uk/ac/starlink/topcat/demo"/>
    <mkdir dir="${build.demo}"/>

    <!-- Set up a file recording which demo files are to be used. -->
    <property name="demo.list" value="${build.demo}/demo_list"/>
    <delete file="${demo.list}" quiet="true"/>
    <touch file="${demo.list}"/>

    <bzip2 src="${src.demo}/votable/6dfgs_mini.xml"
           destfile="${build.demo}/6dfgs_mini.xml.bz2"/>
    <echo append="true" file="${demo.list}" message="6dfgs_mini.xml.bz2&#xA;"/>

    <copy todir="${build.demo}">
      <fileset dir="${src.demo}/fits" includes="863sub.fits"/>
      <fileset dir="${src.demo}/votable" includes="messier.xml,vizier.xml.gz"/>
    </copy>
    <echo append="true" file="${demo.list}" message="messier.xml&#xA;"/>
    <echo append="true" file="${demo.list}" message="vizier.xml.gz&#xA;"/>
    <echo append="true" file="${demo.list}" message="863sub.fits&#xA;"/>

    <gzip src="${src.demo}/fits/tables.fit"
          zipfile="${build.demo}/tables.fit.gz"/>
    <echo append="true" file="${demo.list}" message="tables.fit.gz&#xA;"/>

    <tar destfile="${build.demo}/demo.tar.bz2"
         compression="bzip2">
      <tarfileset dir="${src.etc}">
        <include name="demo/votable/messier.xml"/>
        <include name="demo/fits/tables.fit"/>
        <include name="demo/others/**"/>
      </tarfileset>
    </tar>
    <echo append="true" file="${demo.list}" message="demo.tar.bz2&#xA;"/>
  </target>


  <!--
   !   ============================
   !   Create the package jar files
   !   ============================
   !
   !  Creates a jar file from the build.classes directory tree. If
   !  jars of sub-components are also required these should be also
   !  created here. Note this requires a manifest file that defines the
   !  jars that we directly depend on (using relative URLs) on and
   !  defines the application entrance point. The jar files should be
   !  placed directly in the distribution directories. 
   !-->
  <target name="jars"
          depends="build, docs-html"
          unless="runonly.install"
          description="-> creates the package jar file(s)">

    <mkdir dir="${dist.lib.pkg}"/>
    <jar destfile="${dist.lib.pkg}/${name}.jar">
      <fileset dir="${build.classes}"/>
      <fileset dir="${build.javadocs}"/>
      <manifest>
        <attribute name="Built-By" value="${user.name}"/>
        <attribute name="Main-Class"
                   value="uk.ac.starlink.topcat.Driver"/>
        <attribute name="Class-Path" value="${jar.class.path}"/>
        <!-- Required for WebStart signed jars at java 7u51+ -->
        <attribute name="Permissions" value="all-permissions"/>
        <attribute name="Application-Name" value="TOPCAT"/>
      </manifest>
    </jar>

    <jar destfile="${dist.lib.pkg}/${name}_demo.jar"
         basedir="${build.etc}/demo"/>

    <!-- Sign all jar files -->
    <antcall target="signjars"/>
  </target>

  <target name="signjars" if="sign.jars">
    <signjar alias="${webstart.alias}"
             keystore="${webstart.keystore}"
             keypass="${webstart.keypass}"
             storepass="${webstart.storepass}">
      <fileset dir="${dist.lib}" includes="**/*.jar **/*.zip"/>
    </signjar>
  </target>

  <!--
   !   ========================================
   !   Make package JNLP file for Java webstart
   !   ========================================
   !-->
  <target name="webstart"
          description="-> create webstart descriptor files">

    <!-- Create a webstart JNLP file for this package, this goes into
     !   "dist.lib" -->
    <mkdir dir="${dist.lib}"/>
    <jnlp toFile="${dist.lib}/${name}.jnlp" href="${name}.jnlp"
          codebase="${webstart.codebase}">
      <information>
         <title>TOPCAT</title>
         <vendor>Mark Taylor, Bristol University</vendor>
         <homepage href="${home.page}"/>
         <icon href="${home.page}images/tc_sok.png"/>
         <description>"TOPCAT - Tool for OPerations on Catalogues And Tables"</description>
         <offline_allowed/>
       </information>
       <security>
          <all_permissions/>
       </security>
       <resources>
         <j2se version="1.8+"/>
         <jar href="${name}/${name}.jar"/>
         <extension name="TOPCAT-PARTS" href="${name}-parts.jnlp"/>
       </resources>
       <application_desc main_class="uk.ac.starlink.topcat.Driver"/>
     </jnlp>

     <!-- May be needed as a component so provide that too -->
     <jnlp toFile="${dist.lib}/${name}-parts.jnlp" href="${name}-parts.jnlp"
          codebase="${webstart.codebase}">
      <information>
         <title>TOPCAT - Tool for OPerations on Catalogues And Tables</title>
         <vendor>Starlink UK</vendor>
         <homepage href="${home.page}"/>
         <icon href="${webstart.starlink_logo}"/>
         <description>"Starlink TOPCAT - Webstart edition"</description>
         <offline_allowed/>
       </information>
       <security>
          <all_permissions/>
       </security>
       <resources>
         <j2se version="1.8+"/>
         <fileset dir="${dist.lib}" includes="**/*.jar **/*.zip"/>
         <extension name="TTOOLS" href="ttools.jnlp"/>
         <extension name="DATANODE" href="datanode.jnlp"/>
         <extension name="HELP" href="help.jnlp"/>
         <extension name="CONNECT" href="connect.jnlp"/>
         <extension name="ASTROGRID" href="astrogrid.jnlp"/>
         <extension name="SRB" href="srb.jnlp"/>
         <extension name="PLASTIC" href="plastic.jnlp"/>
       </resources>
       <component_desc/>
     </jnlp>

  </target>

  <!-- Create a MacOS X Java application bundle, using the appbundler task
   !   (see https://github.com/TheInfiniteKind/appbundler).
   !   Prepare to create a .dmg file for distribution.
   !-->
  <target name="build-osxapp"
          depends="build-standalone"
          description="-> prepares .dmg application bundle for MacOS X">
    <delete dir="${dist.osx}" quiet="true"/>
    <mkdir dir="${dist.osx}"/>
    <bundleapp outputdirectory="${dist.osx}"
               name="${Name}"
               displayname="${Name}"
               identifier="uk.ac.starlink.topcat"
               mainclassname="${package.name}.Driver"
               jvmRequired="1.8"
               shortversion="${version}"
               icon="${src.dir}/lib/MacOS/Topcat.icns"
               applicationCategory="public.app-category.education"
               >
      <classpath file="${dist.lib.pkg}/topcat-full.jar"/>
      <option value="-Duk.ac.starlink.topcat.cmdname=topcat"/>
      <option value="-Dapple.laf.useScreenMenuBar=true"/>
      <option value="-Dcom.apple.macos.useScreenMenuBar=true"/>
      <option value="-Dcom.apple.mrj.application.apple.menu.about.name=${Name}"/>
    </bundleapp>

    <!-- Copy the docs into the release directory -->
    <mkdir dir="${dist.osx.docs}"/>
    <copy todir="${dist.osx.docs}">
      <fileset file="${src.dir}/lib/MacOS/index.html"/>
      <fileset dir="${dist.docs}/${name}" excludes="javadocs javadocs/**"/>
      <fileset dir="${star.dir}/docs/ttools/" includes="sun256/**"/>
    </copy>

    <!-- Copy scripts into the release directory.
     !   These used to just go in /bin at the top, but probably that's
     !   not how MacOS applications are normally laid out, so they are
     !   no longer included there.
     !   The Homebrew people want it to go inside TOPCAT.app,
     !   so it can get symlinked from ... somewhere.
     !   So I've put them in /TOPCAT.app/Contents/Resources/bin
     !   (I took advice on what the best place was and got various
     !   different answers, but this seems fairly unobjectionable). -->
    <mkdir dir="${dist.osx.bin}"/>
    <copy todir="${dist.osx.bin}">
      <fileset dir="${star.bin}" includes="topcat stilts"/>
    </copy>
    <chmod perm="ugo+x" type="file" failonerror="yes" maxparallel="50">
      <fileset dir="${dist.osx.bin}"/>
    </chmod>

    <!-- I don't really know what purpose this serves; somebody must have
     !   told me to put it in at some point. -->
    <mkdir dir="${dist.osx}/README.rtfd"/>
    <copy todir="${dist.osx}/README.rtfd">
      <fileset dir="${src.dir}/lib/MacOS/README.rtfd"/>
    </copy>

    <!-- The final step - generating the .dmg file - can only be done on
     !   a Mac.  Either do it, or write a message saying how.  If the build
     !   is being done on a non-Mac system, just copy the ${dist.osx} 
     !   directory to a Mac and run hdiutil there. -->
    <condition property="isMacos">
      <os family="mac"/>
    </condition>
    <!-- Note: to examine the dmg file on OSX do 
     !      % hdiutil attach topcat.dmg 
     ! ...  % hdiutil detach /dev/... -->
    <echo message="Attempt to build .dmg file (will only work on Mac)"/>
    <echo message="   hdiutil create -srcfolder ${dist.osx} -volname ${name} -ov ${dist.dmgfile}"/>
    <exec executable="/usr/bin/hdiutil" os="Mac OS X">
      <arg value="create"/>
      <arg value="-srcfolder"/>
      <arg value="${dist.osx}"/>
      <arg value="-volname"/>
      <arg value="${name}"/>
      <arg value="-ov"/>
      <arg value="${dist.dmgfile}"/>
    </exec>
  </target>

  <!--
   !   =================================
   !   Configures the local distribution
   !   =================================
   !
   !  Completes the creation of the local distribution into the
   !  directory "dist.dir" (usually the current directory).
   !  Installations and exports are based on the state of this
   !  distribution, so it must be performed before installation or
   !  export. If the "runonly.install" parameter is set then this
   !  target is skipped (needed for releases that do not have
   !  source). Much of the work of getting the distribution
   !  directories into the correct state is performed by the dependency
   !  targets.
   !-->
  <target name="dist"
          depends="build,docs-html,jars,javadocs,webstart"
          unless="runonly.install"
          description="-> configures the local binary distribution">

    <!-- Make sure all the distribution directories exist -->
    <mkdir dir="${dist.dir}"/>
    <mkdir dir="${dist.bin.pkg}"/>
    <mkdir dir="${dist.lib.pkg}"/>
    <mkdir dir="${dist.docs.pkg}"/>
    <mkdir dir="${dist.etc.pkg}"/>

    <!-- Copy application scripts. -->
    <copy todir="${dist.bin.pkg}">
      <fileset dir="${script.dir}/" />
    </copy>

    <!-- Copy extra documentation, note doesn't include javadocs these
     !   are generated from the source-->
    <copy todir="${dist.docs.pkg}">
      <fileset dir="${build.docs}"
               includes="images/* figures/* ${user.doc}/* *.pdf"/>
    </copy>

    <!-- Set permissions on contents of distribution directories -->
    <chmod perm="ugo+rx" dir="${dist.dir}" type="dir" includes="**"
           failonerror="${chmod.fail}" maxparallel="50"/>
    <chmod perm="ugo+r" dir="${dist.dir}" type="file" includes="**"
           failonerror="${chmod.fail}" maxparallel="50"/>
    <chmod perm="ugo+x" type="file" failonerror="${chmod.fail}"
           maxparallel="50">
       <fileset dir="${dist.bin}"/>
    </chmod>

  </target>

  <!--
   !   ========================
   !   Create the full releases
   !   ========================
   !
   !  Creates the full "zip", "tar" and "bzip" archives of the
   !  products of the "dist" target and the source directory.
   !  The archives are designed to be unpacked such that the resultant
   !  directory layout can be either used as a local distribution, or
   !  installed into a Starlink tree (installation requires the
   !  Starlink modified version of ANT, use as a local distribution
   !  may need special handling of the extension path). This version
   !  can also be used to rebuild the package from source.
   !
   !  The archive names are ${dist.version}.<ext>.
   !-->
  <target name="export"
          description="-> creates the full distribution archives">

    <antcall target="create_archives">
      <param name="source.required" value="true"/>
      <param name="binary.required" value="true"/>
      <param name="archive.name" value="${dist.version}"/>
    </antcall>

  </target>

  <!--
   !   ==========================
   !   Create the source releases
   !   ==========================
   !
   !  Creates the source only "zip", "tar" and "bzip" archives.
   !  These can be used to rebuild the package (requires the Starlink
   !  modified version of ANT).
   !
   !  The archive names are ${dist.version}-src.<ext>.
   !-->
  <target name="export-source"
          description="-> creates the source distribution archives">

     <antcall target="create_archives">
      <param name="source.required" value="true"/>
      <param name="archive.name" value="${dist.version}-src"/>
    </antcall>

  </target>

  <!--
   !   ===========================
   !   Create the runonly releases
   !   ===========================
   !
   !  Creates the runonly "zip", "tar" and "bzip" archives of the
   !  products of the "dist" target. The archives are designed to be
   !  unpacked such that the resultant directory layout can be either
   !  used as a local distribution, or installed into a Starlink tree
   !  (installation requires the Starlink modified version of ANT).
   !
   !  The archive names are ${dist.version}-bin.<ext>.
   !-->
  <target name="export-runonly"
          description="-> creates the runonly distribution archives">

     <antcall target="create_archives">
      <param name="binary.required" value="true"/>
      <param name="archive.name" value="${dist.version}-bin"/>
    </antcall>

  </target>

  <!--
   ! Create release archives of the various types required. Use this
   ! by an <antcall> and set the property "archive.name" to define what
   ! name to use for the outfile files. The archives are written into
   ! the directory ${star.archive.dir} (the local directory by default).
   !
   ! If the property "binary.required" is set then the files needed
   ! for a run-only release are included and if "source.required" is
   ! defined the source code is also included.
   !-->
  <target name="create_archives"
          depends="dist">

    <mkdir dir="${star.archive.dir}"/>

    <zip destfile="${star.archive.dir}/${archive.name}.zip">

      <!-- All releases have the documentation and build file -->
      <zipfileset dir="${dist.docs}" prefix="${name}/docs"/>
      <zipfileset dir="${dist.dir}" includes="build.xml" prefix="${name}"/>

      <zipfileset dir="${dist.bin}" prefix="${name}/bin">
        <include name="**" if="binary.required"/>
      </zipfileset>
      <zipfileset dir="${dist.lib}" prefix="${name}/lib">
        <include name="**" if="binary.required"/>
      </zipfileset>
      <zipfileset dir="${dist.etc}" prefix="${name}/etc">
        <include name="**" if="binary.required"/>
      </zipfileset>

      <zipfileset dir="${src.dir}" prefix="${name}/src">
        <include name="**" if="source.required"/>

        <!-- Exclude local development support from distribution-->
        <exclude name="local/**" if="source.required"/>
      </zipfileset>

    </zip>

    <!-- Note: creating a tar file with empty directories doesn't
     !   work, so the directory structure may be incomplete -->
    <tar longfile="gnu" destfile="${archive.name}.tar">

      <!-- All releases have the documentation and build file -->
      <tarfileset dir="${dist.docs}" prefix="${name}/docs"/>
      <tarfileset dir="${dist.dir}" prefix="${name}">
        <include name="build.xml"/>
      </tarfileset>

      <tarfileset dir="${dist.bin}" prefix="${name}/bin">
        <include name="**" if="binary.required"/>
      </tarfileset>
      <tarfileset dir="${dist.lib}" prefix="${name}/lib">
        <include name="**" if="binary.required"/>
      </tarfileset>
      <tarfileset dir="${dist.etc}" prefix="${name}/etc">
        <include name="**" if="binary.required"/>
      </tarfileset>

      <tarfileset dir="${src.dir}" prefix="${name}/src">
        <include name="**" if="source.required"/>
        <exclude name="local/**" if="source.required"/>
      </tarfileset>

    </tar>

    <gzip zipfile="${star.archive.dir}/${archive.name}.tar.gz"
          src="${archive.name}.tar"/>
    <bzip2 zipfile="${star.archive.dir}/${archive.name}.tar.bz2"
           src="${archive.name}.tar"/>
    <delete file="${archive.name}.tar"/>

  </target>

  <!--
   !   ============================================
   !   Cleans up build and distribution directories
   !   ============================================
   !-->
  <target name="clean"
          description="-> cleans up build and dist products">

    <delete dir="${build.dir}"/>
    <delete dir="${dist.bin}"/>
    <delete dir="${dist.lib}"/>
    <delete dir="${dist.docs}"/>
    <delete dir="${dist.etc}"/>
    <delete dir="${dist.osx}" quiet="true"/>
    <delete dir="${dist.dmgfile}" quiet="true"/>
  </target>

  <!--
   !   ================================
   !   Install into the "Starlink" tree
   !   ================================
   !
   ! Installs the "dist" target products into another set of
   ! directories.
   !
   ! An installed system is potentially "undoable" as the copied names
   ! and package-specific directories are logged to "${install.log}".
   !-->
  <target name="install"
          depends="dist"
          description="-> installs distribution">

    <!-- Installation based directories (based on "star.install")-->
    <property name="star.bin" value="${star.install}/bin"/>
    <property name="star.lib" value="${star.install}/lib"/>
    <property name="star.etc" value="${star.install}/etc"/>
    <property name="star.docs" value="${star.install}/docs"/>
    <property name="star.bin.pkg" value="${star.bin}/${name}"/>
    <property name="star.lib.pkg" value="${star.lib}/${name}"/>
    <property name="star.etc.pkg" value="${star.etc}/${name}"/>
    <property name="star.docs.pkg" value="${star.docs}/${name}"/>
    <mkdir dir="${star.install}"/>
    <mkdir dir="${star.lib.pkg}"/>
    <mkdir dir="${star.docs.pkg}"/>

    <loggedcopy todir="${star.bin}"
                logfile="${install.log}"
                overwrite="${install.overwrite}"
                logfileAppend="false">
      <fileset dir="${dist.bin}"/>
    </loggedcopy>

    <!-- Also remove the package-specific directory.
     !   Note exact format is required.-->
    <echo file="${install.log}" append="true">${star.bin.pkg}
</echo>

    <chmod perm="ugo+rx" failonerror="${chmod.fail}">
      <fileset dir="${star.bin}">
        <present targetdir="${dist.bin}" present="both"/>
      </fileset>
    </chmod>

    <loggedcopy todir="${star.lib}"
                logfile="${install.log}"
                overwrite="${install.overwrite}"
                logfileAppend="true">
      <fileset dir="${dist.lib}">
        <include name="**/*.jnlp"/>
        <include name="**/*.jar"/>
        <include name="**/*.zip"/>
        <include name="**/*.icns"/>
      </fileset>
    </loggedcopy>
    <echo file="${install.log}" append="true">${star.lib.pkg}
</echo>

    <loggedcopy todir="${star.docs}"
                logfile="${install.log}"
                overwrite="${install.overwrite}"
                logfileAppend="true">
      <fileset dir="${dist.docs}" excludes="${unfiltered.files}"/>
      <filterchain refid="filters"/>
    </loggedcopy>

    <loggedcopy todir="${star.docs}" filtering="false"
                logfile="${install.log}"
                overwrite="${install.overwrite}"
                logfileAppend="true">
      <fileset dir="${dist.docs}" includes="${unfiltered.files}"/>
    </loggedcopy>
    <echo file="${install.log}" append="true">${star.docs.pkg}
</echo>

  </target>

  <!--
   !   ========================================
   !   Install runonly into the "Starlink" tree
   !   ========================================
   !
   ! Do an install using only the contents of a binary release (a
   ! source-free runonly system).
   !-->
  <target name="install-runonly"
          description="-> install a runonly distribution into Starlink tree">

     <!-- Make sure that the expected file structure exists, some
          of these files can be missing if originally empty -->
     <mkdir dir="${dist.dir}"/>
     <mkdir dir="${dist.lib.pkg}"/>
     <mkdir dir="${dist.docs.pkg}"/>

     <!-- Do normal install, but with many targets switched off-->
     <antcall target="install">
      <param name="runonly.install" value="true"/>
      <param name="javadoc.notrequired" value="true"/>
    </antcall>

  </target>

  <!--
   !   ===================================
   !   De-install from the "Starlink" tree
   !   ===================================
   !
   ! Uses the content of the "${install.log}" to remove the files
   !  that were copied into place by the install target. If this fails
   !  then hopefully the log file will not be deleted!
   !-->
 <target name="deinstall"
          description="-> undo the install target">

    <available file="${install.log}" property="install.log.present"/>

    <antcall target="real_deinstall"/>

  </target>

  <!-- Real deinstall target. Only activated if "install.log.present"
   !   is defined -->
  <target name="real_deinstall"
          if="install.log.present">

    <loadfile property="files" srcFile="${install.log}"/>
    <listdelete>
      <filelist dir="/" files="${files}"/>
    </listdelete>

    <delete file="${install.log}"/>

  </target>

  <!--
   !   =============================
   !   Creates the API documentation
   !   =============================
   !
   !  Create documentation from the Java sources. Additional
   !  documentation is kept in the ${src.docs} directory.
   !-->
  <target name="javadocs"
          depends="prepare,javadoc_check"
          unless="javadoc.notrequired"
          description="-> creates the API documentation">

    <mkdir dir="${dist.javadocs}"/>
    <javadoc useexternalfile="yes"
             destdir="${dist.javadocs}"
             author="true"
             version="true"
             locale="en"
             windowtitle="${Name} API"
             doctitle="${Name}"
             defaultexcludes="yes"
             source="${source.version}"
             classpathref="classpath">
      <arg value="-Xdoclint:all,-missing"/>

      <!-- Get a list of directories that name all the potential
       !   java packages -->
      <packageset dir="${java.dir}" defaultexcludes="yes">
         <include name="**"/>
         <exclude name="uk/ac/starlink/topcat/doc"/>
      </packageset>

      <!-- Link to the full Java API at SUNs website -->
      <link offline="true" href="${javaapi.url}"
            packagelistLoc="${javaapi.lis}"/>

      <!-- Cope with custom tags. -->
      <tag name="example"
           description="Examples:"
           scope="methods, fields"
           enabled="true"/>

      <group title="${Name} API" packages="${package.name}*"/>

      <bottom>${copyright.string}</bottom>
    </javadoc>

  </target>

  <!-- This checks if the javadocs are up to date with respect to the
   !   java source, if so then the "javadoc.notrequired" variable is
   !   set true. Note this is check is not performed if
   !   javadoc.notrequired is already set (by .properties) -->
  <target name="javadoc_check"
          unless="javadoc.notrequired">

    <uptodate property="javadoc.notrequired"
              targetfile="${dist.javadocs}/packages.html">
        <srcfiles dir= "${java.dir}" includes="**/*.java"/>
    </uptodate>

  </target>

  <!--
   !   ======================================================
   !   Creates additional HTML documentation from XML sources
   !   ======================================================
   !
   !   The XML user document is downconverted to single- and multiple-
   !   file HTML versions in the docs directory, and a JavaHelp version
   !   on the classpath of the application.
   !-->
  <target name="docs-html"
          depends="build, html_check, docs_depend"
          unless="docs.notrequired"
          description="-> creates the user documentation">

    <!-- Transform the user document XML to a single HTML document. -->
    <mkdir dir="${build.docs}/${user.doc}"/>
    <copy todir="${build.docs}/${user.doc}">
      <fileset dir="${xdoc.etc}" includes="sun-style.css"/>
    </copy>
    <xslt in="${build.docs}/${user.doc}.xml" 
          out="${build.docs}/${user.doc}/${user.doc}.html"
          style="${xdoc.etc}/toHTML1.xslt">
      <param name="VERSION" expression="${version}"/>
      <param name="BASEDIR" expression="${build.docs}/${user.doc}"/>
      <param name="COVERIMAGE" expression="../figures/multishot-mini.png"/>
      <param name="CSS_HREF" expression="sun-style.css"/>
    </xslt>

    <!-- Transform the user document from XML to HTML form for browsing. -->
    <java classpathref="classpath"
          dir="${src.docs}"
          classname="uk.ac.starlink.xdoc.MultiXML"
          failonerror="yes"
          fork="yes">
      <sysproperty key="java.awt.headless" value="true"/>
      <arg value="-style"/> <arg value="${xdoc.etc}/toHTML.xslt"/>
      <arg value="-param"/> <arg value="VERSION=${version}"/>
      <arg value="-param"/> <arg value="BASEDIR=${build.docs}/${user.doc}"/>
      <arg value="-param"/> 
                       <arg value="COVERIMAGE=../figures/multishot-mini.png"/>
      <arg value="-param"/> <arg value="CSS_HREF=sun-style.css"/>
      <arg value="${build.docs}/${user.doc}.xml"/>
      <arg value="${build.docs}/${user.doc}"/>
    </java>

    <!-- Copy same into the classes directory so that it ends up in the
     !   jar file.  -->
    <copy todir="${build.classes}/uk/ac/starlink/topcat/${user.doc}">
      <fileset dir="${build.docs}/${user.doc}"/>
    </copy>

    <!-- Transform the user document from XML to JavaHelp form. -->
    <java classpathref="classpath"
          dir="${src.docs}" 
          classname="uk.ac.starlink.xdoc.MultiXML" 
          failonerror="yes"
          fork="yes">
      <sysproperty key="java.awt.headless" value="true"/>
      <arg value="-style"/> <arg value="${xdoc.etc}/toHelp.xslt"/>
      <arg value="-param"/> <arg value="VERSION=${version}"/>
      <arg value="-param"/> <arg value="BASEDIR=${build.docs}/${user.doc}"/>
      <arg value="-param"/> <arg value="CSS_HREF=sun-style.css"/>
      <arg value="${build.docs}/${user.doc}.xml"/>
      <arg value="${build.classes}/uk/ac/starlink/topcat/help"/>
    </java>

    <!-- NOTE: There is a JavaHelp bug which can result in incomplete
     !   indexing of some input files.  It manifests itself as a message
     !   delivered to stdout: "I/O exception occurred in file 'versions.html'"
     !   (or whichever file is affected).  The Indexer eats the stack
     !   trace unfortunately but it comes down to:
     !     java.lang.ArrayIndexOutOfBoundsException: 256
     !     at com.sun.java.help.search.BitBuffer.concatenate(BitBuffer.java:166)
     !   and I think is the same issue noted at
     !   https://github.com/javaee/javahelp/issues/38
     !   (also labelled java.net JIRA JAVAHELP-38) - looks subtle and
     !   treacherous to try to fix.
     !   It seems(?) to be triggered by large numbers of occurrences of
     !   the same word in one of the HTML files being indexed, e.g. "add"
     !   in versions.html.  Providing the "-nostopwords" flag to the
     !   Indexer invocation seems to make it OK again.  I thought I was
     !   going to have to add the offending word ("add") to the list of
     !   known stop words (run Indexer -h for syntax), but that doesn't
     !   seem to be necessary. -->

    <!-- Builds the help file index database.  Uses the "search-config" file
     !   generated by the toHelp stylesheet, and deletes it when done.
     !   See note above about reported I/O exceptions. -->
    <java classpathref="classpath"
          dir="${build.classes}/uk/ac/starlink/topcat/help"
          fork="true"
          classname="com.sun.java.help.search.Indexer"
          failonerror="yes">
      <arg value="-c"/>
      <arg value="search-config"/>
      <arg value="-nostopwords"/>
    </java>
    <delete file="${build.classes}/uk/ac/starlink/topcat/help/search-config"/>

    <!-- Copy the image icons themselves into the help directory where they
     !   will be referenced from the HTML. -->
    <copy todir="${build.classes}/uk/ac/starlink/topcat/help">
      <fileset dir="${build.docs}/${user.doc}"
               includes="${user.doc}.html sun-style.css"/>
    </copy>
  </target>

  <!--
   !   =================================================
   !   Create user document in PDF form from XML sources
   !   =================================================
   !
   !   The XML document is downconverted to PDF via xsl-fo using Fop.
   !
   !   This process is, for reasons I haven't tried very hard to
   |   understand, rather slow (~3 minutes) and also problematic
   !   in that it can fail due to a Xerces bug in (Sun's) J2SE1.5.
   !   Given that, and the fact that the PDF user document is rather
   !   a special-interest item, this target is no longer invoked as
   !   part of the normal install target.  If the PDF user document
   !   is required, this target must be invoked explicitly.
   !-->
  <target name="docs-pdf"
          depends="build, docs_depend"
          unless="docs.notrequired"
          description="-> creates the user documentation in PDF form">

    <!-- Transform the user document XML to a PDF document via XSL-FO. -->
    <xslt in="${build.docs}/${user.doc}.xml"
          out="${build.docs}/${user.doc}.fo"
          style="${xdoc.etc}/toFo.xslt">
      <param name="VERSION" expression="${version}"/>
      <param name="BASEDIR" expression="${build.docs}/${user.doc}"/>
      <param name="FIGDIR" expression="${build.docs}/figures"/>
      <param name="COVERIMAGE" expression="../multishot.png"/>
    </xslt>
    <java classname="org.apache.fop.apps.Fop"
          failonerror="yes"
          fork="yes"
          maxmemory="512M">
      <classpath>
        <fileset dir="${star.jar.dir}/xdoc" includes="*.jar"/>
      </classpath>
      <sysproperty key="java.awt.headless" value="true"/>

      <!-- This is fiddly.
       !   The version of FOP we're using here (0.20, very old) doesn't
       !   handle PNGs on its own, but can do it with the help of JAI or JIMI.
       !   Trying to do it using JAI fails with various errors
       |   (complains about PNG magic numbers amongst other things).
       !   So we can use JIMI, which is in the XDOC package.  
       !   But, FOP tries JAI in preference to JIMI if both are present
       !   (FOP docs say JAI is faster, though both seem exceedingly slow),
       !   so we have to ensure that JAI is not on the classpath.
       !   Since SoG requires JAI, it is probably in the JDK's
       !   extensions directory.  So here we reset the java.ext.dirs
       !   so that JAI doesn't get picked up.
       !   If we ever upgrade to a later FOP, we can dispense with both JIMI
       !   and these classpath acrobatics. -->
      <sysproperty key="java.ext.dirs" value=""/>
      <arg value="-q"/>
      <arg value="-fo"/> <arg value="${build.docs}/${user.doc}.fo"/>
      <arg value="-pdf"/> <arg value="${build.docs}/${user.doc}.pdf"/>
    </java>
  </target>

  <!-- Checks whether the HTML docs build is up to date. -->
  <target name="html_check" unless="docs.notrequired">
    <uptodate property="docs.notrequired"
              srcfile="${src.docs}/${user.doc}.xml" 
              targetfile="${build.docs}/${user.doc}/${user.doc}.html"/>
  </target>

  <!-- Prepares for document creation.  The XML source document and all
   !   the external entities it requires are copied into the build.docs
   !   directory. -->
  <target name="docs_depend"
          depends="build"
          unless="docs.notrequired">

    <property name="ttools.java" value="${java.dir}/../../../ttools/src/main"/>

    <!-- Make destination directory for built files. -->
    <mkdir dir="${build.docs}"/>

    <!-- Copy required source files there. -->
    <copy todir="${build.docs}">
      <fileset dir="${src.docs}" 
               includes="${user.doc}.xml figures/* multishot.png"/>
      <fileset dir="${build.classes}/uk/ac/starlink/topcat/"
               includes="images/*"/>
      <fileset dir="${xdoc.etc}"
               includes="docs.dtd"/>
      <fileset dir="${gbin.docs}"
               includes="gbin-stil-*.xdoc"/>
    </copy>
    <copy todir="${build.docs}/figures">
      <fileset dir="${plot2.figdir}"
               includesfile="${plot2.figdir}/plot2-figs.lis"/>
    </copy>

    <!-- Write a file containing entity definitions for all the image files
     !   that might be referenced in the user document (this file is 
     !   referenced from within the user document as an external entity).
     !   This JVM needs to be forked in order for the command to run
     !   properly on MacOS X (10.4.9), for reasons I don't really 
     !   understand. -->
    <java classname="uk.ac.starlink.topcat.ResourceIcon" 
          output="${build.docs}/image.defs"
          logerror="true"
          fork="true"
          failonerror="yes">
      <sysproperty key="java.awt.headless" value="true"/>
      <classpath refid="classpath"/>
      <arg value="-entities"/>
    </java>

    <!-- Construct XML documentation for the JEL-accessible classes.
     !   This is built using Javadoc, and forms part of the user document. -->
    <javadoc doclet="uk.ac.starlink.topcat.doc.TopcatXmlDoclet"
             docletpathref="classpath"
             failonerror="true"
             public="true"
             additionalparam="-gen -o ${build.docs}/general-javadocs.xml" 
             sourcepath="${ttools.java}"
             packagenames="uk.ac.starlink.ttools.func"
             classpathref="classpath"
             source="${source.version}"/>
    <javadoc doclet="uk.ac.starlink.topcat.doc.TopcatXmlDoclet"
             docletpathref="docs-classpath"
             failonerror="true"
             public="true"
             additionalparam="-act -o ${build.docs}/activation-javadocs.xml" 
             sourcepath="${java.dir}"
             packagenames="uk.ac.starlink.topcat.func"
             classpathref="classpath"
             source="${source.version}"/>
    <javadoc doclet="uk.ac.starlink.topcat.doc.TopcatXmlDoclet"
             docletpathref="docs-classpath"
             failonerror="true"
             public="true"
             additionalparam="-gen -headonly -o ${build.docs}/general-classes-javadocs.xml"
             sourcepath="${ttools.java}"
             packagenames="uk.ac.starlink.ttools.func"
             classpathref="classpath"
             source="${source.version}"/>
    <javadoc doclet="uk.ac.starlink.topcat.doc.TopcatXmlDoclet"
             docletpathref="docs-classpath"
             failonerror="true"
             public="true"
             additionalparam="-act -headonly -o ${build.docs}/activation-classes-javadocs.xml"
             sourcepath="${java.dir}"
             packagenames="uk.ac.starlink.topcat.func"
             classpathref="classpath"
             source="${source.version}"/>

    <!-- Construct topcat usage message in XML. -->
    <property name="topcat.usage" value="${build.docs}/topcat.usage"/>
    <echo message="&lt;![CDATA[" file="${topcat.usage}" append="no"/>
    <java classname="uk.ac.starlink.topcat.Driver"
          failonerror="yes"
          fork="no"
          output="${topcat.usage}"
          append="yes"
          classpathref="classpath">
      <sysproperty key="java.awt.headless" value="true"/>
      <arg value="-help"/>
    </java>
    <echo message="]]&gt;" file="${topcat.usage}" append="yes"/>

    <!-- Other auto-generated documentation. -->
    <java classname="uk.ac.starlink.ttools.build.SchemeDoc"
          output="${build.docs}/scheme-docs.xml"
          failonerror="yes"
          fork="no"
          logerror="yes"
          classpathref="classpath">
      <sysproperty key="java.awt.headless" value="true"/>
      <arg value="-stil"/>
      <arg value="-stilts"/>
    </java>
    <java classname="uk.ac.starlink.ttools.build.HandlerDoc"
          failonerror="yes"
          fork="yes"
          dir="${build.docs}"
          logerror="yes"
          classpathref="classpath">
      <sysproperty key="java.awt.headless" value="true"/>
      <arg value="-files"/>
    </java>

  </target>

  <!--
   !   =========================================
   !   Makes the API java source files available
   !   =========================================
   !
   !  The full API documentation is created from all the various
   !  packages (of which this package is just one). This target makes
   !  the source code that should be used in the full public API
   !  available in a special part of the build tree so that it can be
   !  automatically discovered. This method works around two potential
   !  problems, not all source code the in src/main directories should be
   !  in the API docs, and it's not possible to make this distinction
   !  easily outside this package (cannot pass out a fileset), plus
   !  some code is generated, so cannot be located by scanning the
   !  src/main tree. When javadocs can be generated incrementally this
   !  arrangement should be reworked to generate whatever is needed as
   !  part of the javadocs target.
   ! 
   !  Application packages should only make public those parts of
   !  their internal APIs that they are prepared to support. Consider
   !  adding such code to proper class libraries (such as util).
   !-->
  <target name="javadoc-sources"
          description="-> make source files for release API documention">

    <mkdir dir="${build.java}"/>

    <!-- Copy and/or generate the source to be included when creating
     !   the full Starlink API javadocs-->
    <copy todir="${build.java}">
      <fileset dir="${java.dir}" defaultexcludes="yes">
          <exclude name="**/README"/>
      </fileset>
    </copy>

  </target>

  <!--
   !   =================
   !   Compile testcases
   !   =================
   !-->
  <target name="compile-tests"
          depends="build"
          if="junit.present">

    <mkdir dir="${build.tests}"/>

    <javac srcdir="${tests.dir}"
           destdir="${build.tests}"
           debug="${debug}"
           source="${source.version}"
           deprecation="${deprecation}" >

      <classpath refid="tests-classpath"/>

    </javac>

  </target>

  <!--
   !   ============
   !   Run testcase
   !   ============
   !-->
  <target name="test"
          depends="run-tests"
          description="-> run JUnit tests"/>

  <target name="run-tests"
          depends="compile-tests,docs-html"
          if="junit.present">

    <junit printsummary="${junit.summary}" haltonfailure="yes"
           filtertrace="${junit.filtertrace}"
           fork="${junit.fork}">

      <classpath refid="tests-classpath"/>

      <jvmarg value="${junit.assertions}"/>

      <sysproperty key="build.tests" value="${build.tests}"/>
      <sysproperty key="tests-classpath.value"
                   value="${tests-classpath.value}"/>
      <sysproperty key="java.library.path" value="${tests-libpath}"/>
      <sysproperty key="basedir" value="${basedir}"/>
      <sysproperty key="xdoc.etc" value="${xdoc.etc}"/>
      <sysproperty key="java.awt.headless" value="${java.awt.headless}"/>
      <sysproperty key="tests.withnet" value="${tests.withnet}"/>

      <formatter type="brief" usefile="false"/>

      <batchtest>
        <fileset dir="${tests.dir}">
          <include name="**/*Test*"/>
        </fileset>
      </batchtest>

    </junit>

  </target>

  <target name="run-single-test"
          if="testcase"
          depends="compile-tests,docs-html"
          description="-> runs the single unit test defined in the testcase property">

    <junit printsummary="${junit.summary}"
          haltonfailure="yes"
          fork="${junit.fork}"
          filtertrace="${junit.filtertrace}">

      <sysproperty key="hdx.home" value="${hdx.home}"/>
      <sysproperty key="build.tests" value="${build.tests}"/>
      <sysproperty key="tests-classpath.value"
                   value="${tests-classpath.value}"/>
      <sysproperty key="java.library.path" value="${tests-libpath}"/>
      <sysproperty key="basedir" value="${basedir}"/>
      <sysproperty key="xdoc.etc" value="${xdoc.etc}"/>
      <sysproperty key="java.awt.headless" value="${java.awt.headless}"/>
      <sysproperty key="tests.withnet" value="${tests.withnet}"/>
      <classpath refid="tests-classpath"/>
      <jvmarg value="${junit.assertions}"/>
      <formatter type="plain" usefile="false"/>
      <test name="${testcase}"/>

    </junit>

  </target>

  <!--
   ! Get a DTD for this build file. Documentation suggests may be incomplete!
   !
   ! Use:
   !
   !    <!DOCTYPE project PUBLIC "-//ANT//DTD project//EN" "./project.dtd">
   !
   ! at head of document to include.
   !-->
  <target name="dtd">
     <antstructure output="project.dtd"/>
  </target>

</project>
