<?xml version="1.0" encoding="UTF-8"?>
<!--
   Copyright 2014, 2015 IBM Corp.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
-->
<project name="dcm_taskdefs" xmlns:dcm="urn:datapower:configuration:manager">

  <taskdef name="dpdownload" classname="com.ibm.dcm.taskDpdownload" classpath="${dcm.jar}"/>
  <taskdef name="dpupload" classname="com.ibm.dcm.taskDpupload" classpath="${dcm.jar}"/>
  <taskdef name="frombase64" classname="com.ibm.dcm.taskFrombase64" classpath="${dcm.jar}"/>
  <taskdef name="getservercerts" classname="com.ibm.dcm.taskGetServerCerts" classpath="${dcm.jar}"/>
  <taskdef name="if" classname="com.ibm.dcm.taskIf" classpath="${dcm.jar}"/>
  <taskdef name="nxslt" classname="com.ibm.dcm.taskNxslt" classpath="${dcm.jar}"/>
  <taskdef name="storexml" classname="com.ibm.dcm.taskStorexml" classpath="${dcm.jar}"/>
  <taskdef name="tobase64" classname="com.ibm.dcm.taskTobase64" classpath="${dcm.jar}"/>
  <taskdef name="wdp" classname="com.ibm.dcm.taskWdp" classpath="${dcm.jar}"/>
  <taskdef name="xpath" classname="com.ibm.dcm.taskXpath" classpath="${dcm.jar}"/>
  <taskdef name="forxpath" classname="com.ibm.dcm.taskForXpath" classpath="${dcm.jar}"/>



  <!--

    Backup all of the domains on the device in a ZIP format.  Note that this is not
    a secure backup that includes keys/certs.  This is functionally just BackupDomains
    with a list of all the domains on the appliance.

    Required parameters:
      host - hostname or IP address of DataPower device
      uid - userid
      pwd - password
      local - filename for ZIP file created by this operation

    Optional parameters:
      port - XML Management Interface port on device (defaults to 5550)
      ignore-errors = true() or false()

  -->
  <macrodef name="backupDevice">
    <attribute name="local"/>
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <wdp operation="BackupDevice" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <local>@{local}</local>
        <hostname>@{host}</hostname>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <ignore-errors>@{ignore-errors}</ignore-errors>
      </wdp>
    </sequential>

  </macrodef>

  <!--
    Export the specified object (name and class) in a ZIP format.

    Required parameters:
      host - hostname or IP address of DataPower device
      uid - userid
      pwd - password
      local - filename for ZIP file created by this operation
      objname - target object's name to be exported
      objclass - target object's class


    Optional parameters:
      port - XML Management Interface port on device (defaults to 5550)
      ignore-errors - defaults to false
      refobjs - Include referenced objects? defaults to true
      reffiles - Include referenced files? defaults to true

  -->
	<macrodef name="exportObject">
    <attribute name="domain"/>
    <attribute name="host"/>
    <attribute name="local"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <attribute name="objclass"/>
    <attribute name="objname" />
    <attribute name="refobjs"  default="true"/>
    <attribute name="reffiles" default="true"/>

    <sequential>
      <local name="export_success"/>
      <local name="export_response"/>

      <!-- Export the specified object based on the options given. -->
      <wdp operation="Export" successprop="export_success" responseprop="export_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
          <objects xmlns:soma="http://www.datapower.com/schemas/management">
              <soma:object class="@{objclass}" name="@{objname}" ref-objects="@{refobjs}" ref-files="@{reffiles}"/>
          </objects>
          <local>@{local}</local>
          <hostname>@{host}</hostname>
          <port>@{port}</port>
          <uid>@{uid}</uid>
          <pwd>@{pwd}</pwd>
          <ignore-errors>@{ignore-errors}</ignore-errors>
          <domain>@{domain}</domain>
      </wdp>

      <if>
        <equals arg1="${export_success}" arg2="true"/>
        <then>
          <echo>Exported object @{objname} into @{local} where</echo>
          <echo>class=@{objclass} ref-objects=@{refobjs} ref-files=@{reffiles} domain=@{domain} hostname=@{host}.</echo>
        </then>
        <else>
          <echo>Raw response for export: ${export_response}</echo>
          <fail message="Failed to export object @{objname} of class=@{objclass} from domain @{domain} on @{host}."/>
        </else>
      </if>

    </sequential>
  </macrodef>

	  <!--
	    Export the specified objects (name and class) in a ZIP format.

	    Required parameters:
	      host - hostname or IP address of DataPower device
	      uid - userid
	      pwd - password
	      local - filename for ZIP file created by this operation
	      objects - target objects to be exported

	    Optional parameters:
	      port - XML Management Interface port on device (defaults to 5550)
	      ignore-errors - defaults to false
	      refobjs - Include referenced objects? defaults to true
	      reffiles - Include referenced files? defaults to true

	  -->
		<macrodef name="exportObjects">
	    <attribute name="domain"/>
	    <attribute name="host"/>
	    <attribute name="local"/>
	    <attribute name="port" default="5550"/>
	    <attribute name="uid"/>
	    <attribute name="pwd"/>
	    <attribute name="dumpinput" default="false"/>
	    <attribute name="dumpoutput" default="false"/>
	    <attribute name="capturesoma" default=""/>
	    <attribute name="ignore-errors" default="false"/>

	    <attribute name="objects"/>
	    <attribute name="refobjs"  default="true"/>
	    <attribute name="reffiles" default="true"/>

	    <sequential>
	      <local name="export_success"/>
	      <local name="export_response"/>

	      <!-- Export the specified object based on the options given. -->
	      <wdp operation="Export" successprop="export_success" responseprop="export_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
	          <objects>@{objects}</objects>
	          <local>@{local}</local>
	          <hostname>@{host}</hostname>
	          <port>@{port}</port>
	          <uid>@{uid}</uid>
	          <pwd>@{pwd}</pwd>
	          <ignore-errors>@{ignore-errors}</ignore-errors>
	          <domain>@{domain}</domain>
	      </wdp>

	      <if>
	        <equals arg1="${export_success}" arg2="true"/>
	        <then>
	          <echo>Exported object @{objname} into @{local} where</echo>
	          <echo>class=@{objclass} ref-objects=@{refobjs} ref-files=@{reffiles} domain=@{domain} hostname=@{host}.</echo>
	        </then>
	        <else>
	          <echo>Raw response for export: ${export_response}</echo>
	          <fail message="Failed to export object @{objname} of class=@{objclass} from domain @{domain} on @{host}."/>
	        </else>
	      </if>

	    </sequential>
	  </macrodef>


  <!--

    Backup some set of domains in a ZIP format.  Backups up the domain=Xxxx domain plus
    any additional domains in the blank-separated domains=A B ... property.

    Required parameters:
      host - hostname or IP address of DataPower device
      uid - userid
      pwd - password
      domains - Blank-separated list of domain names
      local - filename for ZIP file created by this operation

    Optional parameters:
      port - XML Management Interface port on device (defaults to 5550)
      ignore-errors = true() or false()

  -->
  <macrodef name="backupDomains">
    <attribute name="domain"/>  <!-- first domain to backup -->
    <attribute name="domains"/> <!-- optional additional domains to backup -->
    <attribute name="local"/>
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="saveIfNeeded" default="true"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="domainlist"/>
      <local name="combinedNames"/>

      <if>
        <equals arg1="@{saveIfNeeded}" arg2="true"/>
        <then>

          <getDomainStatus host="@{host}" uid="@{uid}" pwd="@{pwd}" port="@{port}" domainsprop="domainlist" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"/>

          <!--
            Determine which of the specified domains to be backed up need to be saved first.  This complex
            xpath is fairly simple once you understand how the domain names are combined.  Domain names
            provided by the user may be separated by blanks and/or commas.  ${combinedNames} contains all
            the domain names, including leading and trailing commas (e.g. ',default,,' or ',dcm-test,default,').
            The SaveNeeded = 'on' selects those domains that need to be saved.  The contains() checks for
            the name of the domain, with leading a trailing commas.  (This strategy avoids false matches on
            domain names.  If the contains() didn't include the leading and trailing commas then
            contains('bob', 'default, angrybob,') would be matched.  By translating all blanks to commas, then,
            contains(',bob,', 'default,,angrybob,') would not match, as expected.)
          -->
          <property name="combinedNames" value=",@{domain},@{domains},"/>
          <forxpath inprop="domainlist" xpath="/status/DomainStatus[SaveNeeded = 'on' and contains(translate('${combinedNames}', ' ', ','), concat(',', string(Domain), ','))]/Domain">
            <sequential>

              <saveDomainUnconditionally host="@{host}" uid="@{uid}" pwd="@{pwd}" port="@{port}" domain="@{forxpath}" ignore-errors="@{ignore-errors}" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"/>

            </sequential>
          </forxpath>

        </then>
      </if>
      <wdp operation="Backup" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <local>@{local}</local>
        <domain>@{domain}</domain>
        <domains>@{domains}</domains>
        <hostname>@{host}</hostname>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <ignore-errors>@{ignore-errors}</ignore-errors>
      </wdp>
    </sequential>

  </macrodef>


  <!--

    Check for access to a device using some userid/password.  Returns the firmware
    version (e.g. XI52.4.0.2.5) in an ant property.  On success the ant property
    (${${versionprop}}) is set to the firmware version.  On failure the ant property
    is either empty or not set.

    Required parameters:
    host - hostname or IP address of DataPower device
    uid - userid
    pwd - password
    versionprop - name of Ant property to set with the firmware version

    Optional parameters:
    port - XML Management Interface port on device (defaults to 5550)
    ignore-errors = true() or false()

  -->
  <macrodef name="checkDeviceAccess">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain" default="default"/>
    <attribute name="versionprop"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="statusDefault"/>
      <local name="statusDomain"/>

      <if>
        <not>
          <isset property="versionprop"/>
        </not>
        <then>
          <wdp operation="GetStatuses" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
            <statuses>FirmwareVersion</statuses>
            <domain>default</domain>
            <hostname>@{host}</hostname>
            <port>@{port}</port>
            <uid>@{uid}</uid>
            <pwd>@{pwd}</pwd>
            <ignore-errors>@{ignore-errors}</ignore-errors>
            <return antprop="statusDefault" somaprop="status"/>
          </wdp>
          <if>
            <equals arg1="${statusDefault}" arg2="&lt;status&gt;&lt;/status&gt;"/>
            <then>
              <!-- Failed to get the firmware version from the default domain so try the target domain. -->
              <wdp operation="GetStatuses" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
                <statuses>FirmwareVersion</statuses>
                <domain>@{domain}</domain>
                <hostname>@{host}</hostname>
                <port>@{port}</port>
                <uid>@{uid}</uid>
                <pwd>@{pwd}</pwd>
                <ignore-errors>@{ignore-errors}</ignore-errors>
                <return antprop="statusDomain" somaprop="status"/>
              </wdp>
              <xpath inprop="statusDomain" outprop="@{versionprop}" xpath="/status/FirmwareVersion/Version"/>
            </then>
            <else>
              <xpath inprop="statusDefault" outprop="@{versionprop}" xpath="/status/FirmwareVersion/Version"/>
            </else>
          </if>
        </then>
      </if>
    </sequential>

  </macrodef>


  <!--

    Ensure that a file containing the preprocessed XML Management Interface schema is available.

    Required parameters:
      host - hostname or IP address of DataPower device
      uid - userid
      pwd - password

    Optional parameters:
      port - XML Management Interface port on device (defaults to 5550)

  -->
  <macrodef name="ensureDPSchema">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="versionprop"/>
    <attribute name="dcmdir"/> <!-- directory where DCM is found -->
    <attribute name="schemadir"/> <!-- directory where cached schemas can be found -->
    <attribute name="workdir"/> <!-- tmpdir where a directory can be created, if necessary -->
    <attribute name="dpschemaFileVbl"/> <!-- name of ANT variable to create that will contain the location of the preprocessed schema file. -->
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>

    <sequential>
      <local name="fileSavedSchema"/>
      <local name="fileCreatedSchema"/>

      <property name="fileSavedSchema" value="@{schemadir}/${@{versionprop}}.dpschema.xml"/>
      <property name="fileCreatedSchema" value="@{workdir}/${@{versionprop}}.dpschema.xml"/>
<!--
      <echo>### schemadir=@{schemadir}</echo>
      <echo>### workdir=@{workdir}</echo>
      <echo>### versionprop=@{versionprop}</echo>
      <echo>### fileSavedSchema=${fileSavedSchema}</echo>
      <echo>### fileCreatedSchema=${fileCreatedSchema}</echo>
      <echo>### dpschemaFileVbl=@{dpschemaFileVbl}</echo>
-->
      <if>
        <available file="${fileSavedSchema}"/>
        <then>

          <!-- Use the dpschema file that the user has saved somewhere. -->
          <property name="@{dpschemaFileVbl}" location="${fileSavedSchema}"/>
          <echo>Using ${fileSavedSchema} for @{host}</echo>

        </then>
        <else>
          <if>
            <available file="${fileCreatedSchema}"/>
            <then>

              <!-- Use the dpschema file that was created earlier during this run. -->
              <property name="@{dpschemaFileVbl}" location="${fileCreatedSchema}"/>
              <echo>Using previously created schema ${fileCreatedSchema} for @{host}</echo>

            </then>
            <else>

              <!-- Time to do the heavy lifting of downloading the schema files from the host and generating the dpschema file. -->

              <dpdownload dir="@{workdir}" dpdir="store:///" filename="xml-mgmt.wsdl"     domain="@{domain}" hostname="@{host}" uid="@{uid}" pwd="@{pwd}" port="@{port}" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"/>
              <dpdownload dir="@{workdir}" dpdir="store:///" filename="xml-mgmt.xsd"      domain="@{domain}" hostname="@{host}" uid="@{uid}" pwd="@{pwd}" port="@{port}" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"/>
              <dpdownload dir="@{workdir}" dpdir="store:///" filename="xml-mgmt-base.xsd" domain="@{domain}" hostname="@{host}" uid="@{uid}" pwd="@{pwd}" port="@{port}" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"/>
              <dpdownload dir="@{workdir}" dpdir="store:///" filename="xml-mgmt-ops.xsd"  domain="@{domain}" hostname="@{host}" uid="@{uid}" pwd="@{pwd}" port="@{port}" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"/>
              <dpdownload dir="@{workdir}" dpdir="store:///" filename="xml-mgmt-b2b.xsd"  domain="@{domain}" hostname="@{host}" uid="@{uid}" pwd="@{pwd}" port="@{port}" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}" ignoreerror="true"/>

              <nxslt infile="@{workdir}/xml-mgmt.wsdl" outfile="@{workdir}/collected.xml" xsl="@{dcmdir}/src/dpschema-collectxml.xsl"/>
              <nxslt infile="@{workdir}/collected.xml" outfile="${fileCreatedSchema}"     xsl="@{dcmdir}/src/dpschema-reformatsoma.xsl"/>

              <property name="@{dpschemaFileVbl}" location="${fileCreatedSchema}"/>

              <echo>Using newly created schema ${fileCreatedSchema} for @{host}</echo>

              <if>
                <isfileselected file="@{schemadir}">
                  <writable/>
                </isfileselected>
                <then>

                  <copy file="${fileCreatedSchema}" tofile="${fileSavedSchema}"/>

                  <echo>Copied the newly created schema into the schema cache (${fileSavedSchema}).</echo>

                </then>
              </if>

            </else>
          </if>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--

    Create a domain, when it does not exist.

    Required parameters:
      host - hostname or IP address of DataPower device
      domain - domain on the device
      uid - userid
      pwd - password

    Optional parameters:
      port - XML Management Interface port on device (defaults to 5550)
      ignore-errors = true() or false()

  -->
  <macrodef name="createDomain">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="create_okay"/>
      <local name="create_response"/>
      <local name="create_success"/>
      <local name="domain_exists"/>
      <local name="domainlist"/>

      <getDomainStatus host="@{host}" uid="@{uid}" pwd="@{pwd}" port="@{port}" domainsprop="domainlist" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"/>

      <xpath inprop="domainlist" outprop="domain_exists"
        xpath="/status/DomainStatus[Domain='@{domain}']"/>

      <if>
        <equals arg1="${domain_exists}" arg2=""/>
        <then>

          <wdp operation="SetConfig" successprop="create_success" responseprop="create_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"
            xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="create_okay">
            <config>
              <Domain name="@{domain}">
                <mAdminState>enabled</mAdminState>
                <NeighborDomain class="Domain">default</NeighborDomain>
                <ConfigMode>local</ConfigMode>
              </Domain>
            </config>
            <hostname>@{host}</hostname>
            <port>@{port}</port>
            <uid>@{uid}</uid>
            <pwd>@{pwd}</pwd>
            <domain>default</domain>
          </wdp>

          <if>
            <and>
              <istrue value="${create_success}"/>
              <equals arg1="${create_okay}" arg2="OK"/>
            </and>
            <then>
              <echo>Domain @{domain} created on @{host}.</echo>
            </then>
            <else>
              <echo>Raw response for createDomain: ${create_response}</echo>
              <fail message="Failed to create domain @{domain} on @{host}."/>
            </else>
          </if>

        </then>
        <else>
          <echo>Did not create domain @{domain} on @{host} since it already exists.</echo>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--

    Delete a domain, when it exists.

    Required parameters:
      host - hostname or IP address of DataPower device
      domain - domain on the device
      uid - userid
      pwd - password

    Optional parameters:
      port - XML Management Interface port on device (defaults to 5550)
      ignore-errors = true() or false()

  -->
  <macrodef name="deleteDomain">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="delete_okay"/>
      <local name="delete_response"/>
      <local name="delete_success"/>
      <local name="domain_exists"/>
      <local name="domainlist"/>

      <getDomainStatus host="@{host}" uid="@{uid}" pwd="@{pwd}" port="@{port}" domainsprop="domainlist" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"/>

      <xpath inprop="domainlist" outprop="domain_exists" xpath="/status/DomainStatus[Domain='@{domain}']"/>

      <if>
        <not>
          <equals arg1="${domain_exists}" arg2=""/>
        </not>
        <then>

          <wdp operation="DeleteConfig" successprop="delete_success" responseprop="delete_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"
            xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="delete_okay">
            <classname>Domain</classname>
            <objname>@{domain}</objname>
            <hostname>@{host}</hostname>
            <port>@{port}</port>
            <uid>@{uid}</uid>
            <pwd>@{pwd}</pwd>
            <domain>default</domain>
          </wdp>

          <if>
            <and>
              <istrue value="${delete_success}"/>
              <equals arg1="${delete_okay}" arg2="OK"/>
            </and>
            <then>
              <echo>Domain @{domain} deleted on @{host}.</echo>
            </then>
            <else>
              <echo>Raw response for deleteDomain: ${delete_response}</echo>
              <fail message="Failed to delete domain @{domain} on @{host}."/>
            </else>
          </if>

        </then>
        <else>
          <echo>Did not delete domain @{domain} on @{host} since it does not exist.</echo>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--

    Disable an object.

    Required parameters:
    host - hostname or IP address of DataPower device
    domain - domain on the device
    uid - userid
    pwd - password

    Optional parameters:
    port - XML Management Interface port on device (defaults to 5550)
    ignore-errors = true() or false()

  -->
  <macrodef name="disableObject">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="objclass"/>
    <attribute name="objname"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="config"/>
      <local name="disable_okay"/>
      <local name="disable_response"/>
      <local name="disable_success"/>

      <storexml outprop="config">
        <config>
          &lt;@{objclass} name="@{objname}">
          <mAdminState>enabled</mAdminState>
          &lt;/@{objclass}>
        </config>
      </storexml>

      <wdp operation="ModifyConfig" domain="@{domain}" hostname="@{host}" uid="@{uid}" pwd="@{pwd}"
        successprop="disable_success" responseprop="disable_response" dumpinput="@{dumpoutput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"
        xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="disable_okay">
        <wrapper>${config}</wrapper>
      </wdp>

      <if>
        <and>
          <istrue value="${disable_success}"/>
          <equals arg1="${disable_okay}" arg2="OK"/>
        </and>
        <then>
          <echo>Disabled object @{objclass}/@{objname} in domain @{domain} on @{host}.</echo>
        </then>
        <else>
          <echo>Raw response for disableObject: ${disable_response}</echo>
          <fail message="Failed to disable object @{objclass}/@{objname} in domain @{domain} on @{host}."/>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--

    Disable one or more objects.

    Required parameters:
    host - hostname or IP address of DataPower device
    domain - domain on the device
    uid - userid
    pwd - password

    Optional parameters:
    port - XML Management Interface port on device (defaults to 5550)
    ignore-errors = true() or false()

  -->
  <macrodef name="disableObjects">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="dcmdir"/> <!-- directory where DCM is found -->
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>
    <element name="definition" implicit="yes"/>

    <sequential>
      <local name="dcmpolicy"/>
      <local name="config"/>
      <local name="disable_okay"/>
      <local name="disable_response"/>
      <local name="disable_success"/>

      <!-- Store the dcm:definition (DCM policy) in a property for easy access. -->
      <storexml outprop="dcmpolicy">
        <definition/> <!-- placeholder for dcm:definition provided as content of <disableObjects> -->
      </storexml>

      <!--
        Generate <xxx name="yyy"><mAdminState>disabled</mAdminState></xxx> elements for each object.
      -->
      <nxslt inprop="dcmpolicy" outprop="config" xsl="@{dcmdir}/src/enable-disable-objects.xsl">
        <param ant="'disable'" xsl="newState"/>
      </nxslt>

      <wdp operation="ModifyConfig"
        successprop="disable_success" responseprop="disable_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"
        xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="disable_okay">
        <domain>@{domain}</domain>
        <hostname>@{host}</hostname>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <local>@{local}</local>
        <wrapper>${config}</wrapper>
      </wdp>

      <if>
        <and>
          <istrue value="${disable_success}"/>
          <equals arg1="${disable_okay}" arg2="OK"/>
        </and>
        <then>
          <echo>Disabled specified object(s) in domain @{domain} on @{host}.</echo>
        </then>
        <else>
          <echo>Raw response for disableObjects: ${disable_response}</echo>
          <fail message="Failed to disable specified object(s) in domain @{domain} on @{host}."/>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--

    Download target files from filestore

    Required parameters:
      host - hostname or IP address of DataPower device
      domain - name of domain
      filestore - name of filestore (e.g. local:, store:)
      files - target files to download from the filestore
      local - target directory in local filesystem
      uid - userid
      pwd - password

    Optional parameters:
      port - XML Management Interface port on device (defaults to 5550)

  -->
  <macrodef name="downloadFiles">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="filestore"/>
    <attribute name="files"/>
    <attribute name="local" default="."/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>

    <sequential>
      <echo>Download target files: @{files}</echo>
      <echo>from @{filestore} to @{local}</echo>

      <forxpath inprop="files" xpath="/downloadFiles/file" propname="filename">
        <sequential>
          <dirname property="dirpath" file="@{local}@{filename}"/>
          <mkdir dir="${dirpath}"/>

          <echo>Downloading @{filestore}@{filename} to @{local}@{filename}</echo>
          <wdp operation="GetFile" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
            <domain>@{domain}</domain>
            <hostname>@{host}</hostname>
            <port>@{port}</port>
            <uid>@{uid}</uid>
            <pwd>@{pwd}</pwd>
            <local>@{local}@{filename}</local>
            <remote>@{filestore}@{filename}</remote>
          </wdp>
        </sequential>
      </forxpath>

    </sequential>

  </macrodef>


	<!--

    Download a filestore

    Required parameters:
      host - hostname or IP address of DataPower device
      domain - name of domain
      filestore - name of filestore (e.g. local:, store:)
      local - target directory in local filesystem
      uid - userid
      pwd - password

    Optional parameters:
      port - XML Management Interface port on device (defaults to 5550)

  -->
  <macrodef name="downloadFilestore">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="filestore"/>
    <attribute name="local" default="."/>
    <attribute name="dcmdir"/> <!-- directory where DCM is found -->
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>

    <sequential>
      <echo>Download all files from @{filestore} to @{local}</echo>

      <local name="rawxml"/>
      <local name="tmp"/>

      <!--
        Get the complete listing of all the files and directories in the filestore,
        then convert that XML to a more useful form.
      -->
      <wdp operation="GetFilestore" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <domain>@{domain}</domain>
        <hostname>@{host}</hostname>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <filestore>@{filestore}</filestore>
        <ignore-errors>@{ignore-errors}</ignore-errors>
        <return antprop="rawxml" somaprop="location"/>
      </wdp>
      <nxslt inprop="rawxml" outprop="tmp" xsl="@{dcmdir}/src/downloadFilestore.xsl"/>
      <!-- <echo>${tmp}</echo> -->

      <forxpath inprop="tmp" xpath="/downloadFilestore/directory" propname="dirname">
        <sequential>
          <mkdir dir="@{local}@{dirname}"/>
        </sequential>
      </forxpath>

      <forxpath inprop="tmp" xpath="/downloadFilestore/file" propname="filename">
        <sequential>
          <echo>Downloading @{filestore}@{filename} to @{local}@{filename}</echo>
          <wdp operation="GetFile" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
            <domain>@{domain}</domain>
            <hostname>@{host}</hostname>
            <port>@{port}</port>
            <uid>@{uid}</uid>
            <pwd>@{pwd}</pwd>
            <local>@{local}@{filename}</local>
            <remote>@{filestore}@{filename}</remote>
          </wdp>
        </sequential>
      </forxpath>

    </sequential>

  </macrodef>


  <!--

    Enable an object.

    Required parameters:
    host - hostname or IP address of DataPower device
    domain - domain on the device
    uid - userid
    pwd - password

    Optional parameters:
    port - XML Management Interface port on device (defaults to 5550)
    ignore-errors = true() or false()

  -->
  <macrodef name="enableObject">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="objclass"/>
    <attribute name="objname"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="config"/>
      <local name="enable_okay"/>
      <local name="enable_response"/>
      <local name="enable_success"/>

      <storexml outprop="config">
        <config>
          &lt;@{objclass} name="@{objname}">
          <mAdminState>enabled</mAdminState>
          &lt;/@{objclass}>
        </config>
      </storexml>

      <wdp operation="ModifyConfig" domain="@{domain}" hostname="@{host}" uid="@{uid}" pwd="@{pwd}"
        successprop="enable_success" responseprop="enable_response" dumpinput="@{dumpoutput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"
        xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="enable_okay">
        <wrapper>${config}</wrapper>
      </wdp>

      <if>
        <and>
          <istrue value="${enable_success}"/>
          <equals arg1="${enable_okay}" arg2="OK"/>
        </and>
        <then>
          <echo>Enabled object @{objclass}/@{objname} in domain @{domain} on @{host}.</echo>
        </then>
        <else>
          <echo>Raw response for enableObject: ${enable_response}</echo>
          <fail message="Failed to enable object @{objclass}/@{objname} in domain @{domain} on @{host}."/>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--

    Enable one or more objects.

    Required parameters:
    host - hostname or IP address of DataPower device
    domain - domain on the device
    uid - userid
    pwd - password

    Optional parameters:
    port - XML Management Interface port on device (defaults to 5550)
    ignore-errors = true() or false()

  -->
  <macrodef name="enableObjects">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="dcmdir"/> <!-- directory where DCM is found -->
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>
    <element name="definition" implicit="yes"/>

    <sequential>
      <local name="dcmpolicy"/>
      <local name="config"/>
      <local name="enable_okay"/>
      <local name="enable_response"/>
      <local name="enable_success"/>

      <!-- Store the dcm:definition (DCM policy) in a property for easy access. -->
      <storexml outprop="dcmpolicy">
        <definition/> <!-- placeholder for dcm:definition provided as content of <enableObjects> -->
      </storexml>

      <!--
        Generate <xxx name="yyy"><mAdminState>enabled</mAdminState></xxx> elements for each object.
      -->
      <nxslt inprop="dcmpolicy" outprop="config" xsl="@{dcmdir}/src/enable-disable-objects.xsl">
        <param ant="'enable'" xsl="newState"/>
      </nxslt>

      <wdp operation="ModifyConfig"
        successprop="enable_success" responseprop="enable_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"
        xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="enable_okay">
        <domain>@{domain}</domain>
        <hostname>@{host}</hostname>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <local>@{local}</local>
        <wrapper>${config}</wrapper>
      </wdp>

      <if>
        <and>
          <istrue value="${enable_success}"/>
          <equals arg1="${enable_okay}" arg2="OK"/>
        </and>
        <then>
          <echo>Enabled specified object(s) in domain @{domain} on @{host}.</echo>
        </then>
        <else>
          <echo>Raw response for enableObjects: ${enable_response}</echo>
          <fail message="Failed to enable specified object(s) in domain @{domain} on @{host}."/>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--

    Export configuration (as opposed to a domain backup).

    Required parameters:
      host - hostname or IP address of DataPower device
      domain - name of domain
      uid - userid
      pwd - password

    Optional parameters:
      port - XML Management Interface port on device (defaults to 5550)
      ignore-errors = true() or false()

  -->
  <macrodef name="exportConfig">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="local"/>
    <attribute name="all-files" default="false"/>
    <attribute name="persisted" default="false"/>
    <attribute name="format" default="ZIP"/>
    <attribute name="deployment-policy" default=""/>
    <attribute name="user-comment" default=""/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>
    <element name="wrapper"/>

    <sequential>
      <local name="export_file"/>
      <local name="export_response"/>
      <local name="status"/>

      <wdp operation="Export" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"
        responseprop="export_response"
        xpathprop="export_file" xpath="string(/env:Envelope/env:Body/soma:response/soma:file)">
        <domain>@{domain}</domain>
        <hostname>@{host}</hostname>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <local>@{local}</local>
        <all-files>@{all-files}</all-files>
        <format>@{format}</format>
        <persisted>@{persisted}</persisted>
        <deployment-policy-name>@{deployment-policy}</deployment-policy-name>
        <user-comment>@{user-comment}</user-comment>
        <ignore-errors>@{ignore-errors}</ignore-errors>
        <wrapper/>
      </wdp>

      <if>
        <not>
          <equals arg1="${export_file}" arg2=""/>
        </not>
        <then>
          <frombase64 base64text="${export_file}" file="@{local}"/>
          <echo>Exported specified object(s) from domain @{domain} on @{host} to @{local}.</echo>
        </then>
        <else>
          <echo>Raw response for export: ${export_response}</echo>
          <fail message="Failed to export specified object(s) in domain @{domain} on @{host}."/>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--
    Firmware rollback to previous version.
  -->
  <macrodef name="firmwareRollback">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="success-update"/>

      <!-- Rollback to previous firmware (and other aspects of file system!). -->
      <wdp operation="FirmwareRollback" successprop="success-update" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <hostname>@{host}</hostname>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
      </wdp>

      <if>
        <isset property="success-update"/>
        <then>
          <echo>Rolled back the firmware on @{host}.</echo>
        </then>
        <else>
          <fail message="Failed to rollback the firmware on @{host}"/>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--
    Firmware update based on the supplied .scrypt2, .scrypt3, or .scrypt4 file. (Or later, who knows?)
  -->
  <macrodef name="firmwareUpdate">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="scryptfile"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="basename-scryptfile"/>
      <local name="dirname-scryptfile"/>
      <local name="success-update"/>

      <basename property="basename-scryptfile" file="@{scryptfile}"/>
      <dirname property="dirname-scryptfile" file="@{scryptfile}"/>

      <!-- Upload the firmware update file. -->
      <echo>Uploading the firmware update</echo>
      <dpupload dir="${dirname-scryptfile}" target="image:///" domain="default" host="@{host}" port="@{port}" uid="@{uid}" pwd="@{pwd}" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <include name="${basename-scryptfile}"/>
      </dpupload>

      <!-- Update that puppy. -->
      <echo>Applying the firmware update, followed automatically by a reboot of the appliance.  This requires a few minutes to complete.</echo>
      <wdp operation="BootUpdate" successprop="success-update" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <name>${basename-scryptfile}</name>
        <hostname>@{host}</hostname>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
      </wdp>

      <if>
        <isset property="success-update"/>
        <then>
          <echo>Updated the firmware on @{host} to @{scryptfile}.</echo>
        </then>
        <else>
          <fail message="Failed to update the firmware on @{host} to @{scryptfile}"/>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--

    Fetch the current status of all the domains.  This is useful for when you want to check whether
    a domain exists, whether it needs to be saved, and whether debug logging, probe, etc. are enabled
    in the domain. If you want to know whether a domain is enabled/up, though, this isn't the task.

    Required parameters:
      host - hostname or IP address of DataPower device
      uid - userid
      pwd - password
      domainsprop - name of Ant property to set with the XML for the domains

    The domainprop contains XML like this:
    <status>
      <DomainStatus>
        <Domain>ABCD</Domain>
        <SaveNeeded>off</SaveNeeded>
        <TraceEnabled>off</TraceEnabled>
        <DebugEnabled>off</DebugEnabled>
        <ProbeEnabled>off</ProbeEnabled>
        <DiagEnabled>off</DiagEnabled>
        <CurrentCommand/>
        <QuiesceState/>
      </DomainStatus>
      <DomainStatus>
        ...
      </DomainStatus>
    </status>

    Optional parameters:
      port - XML Management Interface port on device (defaults to 5550)
      ignore-errors = true() or false()

  -->
  <macrodef name="getDomainStatus">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domainsprop"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="status"/>

      <wdp operation="GetStatuses" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <statuses>DomainStatus</statuses>
        <domain>default</domain>
        <hostname>@{host}</hostname>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <ignore-errors>@{ignore-errors}</ignore-errors>
        <return antprop="@{domainsprop}" somaprop="status"/>
      </wdp>
    </sequential>

  </macrodef>


  <!--
    Determine the operational state (up/down) of a service
  -->
  <macrodef name="getServiceStatus">
    <attribute name="host" />
    <attribute name="port" default="5550" />
    <attribute name="uid" />
    <attribute name="pwd" />
    <attribute name="servicename" />
    <attribute name="servicetype" />
    <attribute name="domain" />
    <attribute name="outputprop" />
    <attribute name="timeout" default="60" />
    <attribute name="dumpinput" default="false" />
    <attribute name="dumpoutput" default="false" />
    <attribute name="capturesoma"/>
    <attribute name="ignore-errors" default="false" />

    <sequential>
      <local name="capture"/>
      <local name="success" />
      <local name="opstate" />

      <wdp operation="GetObjectStatus" successprop="success" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <hostname>@{host}</hostname>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <domain>@{domain}</domain>
        <return antprop="status" somaprop="@{servicetype}.@{servicename}" />
      </wdp>

      <if>
        <and>
          <isset property="status" />
          <istrue value="${success}" />
        </and>
        <then>
          <xpath inprop="status" outprop="opstate" xpath="/ObjectStatus/OpState/text()"/>
          <echo message="@{servicetype}.@{servicename} OpState: ${opstate}" />
          <property name="@{outputprop}.opstate" value="${opstate}" />

        </then>
        <else>
          <if>
            <istrue value="${success}" />
            <then>
              <fail message="Service @{servicetype}.@{servicename} not found in @{domain} on @{host}." />
            </then>
            <else>
              <fail message="Error getting service status for service @{servicetype}.@{servicename} in @{domain} on @{host}." />
            </else>
          </if>

        </else>
      </if>
    </sequential>
  </macrodef>


  <!--
    Create/overwrite an ID Cred and key/cert files and objects.
  -->
  <macrodef name="idcredFromPKCS12">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="p12file"/>
    <attribute name="p12pwd"/>
    <attribute name="objname"/>
    <attribute name="ignoreexpiration" default="off"/> <!-- on or off -->
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="basename"/>
      <local name="basename-no-ext"/>
      <local name="dirname"/>
      <local name="ignoreexpiration"/>
      <local name="success-create-cert"/>
      <local name="success-create-idcred"/>
      <local name="success-create-key"/>
<!--
      <echo>p12file=@{p12file}</echo>
      <echo>p12pwd=@{p12pwd}</echo>
      <echo>objname=@{objname}</echo>
      <echo>ignoreexpiration=@{ignoreexpiration}</echo>
-->
      <basename property="basename" file="@{p12file}"/>
      <basename property="basename-no-ext" file="@{p12file}" suffix=".p12"/>
      <dirname property="dirname" file="@{p12file}"/>

      <!--
        Okay, we now have a #PKCS12 file containing a key/cert pair plus the password for the file.
        Upload the file regardless of whether it may already exist.
      -->
      <dpupload dir="${dirname}" target="cert:///" domain="@{domain}" url="https://@{host}:@{port}/service/mgmt/current" uid="@{uid}" pwd="@{pwd}" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <include name="${basename}"/>
      </dpupload>

      <!-- Create a Crypto Certficate object to wrap the #PKCS12 file. -->
      <wdp operation="SetConfig" successprop="success-create-cert" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <config>
          <CryptoCertificate name="${basename-no-ext}">
            <mAdminState>enabled</mAdminState>
            <Filename>cert:///${basename}</Filename>
            <Password>@{p12pwd}</Password>
            <PasswordAlias>off</PasswordAlias>
            <IgnoreExpiration>@{ignoreexpiration}</IgnoreExpiration>
          </CryptoCertificate>
        </config>
        <hostname>@{host}</hostname>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <domain>@{domain}</domain>
      </wdp>

      <if>
        <and>
          <isset property="success-create-cert"/>
          <equals arg1="${success-create-cert}" arg2="true"/>
        </and>
        <then>

          <!-- Create a Crypto Key object to wrap the #PKCS12 file. -->
          <wdp operation="SetConfig" successprop="success-create-key" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
            <config>
              <CryptoKey name="${basename-no-ext}">
                <mAdminState>enabled</mAdminState>
                <Filename>cert:///${basename}</Filename>
                <Password>@{p12pwd}</Password>
                <PasswordAlias>off</PasswordAlias>
              </CryptoKey>
            </config>
            <hostname>@{host}</hostname>
            <uid>@{uid}</uid>
            <pwd>@{pwd}</pwd>
            <domain>@{domain}</domain>
          </wdp>

          <if>
            <and>
              <isset property="success-create-key"/>
              <equals arg1="${success-create-key}" arg2="true"/>
            </and>
            <then>

              <!-- Create the idcred object. -->
              <wdp operation="SetConfig" successprop="success-create-idcred" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
                <config>
                  <CryptoIdentCred name="@{objname}">
                    <mAdminState>enabled</mAdminState>
                    <Key class="CryptoKey">${basename-no-ext}</Key>
                    <Certificate class="CryptoCertificate">${basename-no-ext}</Certificate>
                  </CryptoIdentCred>
                </config>
                <hostname>@{host}</hostname>
                <uid>@{uid}</uid>
                <pwd>@{pwd}</pwd>
                <domain>@{domain}</domain>
              </wdp>

              <if>
                <and>
                  <isset property="success-create-idcred"/>
                  <equals arg1="${success-create-idcred}" arg2="true"/>
                </and>
                <then>
                  <echo>Created the ID Credential object @{objname} and the ${basename-no-ext} key and cert objects.</echo>
                </then>
                <else>
                  <fail message="Failed to create the ID Credential object @{objname}"/>
                </else>
              </if>

            </then>
            <else>
              <fail message="Failed to create the Crypto Key object ${basename-no-ext}"/>
            </else>
          </if>

        </then>
        <else>
          <fail message="Failed to create the Crypto Certificate object ${basename-no-ext}"/>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--
    Create/overwrite an ID Cred and key/cert files and objects.
  -->
  <macrodef name="idcredFromKeyAndCert">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="certfile"/>
    <attribute name="certpwd"/>
    <attribute name="keyfile"/>
    <attribute name="keypwd"/>
    <attribute name="objname"/>
    <attribute name="ignoreexpiration" default="off"/> <!-- on or off -->
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="basename-cert"/>
      <local name="basename-key"/>
      <local name="dirname-cert"/>
      <local name="dirname-key"/>
      <local name="ignoreexpiration"/>
      <local name="success-create-cert"/>
      <local name="success-create-idcred"/>
      <local name="success-create-key"/>
<!--
      <echo>certfile=@{certfile}</echo>
      <echo>certpwd=@{certpwd}</echo>
      <echo>keyfile=@{keyfile}</echo>
      <echo>keypwd=@{keypwd}</echo>
      <echo>objname=@{objname}</echo>
      <echo>ignoreexpiration=@{ignoreexpiration}</echo>
-->
      <basename property="basename-cert" file="@{certfile}"/>
      <basename property="basename-key" file="@{keyfile}"/>
      <dirname property="dirname-cert" file="@{certfile}"/>
      <dirname property="dirname-key" file="@{keyfile}"/>

      <!--
        Okay, we now have key and certificate files containing a key/cert pair plus passwords for the files.
        Upload the files regardless of whether they may already exist.
      -->
      <if>
        <equals arg1="${dirname-cert}" arg2="${dirname-key}"/>
        <then>

          <!-- Upload the two files from the same source directory. -->
          <dpupload dir="${dirname-cert}" target="cert:///" domain="@{domain}" url="https://@{host}:@{port}/service/mgmt/current" uid="@{uid}" pwd="@{pwd}" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
            <include name="${basename-cert}"/>
            <include name="${basename-key}"/>
          </dpupload>

        </then>
        <else>

          <!-- Upload the two files from different source directories. -->
          <dpupload dir="${dirname-cert}" target="cert:///" domain="@{domain}" url="https://@{host}:@{port}/service/mgmt/current" uid="@{uid}" pwd="@{pwd}" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
            <include name="${basename-cert}"/>
          </dpupload>
          <dpupload dir="${dirname-key}" target="cert:///" domain="@{domain}" url="https://@{host}:@{port}/service/mgmt/current" uid="@{uid}" pwd="@{pwd}" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
            <include name="${basename-key}"/>
          </dpupload>

        </else>
      </if>

      <!-- Create a Crypto Certficate object to wrap the certificate file. -->
      <wdp operation="SetConfig" successprop="success-create-cert" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <config>
          <CryptoCertificate name="${basename-cert}">
            <mAdminState>enabled</mAdminState>
            <Filename>cert:///${basename-cert}</Filename>
            <Password>@{certpwd}</Password>
            <PasswordAlias>off</PasswordAlias>
            <IgnoreExpiration>@{ignoreexpiration}</IgnoreExpiration>
          </CryptoCertificate>
        </config>
        <hostname>@{host}</hostname>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <domain>@{domain}</domain>
      </wdp>

      <if>
        <and>
          <isset property="success-create-cert"/>
          <equals arg1="${success-create-cert}" arg2="true"/>
        </and>
        <then>

          <!-- Create a Crypto Key object to wrap the key file. -->
          <wdp operation="SetConfig" successprop="success-create-key" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
            <config>
              <CryptoKey name="${basename-key}">
                <mAdminState>enabled</mAdminState>
                <Filename>cert:///${basename-key}</Filename>
                <Password>@{keypwd}</Password>
                <PasswordAlias>off</PasswordAlias>
              </CryptoKey>
            </config>
            <hostname>@{host}</hostname>
            <uid>@{uid}</uid>
            <pwd>@{pwd}</pwd>
            <domain>@{domain}</domain>
          </wdp>

          <if>
            <and>
              <isset property="success-create-key"/>
              <equals arg1="${success-create-key}" arg2="true"/>
            </and>
            <then>

              <!-- Create the idcred object. -->
              <wdp operation="SetConfig" successprop="success-create-idcred" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
                <config>
                  <CryptoIdentCred name="@{objname}">
                    <mAdminState>enabled</mAdminState>
                    <Key class="CryptoKey">${basename-key}</Key>
                    <Certificate class="CryptoCertificate">${basename-cert}</Certificate>
                  </CryptoIdentCred>
                </config>
                <hostname>@{host}</hostname>
                <uid>@{uid}</uid>
                <pwd>@{pwd}</pwd>
                <domain>@{domain}</domain>
              </wdp>

              <if>
                <and>
                  <isset property="success-create-idcred"/>
                  <equals arg1="${success-create-idcred}" arg2="true"/>
                </and>
                <then>
                  <echo>Created the ID Credential object @{objname} and the ${basename-key} key and ${basename-cert} certificate objects.</echo>
                </then>
                <else>
                  <fail message="Failed to create the ID Credential object @{objname}"/>
                </else>
              </if>

            </then>
            <else>
              <fail message="Failed to create the Crypto Key object ${basename-key}"/>
            </else>
          </if>

        </then>
        <else>
          <fail message="Failed to create the Crypto Certificate object ${basename-cert}"/>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--
    Import some DataPower export, optionally applying deployment policies in the process.
  -->
  <macrodef name="importConfig">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="inputfile"/> <!-- name of DataPower export file -->
    <attribute name="ignoreError" default=""/> <!-- SOMA error to ignore - Note: Can't be empty -->
    <attribute name="dcmdir"/> <!-- directory where DCM is found -->
    <attribute name="workdir"/> <!-- tmpdir where a directory can be created, if necessary -->
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>
    <attribute name="rewrite-local" default="true"/>
    <attribute name="overwrite-files" default="true"/>
    <attribute name="overwrite-objects" default="true"/>
    <attribute name="changes" default=""/> <!-- Alternative to passing in XML content -->
    <element name="definition" implicit="yes" optional="yes"/>

    <sequential> <!-- permit declaring some variables local in scope. -->
      <local name="dcmdefinition"/>
      <local name="import_errors"/>
      <local name="import_basename"/>
      <local name="import_response"/>
      <local name="import_success"/>

      <!-- Store the dcm:definition (DCM policy) in a property for easy access. -->
      <if>
        <equals arg1="@{changes}" arg2=""/>
        <then>
          <storexml outfile="@{workdir}/1_raw-policy.xml"><definition/></storexml>
        </then>
        <else>
          <storexml outfile="@{workdir}/1_raw-policy.xml">@{changes}</storexml>
        </else>
      </if>

      <!--
        Gather all the deployment policies.
      -->
      <nxslt infile="@{workdir}/1_raw-policy.xml" outfile="@{workdir}/2_included_policies.xml" xsl="@{dcmdir}/src/process-includes.xsl"/>
      <nxslt infile="@{workdir}/2_included_policies.xml" outfile="@{workdir}/3_expanded-deployment-policies.xml" xsl="@{dcmdir}/src/expand-black-white-modify.xsl"/>
      <nxslt infile="@{workdir}/3_expanded-deployment-policies.xml" outfile="@{workdir}/4_gathered-deployment-policies.xml" xsl="@{dcmdir}/src/write-deployment-policy.xsl"/>

      <basename file="@{inputfile}" property="import_basename"/>
      <loadfile srcfile="@{workdir}/2_included_policies.xml" property="dcmdefinition"/>
      <rewriteExport inputfile="@{inputfile}" outputfile="@{workdir}/${import_basename}"
        dcmdir="@{dcmdir}" workdir="@{workdir}" changes="${dcmdefinition}"/>

      <!--
        Import the (possibly rewritten) DataPower export file.
      -->
      <echo>Importing @{inputfile} into domain @{domain} on @{host}.</echo>
      <wdp operation="ImportConfig" responseprop="import_response" successprop="import_success" xpathprop="import_errors"
        xpath="/env:Envelope/env:Body/soma:response/soma:import/import-results/exec-script-results/cfg-result[@status!='SUCCESS'] | /env:Envelope/env:Body/soma:response/soma:import/import-results/file-copy-log/file-result[not(@result='OK' or @result='ignored')] | /env:Envelope/env:Body/soma:response/soma:result"
        dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <domain>@{domain}</domain>
        <local>@{workdir}/${import_basename}</local>
        <deployment-policy-file>@{workdir}/4_gathered-deployment-policies.xml</deployment-policy-file>
        <hostname>@{host}</hostname>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <ignore-errors>@{ignore-errors}</ignore-errors>
        <rewrite-local>@{rewrite-local}</rewrite-local>
        <overwrite-files>@{overwrite-files}</overwrite-files>
        <overwrite-objects>@{overwrite-objects}</overwrite-objects>
        <dumpoutput>@{dumpoutput}</dumpoutput>
      </wdp>
      <!-- <echo>### $${import_success}=${import_success}</echo> -->
      <!-- <echo>### $${import_errors}=${import_errors}</echo> -->
      <if>
        <and>
          <istrue value="${import_success}"/>
          <length string="${import_errors}" when="equal" length="0"/>
        </and>
        <then>
          <echo>Successfully imported @{inputfile} into domain @{domain} on @{host}.</echo>
        </then>
        <else>
          <echo>Raw response to importing @{inputfile}</echo>
          <echo>Import Response: ${import_response}</echo>
          <echo>Import Error(s): '${import_errors}'</echo>
          <echo>Ignore Error Regex: '@{ignoreError}'</echo>
          <!-- If ignoreError regex specified, try to ignore given SOMA error -->
          <if>
            <and>
              <length string="@{ignoreError}" when="greater" length="0"/>
              <matches string="${import_errors}" pattern="@{ignoreError}"/>
            </and>
            <then>
              <echo>Regex successfully matched. Ignoring import error...</echo>
              <echo>Successfully imported @{inputfile} into domain @{domain} on @{host}.</echo>
            </then>
            <else>
              <fail message="Failed to import @{inputfile} into domain @{domain} on @{host}."/>
            </else>
          </if>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--
    Import some DataPower export, applying a built-in deployment policy in the process.
  -->
  <macrodef name="importConfigDPO">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="inputfile"/> <!-- name of DataPower export file -->
    <attribute name="ignoreError" default=""/> <!-- SOMA error to ignore - Note: Can't be empty -->
    <attribute name="dpo"/> <!-- name of deployment policy object -->
    <attribute name="dcmdir"/> <!-- directory where DCM is found -->
    <attribute name="workdir"/> <!-- tmpdir where a directory can be created, if necessary -->
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>
    <attribute name="rewrite-local" default="true"/>
    <attribute name="overwrite-files" default="true"/>
    <attribute name="overwrite-objects" default="true"/>

    <sequential> <!-- permit declaring some variables local in scope. -->
      <local name="import_errors"/>
      <local name="import_response"/>
      <local name="import_success"/>

      <!--
        Import the DataPower export file.
      -->
      <echo>Importing @{inputfile} into domain @{domain} on @{host}.</echo>
      <wdp operation="ImportConfig" responseprop="import_response" successprop="import_success" xpathprop="import_errors"
        xpath="/env:Envelope/env:Body/soma:response/soma:import/import-results/exec-script-results/cfg-result[@status!='SUCCESS'] | /env:Envelope/env:Body/soma:response/soma:import/import-results/file-copy-log/file-result[not(@result='OK' or @result='ignored')] | /env:Envelope/env:Body/soma:response/soma:result"
        dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <domain>@{domain}</domain>
        <local>@{inputfile}</local>
        <deployment-policy>@{dpo}</deployment-policy>
        <hostname>@{host}</hostname>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <ignore-errors>@{ignore-errors}</ignore-errors>
        <rewrite-local>@{rewrite-local}</rewrite-local>
        <overwrite-files>@{overwrite-files}</overwrite-files>
        <overwrite-objects>@{overwrite-objects}</overwrite-objects>
        <dumpoutput>@{dumpoutput}</dumpoutput>
      </wdp>
      <!-- <echo>### $${import_success}=${import_success}</echo> -->
      <!-- <echo>### $${import_errors}=${import_errors}</echo> -->
      <if>
        <and>
          <istrue value="${import_success}"/>
          <length string="${import_errors}" when="equal" length="0"/>
        </and>
        <then>
          <echo>Successfully imported @{inputfile} into domain @{domain} on @{host}.</echo>
        </then>
        <else>
          <echo>Raw response to importing @{inputfile}</echo>
          <echo>Import Response: ${import_response}</echo>
          <echo>Import Error(s): '${import_errors}'</echo>
          <echo>Ignore Error Regex: '@{ignoreError}'</echo>
          <!-- If ignoreError regex specified, try to ignore given SOMA error -->
          <if>
            <and>
              <length string="@{ignoreError}" when="greater" length="0"/>
              <matches string="${import_errors}" pattern="@{ignoreError}"/>
            </and>
            <then>
              <echo>Regex successfully matched. Ignoring import error...</echo>
              <echo>Successfully imported @{inputfile} into domain @{domain} on @{host}.</echo>
            </then>
            <else>
              <fail message="Failed to import @{inputfile} into domain @{domain} on @{host}."/>
            </else>
          </if>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--

    Listing of a filestore

    Required parameters:
      host - hostname or IP address of DataPower device
      domain - name of domain
      filestore - name of filestore (e.g. local:, store:)
      listprop - name of Ant property where the listing should be stored
      uid - userid
      pwd - password

    Optional parameters:
      port - XML Management Interface port on device (defaults to 5550)
      ignore-errors = true() or false()

  -->
  <macrodef name="listFilestore">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="filestore"/>
    <attribute name="listprop"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>

      <wdp operation="GetFilestore" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <domain>@{domain}</domain>
        <hostname>@{host}</hostname>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <filestore>@{filestore}</filestore>
        <ignore-errors>@{ignore-errors}</ignore-errors>
        <return antprop="@{listprop}" somaprop="location"/>
      </wdp>

    </sequential>

  </macrodef>


  <!--
    Create an object based on an existing object.
  -->
  <macrodef name="objectCreateByCopying">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="versionprop"/>
    <attribute name="class"/>
    <attribute name="existing-name"/>
    <attribute name="new-name"/>
    <attribute name="dcmdir"/> <!-- directory where DCM is found -->
    <attribute name="schemadir"/> <!-- directory where cached schemas might be found -->
    <attribute name="workdir"/> <!-- tmpdir where a directory can be created, if necessary -->
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>
    <attribute name="changes" default=""/> <!-- Alternative to passing in XML content -->
    <element name="definition" implicit="yes" optional="yes"/>

    <sequential>
      <local name="config"/>
      <local name="get_response"/>
      <local name="new_config"/>
      <local name="oc_file"/>
      <local name="schema_file"/>
      <local name="set_okay"/>
      <local name="set_response"/>

      <!-- We'll need the preprocessed schema to make our best effort to ensure that the request is schema-compliant. -->
      <ensureDPSchema host="@{host}" uid="@{uid}" pwd="@{pwd}" port="@{port}" versionprop="@{versionprop}"
        domain="@{domain}" dcmdir="@{dcmdir}" schemadir="@{schemadir}" workdir="@{workdir}" dpschemaFileVbl="schema_file"
        dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"/>

      <!-- Get the configuration of the existing object. -->
      <wdp operation="GetConfig" responseprop="get_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <domain>@{domain}</domain>
        <hostname>@{host}</hostname>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <classname>@{class}</classname>
        <objname>@{existing-name}</objname>
        <return antprop="config" somaprop="config"/>
      </wdp>

      <!-- <echo>::: getConfig returned ${config}</echo> -->

      <if>
        <!-- ${config} != '' and ${config} != '<objs></objs>' -->
        <and>
          <not>
            <equals arg1="${config}" arg2=""/>
          </not>
          <not>
            <equals arg1="${config}" arg2="&lt;objs>&lt;/objs>"/>
          </not>
        </and>
        <then>

          <!-- Store any changes in a file, so we can pass them to the stylesheet.-->
          <property name="oc_file" value="@{workdir}/object-create.xml"/>
          <storexml outfile="${oc_file}"><changes><definition/></changes></storexml>

          <!-- <echo>::: oc_file = ${oc_file}</echo> -->
          <!-- <echo>::: schema_file = ${schema_file}</echo> -->

          <!--
            Create the XML for the new object, including its new name, based on the XML from
            the existing object plus any specified changes.  Ensure the resulting XML is as
            schema-compliant as we can make it.
          -->
          <nxslt inprop="config" outprop="new_config" xsl="@{dcmdir}/src/object-modify.xsl">
            <param xsl="input-url" ant="${oc_file}"/>
            <param xsl="schema-url" ant="${schema_file}"/>
            <param xsl="new-name" ant="@{new-name}"/>
          </nxslt>

          <!-- <echo>::: new_config = ${new_config}</echo> -->

          <!-- Create the new object. -->
          <wdp operation="SetConfig" responseprop="set_response"
            xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="set_okay"
            dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
            <domain>@{domain}</domain>
            <hostname>@{host}</hostname>
            <port>@{port}</port>
            <uid>@{uid}</uid>
            <pwd>@{pwd}</pwd>
            <config>${new_config}</config>
          </wdp>

          <!-- <echo>::: set_okay = ${set_okay}</echo> -->
          <!-- <echo>::: set_response = ${set_response}</echo> -->

          <if>
            <equals arg1="${set_okay}" arg2="OK"/>
            <then>
              <echo>Created object (by cloning) @{new-name} in domain @{domain} on @{host}.</echo>
            </then>
            <else>
              <echo>Raw response for dcm:object-create setConfig: ${set_response}</echo>
              <fail message="Failed to create @{class}/@{new-name} in @{domain} on @{host}."/>
            </else>
          </if>

        </then>
        <else>
          <echo>Raw response for dcm:object-create getConfig: ${get_response}</echo>
          <fail message="Failed to get the configuration of @{class}/@{existing-name} in @{domain} on @{host}."/>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--
    Create an object based on inline XML.
  -->
  <macrodef name="objectCreateByInline">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="versionprop"/>
    <attribute name="dcmdir"/> <!-- directory where DCM is found -->
    <attribute name="schemadir"/> <!-- directory where cached schemas might be found -->
    <attribute name="workdir"/> <!-- tmpdir where a directory can be created, if necessary -->
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>
    <attribute name="changes" default=""/> <!-- Alternative to passing in XML content -->
    <element name="definition" implicit="yes" optional="yes"/>

    <sequential>
      <local name="config"/>
      <local name="new_config"/>
      <local name="oc_file"/>
      <local name="schema_file"/>
      <local name="set_okay"/>
      <local name="set_response"/>

      <!-- We'll need the preprocessed schema to make our best effort to ensure that the request is schema-compliant. -->
      <ensureDPSchema host="@{host}" uid="@{uid}" pwd="@{pwd}" port="@{port}" versionprop="@{versionprop}"
        domain="@{domain}" dcmdir="@{dcmdir}" schemadir="@{schemadir}" workdir="@{workdir}" dpschemaFileVbl="schema_file"
        dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"/>

      <!--
        Copy the inline definition to a file, wrapping it in an dcm:object-create
        element for the benefit of the object-modify stylesheet.
      -->
      <property name="oc_file" value="@{workdir}/object-create.xml"/>
      <storexml outfile="${oc_file}"><definition/></storexml>

      <!-- <echo>::: oc_file = ${oc_file}</echo> -->
      <!-- <echo>::: schema_file = ${schema_file}</echo> -->

      <nxslt infile="${oc_file}" outprop="new_config" xsl="@{dcmdir}/src/object-modify.xsl">
        <param xsl="input-url" ant="${oc_file}"/>
        <param xsl="schema-url" ant="${schema_file}"/>
        <!-- <param xsl="new-name" ant="{$oc/@newname}"/> -->
      </nxslt>

      <!-- <echo>::: new_config = ${new_config}</echo> -->

      <!-- Create the new object. -->
      <wdp operation="SetConfig" responseprop="set_response"
        xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="set_okay"
        dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <domain>@{domain}</domain>
        <hostname>@{host}</hostname>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <config>${new_config}</config>
      </wdp>

      <!-- <echo>::: set_okay = ${set_okay}</echo> -->
      <!-- <echo>::: set_response = ${set_response}</echo> -->

      <if>
        <equals arg1="${set_okay}" arg2="OK"/>
        <then>
          <echo>Created object(s) based on inline definition in domain @{domain} on @{host}.</echo>
        </then>
        <else>
          <echo>Raw response for dcm:object-create setConfig: ${set_response}</echo>
          <fail message="Failed to create object(s) based on inline definition in @{domain} on @{host}."/>
        </else>
      </if>
    </sequential>

  </macrodef>


  <!--
    Create an object based on an object in an export file.
  -->
  <macrodef name="objectCreateFromExport">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="versionprop"/>
    <attribute name="class"/>
    <attribute name="existing-name"/>
    <attribute name="new-name"/>
    <attribute name="export"/> <!-- name of the DataPower export file -->
    <attribute name="dcmdir"/> <!-- directory where DCM is found -->
    <attribute name="schemadir"/> <!-- directory where cached schemas might be found -->
    <attribute name="workdir"/> <!-- tmpdir where a directory can be created, if necessary -->
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>
    <attribute name="changes" default=""/> <!-- Alternative to passing in XML content -->
    <element name="definition" implicit="yes" optional="yes"/>

    <sequential>
      <local name="config"/>
      <local name="file_base_name"/>
      <local name="is_zip"/>
      <local name="new_config"/>
      <local name="oc_file"/>
      <local name="private_dir"/>
      <local name="private_xml"/>
      <local name="schema_file"/>
      <local name="set_okay"/>
      <local name="set_response"/>

      <!-- We'll need the preprocessed schema to make our best effort to ensure that the request is schema-compliant. -->
      <ensureDPSchema host="@{host}" uid="@{uid}" pwd="@{pwd}" port="@{port}" versionprop="@{versionprop}"
        domain="@{domain}" dcmdir="@{dcmdir}" schemadir="@{schemadir}" workdir="@{workdir}" dpschemaFileVbl="schema_file"
        dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"/>

      <!-- Determine the file extension. -->
      <basename property="file_base_name" file="@{export}"/>
      <condition property="is_zip">
        <matches pattern=".+\.[zZ][iI][pP]$" string="${file_base_name}"/>
      </condition>

      <!-- <echo>### file_base_name=${file_base_name}, is_zip=${is_zip}</echo> -->

      <property name="private_dir" value="@{workdir}/export_${file_base_name}"/>
      <property name="private_xml" value="${private_dir}/export.xml"/>

      <!-- <echo>### private_dir=${private_dir}</echo> -->
      <!-- <echo>### private_xml=${private_xml}</echo> -->

      <if>
        <istrue value="${is_zip}"/>
        <then>

          <!-- Unzip .zip files so we can access their export.xml. -->
          <mkdir dir="${private_dir}"/>
          <unzip src="@{export}" dest="${private_dir}"/>

          <!-- Extract the configuration of the existing object. -->
          <xpath infile="${private_xml}" outprop="config" xpath="/datapower-configuration/configuration/*[name()='@{class}']" xpathType="node"/>

        </then>
        <else>

          <!-- Extract the configuration of the existing object. -->
          <xpath infile="@{export}" outprop="config" xpath="/datapower-configuration/configuration/*[name()='@{class}']" xpathType="node"/>

        </else>
      </if>

      <!-- <echo>### config=${config}</echo> -->

      <if>
        <!-- ${config} != '' and ${config} != '<objs></objs>' -->
        <and>
          <not>
            <equals arg1="${config}" arg2=""/>
          </not>
          <not>
            <equals arg1="${config}" arg2="&lt;objs>&lt;/objs>"/>
          </not>
        </and>
        <then>

          <!-- Store any changes in a file, so we can pass them to the stylesheet.-->
          <property name="oc_file" value="@{workdir}/object-create.xml"/>
          <storexml outfile="${oc_file}"><changes><definition/></changes></storexml>

          <!-- <echo>::: oc_file = ${oc_file}</echo> -->
          <!-- <echo>::: schema_file = ${schema_file}</echo> -->

          <nxslt inprop="config" outprop="new_config" xsl="@{dcmdir}/src/object-modify.xsl">
            <param xsl="input-url" ant="${oc_file}"/>
            <param xsl="schema-url" ant="${schema_file}"/>
            <param xsl="new-name" ant="@{new-name}"/>
          </nxslt>

          <!-- <echo>::: new_config = ${new_config}</echo> -->

          <!-- Create the new object. -->
          <wdp operation="SetConfig" responseprop="set_response"
            xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="set_okay"
            dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
            <domain>@{domain}</domain>
            <hostname>@{host}</hostname>
            <port>@{port}</port>
            <uid>@{uid}</uid>
            <pwd>@{pwd}</pwd>
            <config>${new_config}</config>
          </wdp>

          <!-- <echo>::: set_okay = ${set_okay}</echo> -->
          <!-- <echo>::: set_response = ${set_response}</echo> -->

          <if>
            <equals arg1="${set_okay}" arg2="OK"/>
            <then>
              <echo>Created object (by importing) @{new-name} in domain @{domain} on @{host}.</echo>
            </then>
            <else>
              <echo>Raw response for dcm:object-create setConfig: ${set_response}</echo>
              <fail message="Failed to create @{class}/@{new-name} in @{domain} on @{host}."/>
            </else>
          </if>

        </then>
        <else>
          <fail message="Failed to get the configuration of @{class}/@{existing-name} in @{domain} on @{host}."/>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--
    Delete an object.
  -->
  <macrodef name="objectDelete">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="class"/> <!-- class of object to delete -->
    <attribute name="name"/> <!-- name of object to delete -->
    <attribute name="dcmdir"/> <!-- directory where DCM is found -->
    <attribute name="workdir"/> <!-- tmpdir where a directory can be created, if necessary -->
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="delete_success"/>
      <local name="delete_response"/>

      <!-- Delete the existing object. -->
      <wdp operation="DeleteConfig" responseprop="delete_response" successprop="delete_success" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <domain>@{domain}</domain>
        <hostname>@{host}</hostname>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <classname>@{class}</classname>
        <objname>@{name}</objname>
      </wdp>

      <!-- <echo>::: delete_success = ${delete_success}</echo> -->
      <!-- <echo>::: delete_response = ${delete_response}</echo> -->

      <if>
        <istrue value="${delete_success}"/>
        <then>
          <echo>Deleted object @{class}/@{name} in domain @{domain} on @{host}.</echo>
        </then>
        <else>
          <echo>Raw response for deleteConfig: ${delete_response}</echo>
          <fail message="Failed to delete @{class}/@{name} in @{domain} on @{host}."/>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--
    Modify an object based on inline XML changes.
  -->
  <macrodef name="objectModify">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="versionprop"/>
    <attribute name="class"/> <!-- object class of object to modify -->
    <attribute name="name"/> <!-- name of object to modify -->
    <attribute name="dcmdir"/> <!-- directory where DCM is found -->
    <attribute name="schemadir"/> <!-- directory where cached schemas might be found -->
    <attribute name="workdir"/> <!-- tmpdir where a directory can be created, if necessary -->
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>
    <attribute name="changes" default=""/> <!-- Alternative to passing in XML content -->
    <element name="definition" implicit="yes" optional="yes"/>

    <sequential>
      <local name="config"/>
      <local name="get_response"/>
      <local name="new_config"/>
      <local name="om_file"/>
      <local name="schema_file"/>
      <local name="set_okay"/>
      <local name="set_response"/>

      <!-- We'll need the preprocessed schema to make our best effort to ensure that the request is schema-compliant. -->
      <ensureDPSchema host="@{host}" uid="@{uid}" pwd="@{pwd}" port="@{port}" versionprop="@{versionprop}"
        domain="@{domain}" dcmdir="@{dcmdir}" schemadir="@{schemadir}" workdir="@{workdir}" dpschemaFileVbl="schema_file"
        dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"/>

      <!-- Get the configuration of the existing object. -->
      <wdp operation="GetConfig" responseprop="get_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <domain>@{domain}</domain>
        <hostname>@{host}</hostname>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <classname>@{class}</classname>
        <objname>@{name}</objname>
        <return antprop="config" somaprop="config"/>
      </wdp>

      <!-- <echo>::: getConfig returned ${config}</echo> -->

      <if>
        <!-- ${config} != '' and ${config} != '<objs></objs>' -->
        <and>
          <not>
            <equals arg1="${config}" arg2=""/>
          </not>
          <not>
            <equals arg1="${config}" arg2="&lt;objs>&lt;/objs>"/>
          </not>
        </and>
        <then>

          <property name="om_file" value="@{workdir}/object-modify.xml"/>
          <storexml outfile="${om_file}"><changes><definition/></changes></storexml>

          <!-- <echo>::: om_file = ${om_file}</echo> -->
          <!-- <echo>::: schema_file = ${schema_file}</echo> -->

          <nxslt inprop="config" outprop="new_config" xsl="@{dcmdir}/src/object-modify.xsl">
            <param xsl="input-url" ant="${om_file}"/>
            <param xsl="schema-url" ant="${schema_file}"/>
          </nxslt>

          <!-- <echo>::: new_config = ${new_config}</echo> -->

          <!-- Create the new object. -->
          <wdp operation="SetConfig" responseprop="set_response"
            xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="set_okay"
            dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
            <domain>@{domain}</domain>
            <hostname>@{host}</hostname>
            <port>@{port}</port>
            <uid>@{uid}</uid>
            <pwd>@{pwd}</pwd>
            <config>${new_config}</config>
          </wdp>

          <!-- <echo>::: set_okay = ${set_okay}</echo> -->
          <!-- <echo>::: set_response = ${set_response}</echo> -->

          <if>
            <equals arg1="${set_okay}" arg2="OK"/>
            <then>
              <echo>Modified object @{class}/@{name} in domain @{domain} on @{host}.</echo>
            </then>
            <else>
              <echo>Raw response for dcm:object-modify setConfig: ${set_response}</echo>
              <fail message="Failed to create @{class}/@{name} in @{domain} on @{host}."/>
            </else>
          </if>

        </then>
        <else>
          <echo>Raw response for dcm:object-modify getConfig: ${get_response}</echo>
          <fail message="Failed to get the configuration of @{class}/@{name} in @{domain} on @{host}."/>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--

    Quiesce all the services in a domain, when it exists.

    Required parameters:
      host - hostname or IP address of DataPower device
      domain - domain on the device
      uid - userid
      pwd - password

    Optional parameters:
      timeout - number of seconds to wait for existing transactions to end
      port - XML Management Interface port on device (defaults to 5550)
      ignore-errors = true() or false()

  -->
  <macrodef name="quiesceDomain">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="timeout" default="60"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="quiesce_okay"/>
      <local name="quiesce_response"/>
      <local name="quiesce_success"/>
      <local name="domain_exists"/>
      <local name="domainlist"/>

      <getDomainStatus host="@{host}" uid="@{uid}" pwd="@{pwd}" port="@{port}" domainsprop="domainlist" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"/>

      <xpath inprop="domainlist" outprop="domain_exists" xpath="/status/DomainStatus[Domain='@{domain}']"/>

      <if>
        <not>
          <equals arg1="${domain_exists}" arg2=""/>
        </not>
        <then>

          <wdp operation="QuiesceDomain" successprop="quiesce_success" responseprop="quiesce_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"
            xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="quiesce_okay">
            <hostname>@{host}</hostname>
            <port>@{port}</port>
            <uid>@{uid}</uid>
            <pwd>@{pwd}</pwd>
            <domain>@{domain}</domain>
            <timeout>@{timeout}</timeout>
          </wdp>

          <if>
            <and>
              <istrue value="${quiesce_success}"/>
              <equals arg1="${quiesce_okay}" arg2="OK"/>
            </and>
            <then>
              <echo>Domain @{domain} quiesced on @{host}.</echo>
            </then>
            <else>
              <echo>Raw response for quiesceDomain: ${quiesce_response}</echo>
              <fail message="Failed to quiesce domain @{domain} on @{host}."/>
            </else>
          </if>

        </then>
        <else>
          <echo>Did not quiesce domain @{domain} on @{host} since it does not exist.</echo>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--
    Quiesce a service
  -->
  <macrodef name="quiesceService">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="servicename"/>
    <attribute name="servicetype"/>
    <attribute name="domain"/>
    <attribute name="timeout" default="60"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma"/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="quiesce_okay"/>
      <local name="quiesce_response"/>
      <local name="quiesce_success"/>
      <local name="capture"/>
      <wdp operation="QuiesceService" successprop="quiesce_success" responseprop="quiesce_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}"
        xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="quiesce_okay" capturesoma="@{capturesoma}">
        <type>@{servicetype}</type>
        <objname>@{servicename}</objname>
        <timeout>@{timeout}</timeout>
        <hostname>@{host}</hostname>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <domain>@{domain}</domain>
      </wdp>
      <if>
        <and>
          <istrue value="${quiesce_success}"/>
          <equals arg1="${quiesce_okay}" arg2="OK"/>
        </and>
        <then>
          <echo>Service @{servicename} quiesced on @{host}.</echo>
        </then>
        <else>
          <echo>Raw response for quiesceService: ${quiesce_response}</echo>
          <fail message="Failed to quiesce service @{servicename} in @{domain} on @{host}."/>
        </else>
      </if>
    </sequential>
  </macrodef>

	<!--
		Make a raw XML management call
	-->
	<macrodef name="rawMgmtCall">
		<attribute name="host"/>
		<attribute name="port" default="5550"/>
		<attribute name="uid"/>
		<attribute name="pwd"/>
		<attribute name="request"/>
		<attribute name="response"/>
		<attribute name="method"/>
		<sequential>
			<wdp operation="RawMgmtCall" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
				<hostname>@{host}</hostname>
				<port>@{port}</port>
				<uid>@{uid}</uid>
				<pwd>@{pwd}</pwd>
				<request>@{request}</request>
				<response>@{response}</response>
				<method>@{method}</method>
			</wdp>
		</sequential>
	</macrodef>

  <!--
    Remove a checkpoint
  -->
  <macrodef name="removeCheckpoint">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="checkpoint-name"/>
    <attribute name="domain"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma"/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="removecheckpoint_okay"/>
      <local name="removecheckpoint_response"/>
      <local name="removecheckpoint_success"/>

      <wdp operation="RemoveCheckpoint" successprop="removecheckpoint_success" responseprop="removecheckpoint_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}"
        xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="removecheckpoint_okay" capturesoma="@{capturesoma}">
        <hostname>@{host}</hostname>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <domain>@{domain}</domain>
        <name>@{checkpoint-name}</name>
      </wdp>

      <if>
        <and>
          <istrue value="${removecheckpoint_success}"/>
          <equals arg1="${removecheckpoint_okay}" arg2="OK"/>
        </and>
        <then>
          <echo>Removed checkpoint @{checkpoint-name} in @{domain} on @{host}.</echo>
        </then>
        <else>
          <echo>Raw response for removing checkpoint: ${rollbackcheckpoint_response}</echo>
          <fail message="Failed to remove checkpoint @{checkpoint-name} in @{domain} on @{host} after failing to import."/>
        </else>
      </if>
    </sequential>
  </macrodef>


  <!--

    Reset a domain conventionally, using ResetDomain, when the domain exists.

    Required parameters:
      host - hostname or IP address of DataPower device
      domain - domain on the device
      uid - userid
      pwd - password

    Optional parameters:
      port - XML Management Interface port on device (defaults to 5550)
      ignore-errors = true() or false()

  -->
  <macrodef name="resetDomainConventionally">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="reset_okay"/>
      <local name="reset_response"/>
      <local name="reset_success"/>
      <local name="domain_exists"/>
      <local name="domainlist"/>

      <getDomainStatus host="@{host}" uid="@{uid}" pwd="@{pwd}" port="@{port}" domainsprop="domainlist" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"/>

      <xpath inprop="domainlist" outprop="domain_exists"
        xpath="/status/DomainStatus[Domain='@{domain}']"/>

      <if>
        <not>
          <equals arg1="${domain_exists}" arg2=""/>
        </not>
        <then>

          <wdp operation="ResetDomain" successprop="reset_success" responseprop="reset_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"
            xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="reset_okay">
            <hostname>@{host}</hostname>
            <port>@{port}</port>
            <uid>@{uid}</uid>
            <pwd>@{pwd}</pwd>
            <domain>@{domain}</domain>
          </wdp>

          <if>
            <and>
              <istrue value="${reset_success}"/>
              <equals arg1="${reset_okay}" arg2="OK"/>
            </and>
            <then>
              <echo>Domain @{domain} reset on @{host}.</echo>
            </then>
            <else>
              <echo>Raw response for resetDomain: ${reset_response}</echo>
              <fail message="Failed to reset domain @{domain} on @{host}."/>
            </else>
          </if>

        </then>
        <else>
          <echo>Did not reset domain @{domain} on @{host} since it does not exist.</echo>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--

    Reset a domain by deleting it (when it exists) and then (re)creating it.

    Required parameters:
      host - hostname or IP address of DataPower device
      domain - domain on the device
      uid - userid
      pwd - password

    Optional parameters:
      port - XML Management Interface port on device (defaults to 5550)
      ignore-errors = true() or false()

  -->
  <macrodef name="resetDomainDeleteCreate">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="create_okay"/>
      <local name="create_response"/>
      <local name="create_success"/>
      <local name="delete_okay"/>
      <local name="delete_response"/>
      <local name="delete_success"/>
      <local name="domain_exists"/>
      <local name="domainlist"/>

      <getDomainStatus host="@{host}" uid="@{uid}" pwd="@{pwd}" port="@{port}" domainsprop="domainlist" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"/>

      <xpath inprop="domainlist" outprop="domain_exists"
        xpath="/status/DomainStatus[Domain='@{domain}']"/>

      <if>
        <not>
          <equals arg1="${domain_exists}" arg2=""/>
        </not>
        <then>

          <wdp operation="DeleteConfig" successprop="delete_success" responseprop="delete_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"
            xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="delete_okay">
            <classname>Domain</classname>
            <objname>@{domain}</objname>
            <hostname>@{host}</hostname>
            <port>@{port}</port>
            <uid>@{uid}</uid>
            <pwd>@{pwd}</pwd>
            <domain>default</domain>
          </wdp>

          <if>
            <and>
              <istrue value="${delete_success}"/>
              <equals arg1="${delete_okay}" arg2="OK"/>
            </and>
            <then/>
            <else>
              <echo>Raw response for resetDomainDeleteCreate (delete): ${delete_response}</echo>
              <fail message="Failed to delete domain @{domain} on @{host}."/>
            </else>
          </if>

        </then>
      </if>

      <wdp operation="SetConfig" successprop="create_success" responseprop="create_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"
        xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="create_okay">
        <config>
          <Domain name="@{domain}">
            <mAdminState>enabled</mAdminState>
            <NeighborDomain class="Domain">default</NeighborDomain>
            <ConfigMode>local</ConfigMode>
          </Domain>
        </config>
        <hostname>@{host}</hostname>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <domain>default</domain>
      </wdp>

      <if>
        <and>
          <istrue value="${create_success}"/>
          <equals arg1="${create_okay}" arg2="OK"/>
        </and>
        <then>
          <echo>Domain @{domain} deleted and recreated on @{host}.</echo>
        </then>
        <else>
          <echo>Raw response for resetDomainDeleteCreate (create): ${create_response}</echo>
          <fail message="Failed to create domain @{domain} on @{host}."/>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--

    Restart a domain, when it exists.

    Required parameters:
      host - hostname or IP address of DataPower device
      domain - domain on the device
      uid - userid
      pwd - password

    Optional parameters:
      port - XML Management Interface port on device (defaults to 5550)
      ignore-errors = true() or false()

  -->
  <macrodef name="restartDomain">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="restart_okay"/>
      <local name="restart_response"/>
      <local name="restart_success"/>
      <local name="domain_exists"/>
      <local name="domainlist"/>

      <getDomainStatus host="@{host}" uid="@{uid}" pwd="@{pwd}" port="@{port}" domainsprop="domainlist" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"/>

      <xpath inprop="domainlist" outprop="domain_exists"
        xpath="/status/DomainStatus[Domain='@{domain}']"/>

      <if>
        <not>
          <equals arg1="${domain_exists}" arg2=""/>
        </not>
        <then>

          <wdp operation="RestartDomain" successprop="restart_success" responseprop="restart_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"
            xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="restart_okay">
            <hostname>@{host}</hostname>
            <port>@{port}</port>
            <uid>@{uid}</uid>
            <pwd>@{pwd}</pwd>
            <domain>@{domain}</domain>
          </wdp>

          <if>
            <and>
              <istrue value="${restart_success}"/>
              <equals arg1="${restart_okay}" arg2="OK"/>
            </and>
            <then>
              <echo>Domain @{domain} restarted on @{host}.</echo>
            </then>
            <else>
              <echo>Raw response for restartDomain: ${restart_response}</echo>
              <fail message="Failed to restart domain @{domain} on @{host}."/>
            </else>
          </if>

        </then>
        <else>
          <echo>Did not restart domain @{domain} on @{host} since it does not exist.</echo>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--
    Restore one or more domains from a backup created by BackupDevice or BackupDevice.
  -->
  <macrodef name="restoreBackup">
    <attribute name="zipfile"/>
    <attribute name="domain"/> <!-- First domain to restore -->
    <attribute name="domains"/> <!-- Additional blank-separated domains to restore -->
    <attribute name="dry-run" default="false"/> <!-- Whether this is a dry run -->
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="success-update"/>

      <!-- Restore the specified domain(s). -->
      <wdp operation="Restore" successprop="success-update" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <local>@{zipfile}</local>
        <domain>@{domain}</domain>
        <domains>@{domains}</domains>
        <dry-run>@{dry-run}</dry-run>
        <hostname>@{host}</hostname>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
      </wdp>

      <if>
        <isset property="success-update"/>
        <then>
          <if>
            <equals arg1="@{domains}" arg2=""/>
            <then>
              <echo>Restored domain @{domain} on @{host}.</echo>
            </then>
            <else>
              <echo>Restored domains "@{domain} @{domains}" on @{host}.</echo>
            </else>
          </if>
        </then>
        <else>
          <fail message="Failed to restore from @{zipfile} on @{host}"/>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--
    Rewrite a DataPower export (.zip or .xml/.xcfg) to change object names or
    replace the existing WSDLs in a WSP with a new set of WSDLs.
  -->
  <macrodef name="rewriteExport">
    <attribute name="inputfile"/> <!-- DP export filename -->
    <attribute name="outputfile"/> <!-- Name of rewritten DP export file -->
    <attribute name="dcmdir"/> <!-- directory where DCM is found -->
    <attribute name="workdir"/> <!-- tmpdir where a directory can be created, if necessary -->
    <attribute name="changes" default=""/> <!-- Alternative to passing in XML content -->
    <element name="definition" implicit="yes" optional="yes"/>

    <sequential> <!-- permit declaring some variables local in scope. -->
      <local name="inputfile.abs"/>
      <local name="object-names-present"/>
      <local name="outputfile.abs"/>
      <local name="wsdls-present"/>

      <!-- Ensure that the input and output files are not the same file. -->
      <property name="inputfile.abs" location="@{inputfile}"/>
      <property name="outputfile.abs" location="@{outputfile}"/>
      <fail message="The DataPower export file to be rewritten (${inputfile.abs}) cannot be rewritten over itself.  (Use a different output file name.)">
        <condition>
          <equals arg1="${inputfile.abs}" arg2="${outputfile.abs}" casesensitive="false"/>
        </condition>
      </fail>

      <if>
        <equals arg1="@{changes}" arg2=""/>
        <then>
          <storexml outfile="@{workdir}/dcmpolicy.xml"><definition/></storexml>
        </then>
        <else>
          <storexml outfile="@{workdir}/dcmpolicy.xml">@{changes}</storexml>
        </else>
      </if>

      <!--
        Prepare the .zip/.xcfg file - rewriting if necessary.  The name of the (rewritten) file ends up in
        ${export_file}.
      -->
      <xpath infile="@{workdir}/dcmpolicy.xml" outprop="object-names-present" xpath="/dcm:definition/dcm:object-name/@match"/>
      <xpath infile="@{workdir}/dcmpolicy.xml" outprop="wsdls-present" xpath="/dcm:definition/dcm:wsdl/@href"/>
      <!-- <echo>### $${object-names-present}=${object-names-present}</echo> -->
      <!-- <echo>### $${wsdls-present}=${wsdls-present}</echo> -->
      <if>
        <or>
          <length string="${object-names-present}" when="gt" length="0"/>
          <length string="${wsdls-present}" when="gt" length="0"/>
        </or>
        <then>
          <!--
            Rewrite the export to account for renaming objects and/or new WSDLs.
          -->
          <if>
            <matches string="@{inputfile}" pattern="\.zip$" casesensitive="false"/>
            <then>
              <!-- Appears to be a .zip DataPower export, based on the filename. -->
              <delete dir="@{workdir}/rewritten_export" quiet="true"/>
              <mkdir dir="@{workdir}/rewritten_export"/>
              <unzip src="@{inputfile}" dest="@{workdir}/rewritten_export"/>
              <move file="@{workdir}/rewritten_export/export.xml" tofile="@{workdir}/rewritten_export/orig.xml"/>
              <nxslt infile="@{workdir}/rewritten_export/orig.xml" outfile="@{workdir}/rewritten_export/export.xml" xsl="@{dcmdir}/src/rewrite-xmlconfig.xsl">
                <param xsl="param1" ant="@{workdir}/dcmpolicy.xml"/>
              </nxslt>
              <zip destfile="@{workdir}/rewritten_export.zip" basedir="@{workdir}/rewritten_export" excludes="orig.xml"/>
              <copy file="${work.dir}/rewritten_export.zip" tofile="@{outputfile}" overwrite="true"/>
            </then>
            <else>
              <!-- Appears to be an XML (xcfg) DataPower export. -->
              <nxslt infile="@{inputfile}" outfile="@{outputfile}" xsl="@{dcmdir}/src/rewrite-xmlconfig.xsl">
                <param xsl="param1" ant="@{workdir}/dcmpolicy.xml"/>
              </nxslt>
            </else>
          </if>
        </then>
        <else>
          <!-- The export is fine just the way it is. -->
          <copy file="@{inputfile}" tofile="@{outputfile}" overwrite="true"/>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--
    Rollback a domain to a checkpoint
  -->
  <macrodef name="rollbackCheckpoint">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="checkpoint-name"/>
    <attribute name="domain"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma"/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="rollbackcheckpoint_okay"/>
      <local name="rollbackcheckpoint_response"/>
      <local name="rollbackcheckpoint_success"/>

      <wdp operation="RollbackCheckpoint" successprop="rollbackcheckpoint_success" responseprop="rollbackcheckpoint_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}"
        xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="rollbackcheckpoint_okay" capturesoma="@{capturesoma}">
        <hostname>@{host}</hostname>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <domain>@{domain}</domain>
        <name>@{checkpoint-name}</name>
      </wdp>

      <if>
        <and>
          <istrue value="${rollbackcheckpoint_success}"/>
          <equals arg1="${rollbackcheckpoint_okay}" arg2="OK"/>
        </and>
        <then>
          <echo>Restored checkpoint @{checkpoint-name} in @{domain} on @{host}.</echo>
        </then>
        <else>
          <echo>Raw response for restoring checkpoint: ${rollbackcheckpoint_response}</echo>
          <fail message="Failed to restore checkpoint @{checkpoint-name} in @{domain} on @{host} after failing to import."/>
        </else>
      </if>
    </sequential>
  </macrodef>


  <!--
    Create (save) a checkpoint
  -->
  <macrodef name="saveCheckpoint">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="checkpoint-name"/>
    <attribute name="domain"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma"/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="savecheckpoint_okay"/>
      <local name="savecheckpoint_response"/>
      <local name="savecheckpoint_success"/>

      <wdp operation="SaveCheckpoint" successprop="savecheckpoint_success" responseprop="savecheckpoint_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}"
        xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="savecheckpoint_okay" capturesoma="@{capturesoma}">
        <hostname>@{host}</hostname>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <domain>@{domain}</domain>
        <name>@{checkpoint-name}</name>
      </wdp>

      <if>
        <and>
          <istrue value="${savecheckpoint_success}"/>
          <equals arg1="${savecheckpoint_okay}" arg2="OK"/>
        </and>
        <then>
          <echo>Saved checkpoint @{checkpoint-name} in @{domain} on @{host}.</echo>
        </then>
        <else>
          <echo>Raw response for saving checkpoint: ${savecheckpoint_response}</echo>
          <fail message="Failed to save checkpoint @{checkpoint-name} in @{domain} on @{host} after failing to import."/>
        </else>
      </if>
    </sequential>
  </macrodef>


  <!--

    Save the domain is changed.

    Required parameters:
      host - hostname or IP address of DataPower device
      domain - name of domain on device
      uid - userid
      pwd - password

    Optional parameters:
      port - XML Management Interface port on device (defaults to 5550)
      ignore-errors = true() or false()

  -->
  <macrodef name="saveDomainIfChanged">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="domainStatusProp"/> <!-- property returned by getDomainStatus -->
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="save_needed"/>

      <fail message="The domainStatusProp attribute was not supplied in the ant script invoking &lt;saveDomainIfChanged&gt;!">
        <condition>
          <equals arg1="@{domainStatusProp}" arg2=""/>
        </condition>
      </fail>

      <xpath inprop="@{domainStatusProp}" outprop="save_needed"
      xpath="/status/DomainStatus[Domain='@{domain}']/SaveNeeded"/>

      <if>
        <equals arg1="${save_needed}" arg2="on"/>
        <then>
          <saveDomainUnconditionally host="@{host}" port="@{port}" uid="@{uid}" pwd="@{pwd}" domain="@{domain}"
            dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}" ignore-errors="@{ignore-errors}"/>
        </then>
      </if>

    </sequential>

  </macrodef>


  <!--

    Save the domain is changed and the user responds affirmatively to a prompt at the console.

    Required parameters:
      host - hostname or IP address of DataPower device
      domain - name of domain on device
      uid - userid
      pwd - password

    Optional parameters:
      port - XML Management Interface port on device (defaults to 5550)
      ignore-errors = true() or false()

  -->
  <macrodef name="saveDomainIfChangedPrompt">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="domainStatusProp"/> <!-- property returned by getDomainStatus -->
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="answer"/>
      <local name="save_needed"/>

      <fail message="The domainStatusProp attribute was not supplied in the ant script invoking &lt;saveDomainIfChangedPrompt&gt;!">
        <condition>
          <equals arg1="@{domainStatusProp}" arg2=""/>
        </condition>
      </fail>

      <xpath inprop="@{domainStatusProp}" outprop="save_needed"
        xpath="/status/DomainStatus[Domain='@{domain}']/SaveNeeded"/>

      <if>
        <equals arg1="${save_needed}" arg2="on"/>
        <then>

          <input validargs="y,s,h" addproperty="answer">Save domain @{domain} now (yes, skip saving, halt ANT script)?</input>
          <if>
            <equals arg1="${answer}" arg2="y"/>
            <then>

              <saveDomainUnconditionally host="@{host}" port="@{port}" uid="@{uid}" pwd="@{pwd}" domain="@{domain}"
                dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}" ignore-errors="@{ignore-errors}"/>

            </then>
          </if>
          <if>
            <equals arg1="${answer}" arg2="h"/>
            <then>
              <fail message="Stopping early because you chose 'halt' when asked about saving a domain."/>
            </then>
          </if>

        </then>
      </if>

    </sequential>

  </macrodef>


  <!--

    Save the domain unconditionally.

    Required parameters:
      host - hostname or IP address of DataPower device
      domain - name of domain on device
      uid - userid
      pwd - password

    Optional parameters:
      port - XML Management Interface port on device (defaults to 5550)
      ignore-errors = true() or false()

  -->
  <macrodef name="saveDomainUnconditionally">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="save_okay"/>
      <local name="save_response"/>
<!--
      <echo>saveDomainUnconditionally : host=@{host}</echo>
      <echo>saveDomainUnconditionally : port=@{port}</echo>
      <echo>saveDomainUnconditionally : uid=@{uid}</echo>
      <echo>saveDomainUnconditionally : pwd=@{pwd}</echo>
      <echo>saveDomainUnconditionally : domain=@{domain}</echo>
      <echo>saveDomainUnconditionally : dumpinput=@{dumpinput}</echo>
      <echo>saveDomainUnconditionally : dumpoutput=@{dumpoutput}</echo>
      <echo>saveDomainUnconditionally : ignore-errors=@{ignore-errors}</echo>
-->
      <!-- Save this domain -->
      <wdp operation="SaveConfig" responseprop="save_response"
        xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="save_okay"
        dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <domain>@{domain}</domain>
        <host>@{host}</host>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <ignore-errors>@{ignore-errors}</ignore-errors>
      </wdp>

      <if>
        <equals arg1="${save_okay}" arg2="OK"/>
        <then>
          <echo>Saved domain @{domain} on @{host}.</echo>
        </then>
        <else>
          <echo>Raw response for saveConfig: ${save_response}</echo>
          <fail message="Failed to save domain @{domain} on @{host}."/>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--
    Perform a secure backup of the appliance.
  -->
  <macrodef name="secureBackup">
    <attribute name="host" />
    <attribute name="port" default="5550" />
    <attribute name="uid" />
    <attribute name="pwd" />
    <attribute name="objname" />
    <attribute name="domain" default="default" />
    <attribute name="remote" /> <!-- ftp, local, temporary -->
    <attribute name="dumpinput" default="false" />
    <attribute name="dumpoutput" default="false" />
    <attribute name="capturesoma"/>
    <attribute name="ignore-errors" default="false" />

    <sequential>

      <local name="capture"/>
      <local name="success" />
      <wdp operation="SecureBackup" successprop="success" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <hostname>@{host}</hostname>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <domain>@{domain}</domain>
        <objname>@{objname}</objname>
        <remote>@{remote}</remote>
      </wdp>

      <if>

        <istrue value="${success}" />
        <then>
          <echo message="Secure backup successful to @{remote}" />
        </then>
        <else>
          <fail message="Secure Backup failed." />
        </else>

      </if>
    </sequential>
  </macrodef>


  <!--

    Set the log level in a domain (for the default log).

    Required parameters:
      host - hostname or IP address of DataPower device
      domain - domain on the device
      loglevel - debug, info, noice, warn, error, critic, alert, emerg
      uid - userid
      pwd - password

    Optional parameters:
      port - XML Management Interface port on device (defaults to 5550)
      ignore-errors = true() or false()

  -->
  <macrodef name="setLogLevel">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="loglevel"/> <!-- debug, info, noice, warn, error, critic, alert, emerg -->
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="set_okay"/>
      <local name="set_success"/>
      <local name="domain_exists"/>
      <local name="domainlist"/>

      <getDomainStatus host="@{host}" uid="@{uid}" pwd="@{pwd}" port="@{port}" domainsprop="domainlist" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"/>

      <xpath inprop="domainlist" outprop="domain_exists"
        xpath="/status/DomainStatus[Domain='@{domain}']"/>

      <if>
        <not>
          <equals arg1="${domain_exists}" arg2=""/>
        </not>
        <then>

          <wdp operation="SetLogLevel" successprop="set_success" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"
            xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="set_okay">
            <hostname>@{host}</hostname>
            <port>@{port}</port>
            <uid>@{uid}</uid>
            <pwd>@{pwd}</pwd>
            <domain>@{domain}</domain>
            <loglevel>@{loglevel}</loglevel>
          </wdp>

          <if>
            <and>
              <istrue value="${set_success}"/>
              <equals arg1="${set_okay}" arg2="OK"/>
            </and>
            <then>
              <echo>Log level in domain @{domain} on @{host} set to @{loglevel}.</echo>
            </then>
            <else>
              <echo>Raw response for setLogLevel: ${set_response}</echo>
              <fail message="Failed to set log level in domain @{domain} on @{host} to @{loglevel."/>
            </else>
          </if>

        </then>
        <else>
          <echo>Did set log level in domain @{domain} on @{host} since that domain does not exist.</echo>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--
    Create a valcred based on a few parameters and an implicit FileSet.
  -->
  <macrodef name="valcredFromFiles">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="dcmdir"/> <!-- directory where DCM is found -->
    <attribute name="rootdir"/> <!-- root directory for implicit FileSet -->
    <attribute name="objname"/> <!-- name of the Validation Credential object to create -->
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <element name="definition" implicit="yes"/>

    <sequential>
      <local name="response-create"/>
      <local name="success-create"/>
      <local name="uploadedfiles"/>
      <local name="valcred-objname"/>

      <!-- Upload all the files in the specified directory.  These are all supposed to be certificate files for this valcred object. -->
      <dpupload dir="@{rootdir}" target="cert:///" domain="@{domain}" url="https://@{host}:@{port}/service/mgmt/current" uid="@{uid}" pwd="@{pwd}"
        uploadedfilesprop="uploaded-files" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <definition/>
      </dpupload>

      <!-- <echo>uploaded-files = ${uploaded-files}</echo> -->

      <!-- Generate the guts of a SetConfig, comprised of Crypto Certificate objects and a Validation Credential object. -->
      <property name="valcred-objname" value="@{objname}"/>
      <nxslt inprop="uploaded-files" outprop="config" xsl="@{dcmdir}/src/generate-valcred.xsl">
        <param ant="valcred-objname" xsl="objname"/>
      </nxslt>

      <!-- <echo>config = ${config}</echo> -->

      <wdp operation="SetConfig" successprop="success-create" responseprop="response-create" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <wrapper>${config}</wrapper>
        <hostname>@{host}</hostname>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <domain>@{domain}</domain>
      </wdp>

      <!-- <echo>response-create = ${response-create}</echo> -->
      <!-- <echo>success-create = ${success-create}</echo> -->

      <if>
        <and>
          <isset property="success-create"/>
          <equals arg1="${success-create}" arg2="true"/>
        </and>
        <then>
          <echo>Created a Validation Credential object @{objname} and certificate objects.</echo>
        </then>
        <else>
          <fail message="Failed to create the Validation Credential object @{objname} or one or more certificate objects"/>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--
    Unimport some DataPower export.
  -->
  <macrodef name="unimportConfig">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="inputfile"/> <!-- name of original DataPower export file -->
    <attribute name="dcmdir"/> <!-- directory where DCM is found -->
    <attribute name="workdir"/> <!-- tmpdir where a directory can be created, if necessary -->
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>
    <element name="definition" implicit="yes"/>

    <sequential>
      <local name="exportname"/>
      <local name="exportxml"/>
      <local name="delete_errors"/>
      <local name="delete_response"/>
      <local name="delete_success"/>
      <local name="objects_delete"/>
      <local name="objects_disable"/>

      <!-- Rewrite the DP export to account for changes to object names or WSDLs (in a WSP), or just copy the DP export file. -->
      <basename property="exportname" file="@{inputfile}"/>
      <rewriteExport inputfile="@{inputfile}" outputfile="@{workdir}/${exportname}" dcmdir="@{dcmdir}" workdir="@{workdir}">
        <definition/> <!-- placeholder for dcm:definition provided as content of <unimportConfig> -->
      </rewriteExport>

      <!-- Access the rewritten export.xml - Note that this code depends on the internals of <rewriteExport>! -->
      <if>
        <matches string="${exportname}" pattern="\.zip$" casesensitive="false"/>
        <then>
          <property name="exportxml" location="@{workdir}/rewritten_export/export.xml"/>
        </then>
        <else>
          <property name="exportxml" location="@{workdir}/${exportname}"/>
        </else>
      </if>

      <!-- Capture the list of objects to delete, in proper order. -->
      <nxslt infile="${exportxml}" outprop="objects_disable" xsl="@{dcmdir}/src/unimport-extract-disable.xsl"/>

      <!-- Capture the list of objects to delete, in proper order. -->
      <nxslt infile="${exportxml}" outprop="objects_delete" xsl="@{dcmdir}/src/unimport-extract-delete.xsl"/>

      <!-- Disable the objects, ignoring some errors for the moment. -->
      <wdp operation="ModifyConfig" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <wrapper>${objects_disable}</wrapper>
        <domain>@{domain}</domain>
        <host>@{host}</host>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <ignore-errors>true</ignore-errors>
      </wdp>

      <!--
        Delete the objects multiple times.  This is due to a race condition where some objects are reported as "deleted"
        but they are in fact still being shut down.  This simple heuristic has been sufficient so far, but it is a heuristic,
        not a perfect solution.

        The race condition first appeared while deleting an MPGW with an MQ FSH and MQ QM.  We deleted the MQ FSH just fine, but
        the next object we deleted, the MQ QM, fails to delete because it was still in use by the MQ FSH, which apparently had not
        finished being destroyed.  Since it was a race condition, sometimes the MQ QM deleted successfully and sometimes not.
      -->
      <wdp operation="DeleteConfig" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <wrapper>${objects_delete}</wrapper>
        <domain>@{domain}</domain>
        <host>@{host}</host>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <ignore-errors>true</ignore-errors>
      </wdp>
      <wdp operation="DeleteConfig" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}">
        <wrapper>${objects_delete}</wrapper>
        <domain>@{domain}</domain>
        <host>@{host}</host>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <ignore-errors>true</ignore-errors>
      </wdp>
      <wdp operation="DeleteConfig" successprop="delete_success" responseprop="delete_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"
        xpath="/env:Envelope/env:Body/soma:response/soma:result[(text() and text() != 'OK') or error-log[log-event[normalize-space() != 'Cannot find configuration object']]]" xpathprop="delete_errors">
        <wrapper>${objects_delete}</wrapper>
        <domain>@{domain}</domain>
        <host>@{host}</host>
        <port>@{port}</port>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <ignore-errors>@{ignore-errors}</ignore-errors>
      </wdp>

      <if>
        <and>
          <istrue value="${delete_success}"/>
          <length string="${delete_errors}" when="equal" length="0"/>
        </and>
        <then>
          <echo>Successfully unimported @{inputfile} from domain @{domain} on @{host}.</echo>
        </then>
        <else>
          <echo>Raw response for unimport: ${delete_response}</echo>
          <fail message="Failed to unimport @{inputfile} from domain @{domain} on @{host}."/>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--

    Unquiesce all the services in a domain, when it exists.

    Required parameters:
      host - hostname or IP address of DataPower device
      domain - domain on the device
      uid - userid
      pwd - password

    Optional parameters:
      port - XML Management Interface port on device (defaults to 5550)
      ignore-errors = true() or false()

  -->
  <macrodef name="unquiesceDomain">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="domain"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma" default=""/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="unquiesce_okay"/>
      <local name="unquiesce_response"/>
      <local name="unquiesce_success"/>
      <local name="domain_exists"/>
      <local name="domainlist"/>

      <getDomainStatus host="@{host}" uid="@{uid}" pwd="@{pwd}" port="@{port}" domainsprop="domainlist" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"/>

      <xpath inprop="domainlist" outprop="domain_exists" xpath="/status/DomainStatus[Domain='@{domain}']"/>

      <if>
        <not>
          <equals arg1="${domain_exists}" arg2=""/>
        </not>
        <then>

          <wdp operation="UnquiesceDomain" successprop="unquiesce_success" responseprop="unquiesce_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}" capturesoma="@{capturesoma}"
            xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="unquiesce_okay">
            <hostname>@{host}</hostname>
            <port>@{port}</port>
            <uid>@{uid}</uid>
            <pwd>@{pwd}</pwd>
            <domain>@{domain}</domain>
            <timeout>@{timeout}</timeout>
          </wdp>

          <if>
            <and>
              <istrue value="${unquiesce_success}"/>
              <equals arg1="${unquiesce_okay}" arg2="OK"/>
            </and>
            <then>
              <echo>Domain @{domain} unquiesced on @{host}.</echo>
            </then>
            <else>
              <echo>Raw response for unquiesceDomain: ${unquiesce_response}</echo>
              <fail message="Failed to unquiesce domain @{domain} on @{host}."/>
            </else>
          </if>

        </then>
        <else>
          <echo>Did not unquiesce domain @{domain} on @{host} since it does not exist.</echo>
        </else>
      </if>

    </sequential>

  </macrodef>


  <!--
    Unquiesce a service
  -->
  <macrodef name="unquiesceService">
    <attribute name="host"/>
    <attribute name="port" default="5550"/>
    <attribute name="uid"/>
    <attribute name="pwd"/>
    <attribute name="servicename"/>
    <attribute name="servicetype"/>
    <attribute name="domain"/>
    <attribute name="timeout" default="60"/>
    <attribute name="dumpinput" default="false"/>
    <attribute name="dumpoutput" default="false"/>
    <attribute name="capturesoma"/>
    <attribute name="ignore-errors" default="false"/>

    <sequential>
      <local name="unquiesce_okay"/>
      <local name="unquiesce_response"/>
      <local name="unquiesce_success"/>
      <local name="capture"/>
      <wdp operation="UnquiesceService" successprop="unquiesce_success" responseprop="unquiesce_response" dumpinput="@{dumpinput}" dumpoutput="@{dumpoutput}"
        xpath="normalize-space(/env:Envelope/env:Body/soma:response/soma:result)" xpathprop="unquiesce_okay" capturesoma="@{capturesoma}">
        <type>@{servicetype}</type>
        <objname>@{servicename}</objname>
        <timeout>@{timeout}</timeout>
        <hostname>@{host}</hostname>
        <uid>@{uid}</uid>
        <pwd>@{pwd}</pwd>
        <domain>@{domain}</domain>
      </wdp>
      <if>
        <and>
          <istrue value="${unquiesce_success}"/>
          <equals arg1="${unquiesce_okay}" arg2="OK"/>
        </and>
        <then>
          <echo>Service @{servicename} unquiesced on @{host}.</echo>
        </then>
        <else>
          <echo>Raw response for unquiesceService: ${unquiesce_response}</echo>
          <fail message="Failed to unquiesce service @{servicename} in @{domain} on @{host}."/>
        </else>
      </if>
    </sequential>
  </macrodef>

  <!-- Convenient definition for using Xalan, specifically, to process XSLT. -->
  <macrodef name="xalan">
    <attribute name="in"/>
    <attribute name="out"/>
    <attribute name="xsl"/>
    <attribute name="param1" default=""/>
    <attribute name="param2" default=""/>
    <attribute name="param3" default=""/>

    <sequential>
      <xslt in="@{in}" out="@{out}" style="@{xsl}">
        <factory name="org.apache.xalan.processor.TransformerFactoryImpl">
          <attribute name="http://xml.apache.org/xalan/features/optimize" value="true"/>
        </factory>
        <param name="srcFile" expression="${src.file.absolute}"/>
        <param name="dirWork" expression="${work.dir}"/>
        <param name="dirDcm" expression="${dcm.dir}"/>
        <param name="param1" expression="@{param1}"/>
        <param name="param2" expression="@{param2}"/>
        <param name="param3" expression="@{param3}"/>
      </xslt>
    </sequential>

  </macrodef>


  <!-- Convenient definition to supply a default value when the specified value is empty. -->
  <macrodef name="defprop">
    <attribute name="name"/>
    <attribute name="value" default=""/>
    <attribute name="defvalue" default=""/>
    <sequential>
      <!--
        Define property using non-empty value or defvalue.
      -->
      <if>
        <equals arg1="@{value}" arg2=""/>
        <then>
          <property name="@{name}" value="@{defvalue}"/>
        </then>
        <else>
          <property name="@{name}" value="@{value}"/>
        </else>
      </if>
    </sequential>
  </macrodef>


  <!-- Convenient definition to supply a default value when the specified property is empty or not set. -->
  <macrodef name="defprop-set">
    <attribute name="name"/>
    <attribute name="from" default=""/>
    <attribute name="defvalue" default=""/>
    <sequential>
      <!--
        Define property based either on a non-empty property or a default value.
      -->
      <if>
        <and>
          <isset property="@{from}"/>
          <not>
            <equals arg1="${@{from}}" arg2=""/>
          </not>
        </and>
        <then>
          <property name="@{name}" value="${@{from}}"/>
          <!-- <echo>### name=@{name}, from=@{from}, defvalue=@{defvalue} : 1 : result=${@{name}}</echo> -->
        </then>
        <else>
          <property name="@{name}" value="@{defvalue}"/>
          <!-- <echo>### name=@{name}, from=@{from}, defvalue=@{defvalue} : 2 : result=${@{name}}</echo> -->
        </else>
      </if>
    </sequential>
  </macrodef>


</project>
