<?xml version="1.0" encoding="UTF-8"?>
<!--
// $Id: //open/dev/farrago/buildMacros.xml#90 $
// Farrago is an extensible data management system.
// Copyright (C) 2005-2009 The Eigenbase Project
// Copyright (C) 2005-2009 SQLstream, Inc.
// Copyright (C) 2005-2009 LucidEra, Inc.
// Portions Copyright (C) 2003-2009 John V. Sichi
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later Eigenbase-approved version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307  USA
-->

<!-- Farrago build macro definitions -->

<!-- NOTE:  names defined in this file are visible to
     dependent projects, so they should always be qualified with a
     "farrago." prefix -->

<!-- These XML ENTITY "macros" help avoid redundancy in property -->
<!-- settings. They can be used with <jvmarg> or <arg> as the line -->
<!-- attribute. -->
<!DOCTYPE project [

<!ENTITY FarragoProps
"
-Dnet.sf.farrago.home=${farrago.dir}
-Dnet.sf.farrago.catalog=${project.catalog.dir}
-Djava.util.logging.config.file=${project.trace.propfile}
${farrago.test.jvmargs}
">

<!ENTITY FarragoSqlLineProps
"
&FarragoProps;
-Dsqlline.historyFile=${sqlline.hist.file}
">

]>

<project name="farragoBuildMacros" >
  <taskdef resource="net/sf/antcontrib/antlib.xml" />

  <!-- Project locations and properties -->

  <!-- determine Farrago home based on location of this buildfile -->
  <dirname property="farrago.dir" file="${ant.file.farragoBuildMacros}"/>

  <!-- Alias for farrago.dir to match runtime properties convention -->
  <property name="FARRAGO_HOME" location="${farrago.dir}"/>

  <!-- assume common parent of farrago and fennel  -->
  <property name="open.dir" location="${farrago.dir}/.."/>

  <!-- Override these locations in customBuild.properties -->
  <property name="thirdparty.dir" value="${open.dir}/thirdparty"/>

  <!-- import environment variables as properties -->
  <property environment="env"/>

  <!-- runtime assertion control -->
  <property name="assertions.jvmarg" value="-ea -esa"/>

  <!-- Set a default for test jvmargs in case it's not set in
       customBuild.properties. -->
  <property name="farrago.test.jvmargs" value=""/>

  <!-- Catalog schema (or database) name (for Postgres or
       Enki+Hibernate on Mysql. -->
  <property name="farrago.catalog.schema" value="farrago"/>

  <!-- forked ant verbosity control -->
  <property name="farrago.forkVerbosity" value="-e"/>

  <!-- Java installation root -->
  <property name="javahome.dir" location="${env.JAVA_HOME}"/>

  <!-- Java source version -->
  <!-- NOTE jvs 8-Oct-2008:  farrago.javasrc.14 is not actually supported -->
  <!-- any more; delete it once red zone dependencies are gone.  -->
  <property name="farrago.javasrc.version" value="1.5"/>
  <condition property="farrago.javasrc.14">
    <equals arg1="${farrago.javasrc.version}" arg2="1.4"/>
  </condition>

  <!-- Java source version for client dependencies; this -->
  <!-- tends to lag the server by one version.  So when we're building -->
  <!-- Farrago with JDK 1.5, we want JVM 1.4 client compatibility; -->
  <!-- building with JDK 1.6, we want JVM 1.5 client compatibility; -->
  <condition property="farrago.client.javasrc.version" value="1.4" else="1.5">
    <equals arg1="${ant.java.version}" arg2="1.5"/>
  </condition>

  <!-- JRE location for test execution -->
  <property name="farrago.jre.dir" location="${javahome.dir}"/>

  <!-- import thirdparty library settings -->
  <property file="${thirdparty.dir}/build.properties"/>

  <!-- verify that required dependencies are defined -->
  <fail unless="javacc.dir"/>
  <fail unless="junit.dir"/>
  <fail unless="macker.dir"/>
  <fail unless="janino.dir"/>
  <fail unless="jswat.dir"/>
  <fail unless="sqlline.dir"/>
  <fail unless="sqlline.lib.dir"/>
  <fail unless="mdrlibs.dir"/>
  <fail unless="enki.dir"/>
  <fail unless="rmijdbc.dir"/>
  <fail unless="emma.dir"/>
  <fail unless="vjdbc.dir"/>
  <fail unless="findbugs.dir"/>
  <fail unless="mysql.dir"/>

  <!-- Directories -->

  <!-- project directory for Fennel -->
  <property name="fennel.dir" location="${open.dir}/fennel"/>

  <!-- directory for non-generated Java source code -->
  <property name="farrago.src.dir" location="${farrago.dir}/src"/>

  <!-- directory for Farrago compiled class files (other than plugins) -->
  <property name="farrago.classes.dir" location="${farrago.dir}/classes"/>

  <property name="emma.farrago.classes.dir" location="${farrago.dir}/classes-cov"/>

  <!-- directory for Farrago compiled plugin .jars -->
  <property name="farrago.plugin.dir" location="${farrago.dir}/plugin"/>

  <!-- directory in which catalog data is stored -->
  <property name="farrago.catalog.dir" location="${farrago.dir}/catalog"/>

  <!-- overridable alias for farrago.catalog.dir -->
  <property name="project.catalog.dir" location="${farrago.catalog.dir}"/>

  <!-- Alias for project.catalog.dir to match runtime properties convention -->
  <property name="FARRAGO_CATALOG_DIR" location="${project.catalog.dir}"/>

  <!-- overridable alias for farrago.catalog.schema -->
  <property name="project.catalog.schema" value="${farrago.catalog.schema}"/>

  <!-- directory for JUnit run output -->
  <property name="project.testlog.dir" location="${farrago.dir}/testlog"/>

  <!-- directory in which catalog sources are generated -->
  <property name="farrago.catalog.src.dir"
    location="${farrago.catalog.dir}/java"/>

  <!-- directory in which SQL parser source code is stored -->
  <property name="farrago.parser.sql.dir"
    location="${farrago.src.dir}/org/eigenbase/sql/parser"/>

  <!-- directory in which DDL parser source code is stored -->
  <property name="farrago.parser.ddl.dir"
    location="${farrago.src.dir}/net/sf/farrago/parser"/>

  <!-- directory in which Eigenbase resources are stored -->
  <property name="eigenbase.resource.dir"
    location="${farrago.src.dir}/org/eigenbase/resource"/>

  <!-- directory in which Eigenbase resource properties are stored -->
  <property name="eigenbase.resource.properties.dir"
    location="${farrago.classes.dir}/org/eigenbase/resource"/>

  <!-- directory in which Farrago resources are stored -->
  <property name="farrago.resource.dir"
    location="${farrago.src.dir}/net/sf/farrago/resource"/>

  <!-- directory in which Farrago resource properties are stored -->
  <property name="farrago.resource.properties.dir"
    location="${farrago.classes.dir}/net/sf/farrago/resource"/>

  <!-- directory in which catalog data is backed up -->
  <property name="farrago.catalog.backup.dir"
    location="${farrago.catalog.dir}/backup"/>

  <!-- directory in which unconfigured catalog data is backed up -->
  <property name="farrago.catalog.unconfigured.dir"
    location="${farrago.catalog.dir}/unconfigured"/>

  <!-- directory in which catalog-related XMI files are stored -->
  <property name="farrago.xmi.dir" location="${farrago.catalog.dir}/xmi"/>

  <!-- directory in which catalog-related SQL files are stored -->
  <property name="farrago.catalog.sql.dir" location="${farrago.catalog.dir}/sql"/>

  <!-- directory in which trace files are configured and generated -->
  <property name="farrago.trace.dir" location="${farrago.dir}/trace"/>

  <!-- directory for initialization scripts -->
  <property name="farrago.initsql.dir" location="${farrago.dir}/initsql"/>

  <!-- target directory for JDBC4 compatibility gunk -->
  <property name="farrago.jdbc4.gen.dir"
    location="${farrago.src.dir}/org/eigenbase/jdbc4"/>

  <!-- We direct SqlLine to squelch its history file by setting the system
       property sqlline.historyFile. This keeps the normal history
       file (~/.sqlline/history under Unix) free from the clutter
       of Farrago sqlline test commands, and also speeds up
       SQL-based tests by avoiding reloading history on startup. -->
  <condition property="sqlline.hist.file" value="nul">
    <os family="windows"/>
  </condition>
  <property name="sqlline.hist.file" location="/dev/null"/>
  <!-- Files -->

  <!-- file controlling repository storage -->
  <property name="farrago.ReposStorage.propfile"
    location="${farrago.catalog.dir}/ReposStorage.properties"/>

  <!-- NOTE:  it would be nice if we could combine parser filesets below, -->
  <!-- and use filelist instead; however, filesets/filelists have to share -->
  <!-- a common root, and the uptodate task doesn't like filelists -->

  <!-- a fileset of the common SQL parser -->
  <fileset id="farrago.parser.common.sql" dir="${farrago.parser.sql.dir}"
    includes="CommonParser.jj"/>

  <!-- a fileset of the Farrago-specific DDL parser -->
  <fileset id="farrago.parser.ddl" dir="${farrago.parser.ddl.dir}"
    includes="DdlParser.jj"/>

  <!-- a fileset of the Farrago common DDL parser -->
  <fileset id="farrago.parser.common.ddl" dir="${farrago.parser.ddl.dir}"
    includes="CommonDdlParser.jj"/>

  <!-- XMI file containing CWM defintion  -->
  <property name="farrago.cwm.xmi" location="${farrago.xmi.dir}/cwm-1.1.xml"/>

  <!-- XMI file containing Farrago final metamodel  -->
  <property name="FarragoMetamodel.xmi"
    location="${farrago.xmi.dir}/FarragoMetamodel.xmi"/>

  <!-- Farrago metamodel XMI file before CWM references are resolved -->
  <property name="FarragoMetamodelUnresolved.xmi"
    location="${farrago.xmi.dir}/FarragoMetamodelUnresolved.xmi"/>

  <!-- XMI file containing Farrago metamodel -->
  <property name="FarragoExtMetamodel.xmi"
    location="${farrago.xmi.dir}/FarragoExtMetamodel.xmi"/>

  <!-- XMI file containing renumbered Farrago metamodel -->
  <property name="FarragoExtMetamodelTransformed.xmi"
    location="${farrago.xmi.dir}/FarragoExtMetamodelTransformed.xmi"/>

  <!-- Same as FarragoExtMetamodel.xmi, but with diagrams deleted -->
  <property name="FarragoExtMetamodelSansDiagrams.xmi"
    location="${farrago.xmi.dir}/FarragoExtMetamodelSansDiagrams.xmi"/>

  <!-- File containing ArgoUML XMI representation of -->
  <!-- Farrago metamodel -->
  <property name="FarragoExtMetamodel.uml"
    location="${farrago.xmi.dir}/FarragoExtMetamodel.uml"/>

  <!-- File defining Farrago tracing -->
  <property name="FarragoTrace.properties"
    location="${farrago.trace.dir}/FarragoTrace.properties"/>

  <!-- overridable alias for FarragoTrace.properties (must come after the
       property it uses) -->
  <property name="project.trace.propfile"
    location="${FarragoTrace.properties}"/>

  <!-- File for Farrago trace log -->
  <property name="FarragoTrace.log"
    location="${farrago.trace.dir}/FarragoTrace.log"/>

  <!-- File defining Farrago MDR build tracing -->
  <property name="FarragoMdrBuildTrace.properties"
    location="${farrago.trace.dir}/MdrBuildTrace.properties"/>

  <!-- File for Farrago trace log -->
  <property name="FarragoMdrBuildTrace.log"
    location="${farrago.trace.dir}/MdrBuildTrace.log"/>

  <!-- Start Enki Hibernate MDR properties.  The following properties
       are only used if the farrago.enki.provider is ENKI_HIBERNATE.
       Override them via customBuild.properties or before importing
       this file.  These should come after project.catalog.schema -->

  <!-- Database backup executable (backup data expected on stdout) -->
  <property 
    name="farrago.enki.hibernate.backup.cmd"
    value="mysqldump"/>

  <property 
    name="farrago.enki.hibernate.backup.user"
    value="root"/>

  <!-- Database backup arguments -->
  <property 
    name="farrago.enki.hibernate.backup.args"
    value="-u ${farrago.enki.hibernate.backup.user} --opt ${project.catalog.schema}"/>

  <!-- Database restore executable -->
  <property 
    name="farrago.enki.hibernate.restore.cmd"
    value="mysql"/>

  <!-- Database backup arguments (backup data provided on stdin) -->
  <property 
    name="farrago.enki.hibernate.restore.args"
    value="-u ${farrago.enki.hibernate.backup.user} -D ${project.catalog.schema}"/>

  <!-- End Enki Hibernate MDR properties -->

  <!-- UML2MOF Defaults to Netbeans MDR's btree implementation.  That
       implementation has a bug which intermittently causes ordered 
       multi-value associations to be re-ordered during XMI import.
       The re-ordering can cause attributes to be re-ordered which 
       causes FRG-322. The memory implementation provides deterministic
       output. -->
  <property
     name="uml2mof.default.storageModel"
     value="org.netbeans.mdr.persistence.memoryimpl.StorageFactoryImpl"/>

  <!-- Classpaths -->

  <!-- Set a default for this classpath in case it's not set in a
       properties file.  The properties file will take precedence. -->
  <property name="farrago.custom.classpath" value=""/>

  <path id="emma.classpath">
    <fileset dir="${emma.dir}" includes="lib/*.jar"/>
  </path>
  <property name="emma.classpath" refid="emma.classpath"/>

  <taskdef resource="emma_ant.properties" classpathref="emma.classpath"/>

  <!-- set test.emma.classpath for emma test only -->
  <if>
    <isset property="codecov.build"/>
    <then>
	    <property name="test.emma.classpath" value="${emma.classpath}"/>
    </then>
    <else>
	    <property name="test.emma.classpath" value=""/>
    </else>
  </if>

  <!-- xerces path -->
  <path id="xerces.classpath">
    <fileset dir=".">
      <include name="${ant.home}/lib/xml-apis.jar" if="farrago.javasrc.14" />
      <include name="${ant.home}/lib/xercesImpl.jar" if="farrago.javasrc.14" />
    </fileset>
    <fileset dir=".">
      <include name="${java.home}/lib/endorsed/xercesImpl.jar" unless="farrago.javasrc.14" />
    </fileset>
  </path>

  <!-- third-party libraries -->
  <path id="farrago.3p.classpath">
    <fileset dir="${enki.dir}" includes="*.jar"/>
    <pathelement location="${mdrlibs.dir}/mdrant.jar"/>
    <pathelement location="${mdrlibs.dir}/nbmdr.jar"/>
    <pathelement location="${mdrlibs.dir}/mdrapi.jar"/>
    <pathelement location="${mdrlibs.dir}/jmiutils.jar"/>
    <pathelement location="${mdrlibs.dir}/mof.jar"/>
    <pathelement location="${mdrlibs.dir}/jmi.jar"/>
    <pathelement location="${mdrlibs.dir}/openide-util.jar"/>
    <pathelement location="${mdrlibs.dir}/mdrjdbc.jar"/>
    <pathelement location="${mysql.dir}/mysql-connector-java-3.1.14-bin.jar"/>
    <pathelement location="${resgen.dir}/lib/eigenbase-resgen.jar"/>
    <pathelement location="${resgen.dir}/lib/eigenbase-xom.jar"/>
    <pathelement location="${junit.dir}/junit.jar"/>
    <path refid="xerces.classpath"/>
    <pathelement location="${javahome.dir}/lib/tools.jar"/>
    <pathelement location="${rmijdbc.dir}/dist/lib/RmiJdbc.jar"/>
    <pathelement location="${csvjdbc.dir}/csvjdbc.jar"/>
    <pathelement location="${janino.dir}/lib/janino.jar"/>
    <pathelement location="${openjava.dir}/openjava.jar"/>
    <pathelement location="${hsqldb.dir}/lib/hsqldb.jar"/>
    <pathelement location="${thirdparty.dir}/commons-transaction-1.1.jar"/>
    <pathelement location="${thirdparty.dir}/postgresql-8.1-406.jdbc2.jar"/>
    <pathelement location="${vjdbc.dir}/lib/vjdbc_server.jar"/>
    <pathelement location="${vjdbc.dir}/lib/vjdbc.jar"/>
    <pathelement location="${vjdbc.dir}/lib/commons-logging-1.1.jar"/>
    <pathelement location="${vjdbc.dir}/lib/commons-pool-1.3.jar"/>
    <pathelement location="${vjdbc.dir}/lib/commons-dbcp-1.2.1.jar"/>
    <pathelement location="${vjdbc.dir}/lib/commons-digester-1.7.jar"/>
    <pathelement location="${jgrapht.dir}/jgrapht-jdk1.5.jar"/>
    <pathelement path="${farrago.custom.classpath}"/>
  </path>
  <property name="farrago.3p.classpath" refid="farrago.3p.classpath"/>

  <!-- classpath for execution -->
  <path id="farrago.run.classpath">
    <pathelement path="${farrago.3p.classpath}"/>
    <pathelement location="${farrago.classes.dir}"/>
    <pathelement location="${farrago.catalog.src.dir}"/>
    <pathelement path="${test.emma.classpath}" />
  </path>
  <property name="farrago.run.classpath" refid="farrago.run.classpath"/>

  <!-- classpath for running javadoc -->
  <path id="farrago.javadoc.classpath">
    <pathelement path="${farrago.3p.classpath}"/>
    <pathelement path="${farrago.sqlline.classpath}"/>
    <pathelement location="${jgraphaddons.dir}/lib/jgraphaddons.jar"/>
    <pathelement location="${jgrapht.dir}/lib/jgraph.jar"/>
  </path>
  <property name="farrago.javadoc.classpath" refid="farrago.javadoc.classpath"/>

  <!-- classpath for reentrantly invoking ant -->
  <path id="ant.classpath">
    <pathelement location="${ant.home}/lib/ant.jar"/>
    <pathelement location="${ant.home}/lib/ant-launcher.jar"/>
    <pathelement location="${ant.home}/lib/junit.jar"/>
    <pathelement location="${ant.home}/lib/ant-contrib.jar"/>
    <path refid="xerces.classpath"/>
    <pathelement location="${ant.home}/lib/ant-junit.jar"/>
    <pathelement location="${ant.home}/lib/ant-nodeps.jar"/>
    <pathelement location="${ant.home}/lib/ant-trax.jar"/>
    <pathelement path="${test.emma.classpath}"/>
  </path>
  <property name="ant.classpath" refid="ant.classpath"/>

  <!-- classpath for model import -->
  <path id="farrago.model.classpath">
    <pathelement path="${farrago.3p.classpath}"/>
    <pathelement location="${farrago.catalog.src.dir}"/>
    <pathelement path="${ant.classpath}"/>
  </path>
  <property name="farrago.model.classpath" refid="farrago.model.classpath"/>

  <!-- classpath for running from sqlline -->
  <path id="farrago.sqlline.classpath">
    <pathelement location="${sqlline.lib.dir}/sqlline.jar"/>
    <pathelement location="${sqlline.lib.dir}/jline.jar"/>
    <pathelement location="${diffj.dir}/share/diffj/diffj.jar"/>
    <pathelement path="${farrago.run.classpath}"/>
  </path>
  <property name="farrago.sqlline.classpath" refid="farrago.sqlline.classpath"/>

  <!-- classpath for running Jalopy -->
  <path id="farrago.jalopy.classpath">
    <pathelement path="${farrago.sqlline.classpath}"/>
    <pathelement location="${farrago.plugin.dir}/classes"/>
  </path>
  <property name="farrago.jalopy.classpath" refid="farrago.jalopy.classpath"/>

  <!-- classpath for running blackhawk based tests -->
  <property name="bh.home" location="${thirdparty.dir}/blackhawk"/>

  <!-- classpath for running blackhawk based tests -->
  <property name="bh.home" location="${thirdparty.dir}/blackhawk"/>

  <path id="blackhawk.run.classpath">
    <pathelement path="${ant.classpath}"/>
    <pathelement location="${bh.home}/bhx.jar"/>
    <pathelement
      location="${thirdparty.dir}/jakarta-regexp-1.4.jar"/>
    <pathelement
      location="${thirdparty.dir}/xmlbeans/lib/xbean.jar"/>
    <pathelement
      location="${thirdparty.dir}/xmlbeans/lib/jsr173_1.0_api.jar"/>
    <pathelement location="${bh.home}/schema.jar"/>
  </path>
  <property name="blackhawk.run.classpath" refid="blackhawk.run.classpath"/>

  <taskdef name="blackhawk"
    classname="org.eigenbase.blackhawk.BhVMTask"
    classpathref="blackhawk.run.classpath"
    onerror="ignore"/>

  <macrodef name="blackhawk.fork">
    <attribute name="dir" default="."/>
    <attribute name="basedir" default="."/>
    <attribute name="testscript" default="test.xml"/>
    <attribute name="bhhome" default="${bh.home}"/>
    <attribute name="fail.on.error" default="true"/>
    <attribute name="verbose" default="false"/>
    <attribute name="classpathref" default="blackhawk.run.classpath"/>
    <attribute name="inheritAll" default="true"/>
    <attribute name="gtlf.dtd.use.remote" default="false"/>
    <attribute name="gtlf.dtd.local" default="${thirdparty.dir}/blackhawk/gtlf-config-2-1.dtd"/>
    <attribute name="luciddb.listener.port" default=""/>
    <sequential>
      <taskdef
        name="bh"
        classname="org.eigenbase.blackhawk.BhVMTask"
        classpathref="blackhawk.run.classpath"
        onerror="fail"/>
      <bh
        dir="@{dir}"
        testfile="@{basedir}/@{testscript}"
        bhHome="@{bhhome}"
        failOnError="@{fail.on.error}"
        verbose="@{verbose}"
        inheritAll="@{inheritAll}"
        fork="true"
        classpathref="@{classpathref}">
        <jvmarg line="-Xmx256m"/>
        <jvmarg line="&FarragoSqlLineProps;"/>
        <jvmarg line="${assertions.jvmarg}"/>
        <sysproperty key="gtlf.dtd.use.remote" value="@{gtlf.dtd.use.remote}"/>
        <sysproperty key="gtlf.dtd.local" value="@{gtlf.dtd.local}"/>
        <sysproperty key="luciddb.listener.port"
          value="@{luciddb.listener.port}"/>
      </bh>
    </sequential>
  </macrodef>



  <!-- Macros -->

  <!-- Macro for forking ant -->
  <macrodef name="farrago.antFork">
    <attribute name="dir" default="."/>
    <attribute name="target" default="unspecifiedTarget"/>
    <attribute name="classpathref" default="ant.classpath"/>
    <attribute name="jvm" default="${farrago.jre.dir}/bin/java"/>
    <attribute name="failonerror" default="true"/>
    <element name="jvmargs" optional="yes"/>
    <sequential>
      <java classname="org.apache.tools.ant.Main" fork="true" failonerror="@{failonerror}"
        dir="@{dir}"
        classpathref="@{classpathref}" jvm="@{jvm}">
        <jvmargs/>
        <arg line="${farrago.forkVerbosity}"/>
        <arg value="@{target}"/>
      </java>
    </sequential>
  </macrodef>

  <!-- Macro for forking ant to run an MDR task -->
  <!-- NOTE:  Logger setting squelches unwanted INFORMATIONAL messages -->
  <macrodef name="farrago.mdrFork">
    <attribute name="target" default="unspecifiedTarget"/>
    <attribute name="classpathref" default="farrago.model.classpath"/>
    <sequential>
      <farrago.antFork 
          target="@{target}"
          jvm="java"
          classpathref="@{classpathref}">
        <!-- REVIEW: SWZ: 2008-03-26: Remove when all callers
             explicitly set storage properties (by file or element). -->
        <jvmargs>
          <sysproperty 
              key="enki.compatibility.storagePropertiesFile"
              value="${project.catalog.dir}/ReposStorage.properties"/>
          <sysproperty 
              key="enki.compatibility.substPropertyName"
              value="FARRAGO_CATALOG_DIR"/>
          <sysproperty
              key="enki.compatibility.substPropertyValue"
              value="${project.catalog.dir}"/>
        </jvmargs>
      </farrago.antFork>
    </sequential>
  </macrodef>

  <!-- Customization for javac task -->
  <presetdef name="farrago.javaCompile">
    <javac debug="on" deprecation="on" source="${farrago.javasrc.version}"/>
  </presetdef>

  <!-- Customization for javac task for compiling client-side code -->
  <presetdef name="farrago.javaCompileClient">
    <javac debug="on" deprecation="on" 
      source="${farrago.client.javasrc.version}" 
      target="${farrago.client.javasrc.version}"/>
  </presetdef>

  <!-- Customization for java task -->
  <presetdef name="farrago.javaExec">
    <java fork="yes" failonerror="true">
      <jvmarg line="${assertions.jvmarg}"/>
      <jvmarg line="&FarragoProps;"/>
    </java>
  </presetdef>

  <!-- Macro for running JSwat -->
  <macrodef name="farrago.jswatDebug">
    <attribute name="classpath" default="unspecified"/>
    <attribute name="sourcepath" default="unspecified"/>
    <attribute name="classname" default="unspecified"/>
    <element name="jvmargs" optional="yes"/>
    <element name="programargs" optional="yes"/>
    <sequential>
      <java
        jar="${jswat.dir}/jswat.jar"
        fork="yes">
        <sysproperty key="java.ext.dirs" value="${java.home}/../lib"/>
        <arg value="classpath"/>
        <arg value="'@{classpath}'"/>
        <arg value=";"/>
        <arg value="sourcepath"/>
        <arg value="'@{sourcepath}'"/>
        <arg value=";"/>
        <arg value="options"/>
        <arg value="stopOnMain"/>
        <arg value="true"/>
        <arg value=";"/>
        <arg value="run"/>
        <arg line="${assertions.jvmarg}"/>
        <jvmargs/>
        <arg value="@{classname}"/>
        <programargs/>
      </java>
    </sequential>
  </macrodef>

  <!-- Macro for converting metamodel from UML to MOF -->
  <macrodef name="farrago.uml2mof">
    <attribute name="umlmodelname" default="unspecified" />
    <attribute name="outputfilename" default="unspecified" />
    <attribute name="umlsansdiagrams" default="unspecified" />
    <attribute name="storageModel" default="${uml2mof.default.storageModel}"/>
    <sequential>
      <xslt style="${farrago.xmi.dir}/deleteUmlDiagrams.xsl"
        in="@{umlmodelname}"
        out="@{umlsansdiagrams}">
      </xslt>
      <java classname="org.netbeans.lib.jmi.uml2mof.Main"
        fork="true" failonerror="true">
        <sysproperty
          key="org.netbeans.mdr.storagemodel.StorageFactoryClassName"
          value="@{storageModel}"/>
        <sysproperty key="org.netbeans.mdr.Logger" value="256"/>
        <classpath>
          <pathelement location="${mdrlibs.dir}/openide-util.jar"/>
          <pathelement location="${mdrlibs.dir}/uml-1.4.jar"/>
          <pathelement location="${mdrlibs.dir}/uml2mof.jar"/>
        </classpath>
        <arg value="@{umlsansdiagrams}"/>
        <arg value="@{outputfilename}"/>
      </java>
      <delete>
        <fileset dir="." includes="mdr.bt*"/>
      </delete>
    </sequential>
  </macrodef>

  <!-- Macro for extracting a UML model from Poseidon .zuml format,
  and converting it to MOF -->
  <macrodef name="farrago.extractPoseidonModel">
    <attribute name="zumlFile" default="unspecified" />
    <attribute name="umlBasename" default="unspecified" />
    <attribute name="mofBasename" default="unspecified" />
    <attribute name="xmiDir" default="unspecified" />
    <attribute name="storageModel" default="${uml2mof.default.storageModel}"/>
    <sequential>
      <unzip src="@{zumlFile}" dest="@{xmiDir}">
        <patternset>
          <include name="@{umlBasename}.xmi"/>
        </patternset>
      </unzip>
      <farrago.uml2mof umlmodelname="@{xmiDir}/@{umlBasename}.xmi"
        outputfilename="@{xmiDir}/@{mofBasename}.xmi"
        umlsansdiagrams="@{xmiDir}/@{umlBasename}SansDiagrams.xmi"
        storageModel="@{storageModel}"/>
    </sequential>
  </macrodef>

  <!-- Macro for extracting a UML model from ArgoUML .uml format,
  and converting it to MOF -->
  <macrodef name="farrago.extractArgoModel">
    <attribute name="umlFile" default="unspecified" />
    <attribute name="umlBasename" default="unspecified" />
    <attribute name="mofBasename" default="unspecified" />
    <attribute name="xmiDir" default="unspecified" />
    <attribute name="storageModel" default="${uml2mof.default.storageModel}"/>
    <sequential>
      <xslt style="${farrago.xmi.dir}/extractArgoModel.xsl"
        in="@{umlFile}"
        out="@{xmiDir}/@{umlBasename}.xmi">
      </xslt>
      <farrago.uml2mof umlmodelname="@{xmiDir}/@{umlBasename}.xmi"
        outputfilename="@{xmiDir}/@{mofBasename}.xmi"
        umlsansdiagrams="@{xmiDir}/@{umlBasename}SansDiagrams.xmi"
        storageModel="@{storageModel}"/>
    </sequential>
  </macrodef>

  <!-- Macro for performing cleansing transformations on an extension model -->
  <macrodef name="farrago.transformExtensionModel">
    <attribute name="mofBasename" default="unspecified" />
    <attribute name="xmiDir" default="unspecified" />
    <attribute name="modelPrefix" default="unspecified" />
    <sequential>
      <xslt style="${farrago.xmi.dir}/transformFEME.xsl"
        in="@{xmiDir}/@{mofBasename}.xmi"
        out="@{xmiDir}/@{mofBasename}Transformed.xmi">
        <param name="modelPrefix"
          expression="@{modelPrefix}"/>
      </xslt>
      <replace file="@{xmiDir}/@{mofBasename}Transformed.xmi"
        token="org.omg.xmi.namespace.Model" value="omg.org/mof.Model/1.3" />
    </sequential>
  </macrodef>

  <!-- Macro for combining CWM and FEM -->
  <macrodef name="farrago.synthesizeMetamodel">
    <attribute name="xmiDir" default="unspecified" />
    <attribute name="extMofBasename" default="unspecified" />
    <attribute name="extPresent" default="true" />
    <sequential>
      <xslt style="${farrago.xmi.dir}/transformCWM.xsl"
        in="${farrago.cwm.xmi}"
        out="@{xmiDir}/FarragoMetamodelUnresolved.xmi">
        <param name="femXmiFilename"
          expression="${FarragoExtMetamodelTransformed.xmi}"/>
        <param name="extXmiFilename"
          expression="@{xmiDir}/@{extMofBasename}Transformed.xmi"/>
        <param name="extPresent" expression="@{extPresent}"/>
      </xslt>
      <xslt style="${farrago.xmi.dir}/resolveCwmRefs.xsl"
        in="@{xmiDir}/FarragoMetamodelUnresolved.xmi"
        out="@{xmiDir}/FarragoMetamodel.xmi"/>
    </sequential>
  </macrodef>

  <!-- Macro for generating an SQL parser -->
  <macrodef name="farrago.generateParser">
    <attribute name="combined" default="unspecified"/>
    <element name="components"/>
    <sequential>
      <delete file="@{combined}" quiet="true"/>
      <concat destfile="@{combined}" append="false">
        <components/>
      </concat>
      <chmod file="@{combined}" perm="a-w"/>
      <javacc
        target="@{combined}" javacchome="${javacc.dir}"/>
    </sequential>
  </macrodef>

  <!-- Macro for uncommenting generics in classes generated by MDR -->
  <macrodef name="farrago.uncommentGenerics">
    <attribute name="javadir" default="/unspecified/path"/>
    <sequential>
      <replace dir="@{javadir}">
        <replacefilter token="/*&lt;" value="&lt;" />
        <replacefilter token="&gt;*/" value="&gt;" />
      </replace>
    </sequential>
  </macrodef>

  <!-- Macro for extracting the timestamp from an ArgoUML model  -->
  <macrodef name="farrago.extractModelTimestamp">
    <attribute name="umlFile" default="unspecified" />
    <attribute name="outFile" default="unspecified" />
    <sequential>
      <xslt style="${farrago.xmi.dir}/extractArgoTimestamp.xsl" in="@{umlFile}"
        out="@{outFile}"/>
    </sequential>
  </macrodef>

  <!-- Macro for running JUnit and sqlline tests -->
  <macrodef name="farrago.runTests">
    <attribute name="targetonerror" default=""/>
    <element name="testfileset" optional="no"/>
    <element name="junitargs" optional="yes"/>
    <sequential>
      <fail unless="testlog.dir"/>
      <mkdir dir="${testlog.dir}"/>
      <junit printsummary="yes" fork="no" failureproperty="junit.failure"
        tempdir="${testlog.dir}" reloading="false">
        <sysproperty key="java.ext.dirs" value="${sqlline.dir}"/>
        <junitargs/>
        <formatter type="plain"/>
        <formatter type="xml"/> <!-- for integration builds -->
        <batchtest todir="${testlog.dir}" unless="junit.class">
          <testfileset/>
        </batchtest>
        <test todir="${testlog.dir}" if="junit.class"
          name="${junit.class}" />
      </junit>
      <if>
        <and>
          <isset property="junit.failure"/>
          <not>
            <equals arg1="@{targetonerror}" arg2=""/>
          </not>
        </and>
      <then>
        <antcall target="@{targetonerror}"/>
      </then>
      </if>
      <fail message="Test failure(s)" if="junit.failure"/>
    </sequential>
  </macrodef>

  <!-- Macro for running a single forked sqlline test -->
  <macrodef name="farrago.runSqlTest">
    <attribute name="file" default="unspecified"/>
    <sequential>
      <junit printsummary="yes" fork="yes" haltonerror="yes" haltonfailure="yes"
        tempdir="${testlog.dir}" forkmode="perBatch">
        <classpath refid="farrago.sqlline.classpath"/>
        <jvmarg line="${assertions.jvmarg}"/>
        <jvmarg line="&FarragoSqlLineProps;"/>
        <sysproperty key="java.ext.dirs" value="${sqlline.dir}"/>
        <sysproperty key="net.sf.farrago.fileset.unitsql"
          file="@{file}"/>
        <formatter type="plain"/>
        <formatter type="xml"/> <!-- for integration builds -->
        <test todir="${testlog.dir}"
          name="net.sf.farrago.test.FarragoSqlTest" />
      </junit>
    </sequential>
  </macrodef>

  <!--

  Declare mdr task used for catalog manipulation.  Note that in order
  to use this task, we always fork an ant subprocess using java (not
  ant or antcall).  There are two reasons for this.  Most importantly,
  it makes sure that the repository is shut down properly.  Without
  this, invocations of mdr sometimes interfere with our own java tasks
  (e.g. populateCatalog).  Another reason is that it gives us a chance
  to set Java properties, most importantly the one that controls the
  mdr logging level, so we can suppress some spurious exception
  reports.

  -->

  <target name="farrago.mdr_taskdef">
    <taskdef name="mdr" 
      classname="org.eigenbase.enki.ant.EnkiTask"
      classpathref="farrago.3p.classpath"
      loaderRef="mdr_loader"/>

    <!-- Enki provider-specific sub tasks. -->
    <typedef 
      name="exportSchema"
      classname="org.eigenbase.enki.hibernate.ant.ExportSchemaSubTask"
      classpathref="farrago.3p.classpath"
      loaderRef="mdr_loader"/>
    <typedef 
      name="applyTablePrefix"
      classname="org.eigenbase.enki.hibernate.ant.ApplyTablePrefixSubTask"
      classpathref="farrago.3p.classpath"
      loaderRef="mdr_loader"/>
  </target>

  <!-- Macro for creating a TAGS file suitable for use in Emacs -->
  <macrodef name="farrago.createEmacsTags">
    <attribute name="filesetPropertyName" default="unspecified"/>
    <sequential>
      <delete file="${basedir}/taggedfiles.tmp" quiet="true"/>
      <concat destfile="taggedfiles.tmp">replaceme</concat>
      <pathconvert property="files.taggable"
          pathsep="${line.separator}"
          dirsep="/" refid="@{filesetPropertyName}" >
        <map from="${basedir}" to="." />
      </pathconvert>
      <replace file="taggedfiles.tmp"
        token="replaceme" value="${files.taggable}" />
      <fixcrlf srcDir="${basedir}" includes="taggedfiles.tmp"
        eol="lf" eof="remove" />
      <exec dir="${basedir}" executable="ctags">
        <arg line="--langmap=java:+.jj"/>
        <arg line="-e"/>
        <arg line="-L taggedfiles.tmp"/>
      </exec>
      <delete file="${basedir}/taggedfiles.tmp" quiet="true"/>
    </sequential>
  </macrodef>

  <!-- Sets the farrago.enki.provider property -->
  <macrodef name="farrago.setReposProvider">
    <attribute name="reposStorageProps" default="${farrago.ReposStorage.propfile}"/>
    <sequential>
      <ac:if xmlns:ac="antlib:net.sf.antcontrib">
        <not>
          <isset property="farrago.enki.provider"/>
        </not>
        <then>
          <loadproperties srcFile="@{reposStorageProps}">
            <filterchain>
              <linecontainsregexp>
                <regexp pattern="(org.eigenbase.enki.implementationType|hibernate.dialect=)"/>
              </linecontainsregexp>
              <tokenfilter>
                <replacestring 
                  from="org.eigenbase.enki.implementationType"
                  to="farrago.enki.provider"/>
                <replacestring 
                  from="hibernate.dialect="
                  to="farrago.enki.dialect="/>
              </tokenfilter>
            </filterchain>
          </loadproperties>
      
          <condition 
              property="farrago.enki.generator"
              value="org.eigenbase.enki.hibernate.codegen.HibernateGenerator">
            <equals arg1="${farrago.enki.provider}" arg2="ENKI_HIBERNATE"/>
          </condition>
          <condition 
              property="farrago.enki.generator"
              value="org.eigenbase.enki.trans.codegen.TransientGenerator">
            <equals arg1="${farrago.enki.provider}" arg2="ENKI_TRANSIENT"/>
          </condition>
          <condition 
              property="farrago.enki.generator"
              value="org.eigenbase.enki.netbeans.codegen.NetbeansGenerator">
            <not>
              <isset property="farrago.enki.generator"/>
            </not>
          </condition>
        </then>
      </ac:if>
    </sequential>
  </macrodef>

  <!-- Macro for cleaning out a catalog directory -->
  <macrodef name="farrago.cleanCatalog">
    <attribute name="catalogDir" default="${farrago.catalog.dir}"/>
    <attribute name="dropStorage" default="false"/>

    <sequential>
      <delete>
        <fileset dir="@{catalogDir}" includes="*.dat"/>
        <fileset dir="@{catalogDir}" includes="*Dump.xmi"/>
        <fileset dir="@{catalogDir}" includes="FarragoBootUrls.lst"/>

        <!-- Deletes HSQLDB files or MYSQL .dump files. -->
        <fileset dir="@{catalogDir}" includes="FarragoCatalog.*"/>
      </delete>

      <property 
          file="@{catalogDir}/ReposStorage.properties"
          prefix="cleanCatalog"/>

      <if>
        <and>
          <equals arg1="@{dropStorage}" arg2="true"/>
          <isset property="cleanCatalog.net.sf.farrago.dev.dropStorage"/>
          <isset property="cleanCatalog.net.sf.farrago.dev.createStorage"/>
        </and>
        <then>
          <echo>
            Database URL:
            ${cleanCatalog.net.sf.farrago.dev.connection.url}

            Executing:
            ${cleanCatalog.net.sf.farrago.dev.dropStorage}
            ${cleanCatalog.net.sf.farrago.dev.createStorage}
          </echo>
          <!-- Allow drop to fail (may be first time we run this). -->
          <!-- propertyresource allows semi-colon delimited statements. -->
          <sql
              driver="${cleanCatalog.net.sf.farrago.dev.connection.driver_class}"
              url="${cleanCatalog.net.sf.farrago.dev.connection.url}" 
              userid="${cleanCatalog.net.sf.farrago.dev.connection.username}"
              password="${cleanCatalog.net.sf.farrago.dev.connection.password}"
              classpathref="farrago.3p.classpath"
              onerror="continue"
              autocommit="true">
            <propertyresource 
                name="cleanCatalog.net.sf.farrago.dev.dropStorage"/>
          </sql>
          <sql
              driver="${cleanCatalog.net.sf.farrago.dev.connection.driver_class}"
              url="${cleanCatalog.net.sf.farrago.dev.connection.url}" 
              userid="${cleanCatalog.net.sf.farrago.dev.connection.username}"
              password="${cleanCatalog.net.sf.farrago.dev.connection.password}"
              classpathref="farrago.3p.classpath"
              autocommit="true">
            <propertyresource
                name="cleanCatalog.net.sf.farrago.dev.createStorage"/>
          </sql>
        </then>
      </if>
    </sequential>
  </macrodef>

  <!-- Macro for backing up a catalog directory -->
  <macrodef name="farrago.backupCatalog">
    <attribute name="catalogDir" default="${farrago.catalog.dir}"/>
    <attribute name="backupDir" default="${farrago.catalog.backup.dir}"/>
    <attribute name="catalogOnly" default="false"/>
    <attribute name="includeTempDataFile" default="false"/>

    <sequential>
      <farrago.setReposProvider reposStorageProps="@{catalogDir}/ReposStorage.properties"/>

      <delete includeEmptyDirs="true" quiet="true">
        <fileset dir="@{backupDir}" includes="*"/>
      </delete>
      <mkdir dir="@{backupDir}"/>

      <ac:if xmlns:ac="antlib:net.sf.antcontrib">
        <and>
          <equals arg1="${farrago.enki.provider}" arg2="ENKI_HIBERNATE"/>
          <not>
            <equals 
                arg1="${farrago.enki.dialect}"
                arg2="org.hibernate.dialect.HSQLDialect"/>
          </not>
        </and>
        <then>
          <!-- Backup the hibernate database to FarragoCatalog.dump. -->
          <echo message="Backing up Enki/Hibernate repository from schema '${project.catalog.schema}'"/> 
          <exec 
              executable="${farrago.enki.hibernate.backup.cmd}"
              output="@{backupDir}/FarragoCatalog.dump"
              logError="true"
              failonerror="true">
            <arg line="${farrago.enki.hibernate.backup.args}"/>
          </exec>
        </then>
      </ac:if>

      <copy todir="@{backupDir}">
        <fileset dir="@{catalogDir}" includes="FarragoCatalog.*"/>
      </copy>
      <ac:if xmlns:ac="antlib:net.sf.antcontrib">
        <isfalse value="@{catalogOnly}"/>
        <then>
          <copy todir="@{backupDir}">
            <fileset dir="@{catalogDir}" includes="db.dat"/>
          </copy>
          <if>
            <istrue value="@{includeTempDataFile}"/>
            <then>
              <copy todir="@{backupDir}">
                <fileset dir="@{catalogDir}" includes="temp.dat"/>
              </copy>
            </then>
          </if>
        </then>
      </ac:if>
    </sequential>
  </macrodef>

  <!-- Macro for restoring a backed up catalog directory -->
  <macrodef name="farrago.restoreCatalog">
    <attribute name="catalogDir" default="${farrago.catalog.dir}"/>
    <attribute name="backupDir" default="${farrago.catalog.backup.dir}"/>
    <attribute name="catalogOnly" default="false"/>

    <sequential>
      <farrago.setReposProvider reposStorageProps="@{catalogDir}/ReposStorage.properties"/>

      <copy overwrite="true" todir="@{catalogDir}">
        <fileset dir="@{backupDir}">
          <exclude name="*.dump"/>
          <exclude name="*.dat"/>
        </fileset>
      </copy>
      
      <ac:if xmlns:ac="antlib:net.sf.antcontrib">
        <isfalse value="@{catalogOnly}"/>
        <then>
          <copy overwrite="true" todir="@{catalogDir}">
            <fileset dir="@{backupDir}">
              <include name="*.dat"/>
            </fileset>
          </copy>
        </then>
      </ac:if>
      
      <ac:if xmlns:ac="antlib:net.sf.antcontrib">
        <and>
          <equals arg1="${farrago.enki.provider}" arg2="ENKI_HIBERNATE"/>
          <not>
            <equals 
                arg1="${farrago.enki.dialect}"
                arg2="org.hibernate.dialect.HSQLDialect"/>
          </not>
        </and>
        <then>
          <!-- Restore the hibernate database from FarragoCatalog.dump. -->
          <echo message="Restoring Enki/Hibernate repository to schema '${project.catalog.schema}'"/> 
          <exec 
              executable="${farrago.enki.hibernate.restore.cmd}"
              input="@{backupDir}/FarragoCatalog.dump"
              logError="true"
              failonerror="true">
            <arg line="${farrago.enki.hibernate.restore.args}"/>
          </exec>
        </then>
      </ac:if>
    </sequential>
  </macrodef>

  <!-- Macro for comparing catalog export before/after test run -->
  <macrodef name="farrago.compareCatalogExport">
    <attribute name="log.dir" default="unspecified"/>
    <attribute name="export.file" default="unspecified"/>
    <attribute name="export.target" default="exportCatalog"/>
    <sequential>
      <delete quiet="true" dir="@{log.dir}"/>
      <mkdir dir="@{log.dir}"/>
      <move file="@{export.file}"
        tofile="@{log.dir}/before.xmi"/>
      <antcall target="@{export.target}"/>
      <move file="@{export.file}"
        tofile="@{log.dir}/after.xmi"/>
      <xslt style="${farrago.xmi.dir}/maskIds.xsl"
        in="@{log.dir}/before.xmi"
        out="@{log.dir}/before.masked.xmi" />
      <xslt style="${farrago.xmi.dir}/maskIds.xsl"
        in="@{log.dir}/after.xmi"
        out="@{log.dir}/after.masked.xmi" />
      <fail message="catalog differs from clean state">
        <condition>
          <not>
            <filesmatch
              file1="@{log.dir}/before.masked.xmi"
              file2="@{log.dir}/after.masked.xmi" />
          </not>
        </condition>
      </fail>
    </sequential>
  </macrodef>

  <!-- Macro for configuring tracing properties -->
  <macrodef name="farrago.configureTrace">
    <attribute name="propFile" default="unspecified"/>
    <attribute name="logFile" default="unspecified"/>
    <sequential>
      <touch file="@{propFile}" mkdirs="true"/>
      <propertyfile file="@{propFile}"
        comment="Developer tracing configuration (do not add comments)">
        <entry key="handlers" default="java.util.logging.FileHandler"/>
        <entry key="java.util.logging.FileHandler.formatter"
          default="java.util.logging.SimpleFormatter"/>
        <entry key=".level" default="CONFIG"/>
        <entry key="java.util.logging.FileHandler.pattern"
          default="@{logFile}"/>
        <entry key="java.util.logging.FileHandler.append" default="true"/>
        <entry key="net.sf.farrago.jdbc.level" default="FINER"/>
      </propertyfile>
    </sequential>
  </macrodef>

  <!-- Macro for generating a test wrapper for .sql diff-based test scripts -->
  <macrodef name="farrago.generateSqlTestWrapper">
    <attribute name="filesetref" default="unspecified"/>
    <attribute name="outputfile" default="unspecified"/>
    <attribute name="rootpath" default="unspecified"/>
    <attribute name="packagename" default="unspecified"/>
    <attribute name="classname" default="unspecified"/>
    <attribute name="basename" default="FarragoTestCase"/>
    <sequential>
      <property name="list.xml" location="${farrago.dir}/testgen/list.xml"/>
      <delete file="${list.xml}"/>
      <delete file="@{outputfile}"/>
      <pathconvert property="filename.list" pathsep="," refid="@{filesetref}">
        <map from="@{rootpath}" to=""/>
      </pathconvert>
      <echo file="${list.xml}" append="true"
        message="&lt;fileset&gt;${line.separator}"/>
      <ac:for param="filename" xmlns:ac="antlib:net.sf.antcontrib"
        list="${filename.list}">
        <sequential>
          <echo file="${list.xml}" append="true"
            message="&lt;file path='@{filename}'/&gt;${line.separator}"/>
        </sequential>
      </ac:for>
      <echo file="${list.xml}" append="true"
        message="&lt;/fileset&gt;${line.separator}"/>
      <xslt style="${farrago.dir}/testgen/generateSqlTestWrapper.xsl"
        in="${list.xml}"
        out="@{outputfile}">
        <param name="rootpath"
          expression="@{rootpath}"/>
        <param name="packagename"
          expression="@{packagename}"/>
        <param name="classname"
          expression="@{classname}"/>
        <param name="basename"
          expression="@{basename}"/>
      </xslt>
    </sequential>
  </macrodef>

  <!--
      Macro for generating a FarragoRelease.properties file.  Normally
      it's empty, but the property "jdbc.url.port.default" (from
      customBuild.properties or the command line) can be used to set a
      JDBC URL port.
  -->
  <macrodef name="farrago.configureReleaseProperties">
    <attribute name="file" default="unspecified"/>
    <sequential>
      <touch file="@{file}"/>
      <!-- If the property jdbc.url.port.default is set, set the
           FarragoRelease.properties value of jdbc.url.port.default to
           be the same (unless already set in that file). -->
      <property file="@{file}" prefix="RELEASE_PROPS"/>

      <if>
        <and>
          <isset property="jdbc.url.port.default"/>
          <not>
            <equals
                arg1="${RELEASE_PROPS.jdbc.url.port.default}"
                arg2="${jdbc.url.port.default}"/>
          </not>
        </and>
        <then>
          <propertyfile file="@{file}">
            <entry
                key="jdbc.url.port.default"
                value="${jdbc.url.port.default}"/>
          </propertyfile>
        </then>
      </if>
    </sequential>
  </macrodef>

</project>
