<?xml version="1.0" encoding="UTF-8"?>
<!--
- Licensed Materials - Property of IBM Corp.
- IBM UrbanCode Build
- IBM UrbanCode Deploy
- IBM UrbanCode Release
- IBM AnthillPro
- (c) Copyright IBM Corporation 2002, 2016. All Rights Reserved.
-
- U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
- GSA ADP Schedule Contract with IBM Corp.
-->
<plugin
        xmlns="http://www.urbancode.com/PluginXMLSchema_v1"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <header>
      <identifier id="com.urbancode.air.plugin.FileUtils" version="48" name="File Utils"/>
      <description>The File Utils plug-in includes steps, such as deleting or creating directories and replacing tokens in a file, that perform folder-level and file-level tasks as part of a deployment process.</description>
      <tag>Utilities/FileUtils</tag>
    </header>

    <!-- ==================================== -->
    <!--   STEPS                              -->
    <!-- ==================================== -->


    <!-- ==================================== -->
    <!--   Replace Tokens                  -->
    <!-- ==================================== -->
    <step-type name="Replace Tokens">
      <description>Replace tokens in files using properties.</description>
      <properties>
        <property name="includes" required="true">
          <property-ui type="textAreaBox" default-value="**/*" label="Include Files"
                       description="A list of patterns, separated by commas or spaces, that describe the files to include."/>
        </property>
        <property name="excludes">
          <property-ui type="textAreaBox" label="Exclude Files"
                       description="A list of patterns, separated by commas or spaces, that describe the files to exclude."/>
        </property>
        <property name="envPropValues">
          <property-ui type="textBox"
                       default-value="${p:environment/allProperties}"
                       label="Property List"
                       description="Specify a property value here to use existing property names as tokens to replace in the
                                    target files. For example: Specify ${p:environment/allProperties} to use the names of all
                                    component environment properties as tokens and the property values as the replacements.
                                    Similarly, specify ${p:component/allProperties},${p:environment/allProperties} to use the
                                    names of all component and component environment properties as tokens. The token delimiter
                                    and property prefix settings apply. If you specify @ for the start and end token delimiters
                                    and a property named token1 exists, then the step searches for @token1@ to replace."/>
        </property>
        <property name="propertyPrefix">
          <property-ui type="textBox" label="Property Prefix"
                       description="Specify a prefix to use to determine which properties are included in token replacement.
                                    Leave blank to include all properties."/>
        </property>
        <property name="explicitTokens">
          <property-ui type="textAreaBox"
                       label="Explicit Tokens"
                       description="A list, separated by newline characters, of explicit tokens to replace in the form of
                                    token->value. For example: if you specify mytoken->new_value, the step replaces mytoken with
                                    new_value. The token delimiter and property prefix settings apply. If you specified a value
                                    in the Property List field, the explicit tokens are added as additional values to replace,
                                    and override any properties that have the same name. You cannot use regular expressions."/>
        </property>
        <property name="startDelimiter">
          <property-ui type="textBox" default-value="@" label="Start Token Delimiter"
                       description="The start delimiter character used to identify tokens."/>
        </property>
        <property name="endDelimiter">
          <property-ui type="textBox" default-value="@" label="End Token Delimiter"
                       description="The end delimiter character used to identify tokens."/>
        </property>
        <property name="propFile">
          <property-ui type="textBox" label="Property File Name"
                       default-value="replace_tokens.properties"
                       description="The name of the file used to store the replacement name-value pairs. You can use an existing
                                    file. If the file does not exist, it is created and then removed when the step completes."/>
        </property>
        <property name="dir">
          <property-ui type="textBox" label="Directory Offset"
                       description="The directory relative to the current working directory that contains the files to operate
                                     on."/>
        </property>
        <property name="customEncoding">
          <property-ui type="textBox"
                       label="Custom Encoding"
                       description="Specify a character encoding to use.  If blank, the replacement file is created with the local character encoding of the agent. Example encodings: UTF-8, US-ASCII, UCS-2, JIS X 0201, UTF-16, UTF-16LE, EUC."/>
        </property>
      </properties>
      <post-processing>
        <![CDATA[
          if (properties.get("exitCode") != 0) {
              properties.put(new java.lang.String("Status"), new java.lang.String("Failure"));
          }
          else {
              properties.put("Status", "Success");
          }
       ]]>
      </post-processing>

      <command program="${GROOVY_HOME}/bin/groovy">
        <arg value="-cp"/>
        <arg path="lib"/>
        <arg file="replace_tokens.groovy"/>
        <arg file="${PLUGIN_INPUT_PROPS}"/>
        <arg file="${PLUGIN_OUTPUT_PROPS}"/>
      </command>
    </step-type>

    <!-- ==================================== -->
    <!--   Untar tarball                  -->
    <!-- ==================================== -->
    <step-type name="Untar Tarball">
      <description>Extract a .tar file.</description>
      <properties>
        <property name="dir" required="false">
          <property-ui type="textBox" label="Extract directory"
                       description="The directory to extract the .tar file to."/>
        </property>
        <property name="tarball" required="true">
          <property-ui type="textBox" label="Tarball"
                       description="The .tar file to extract. Use wildcards that are supported by Ant pattern matching to extract
                                    multiple .tar files. For example, if you specify json-*.tar, both json-c-0.10.tar and
                                    json-c-0.20.tar are extracted."/>
        </property>
        <property name="compression">
          <property-ui type="selectBox" label="Tarball"
                       description="Select the compression algorithm for the .tar file."/>
          <value label="none">none</value>
          <value label="gzip">gzip</value>
          <value label="bzip2">bzip2</value>
        </property>
        <property name="overwrite">
          <property-ui type="checkBox" label="Overwrite files"
                       description="If selected, files are overwritten even if they are newer than files in the .tar file."/>
        </property>
      </properties>
      <post-processing>
        <![CDATA[
          if (properties.get("exitCode") != 0) {
              properties.put(new java.lang.String("Status"), new java.lang.String("Failure"));
          }
          else {
              properties.put("Status", "Success");
          }
       ]]>
      </post-processing>

      <command program="${GROOVY_HOME}/bin/groovy">
        <arg value="-cp"/>
        <arg path="lib"/>
        <arg file="untar.groovy"/>
        <arg file="${PLUGIN_INPUT_PROPS}"/>
        <arg file="${PLUGIN_OUTPUT_PROPS}"/>
      </command>
    </step-type>
     <!-- ==================================== -->
    <!--               Unzip                   -->
    <!-- ==================================== -->
    <step-type name="Unzip">
      <description>Extract a .zip file.</description>
      <properties>
        <property name="dir" required="false">
          <property-ui type="textBox" label="Extract directory"
                       description="The directory to extract the .zip file to."/>
        </property>
        <property name="zip" required="true">
          <property-ui type="textBox" label=".zip files"
                       description="A list of patterns, separated by commas or spaces, that describe the .zip files to
                                    extract."/>
        </property>
        <property name="includes" required="true">
          <property-ui type="textAreaBox" default-value="**/*" label="Include Files"
                       description="A list of patterns, separated by commas or spaces, that describe the files in the archive to
                                    extract."/>
        </property>
        <property name="excludes" required="false">
          <property-ui type="textAreaBox" label="Exclude Files"
                       description="A list of patterns, separated by commas or spaces, that describe the files in the archive to
                                    skip."/>
        </property>
        <property name="overwrite">
          <property-ui type="checkBox" label="Overwrite files"
                       description="If selected, files are overwritten even if they are newer than files in the .zip file."/>
        </property>
        <property name="customEncoding">
          <property-ui type="textBox"
                       label="Custom Encoding"
                       description="Specify a character encoding to use when extracting files. If blank, the .zip file is created
                                    with the local character encoding of the agent. Example encodings: UTF-8, US-ASCII, UCS-2,
                                    JIS X 0201, UTF-16, UTF-16LE, EUC."/>
        </property>
      </properties>
      <post-processing>
        <![CDATA[
          if (properties.get("exitCode") != 0) {
              properties.put(new java.lang.String("Status"), new java.lang.String("Failure"));
          }
          else {
              //Failure callbacks will run after scanner.scan()
              scanner.register(".unzip. Failed to change file modification time.*", function(lineNumber, line) {
                scanner.addLOI(lineNumber);
                properties.put("Status", "Failure");
              });
              scanner.register(".unzip. Unable to expand to file.*", function(lineNumber, line) {
                scanner.addLOI(lineNumber);
                properties.put("Status", "Failure");
              });

              properties.put("Status", "Success");
              scanner.scan();
          }
       ]]>
      </post-processing>

      <command program="${GROOVY_HOME}/bin/groovy">
        <arg value="-cp"/>
        <arg path="classes"/>
        <arg file="unzip.groovy" />
        <arg file="${PLUGIN_INPUT_PROPS}"/>
        <arg file="${PLUGIN_OUTPUT_PROPS}"/>
      </command>
    </step-type>

    <!-- ==================================== -->
    <!--   Update Java Properties File        -->
    <!-- ==================================== -->
    <step-type name="Update Java Properties File">
      <description>Add, remove, or update properties in a Java properties file.</description>
      <properties>
        <property name="customEncoding" >
          <property-ui type="textBox"
                       label="Custom Encoding"
                       description="Specify a character encoding to use when accessing the properties file. This field takes
                                    precedence over Use System Encoding." />
        </property>
        <property name="useSystemEncoding" >
          <property-ui type="checkBox"
                       label="Use System Encoding"
                       description="Select to use the local character encoding of the agent when accessing the properties
                                    file."/>
        </property>
        <property name="dir">
          <property-ui type="textBox"
                       label="Directory Offset"
                       description="The directory relative to the current working directory that contains the files to operate
                                    on."/>
        </property>
        <property name="includes" required="true">
          <property-ui type="textAreaBox"
                       label="File Includes"
                       description="A list of patterns, separated by newline characters, that describe the property files to
                                    edit."/>
        </property>
        <property name="excludes">
          <property-ui type="textAreaBox"
                       label="File Excludes"
                       description="A list of patterns, separated by newline characters, that describe the property files to
                                    skip."/>
        </property>
        <property name="updateProps">
          <property-ui type="textAreaBox"
                       label="Add/Update properties"
                       description="A list of name-value pairs, separated by newline characters. This field takes precedence over
                                    Additional properties. Use the format property_name=property_value."/>
        </property>
        <property name="additionalProps">
          <property-ui type="textBox"
                       label="Additional properties"
                       description="A list of additional properties, separated by commas. For example, specify
                                    ${p:environment/allProperties} to add all environment properties as name-value pairs to the
                                    list of properties to update. The Additional properties field takes precedence over this
                                    field."/>
        </property>
        <property name="additionalPropsPrefix">
          <property-ui type="textBox"
                       label="Additional properties prefix"
                       description="Specify a prefix to use to filter the properties specified in the Additional properties
                                    field. The prefix is removed from the property name to form the property that is added to the
                                    property file. For example: if the Additional properties field is set to
                                    ${p:enviroment/allProperties}, specify &quot;proxy&quot; to update only the properties that
                                    begin with &quot;proxy.&quot;"/>
        </property>
        <property name="deleteProps">
          <property-ui type="textAreaBox"
                       label="Remove properties"
                       description="A list of names of properties to remove, separated by newline characters."/>
        </property>
      </properties>
      <post-processing>
        <![CDATA[
          if (properties.get("exitCode") != 0) {
              properties.put(new java.lang.String("Status"), new java.lang.String("Failure"));
          }
          else {
              properties.put("Status", "Success");
          }
       ]]>
      </post-processing>

      <command program="${GROOVY_HOME}/bin/groovy">
        <arg value="-cp"/>
        <arg path="classes:lib"/>
        <arg file="update_property_file.groovy" />
        <arg file="${PLUGIN_INPUT_PROPS}"/>
        <arg file="${PLUGIN_OUTPUT_PROPS}"/>
      </command>
    </step-type>

    <!-- ==================================== -->
    <!--   Copy Directory                     -->
    <!-- ==================================== -->
    <step-type name="Copy Directory">
      <description>Copy the contents of a directory to other directories. This step overwrites files but does not delete files.</description>
      <properties>
        <property name="sourceDir" required="true">
          <property-ui type="textBox"
                       label="Source Directory"
                       description="The directory to copy."/>
        </property>
        <property name="destDirList" required="true">
          <property-ui type="textAreaBox"
                       label="Destination Directories"
                       description="A list of directories to copy to, separated by newline characters."/>
        </property>
        <property name="includes" required="true">
          <property-ui type="textAreaBox"
                       label="Include Files"
                       default-value="**/*"
                       description="A list of patterns, separated by newline characters, that describe the files to copy. The
                                    default, **/*, includes all files."/>
        </property>
        <property name="excludes">
          <property-ui type="textAreaBox"
                       label="Exclude Files"
                       description="A list of patterns, separated by newline characters, that describe the files to skip. For
                                    example, if you specify **/*.zip, all .zip files in all subdirectories are excluded."/>
        </property>
        <property name="mapperRules">
          <property-ui type="textAreaBox"
                       label="Rename Rules"
                       description="A list of rules, separated by newline characters, for renaming the files in the destination
                                    directories. Use the format &quot;FROM-&gt;TO&quot;. For example, specify a.txt-&gt;b.txt to
                                    rename files named &quot;a.txt&quot; to &quot;b.txt&quot; and use *.java-&gt;*.java.bak to
                                    change file suffixes from .java to .java.bak. Rules are applied in the order that they are
                                    specified. No more than one rule is applied to a file."/>
        </property>
      </properties>
      <post-processing>
        <![CDATA[
          if (properties.get("exitCode") != 0) {
              properties.put(new java.lang.String("Status"), new java.lang.String("Failure"));
          }
          else {
              properties.put("Status", "Success");
          }
       ]]>
      </post-processing>

      <command program="${GROOVY_HOME}/bin/groovy">
        <arg value="-cp"/>
        <arg path="lib"/>
        <arg file="copy_dir.groovy" />
        <arg file="${PLUGIN_INPUT_PROPS}"/>
      <arg file="${PLUGIN_OUTPUT_PROPS}"/>
      </command>
    </step-type>

    <!-- ==================================== -->
    <!--   Move Directory                          -->
    <!-- ==================================== -->
    <step-type name="Move Directory">
      <description>Move the contents of a directory to another directory.</description>
      <properties>
        <property name="sourceDir" required="true">
          <property-ui type="textBox"
                       label="Source Directory"
                       description="The directory to move."/>
        </property>
        <property name="destDir" required="true">
          <property-ui type="textBox"
                       label="Destination Directory"
                       description="The directory to move to."/>
        </property>
        <property name="includes" required="true">
          <property-ui type="textAreaBox"
                       label="Include Files"
                       default-value="**/*"
                       description="A list of patterns, separated by newline characters, that describe the files to move. The
                                    default, **/*, includes all files."/>
        </property>
        <property name="excludes">
          <property-ui type="textAreaBox"
                       label="Exclude Files"
                       description="A list of patterns, separated by newline characters, that describe the files to skip. For
                                    example, if you specify **/*.zip, all .zip files in all subdirectories are excluded."/>
        </property>
        <property name="mapperRules">
          <property-ui type="textAreaBox"
                       label="Rename Rules"
                       description="A list of rules, separated by newline characters, for renaming the files in the destination
                                    directories. Use the format &quot;FROM-&gt;TO&quot;. For example, specify a.txt-&gt;b.txt to
                                    rename files named &quot;a.txt&quot; to &quot;b.txt&quot; and use *.java-&gt;*.java.bak to
                                    change file suffixes from .java to .java.bak. Rules are applied in the order that they are
                                    specifed. No more than one rule is applied to a file."/>
        </property>
      </properties>
      <post-processing>
        <![CDATA[
          if (properties.get("exitCode") != 0) {
              properties.put(new java.lang.String("Status"), new java.lang.String("Failure"));
          }
          else {
              properties.put("Status", "Success");
          }
       ]]>
      </post-processing>

      <command program="${GROOVY_HOME}/bin/groovy">
        <arg value="-cp"/>
        <arg path="lib"/>
        <arg file="move_dir.groovy" />
        <arg file="${PLUGIN_INPUT_PROPS}"/>
        <arg file="${PLUGIN_OUTPUT_PROPS}"/>
      </command>
    </step-type>


    <!-- ==================================== -->
    <!--   Sync Directory                     -->
    <!-- ==================================== -->
    <step-type name="Synchronize Directories">
      <description>Move new files in a source directory to a destination directory, and delete files in the destination directory that are not in the source directory. Synchronization is based on the time stamp of the file.</description>
      <properties>
        <property name="sourceDir" required="true">
          <property-ui type="textBox"
                       label="Source Directory"
                       description="The synchronization source directory."/>
        </property>
        <property name="destDirList" required="true">
          <property-ui type="textAreaBox"
                       label="Destination Directories"
                       description="A list of directories to copy to and synchronize, separated by newline characters."/>
        </property>

        <property name="overwrite">
          <property-ui type="checkBox"
                       label="Overwrite"
                       description="Select to overwrite target files even if they are newer than source files."/>
        </property>

        <property name="includes" required="true">
          <property-ui type="textAreaBox"
                       label="Include Files"
                       default-value="**/*"
                       description="A list of patterns, separated by newline characters, that describe the files to synchronize.
                                    The default, **/*, includes all files."/>
        </property>
        <property name="excludes">
          <property-ui type="textAreaBox"
                       label="Exclude Files"
                       description="A list of patterns, separated by newline characters, that describe the files to skip. For
                                    example, if you specify **/*.zip, all .zip files in all subdirectories are excluded."/>
        </property>
        <property name="preserveInTargetIncludes">
          <property-ui type="textAreaBox"
                       label="Preserve In Target Include Files"
                       description="A list of patterns, separated by newline characters, that describe files to include for
                                    preservation in the target directories."/>
        </property>
        <property name="preserveInTargetExcludes">
          <property-ui type="textAreaBox"
                       label="Preserve In Target Exclude Files"
                       description="A list of patterns, separated by newline characters, that describe files to skip for
                                    preservation in the target directories."/>
        </property>
      </properties>
      <post-processing>
        <![CDATA[
          if (properties.get("exitCode") != 0) {
              properties.put(new java.lang.String("Status"), new java.lang.String("Failure"));
          }
          else {
              properties.put("Status", "Success");
          }
       ]]>
      </post-processing>

      <command program="${GROOVY_HOME}/bin/groovy">
        <arg value="-cp"/>
        <arg path="lib"/>
        <arg file="sync_dir.groovy" />
        <arg file="${PLUGIN_INPUT_PROPS}"/>
        <arg file="${PLUGIN_OUTPUT_PROPS}"/>
      </command>
    </step-type>

    <!-- ==================================== -->
    <!--   Create Directory                     -->
    <!-- ==================================== -->
    <step-type name="Create Directories">
      <description>Create a set of directories, including nested directories.</description>
      <properties>
        <property name="dir" required="true">
          <property-ui type="textAreaBox"
                       default-value="."
                       label="Directories"
                       description="A list of directories to create, separated by newline characters."/>
        </property>
      </properties>
      <post-processing>
        <![CDATA[
          if (properties.get("exitCode") != 0) {
              properties.put(new java.lang.String("Status"), new java.lang.String("Failure"));
          }
          else {
              properties.put("Status", "Success");
          }
       ]]>
      </post-processing>

      <command program="${GROOVY_HOME}/bin/groovy">
        <arg value="-cp"/>
        <arg path="lib"/>
        <arg file="create_dir.groovy" />
        <arg file="${PLUGIN_INPUT_PROPS}"/>
        <arg file="${PLUGIN_OUTPUT_PROPS}"/>
      </command>
    </step-type>

    <!-- ==================================== -->
    <!--   Delete File/Directory              -->
    <!-- ==================================== -->
    <step-type name="Delete Files and Directories">
      <description>Delete files and directories.</description>
      <properties>
        <property name="baseDir" required="true">
          <property-ui type="textBox"
                       label="Base Directory"
                       description="The base directory where files and directories are deleted."/>
        </property>
        <property name="includes" required="true">
          <property-ui type="textAreaBox"
                       label="Include"
                       description="A list of patterns, separated by newline characters, that describe the files and directories
                                    to delete. For example, specify **/* to delete all files."/>
        </property>
        <property name="excludes">
          <property-ui type="textAreaBox"
                       label="Exclude"
                       description="A list of patterns, separated by newline characters, that describe the files and directories
                                    to skip when deleting. For example, specify **/*.txt to skip all .txt files."/>
        </property>
        <property name="followSymlinks">
          <property-ui type="checkBox"
                       label="Follow Symlinks"
                       description="Select to follow symlinks when deleting."/>
        </property>
        <property name="caseSensitive">
          <property-ui type="checkBox"
                       label="Case Sensitive"
                       default-value="true"
                       description="Select to use case-sensitive matching."/>
        </property>
      </properties>
      <post-processing>
        <![CDATA[
          if (properties.get("exitCode") != 0) {
              properties.put(new java.lang.String("Status"), new java.lang.String("Failure"));
          }
          else {
              properties.put("Status", "Success");
          }
       ]]>
      </post-processing>

      <command program="${GROOVY_HOME}/bin/groovy">
        <arg value="-cp" />
        <arg path="classes" />
        <arg file="delete_dir.groovy" />
        <arg file="${PLUGIN_INPUT_PROPS}"/>
        <arg file="${PLUGIN_OUTPUT_PROPS}"/>
      </command>
    </step-type>

    <!-- ==================================== -->
    <!--   Create File                        -->
    <!-- ==================================== -->
    <step-type name="Create File">
      <description>Create a text file.</description>
      <properties>
        <property name="file" required="true">
          <property-ui type="textBox"
                       label="File Name"
                       description="The name of the file."/>
        </property>
        <property name="contents">
          <property-ui type="textAreaBox"
                       label="Contents"
                       description="The contents of the file."/>
        </property>
        <property name="overwrite">
          <property-ui type="checkBox"
                       label="Overwrite if exists"
                       description="Select to overwrite an existing file with the same name."/>
        </property>
        <property name="customEncoding">
          <property-ui type="textBox"
                       label="Custom Encoding"
                       description="Specify a character encoding to use when creating the file. If blank, the .zip file is
                                    created with thelocal character encoding of the agent. Example encodings: US-ASCII, UCS-2,
                                    JIS X 0201, UTF-16, UTF-16LE, EUC."/>
        </property>
      </properties>
      <post-processing>
        <![CDATA[
          if (properties.get("exitCode") != 0) {
              properties.put(new java.lang.String("Status"), new java.lang.String("Failure"));
          }
          else {
              properties.put("Status", "Success");
          }
       ]]>
      </post-processing>

      <command program="${GROOVY_HOME}/bin/groovy">
        <arg value="-cp"/>
        <arg path="lib"/>
        <arg file="create_file.groovy" />
        <arg file="${PLUGIN_INPUT_PROPS}"/>
        <arg file="${PLUGIN_OUTPUT_PROPS}"/>
      </command>
    </step-type>

    <!-- ==================================== -->
    <!--   Update INI File                    -->
    <!-- ==================================== -->
    <step-type name="Update INI File">
      <description>Update a file in the Microsoft Windows INI format. This step supports property sections.</description>
      <properties>
        <property name="file" required="true">
          <property-ui type="textBox"
                       label="File Name"
                       description="The name of the file to update."/>
        </property>
        <property name="add">
          <property-ui type="textAreaBox"
                       label="Update properties"
                       description="A list of name-value pairs to update, separated by newline characters. Use the format
                                    section\name=value. Comments that precede a property line are added to the property. Comment
                                    lines begin with a semicolon (;) or number sign (#). To update properties in subsections, add
                                    the full path of the parent sections to the property name, using a backslash (\) as a
                                    separator. For example, specify section1\section2\propertyName=value to update the
                                    propertyName property in the section2 subsection of the section1 section."/>
        </property>
        <property name="remove">
          <property-ui type="textAreaBox"
                       label="Remove properties"
                       description="A list of properties to remove, separated by newline characters. To remove properties in
                                    subsections, add the full path of the parent sections to the property name, using a backslash
                                    (\) as a separator. For example, specify section1\section2\propertyName to remove the
                                    propertyName property in the section2 subsection of the section1 section."/>
        </property>
        <property name="addComments">
          <property-ui type="textAreaBox"
                       label="Add Section Comments"
                       description="Specify a list of comments, separated by newline characters, to add to sections. For example,
                                    specify section1=newComment to add newComment in a comment line above the section1
                                    section."/>
        </property>
        <property name="removeSection">
          <property-ui type="textAreaBox"
                       label="Remove Section"
                       default-value=""
                       description="A list of sections to remove, separated by newline characters. Removing a section removes the
                                    properties and property comments in the section." />
        </property>
        <property name="poundComments">
          <property-ui type="checkBox"
                       label="Use '#' character for comments"
                       default-value="false"
                       description="Select to use the number sign (#) to indicate a comment. Clear to use the semicolon (;) to
                                    indicate a comment." />
        </property>
        <property name="customEncoding" >
          <property-ui type="textBox"
                       label="Custom Encoding"
                       description="Specify a character encoding to use when accessing the INI file. If you do not specify an
                                    encoding, the local character encoding of the agent is used." />
        </property>
      </properties>
      <post-processing>
        <![CDATA[
          if (properties.get("exitCode") != 0) {
              properties.put(new java.lang.String("Status"), new java.lang.String("Failure"));
          }
          else {
              properties.put("Status", "Success");
          }
       ]]>
      </post-processing>

      <command program="${GROOVY_HOME}/bin/groovy">
        <arg value="-cp" />
        <arg path="classes:lib/ini4j-0.5.2.jar" />
        <arg value="-Dorg.ini4j.config.multiComment=true"/>
        <arg file="update_ini_file.groovy" />
        <arg file="${PLUGIN_INPUT_PROPS}"/>
        <arg file="${PLUGIN_OUTPUT_PROPS}"/>
      </command>
    </step-type>

    <!-- ==================================== -->
    <!--   Monitor file contents              -->
    <!-- ==================================== -->
    <step-type name="Monitor File Contents">
      <description>Monitor a file for a token. The step continues when the token is found, and fails if the token is not found in the specified time. This step is similar to the UNIX tail command, and ignores content in the file that is present before the step starts.</description>
      <properties>
        <property name="dirOffset">
          <property-ui type="textBox"
                       label="Directory Offset"
                       description="The directory relative to the current working directory that contains the file to monitor."/>
        </property>
        <property name="file" required="true">
          <property-ui type="textBox"
                       label="File Name"
                       description="The name of the file to monitor."/>
        </property>
        <property name="regex" required="true">
          <property-ui type="textBox"
                       label="Regular Expression"
                       description="A regular expression that describes the token to match in the file."/>
        </property>
        <property name="timeout" required="true">
          <property-ui type="textBox"
                       label="Timeout (s)"
                       description="The time, in seconds, to wait for a match to the regular expression. The step fails if a
                                    match is not found before the timeout expires."/>
        </property>
        <property name="failIfFound">
          <property-ui type="checkBox"
                       label="Fail if found"
                       description="Select to configure the step to fail if the regular expression is matched. When selected, the
                                    step does not fail when the timeout expires."/>
        </property>
      </properties>
      <post-processing>
        <![CDATA[
          if (properties.get("exitCode") != 0) {
              properties.put(new java.lang.String("Status"), new java.lang.String("Failure"));
          }
          else {
              properties.put("Status", "Success");
          }
       ]]>
      </post-processing>

      <command program="${GROOVY_HOME}/bin/groovy">
        <arg value="-cp" />
        <arg path="classes" />
        <arg file="monitor_file.groovy" />
        <arg file="${PLUGIN_INPUT_PROPS}"/>
        <arg file="${PLUGIN_OUTPUT_PROPS}"/>
      </command>
    </step-type>
    <!-- ==================================== -->
    <!--   Flip Line Endings              -->
    <!-- ==================================== -->
    <step-type name="Flip Line Endings">
      <description>Convert file line endings between UNIX and Microsoft Windows formats.</description>
      <properties>
        <property name="includes" required="true">
          <property-ui type="textAreaBox"
                       label="Includes"
                       description="A list of patterns, separated by newline characters, that describe the files to convert."/>
        </property>
        <property name="excludes">
          <property-ui type="textAreaBox"
                       label="Excludes"
                       description="A list of patterns, separated by newline characters, that describe the files to skip."/>
        </property>
        <property name="lineEnding">
          <property-ui type="selectBox"
                       label="Ending"
                       description="The line ending type to use."/>
          <value label="OS">os</value>
          <value label="Windows">windows</value>
          <value label="Unix">unix</value>
        </property>
      </properties>
      <post-processing>
        <![CDATA[
          if (properties.get("exitCode") != 0) {
              properties.put(new java.lang.String("Status"), new java.lang.String("Failure"));
          }
          else {
              properties.put("Status", "Success");
          }
       ]]>
      </post-processing>

      <command program="${GROOVY_HOME}/bin/groovy">
        <arg value="-cp" />
        <arg path="classes" />
        <arg file="flip.groovy" />
        <arg file="${PLUGIN_INPUT_PROPS}"/>
        <arg file="${PLUGIN_OUTPUT_PROPS}"/>
      </command>
    </step-type>

  <!-- ==================================== -->
  <!--   Create Zip archive                 -->
  <!-- ==================================== -->
  <step-type name="Create .zip File">
    <description>Create a .zip file.</description>
    <properties>
      <property name="zipName" required="true">
        <property-ui type="textBox"
                     label=".zip File Name"
                     description="Name of the new .zip file."/>
      </property>
      <property name="baseDir" required="true">
        <property-ui type="textBox"
                     label="Base Directory"
                     description="The directory that contains the files to add to the archive."/>
      </property>
      <property name="includes" required="true">
        <property-ui type="textAreaBox"
                     label="Include"
                     description="A list of patterns, separated by newline characters, that describe the files and directories to
                                  include. For example: **/*"/>
      </property>
      <property name="excludes">
        <property-ui type="textAreaBox"
                     label="Exclude"
                     description="A list of patterns, separated by newline characters, that describe the files and directories to
                                  skip. For example: **/*.txt"/>
      </property>
      <property name="update">
        <property-ui type="checkBox"
                     label="Update existing"
                     description="Select to update or overwrite the destination file if a file with that name already exists."/>
      </property>
      <property name="followSymlinks">
        <property-ui type="checkBox"
                     label="Follow Symlinks"
                     description="Select to follow symlinks when including files."/>
      </property>
      <property name="caseSensitive">
        <property-ui type="checkBox"
                     label="Case Sensitive"
                     default-value="true"
                     description="Select to use case-sensitive matching."/>
      </property>
      <property name="customEncoding">
          <property-ui type="textBox"
                       label="Custom Encoding"
                       description="Specify a character encoding to use when creating the .zip file. If blank, the .zip file is
                                    created with the local character encoding of the agent. Example encodings: US-ASCII, UCS-2,
                                    JIS X 0201, UTF-16, UTF-16LE, EUC."/>
        </property>
    </properties>
    <post-processing>
      <![CDATA[
          if (properties.get("exitCode") != 0) {
              properties.put(new java.lang.String("Status"), new java.lang.String("Failure"));
          }
          else {
              properties.put("Status", "Success");
          }
       ]]>
    </post-processing>

    <command program="${GROOVY_HOME}/bin/groovy">
      <arg value="-cp" />
      <arg path="classes" />
      <arg file="zip.groovy" />
      <arg file="${PLUGIN_INPUT_PROPS}"/>
      <arg file="${PLUGIN_OUTPUT_PROPS}"/>
    </command>
  </step-type>

  <!-- ==================================== -->
  <!--   Update XML File with XPath         -->
  <!-- ==================================== -->
  <step-type name="Update XML File with XPath">
    <description>Update XML files using XPath to locate items to edit.</description>
    <properties>
      <property name="srcDirOffset">
        <property-ui type="textBox"
                     label="Source Directory Offset"
                     description="The directory relative to the current working directory that contains the files to operate on."
                     default-value="."/>
      </property>
      <property name="destDirOffset">
        <property-ui type="textBox"
                     label="Destination Directory Offset"
                     description="The directory relative to the current working directory where the edited XML files will be
                                  stored."
                     default-value="."/>
      </property>
      <property name="includes" required="true">
        <property-ui type="textAreaBox"
                     label="File Includes"
                     description="A list of patterns, separated by newline characters, that describe the files to modify."/>
      </property>
      <property name="excludes">
        <property-ui type="textAreaBox"
                     label="File Excludes"
                     description="A list of patterns, separated by newline characters, the describe the files to skip."/>
      </property>
      <property name="replaceText">
        <property-ui type="textAreaBox"
                     label="Replace with text"
                     description="A list of XPath expression-replacement pairs, separated by newline characters. Use the format
                                  expression->replacement. For example, specify /root/foo/@bar->my_bar to replace the bar
                                  attribute value for all foo elements under the root element with my_bar. The step does nothing
                                  if the specified expression does not exist in the source files."/>
      </property>
      <property name="remove">
        <property-ui type="textAreaBox"
                     label="Remove"
                     description="A list of XPath expressions, separated by newline characters, that specify elements to remove.
                                  For example, specify /root/foo to remove all foo elements under the root element."/>
      </property>
      <property name="insert">
        <property-ui type="textAreaBox"
                     label="Insert XML"
                     description="A list of XPath expression-content pairs, separated by newline characters. Use the format
                                  expression->content. For example, specify /root/foo->&amp;lt;bar/&amp;gt; to insert an empty
                                  bar element under all foo elements in the root element."/>
      </property>
      <property name="setAttr">
        <property-ui type="textAreaBox"
                     label="Set Attributes"
                     description="A list of XPath expression-content pairs, separated by newline characters. Use the format
                                  expression->content. For example, specify /root/foo/@bar->my_bar to replace the bar attribute
                                  value for all foo elements under the root element with my_bar. The XPath expression must end
                                  with the /@name of the attribute to insert or update."/>
      </property>
      <property name="failWithoutMatch">
        <property-ui type="checkBox"
                     label="Fail if no match found"
                     description="Select to configure the step to fail if any of the XPath expressions do not return a match."/>
      </property>
    </properties>
    <post-processing>
      <![CDATA[
          if (properties.get("exitCode") != 0) {
              properties.put(new java.lang.String("Status"), new java.lang.String("Failure"));
          }
          else {
              properties.put("Status", "Success");
          }
       ]]>
    </post-processing>

    <command program="${GROOVY_HOME}/bin/groovy">
      <arg value="-cp" />
      <arg path="classes:lib/xmltask.jar:lib/xalan.jar" />
      <arg file="update_xml_with_xpath.groovy" />
      <arg file="${PLUGIN_INPUT_PROPS}"/>
      <arg file="${PLUGIN_OUTPUT_PROPS}"/>
    </command>
  </step-type>

  <!-- ==================================== -->
  <!--   Read Properties From XML File      -->
  <!-- ==================================== -->
  <step-type name="Read Properties From XML File">
    <description>Parse an XML file to search for properties defined by element names.</description>
    <properties>
      <property name="dirOffset">
        <property-ui type="textBox"
                     label="Directory Offset"
                     description="The directory relative to the current working directory that contains the files to operate
                                  on."/>
      </property>
      <property name="includes" required="true">
        <property-ui type="textBox"
                     label="XML File"
                     description="The full path to the XML file to read properties from."/>
      </property>
      <property name="propertyKeys" required="true">
        <property-ui type="textAreaBox"
                     label="Property Keys"
                     description="A list of elements, separated by newline characters, whose values will be used for properties.
                                  Use dot notation to refer to nested elements. For example, specify foo.bar.baz to retrieve the
                                  value of the baz element under the bar element under the foo element."/>
      </property>
      <property name="failWithoutMatch">
        <property-ui type="checkBox"
                     label="Fail if no match found"
                     description="Select to configure the step to fail if any of the XPath expressions do not return a match."/>
      </property>
    </properties>
    <post-processing>
      <![CDATA[
                if (properties.get("exitCode") != 0) {
              properties.put(new java.lang.String("Status"), new java.lang.String("Failure"));
          }
          else {
              properties.put("Status", "Success");
          }
       ]]>
           </post-processing>

        <command program="${GROOVY_HOME}/bin/groovy">
          <arg value="-cp" />
          <arg path="classes:lib/xmltask.jar" />
          <arg file="read_xml_properties.groovy" />
          <arg file="${PLUGIN_INPUT_PROPS}"/>
          <arg file="${PLUGIN_OUTPUT_PROPS}"/>
        </command>
    </step-type>
    <!-- ==================================== -->
    <!--   Read Property File                 -->
    <!-- ==================================== -->
    <step-type name="Read Property File">
      <description>Read properties from a file and set them as output properties for the step.</description>
      <properties>
        <property name="dir">
          <property-ui type="textBox"
                       label="Directory Offset"
                       description="The directory relative to the current working directory that contains the files to operate
                                    on."/>
        </property>
        <property name="file" required="true">
          <property-ui type="textBox"
                       label="Property File"
                       description="The name of the property file to read."/>
        </property>
      </properties>
      <post-processing>
        <![CDATA[
                if (properties.get("exitCode") != 0) {
              properties.put(new java.lang.String("Status"), new java.lang.String("Failure"));
          }
          else {
              properties.put("Status", "Success");
          }
       ]]>
      </post-processing>

      <command program="${GROOVY_HOME}/bin/groovy">
        <arg value="-cp" />
        <arg path="classes" />
        <arg file="read_property_file.groovy" />
        <arg file="${PLUGIN_INPUT_PROPS}"/>
        <arg file="${PLUGIN_OUTPUT_PROPS}"/>
      </command>
    </step-type>
</plugin>
