Merge branch '1.9.x'
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 79f94be..3f45cf2 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -23,11 +23,24 @@
 first. This way you can make sure you're not wasting your time on
 something that isn't considered to be in Ant's scope.
 
+Branches
+--------
+
+The master branch is where we develop the next release of Ant 1.10.x -
+any patch or PR against this branch must be buildable using Java8.
+
+The branch 1.9.x is where we develop the next release of Ant 1.9.x -
+any patch or PR against this branch must be buildable using Java5.
+
+Please state clearly whether you are targeting 1.9.x or 1.10.x -
+usually we port changes from 1.9.x to 1.10.x but not necessarily the
+other way around.
+
 Making Changes
 --------------
 
 + Create a topic branch from where you want to base your work (this is
-  usually the master branch).
+  usually the master or the 1.9.x branch, see above).
 + Make commits of logical units.
 + Respect the original code style:
   + Only use spaces for indentation.
diff --git a/ReleaseInstructions b/ReleaseInstructions
index fe2cd4f..5a8af4b 100644
--- a/ReleaseInstructions
+++ b/ReleaseInstructions
@@ -5,8 +5,9 @@
          Magesh Umasankar
          Antoine Levy-Lambert
 
-Note: This document was updated in the context of releasing Ant
-      1.9.7 which was the first release cut from the 1.9.x branch.
+Note: This document was adapted from the one created in the context of
+      releasing Ant 1.9.7. It assumes the first release created from
+      master will be 1.10.
       Please interpret the branch names, tags, etc. according to
       your context.
 
@@ -31,7 +32,7 @@
 
 2.  Ensure you have all the external libraries that Ant uses in your
     lib/optional directory.  All dependencies are either provided by
-    JDK 1.5.0 or downloadable using
+    JDK 1.8.0 or downloadable using
     ant -f fetch.xml -Ddest=optional
     To find out whether you have all the libraries you need, execute
     the build with -verbose option and scan for lines beginning with
@@ -40,9 +41,9 @@
 3.  We don't want tags for failed votes to end up on out branches so
     the release is first created from a detached head.
 
-    Checkout the HEAD of the 1.9.x branch as a detached head:
+    Checkout the HEAD of the master branch as a detached head:
 
-    $ git checkout 1.9.x^0
+    $ git checkout master^0
 
 4.  Make sure that your directory tree is clean by running git status.
     Some tests leave behind leftovers which end up in the source
@@ -57,7 +58,7 @@
     * POM files under src/etc/poms and subdirectories
       if you've got mvn installed
 
-      $ mvn versions:set -DnewVersion=1.9.7 -DgenerateBackupPoms=false
+      $ mvn versions:set -DnewVersion=1.10.0 -DgenerateBackupPoms=false
 
       inside src/etc/poms should do the trick.
 
@@ -82,11 +83,11 @@
     $ ./dist/bin/ant -nouserlib -lib lib/optional distribution
 
     build.xml specifies that the code should be compiled with
-    source=1.5 and target=1.5.
+    source=1.8 and target=1.8.
 
 8.  Commit your changes, tag them, push them.
 
-    $ git tag -s -m "Tagging RC1 for version 1.9.7 of Ant" ANT_197_RC1
+    $ git tag -s -m "Tagging RC1 for version 1.10.0 of Ant" ANT_1.10.0_RC1
     $ git push
     $ git push --tags
 
@@ -146,12 +147,12 @@
     This target generates a file build/html/WHATSNEW.html
 
     Add an html head element with a title like "Release Notes of Apache Ant
-    1.9.7" (from the default txt2html)
+    1.10.0" (from the default txt2html)
 
     Cut all sections about previous releases to keep only the current release,
-    and save as  RELEASE-NOTES-1.9.7.html inside the distribution folder.
+    and save as  RELEASE-NOTES-1.10.0.html inside the distribution folder.
 
-    Copy the file RELEASE-NOTES-1.9.7.html also as README.html
+    Copy the file RELEASE-NOTES-1.10.0.html also as README.html
 
 12. The distribution is now ready to go.
     Create a SVN sandbox on your computer with https://dist.apache.org/repos/dist/dev/ant in it
@@ -195,7 +196,7 @@
 
 16. Once the vote has passed, tag the last RC created with the final tag
 
-    $ git tag -s -m "Tagging version 1.9.7 of Ant" rel/1.9.7 HASH_OF_LAST_RC
+    $ git tag -s -m "Tagging version 1.10.0 of Ant" rel/1.10.0 HASH_OF_LAST_RC
     $ git push --tags
 
 17. The distrib artifacts should be published the apache dist. It is
@@ -223,36 +224,36 @@
     https://reporter.apache.org/addrelease.html?ant
 
 19. Address the available version tags in BugZilla. Create new
-    milestone 1.9.8 and version 1.9.7.
+    milestone 1.10.1 and version 1.10.0.
 
 20. Add a new release tag to doap_Ant.rdf in Ant's site.
 
-21. checkout the 1.9.x branch, merge the tag but don't push the
+21. checkout the master branch, merge the tag but don't push the
     commit
 
-    $ git checkout 1.9.x
-    $ git merge rel/1.9.7
+    $ git checkout master
+    $ git merge rel/1.10.0
 
     Set the version number in several files to the required version of
-    the next 1.9.x release. These are:
+    the next 1.10.x release. These are:
 
     * manual/cover.html
     * manual/credits.html
     * build.xml properties : project.version,manifest-version,pom.version
 
       project.version property in build.xml gets bumped to
-      [newversion]alpha, for example 1.9.8alpha
+      [newversion]alpha, for example 1.10.1alpha
 
       manifest-version gets bumped to the exact next release number
-      for example 1.9.8.
+      for example 1.10.1.
 
       pom.version gets bumped to [newversion]-SNAPSHOT
-      for example 1.9.8-SNAPSHOT.
+      for example 1.10.1-SNAPSHOT.
 
     * POM files under src/etc/poms and subdirectories
       if you've got mvn installed
 
-      $ mvn versions:set -DnewVersion=1.9.8-SNAPSHOT -DgenerateBackupPoms=false
+      $ mvn versions:set -DnewVersion=1.10.1-SNAPSHOT -DgenerateBackupPoms=false
 
       inside src/etc/poms should do the trick.
 
@@ -266,15 +267,9 @@
     $ git commit -a --amend
     $ git push
 
-22. checkout the master branch, merge the 1.9.x branch
+22. wait a few hours for the mirrors to catch up
 
-    $ git checkout master
-    $ git merge 1.9.x
-    $ git push
-
-23. wait a few hours for the mirrors to catch up
-
-24. Update the ant.apache.org site :
+23. Update the ant.apache.org site :
 
     The website is managed here: https://svn.apache.org/repos/asf/ant/site/ant/
 
@@ -282,6 +277,10 @@
     the site still uses svn and Ant proper uses git there currently is
     no way to use the scm for this.
 
+    [TODO once there is the first release of 1.10.0, we'll likely need
+    to restructure the site to allow two versions of the manual to
+    exist in parallel]
+
     Update the following files for version number:
 
     * source/antnews.xml (Announcement)
@@ -296,17 +295,20 @@
     Commit the modified/generated files in the 'production' folder, it will go
     live on ant.apache.org in a matter on seconds.
 
-25. At this point in time, the release is done and announcements are made.
+24. At this point in time, the release is done and announcements are made.
     PGP-sign your announcement posts.
 
     Apache mailing lists that should get the announcements:
     announce@apache.org, dev@ant and user@ant.
 
-26. You can now reacquaint yourself with your family and friends.
+25. You can now reacquaint yourself with your family and friends.
 
-27. After a few days "svn rm" the older release artifacts and release
+26. After a few days "svn rm" the older release artifacts and release
     notes from https://dist.apache.org/repos/dist/release/ant/
 
+    "older" here means any older 1.10.x release but not the latest
+    1.9.x release.
+
 Related Information
 
 http://www.apache.org/dev/#releases
diff --git a/STATUS b/STATUS
index 874396d..67ba9d8 100644
--- a/STATUS
+++ b/STATUS
@@ -1,10 +1,10 @@
 Apache Ant Status
-Last modified at 2016-02-24
+Last modified at 2016-04-09
 
 Release:
-    Current:        1.9.6  (in GIT Tag: ANT_196)
-    Maintenance:    1.9.x  (in GIT Branch: master)
-    Development:    1.9.7  (in GIT Branch: master)
+    Current:        1.9.6  (in GIT Tag: rel/1.9.6)
+    Maintenance:    1.9.x  (in GIT Branch: 1.9.x)
+    Development:    1.10.x (in GIT Branch: master)
 
 Assets:
     DNS:                ant.apache.org
diff --git a/WHATSNEW b/WHATSNEW
index 019b8a4..884d9b5 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -1,14 +1,23 @@
-Changes from Ant 1.9.7 TO Ant 1.9.8
-===================================
+Changes from Ant 1.9.7 TO Ant 1.10.0
+====================================
 
 Changes that could break older environments:
 -------------------------------------------
 
+ * Ant 1.10.x requires Java8 or newer at compile or build time.
+   The 1.9.x series wil stay compatible with Java5.
+
+ * The <apt> task has been removed since apt itself has been removed
+   with Java8.
+
  * <fileset>/<zipfileset>/<tarfileset> exhibited undefined
    behavior when both the dir and file attribute have been used on the
    same instance. This will now cause the build to fail.
    Bugzilla Report 59402
 
+ * <native2ascii> will default to the buitin implementation on Java8
+   as well (sun isn't available for Java9+ anyway).
+
  * The ant.java.version property will now hold the value "9" rather
    than "1.9" if running on Java 9.
 
@@ -43,6 +52,11 @@
 Other changes:
 --------------
 
+ * New file selectors <executable>, <symlink> and <ownedBy>.
+
+ * New task <setpermissions> that provides the ability to set POSIX
+   compatible permssions via NIO's PosixFilePermission
+
  * <junit> now initializes the cause of the AssertionFailedError when
    converting from AssertionError.
    Bugzilla Report 58982
@@ -50,6 +64,9 @@
  * <scp> now supports compression via the optional compressed attribute.
    Bugzilla Report 47552
 
+ * <junit> now supports JDK9 modules
+   Github Pull Request #18
+
  * a new implementation "builtin" has been added to <native2ascii> and
    is the default when running on JDK9+ since the tool itself has been
    removed from the JDK.
diff --git a/build.xml b/build.xml
index eba9fc8..9e8cc1f 100644
--- a/build.xml
+++ b/build.xml
@@ -34,10 +34,10 @@
   <property name="name" value="ant"/>
   <!-- this is the groupId of ant in the Maven repository -->
   <property name="groupid" value="org/apache/ant"/>
-  <property name="project.version" value="1.9.8alpha"/>
+  <property name="project.version" value="1.10.0alpha"/>
   <!-- pom.version is used when doing a distribution and must match with what is checked in under src/etc/poms -->
-  <property name="pom.version" value="1.9.8-SNAPSHOT"/>
-  <property name="manifest-version" value="1.9.8"/>
+  <property name="pom.version" value="1.10.0-SNAPSHOT"/>
+  <property name="manifest-version" value="1.10.0"/>
   <property name="bootstrap.jar" value="ant-bootstrap.jar"/>
 
   <property name="ant.package" value="org/apache/tools/ant"/>
@@ -100,12 +100,11 @@
        ===================================================================
   -->
   <property name="debug" value="true"/>
-  <property name="chmod.fail" value="true"/>
-  <property name="chmod.maxparallel" value="250"/>
+  <property name="setpermissions.fail" value="true"/>
   <property name="deprecation" value="false"/>
   <property name="optimize" value="true"/>
-  <property name="javac.target" value="1.5"/>
-  <property name="javac.source" value="1.5"/>
+  <property name="javac.target" value="1.8"/>
+  <property name="javac.source" value="1.8"/>
   <property name="junit.filtertrace" value="off"/>
   <property name="junit.summary" value="no"/>
   <property name="test.haltonfailure" value="false"/>
@@ -122,7 +121,6 @@
   <property name="junit.collector.dir" value="${build.dir}/failingTests"/>
   <property name="junit.collector.class" value="FailedTests"/>
 
-
   <!--
        ===================================================================
          Set the paths used in the build
@@ -375,9 +373,6 @@
       </not>
     </condition>
     <property name="ignoresystemclasses" value="false"/>
-    <available property="jdk1.6+" classname="java.net.CookieStore"/>
-    <available property="jdk1.7+" classname="java.nio.file.FileSystem"/>
-    <available property="jdk1.8+" classname="java.lang.reflect.Executable"/>
     <available property="jdk9+" classname="java.lang.module.ModuleDescriptor"/>
     <available property="kaffe" classname="kaffe.util.NotImplemented"/>
     <available property="harmony"
@@ -531,10 +526,7 @@
       property="javadoc.doclint.none" 
       value="-Xdoclint:none" 
       else="">
-      <and>
-        <isset property="jdk1.8+"/>
-        <not><isset property="withDoclint"/></not>
-      </and>
+      <not><isset property="withDoclint"/></not>
     </condition>
   </target>
 
@@ -918,18 +910,20 @@
       <include name="*.pl"/>
     </fixcrlf>
 
-    <chmod perm="ugo+rx" dir="${dist.dir}" type="dir" includes="**"
-      failonerror="${chmod.fail}"/>
-    <chmod perm="ugo+r" dir="${dist.dir}" type="file" includes="**"
-      failonerror="${chmod.fail}" maxparallel="${chmod.maxparallel}"/>
-    <chmod perm="ugo+x" type="file" failonerror="${chmod.fail}">
+    <setpermissions mode="755" failonerror="${setpermissions.fail}">
+      <dirset dir="${dist.dir}"/>
+    </setpermissions>
+    <setpermissions mode="644" failonerror="${setpermissions.fail}">
+      <fileset dir="${dist.dir}"/>
+    </setpermissions>
+    <setpermissions mode="755" failonerror="${setpermissions.fail}">
       <fileset dir="${dist.bin}">
         <include name="**/ant"/>
         <include name="**/antRun"/>
         <include name="**/*.pl"/>
         <include name="**/*.py"/>
       </fileset>
-    </chmod>
+    </setpermissions>
 
   </target>
 
@@ -1030,18 +1024,20 @@
       </fileset>
     </copy>
 
-    <chmod perm="ugo+rx" dir="${dist.dir}" type="dir" includes="**"
-      failonerror="${chmod.fail}"/>
-    <chmod perm="ugo+r" dir="${dist.dir}" type="file" includes="**"
-      failonerror="${chmod.fail}" maxparallel="${chmod.maxparallel}"/>
-    <chmod perm="ugo+x" type="file" failonerror="${chmod.fail}">
+    <setpermissions mode="755" failonerror="${setpermissions.fail}">
+      <dirset dir="${dist.dir}"/>
+    </setpermissions>
+    <setpermissions mode="644" failonerror="${setpermissions.fail}">
+      <fileset dir="${dist.dir}"/>
+    </setpermissions>
+    <setpermissions mode="755" failonerror="${setpermissions.fail}">
       <fileset dir="${dist.bin}">
         <include name="**/ant"/>
         <include name="**/antRun"/>
         <include name="**/*.pl"/>
         <include name="**/*.py"/>
       </fileset>
-    </chmod>
+    </setpermissions>
 
     <!-- publish some useful stylesheets -->
     <copy todir="${dist.etc}">
@@ -1148,18 +1144,21 @@
       <exclude name="${tests.etc.dir}/taskdefs/fixcrlf/input/Junk?.java"/>
     </fixcrlf>
 
-    <chmod perm="ugo+x" dir="${src.dist.dir}" type="dir"
-      failonerror="${chmod.fail}"/>
-    <chmod perm="ugo+r" dir="${src.dist.dir}" failonerror="${chmod.fail}"/>
-    <chmod perm="ugo+x" failonerror="${chmod.fail}">
+    <setpermissions mode="755" failonerror="${setpermissions.fail}">
+      <dirset dir="${src.dist.dir}"/>
+    </setpermissions>
+    <setpermissions mode="644" failonerror="${setpermissions.fail}">
+      <fileset dir="${src.dist.dir}"/>
+    </setpermissions>
+    <setpermissions mode="755" failonerror="${setpermissions.fail}">
       <fileset dir="${src.dist.dir}">
-        <include name="**/.sh"/>
-        <include name="**/.pl"/>
-        <include name="**/.py"/>
+        <include name="**/*.sh"/>
+        <include name="**/*.pl"/>
+        <include name="**/*.py"/>
         <include name="**/ant"/>
         <include name="**/antRun"/>
       </fileset>
-    </chmod>
+    </setpermissions>
 
   </target>
 
diff --git a/check.xml b/check.xml
index 5509522..92d0346 100644
--- a/check.xml
+++ b/check.xml
@@ -15,7 +15,7 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<project default="checkstyle" name="CheckAnt" xmlns:ivy="antlib:org.apache.ivy.ant">
+<project default="checkstyle" name="CheckAnt" xmlns:ivy="antlib:org.apache.ivy.ant" xmlns:if="ant:if" xmlns:unless="ant:unless">
 
   <description>
     Check Ants codebase against certain code styleguide rules using
@@ -34,35 +34,48 @@
   </description>
 
   <import file="build.xml"/>
+  
   <property name="config.dir" location="${etc.dir}/checkstyle"/>
 
-  <property name="checkstyle.reportdir" location="${build.dir}/reports/checkstyle"/>
-  <property name="checkstyle.raw" location="${checkstyle.reportdir}/raw.xml"/>
-  <property name="stylesheet.html" location="${config.dir}/checkstyle-frames.xsl"/>
-  <property name="stylesheet.html.sorted" location="${config.dir}/checkstyle-frames-sortby-check.xsl"/>
-  <property name="stylesheet.text" location="${config.dir}/checkstyle-text.xsl"/>
-  <property name="stylesheet.xdoc" location="${config.dir}/checkstyle-xdoc.xsl"/>
-
-  <property name="checkstyle.basedir" location="${java.dir}"/>
-
   <!-- Ant Checkstyle report -->
-  <property name="tocheck" value="**/*.java"/>
-  <property name="javadoc.scope" value="public"/>
+  <property name="checkstyle.reportdir"
+            location="${build.dir}/reports/checkstyle"
+            description="Where to store Checkstyle reports"/>
+  <property name="checkstyle.raw"
+            location="${checkstyle.reportdir}/raw.xml"
+            description="Name of Checkstyle XML-Report"/>
+  <property name="stylesheet.html"
+            location="${config.dir}/checkstyle-frames.xsl"
+            description="Name of Checkstyle XSLT for generating HTML"/>
+  <property name="stylesheet.html.sorted"
+            location="${config.dir}/checkstyle-frames-sortby-check.xsl"
+            description="Name of Checkstyle XSLT for generating 2nd HTML"/>
+  <property name="stylesheet.text"
+            location="${config.dir}/checkstyle-text.xsl"
+            description="Name of Checkstyle XSLT for generating plain text"/>
+  <property name="stylesheet.xdoc"
+            location="${config.dir}/checkstyle-xdoc.xsl"
+            description="Name of Checkstyle XSLT for generating XDOC"/>
 
-  <taskdef resource="simiantask.properties"/>
-  
+  <property name="checkstyle.basedir"
+            location="${java.dir}"
+            description="Where are the Java sources to check"/>
+  <property name="tocheck"
+            value="**/*.java"
+            description="Include pattern of the files to check"/>
+
   <!-- Findbugs: Running Findbugs -->
-  <property name="findbugs.reportdir" 
-            location="${build.dir}/reports/findbugs" 
+  <property name="findbugs.reportdir"
+            location="${build.dir}/reports/findbugs"
             description="Where to store Findbugs results"/>
-  <property name="findbugs.raw"       
-            value="raw.xml" 
+  <property name="findbugs.raw"
+            value="raw.xml"
             description="Findbugs Output xml-file"/>
-  <property name="findbugs.xsl"       
-            value="fancy.xsl" 
+  <property name="findbugs.xsl"
+            value="fancy.xsl"
             description="Which XSL to use for generating Output: default, fancy, plain, summary"/>
-  <property name="findbugs.jvmargs"   
-            value="-Xms128m -Xmx512m" 
+  <property name="findbugs.jvmargs"
+            value="-Xms128m -Xmx512m"
             description="JVMArgs for invoking Findbugs"/>
 
   <!-- RAT Release Auditing Tool -->
@@ -73,13 +86,26 @@
             value="${rat.report.dir}/report.html"
             description="RAT-Report file"/>
   <property name="rat.version"
-            value="0.7"
+            value="0.11"
             description="Which Version of RAT to use"/>
 
+  <!-- Simian -->
+  <property name="simian.version"
+            value="2.4.0"
+            description="Which Version of Simian to use"/>
+  <property name="simian.uri"
+            value="http://www.harukizaemon.com/simian/simian-${simian.version}.tar.gz"
+            description="Where to get Simian"/>
+  <property name="simian.lib.dir"
+            value="${build.dir}/simian-lib"
+            description="Where to store Simian resources"/>
+  <property name="simian.report.dir"
+            value="${build.dir}/simian"
+            description="Where to store Simian reports"/>
 
 
   <target name="init-ivy">
-    <property name="ivy.version"  value="2.4.0-rc1"/>
+    <property name="ivy.version"  value="2.4.0"/>
     <property name="ivy.jar.url"  value="http://repo1.maven.org/maven2/org/apache/ivy/ivy/${ivy.version}/ivy-${ivy.version}.jar"/>
     <property name="ivy.jar.dir"  value="${build.dir}/ivy"/>
     <property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar"/>
@@ -92,21 +118,30 @@
   </target>
 
   <target name="checkstyle" description="--> checks Ant codebase according to ${config.dir}/checkstyle-config" depends="init-ivy">
-    <ivy:cachepath organisation="com.puppycrawl.tools" module="checkstyle" revision="5.7"
-                   inline="true" conf="default" pathid="checkstyle.classpath" transitive="true"/>
-    <taskdef resource="checkstyletask.properties" classpathref="checkstyle.classpath" />
-    <mkdir dir="${checkstyle.reportdir}"/>
-    <checkstyle config="${config.dir}/checkstyle-config" failOnViolation="false">
-      <formatter type="xml" toFile="${checkstyle.raw}"/>
-      <fileset dir="${java.dir}">
-        <include name="${tocheck}"/>
-        <exclude name="**/bzip2/*.java"/>
-        <exclude name="**/CVSPass.java"/>
-      </fileset>
-    </checkstyle>
+    <available property="antlr.present" classname="antlr.CommonAST"/>
+    <echo if:set="antlr.present">
+        Found antlr on the classpath.
+        Having a wrong antlr version on the same classpath as Checkstyle may produce errors like
+            'Can't find/access AST Node typecom.puppycrawl.tools.checkstyle.api.DetailAST'
+        Skip running Checkstyle.
+    </echo>
+    <sequential unless:set="antlr.present">
+      <ivy:cachepath organisation="com.puppycrawl.tools" module="checkstyle" revision="6.18"
+                     inline="true" conf="default" pathid="checkstyle.classpath" transitive="true"/>
+      <taskdef resource="com/puppycrawl/tools/checkstyle/ant/checkstyle-ant-task.properties" classpathref="checkstyle.classpath" />
+      <mkdir dir="${checkstyle.reportdir}"/>
+      <checkstyle config="${config.dir}/checkstyle-config" failOnViolation="false">
+        <formatter type="xml" toFile="${checkstyle.raw}"/>
+        <fileset dir="${java.dir}">
+          <include name="${tocheck}"/>
+          <exclude name="**/bzip2/*.java"/>
+          <exclude name="**/CVSPass.java"/>
+        </fileset>
+      </checkstyle>
+    </sequential>
   </target>
 
-  <target name="htmlreport" description="--> generates a html checkstyle report">
+  <target name="htmlreport" description="--> generates a html checkstyle report" unless="antlr.present">
     <xslt in="${checkstyle.raw}" style="${stylesheet.html}"
           out="${checkstyle.reportdir}/html/output.txt">
       <param name="basedir" expression="${checkstyle.basedir}"/>
@@ -119,7 +154,7 @@
     </xslt>
   </target>
 
-  <target name="textreport" description="--> generates a text checkstyle report">
+  <target name="textreport" description="--> generates a text checkstyle report" unless="antlr.present">
     <xslt in="${checkstyle.raw}" style="${stylesheet.text}"
           out="${checkstyle.reportdir}/report.txt">
     </xslt>
@@ -130,7 +165,7 @@
       <echo>${report}</echo>
   </target>
 
-  <target name="xdocreport" description="--> generates a xdoc checkstyle report">
+  <target name="xdocreport" description="--> generates a xdoc checkstyle report" unless="antlr.present">
     <xslt in="${checkstyle.raw}" style="${stylesheet.xdoc}"
            out="${checkstyle.reportdir}/xdocs/index.xml">
       <param name="basedir" expression="${checkstyle.basedir}"/>
@@ -145,11 +180,34 @@
   </target>
 
   <target name="simiancheck" description="--> runs the check for duplicates">
-    <simian>
+    <available property="simian.jar.present" file="${simian.lib.dir}/simian-${simian.version}.jar"/>
+    <sequential unless:set="simian.jar.present">
+      <mkdir dir="${simian.lib.dir}"/>
+      <get src="${simian.uri}" dest="${simian.lib.dir}"/>
+      <gunzip src="${simian.lib.dir}/simian-${simian.version}.tar.gz" dest="${simian.lib.dir}/simian-${simian.version}.tar"/>
+      <untar src="${simian.lib.dir}/simian-${simian.version}.tar" dest="${simian.lib.dir}">
+        <patternset>
+          <include name="**/simian*.jar"/>
+          <include name="**/simian*.xsl"/>
+        </patternset>
+        <flattenmapper/>
+      </untar>
+    </sequential>
+
+    <taskdef resource="simiantask.properties">
+      <classpath>
+        <fileset dir="${simian.lib.dir}" includes="*.jar"/>
+      </classpath>
+    </taskdef>
+    <mkdir dir="${simian.report.dir}"/>
+    <simian failureProperty="simian.duplicates.found">
         <fileset dir="${java.dir}" />
+        <formatter type="plain" toFile="${simian.report.dir}/simian-log.txt"/>
+        <formatter type="xml" toFile="${simian.report.dir}/simian-log.xml"/>
     </simian>
+    <xslt in="${simian.report.dir}/simian-log.xml" style="${simian.lib.dir}/simian.xsl" out="${simian.report.dir}/simian.html"/>
   </target>
-	
+
   <target name="fixTS" description="--> fix checkstyle errors 'Line has trailing spaces'">
     <fail message="Define path to java file 'path'">
       <condition><not><isset property="path"/></not></condition>
@@ -163,11 +221,11 @@
     <fail message="Define path to java file 'path'">
       <condition><not><isset property="path"/></not></condition>
     </fail>
-  	<fixcrlf srcdir="src/main" includes="${path}" javafiles="yes" tab="remove" tablength="4"/>
+    <fixcrlf srcdir="src/main" includes="${path}" javafiles="yes" tab="remove" tablength="4"/>
   </target>
 
   <target name="findbugs" description="--> checks Ant codebase with Findbugs" depends="init-ivy,build" xmlns:fb="http://findbugs.sourceforge.net/">
-    <ivy:cachepath organisation="com.google.code.findbugs" module="findbugs-ant" revision="1.3.9"
+    <ivy:cachepath organisation="com.google.code.findbugs" module="findbugs-ant" revision="3.0.0"
                    inline="true" conf="default" pathid="findbugs.real.classpath" transitive="true"/>
     <!-- Load the Findbugs AntTasks -->               
     <taskdef uri="http://findbugs.sourceforge.net/" resource="edu/umd/cs/findbugs/anttask/tasks.properties" classpathref="findbugs.real.classpath" />
diff --git a/docs.xml b/docs.xml
index f49e70f..1cb7806 100644
--- a/docs.xml
+++ b/docs.xml
@@ -17,9 +17,7 @@
 -->
 <project name="docs" default="txt2html">
 
-    <available property="jdk1.5+" classname="java.net.Proxy"/>
     <target name="txt2html">
-        <fail unless="jdk1.5+" message="Tomcat BuildUtils requires Java5+"/>
         <property name="build.dir" value="build"/>
         <tempfile property="temp.dir"/>
         <mkdir dir="${temp.dir}/org/apache/tomcat/buildutil"/>
diff --git a/manual/Tasks/apt.html b/manual/Tasks/apt.html
deleted file mode 100644
index 4bdd9a9..0000000
--- a/manual/Tasks/apt.html
+++ /dev/null
@@ -1,179 +0,0 @@
-<!--
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.
--->
-<html lang="en-us"><head>
-<meta http-equiv="Content-Language" content="en-us"><link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
-<title>Apt Task</title></head>
-
-<body>
-
-<h2><a name="Apt">Apt</a></h2>
-<h3>Description</h3>
-<p>Runs the annotation processor tool (apt), and then optionally compiles
-   the original code, and any generated source code.
-   <p>This task runs on Java 1.5 to Java 1.7.</p>
-   <p>Apt is deprecated in Java 1.6, which can run annotation
-   processors as part of javac, and removed from the distribution in Java 1.8.
-   The task will fire an exception when attempting to run under Java 1.8.</p>
-
-
-<p>This task inherits from the <a href="javac.html">Javac Task</a>, and thus
-   supports nearly all of the same attributes, and subelements.  
-   There is one special case, the <tt>fork</tt> attribute, which is present
-   but which can only be set to <tt>true</tt>. That is, apt only works as
-   a forked process.
- </p>
- <p>
-   In addition, it supports
-   the following addition items:</p>
-
-<h3>Parameters</h3>
-<table border="1" cellpadding="2" cellspacing="0">
-  <tbody><tr>
-    <td valign="top"><b>Attribute</b></td>
-    <td valign="top"><b>Description</b></td>
-    <td align="center" valign="top"><b>Required</b></td>
-  </tr>
-  <tr>
-    <td valign="top">compile</td>
-    <td valign="top">After running the Apt, should the code be compiled.  (see the
-                     <code>-nocompile</code> flag on the Apt executable)</td>
-    <td align="center" valign="top">No, defaults to false.</td>
-  </tr>
-  <tr>
-    <td valign="top">factory</td>
-    <td valign="top">The fully qualified classname of the AnnotationProcessFactory to be used
-                     to construct annotation processors.  This represents the <code>-factory</code>
-                     command line flag of the Apt executable.</td>
-    <td align="center" valign="top">No</td>
-  </tr>
-  <tr>
-    <td valign="top">factorypathref</td>
-    <td valign="top">The reference id of the path used to find the classes needed by the
-                     AnnotationProcessorFactory (and the location of the factory itself).
-                     This represents the <code>-factorypath</code> flag on the Apt executable.</td>
-    <td align="center" valign="top">No</td>
-  </tr>
-  <tr>
-    <td valign="top">preprocessdir</td>
-    <td valign="top">The directory used for preprocessing.  This is the directory where the
-                     generated source code will be place.  This represents the <code>-s</code> flag on
-                     the Apt executable.</td>
-    <td align="center" valign="top">No</td>
-  </tr>
-</tbody></table>
-
-<h3>Parameters specified as nested elements</h3>
-
-
-<h4>factorypath</h4>
-
-<p>You can specify the path used to find the classes needed by the AnnotationProcessorFactory
-   at runtime, using this element.  It is represents as a generic path like structure.  This
-   represents the <code>-factorypath</code> flag on the Apt executable.</p>
-
-
-<h4>option</h4>
-
-<p>Used to represent a generic option to pass to Apt.  This represents the <code>-A</code> flag on the
-   Apt executable.  You can specify zero or more <code>&lt;option&gt;</code> elements.</p>
-
-<table border="1" cellpadding="2" cellspacing="0">
-<tbody><tr>
-  <td valign="top" width="12%"><b>Attribute</b></td>
-  <td valign="top" width="78%"><b>Description</b></td>
-  <td valign="top" width="10%"><b>Required</b></td>
-</tr>
-  <tr>
-    <td valign="top">name</td>
-    <td align="center">The name of the option</td>
-    <td align="center">Yes.</td>
-  </tr>
-  <tr>
-    <td valign="top">value</td>
-    <td align="center">The value to set the option to</td>
-    <td align="center">Yes.</td>
-  </tr>
-</tbody></table>
-
-<h3>Examples</h3>
-<blockquote><pre>
-&lt;apt srcdir="${src}"
-     destdir="${build}"
-     classpath="xyz.jar"
-     debug="on"
-     compile="true"
-     factory="com.mycom.MyAnnotationProcessorFactory"
-     factorypathref="my.factorypath.id"
-     preprocessdir="${preprocess.dir}"&gt;
-&lt;/apt&gt;
-</pre></blockquote>
-<p>compiles all <code>.java</code> files under the <code>${src}</code>
-directory, and stores
-the <code>.class</code> files in the <code>${build}</code> directory.
-The classpath used includes <code>xyz.jar</code>, and compiling with
-debug information is on.  It also forces the generated source code to
-be compiled.  The generated source code will be placed in
-<code>${preprocess.dir}</code> directory, using the class
-<code>com.mycom.MyAnnotationProcessorFactory</code> to supply
-AnnotationProcessor instances.</p>
-
-
-<h3>Notes</h3>
-
-<p>
-The inherited "fork" attribute is set to true by default; please do not change it.
-</p>
-
-<p>
-The inherited "compiler" attribute is ignored, as it is forced to use the Apt compiler
-</p>
-
-<p>Using the Apt compiler with the "compile" option set to "true"
-   forces you to use Sun's Apt compiler, which will use the JDK's Javac compiler.
-   If you wish to use another compiler, you will first need run the Apt processor
-   with the "compile" flag set to "false", and then use a
-   <code>&lt;javac&gt;</code> task to compile first your original source code, and then the
-   generated source code:</p>
-
-<blockquote><pre>
-&lt;apt srcdir="${src}"
-     destdir="${build}"
-     classpath="xyz.jar"
-     debug="true"
-     compile="false"
-     factory="com.mycom.MyAnnotationProcessorFactory"
-     factorypathref="my.factorypath.id"
-     preprocessdir="${preprocess.dir}"&gt;
-&lt;/apt&gt;
-
-&lt;javac srcdir="${src}"
-       destdir="${build}"
-       classpath="xyz.jar"
-       debug="on"/&gt;
-
-&lt;javac srcdir="${preprocess.dir}"
-       destdir="${build}"
-       classpath="xyz.jar"
-       debug="true"/&gt;
-</pre></blockquote>
-
-This may involve more build file coding, but the speedup gained from switching
-to jikes may justify the effort.
-<p>
-</p>
-
-</body></html>
diff --git a/manual/Tasks/attrib.html b/manual/Tasks/attrib.html
index a26f0c5..ab09f65 100644
--- a/manual/Tasks/attrib.html
+++ b/manual/Tasks/attrib.html
@@ -57,6 +57,9 @@
   the Windows command, you can use the task's os attribute and set its
   value to your current os.</p>
 
+<p>See the <a href="setpermissions.html">setpermissions</a> task for a
+  platform independent alternative.</p>
+
 <h3>Parameters</h3>
 <table border="1" cellpadding="2" cellspacing="0">
   <tr>
diff --git a/manual/Tasks/chmod.html b/manual/Tasks/chmod.html
index 74e71d0..59ecc5a 100644
--- a/manual/Tasks/chmod.html
+++ b/manual/Tasks/chmod.html
@@ -63,6 +63,9 @@
   the Unix command, you can use the task's os attribute and set its
   value to your current os.</p>
 
+<p>See the <a href="setpermissions.html">setpermissions</a> task for a
+  platform independent alternative.</p>
+
 <h3>Parameters</h3>
 <table border="1" cellpadding="2" cellspacing="0">
   <tr>
diff --git a/manual/Tasks/junit.html b/manual/Tasks/junit.html
index 76df9ce..595f73f 100644
--- a/manual/Tasks/junit.html
+++ b/manual/Tasks/junit.html
@@ -371,6 +371,21 @@
 
 <p><em>since Ant 1.6.</em></p>
 
+<h4>modulepath</h4>
+
+<p>The location of modules can be specified using this <a href="../using.html#path">PATH like structure</a>.<br/>
+The modulepath requires <i>fork</i> to be set to <code>true</code>.
+
+<p><em>since Ant 1.10.0</em></p>
+
+<h4>upgrademodulepath</h4>
+
+<p>The location of modules that replace upgradeable modules in the runtime image
+can be specified using this <a href="../using.html#path">PATH like structure</a>.<br/>
+The upgrademodulepath requires <i>fork</i> to be set to <code>true</code>.
+
+<p><em>since Ant 1.10.0</em></p>
+
 <h4>formatter</h4>
 
 <p>The results of the tests can be printed in different
@@ -796,7 +811,47 @@
 The two nested formatters are for displaying (for the user) and for updating the collector
 class.
 </p>
-
-
+<pre>
+    &lt;junit fork="true"
+        jvm="${platform.java}"&gt;
+        &lt;jvmarg value="-Xpatch:${module.name}=${build.test.classes}"/&gt;
+        &lt;jvmarg line="-addmods ${module.name}"/&gt;
+        &lt;jvmarg value="-XaddReads:${module.name}=ALL-UNNAMED"/&gt;
+        &lt;jvmarg value="-XaddExports:${module.name}/my.test=ALL-UNNAMED"/&gt;
+        &lt;classpath&gt;
+            &lt;pathelement path="${libs.junit}"/&gt;
+        &lt;/classpath&gt;
+        &lt;modulepath&gt;
+            &lt;pathelement path="${modules}:${build.classes}"/&gt;
+        &lt;/modulepath&gt;
+        &lt;formatter type="plain"/&gt;
+        &lt;test name="my.test.TestCase"/&gt;
+    &lt;/junit&gt;
+</pre>
+<p>Runs my.test.TestCase as a white-box test in the forked VM given by the <code>platform.java</code> property.
+The junit library is a part of an unnamed module while the tested project and required modules are on the module path. The tests
+do not have module-info file and are executed in the project module given by <code>module.name</code> property.<br/>
+The <code>-Xpatch</code> java option executes the tests built into <code>${build.test.classes}</code> in a module given
+by <code>module.name</code> property.<br/>
+The <code>-addmods</code> java option enables the tested module.<br/>
+The <code>-XaddReads</code> java option makes the unnamed module containing the junit readable by tested module.<br/>
+The <code>-XaddExports</code> java option makes the non-exported test package <code>my.test</code> accessible from the unnamed module containing the junit.<br/>
+<pre>
+    &lt;junit fork="true"
+        jvm="${platform.java}"&gt;
+        &lt;jvmarg line="-addmods ${test.module.name}"/&gt;
+        &lt;jvmarg value="-XaddExports:${test.module.name}/my.test=junit,ALL-UNNAMED"/&gt;
+        &lt;modulepath&gt;
+            &lt;pathelement path="${modules}:${build.classes}:${libs.junit}"/&gt;
+        &lt;/modulepath&gt;
+        &lt;formatter type="plain"/&gt;
+        &lt;test name="my.test.TestCase"/&gt;
+    &lt;/junit&gt;
+</pre>
+<p>Runs my.test.TestCase as a black-box test in the forked VM given by the <code>platform.java</code> property.
+The junit library is used as an automatic module. The tests module-info requires the tested module and junit.<br/>
+The <code>-addmods</code> java option enables the test module.<br/>
+The <code>-XaddExports</code> java option makes the non-exported test package <code>my.test</code> accessible from the junit module and Ant's test runner.
+Another possibility is to export the test package in the tests module-info by <code>exports my.test</code> directive.<br/>
 </body>
 </html>
diff --git a/manual/Tasks/native2ascii.html b/manual/Tasks/native2ascii.html
index ecc065a..1017714 100644
--- a/manual/Tasks/native2ascii.html
+++ b/manual/Tasks/native2ascii.html
@@ -62,13 +62,12 @@
       <a name="implementationvalues">Here are the choices of the attribute</a>:</p>
     <ul>
       <li>default - the default converter for the platform - kaffee
-        when run on Kaffee, builtin if JDK9 or newer is detected, sun
-        otherwise.</li>
-      <li>sun (the standard converter of the JDK < 9)</li>
+        when run on Kaffee, builtin otherwise.</li>
+      <li>sun (used to be the standard converter of the JDK < 9)</li>
       <li>kaffe (the standard converter
         of <a href="http://www.kaffe.org" target="_top">Kaffe</a>)</li>
-      <li>builtin - Ant's internal implementation used for
-        JDK9+. <em>since ant 1.9.8</em></li>
+      <li>builtin - Ant's internal implementation. <em>since ant
+          1.9.8</em></li>
     </ul>
 
     <table border="1" cellpadding="2" cellspacing="0">
diff --git a/manual/Tasks/setpermissions.html b/manual/Tasks/setpermissions.html
new file mode 100644
index 0000000..22a6fb8
--- /dev/null
+++ b/manual/Tasks/setpermissions.html
@@ -0,0 +1,109 @@
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.
+-->
+<html>
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
+<title>SetPermissions Task</title>
+</head>
+
+<body>
+
+<h2><a name="setpermissions">SetPermissions</a></h2>
+<p><em>Since Ant 1.10.0.</em></p>
+<h3>Description</h3>
+<p>Changes the file permissions using Java's NIO support for
+  permissions.</p>
+<p>This task provides a subset of the platform specific abilities of
+  <a href="chmod.html">chmod</a> and <a href="attrib.html">attrib</a>
+  in a platform independent way.</p>
+<p>If no permissions are specified either via the mode or the
+  permissions attribute, then all permissions will be removed from the
+  nested resources.</p>
+<p>The task accepts aribitrary resources as part of the nested
+  resource collections, but not all resources support setting
+  permissions. This task won't do anything for resources that don't
+  support setting permissions - for example URLs.</p>
+<p>The permissions are applied to all resources contained within the
+  nested resources collections. You may want to ensure the collection
+  only returns files or directories if you want different sets of
+  permissions to apply to either type of resource.</p>
+
+<h3>Parameters</h3>
+<table border="1" cellpadding="2" cellspacing="0">
+  <tr>
+    <td valign="top"><b>Attribute</b></td>
+    <td valign="top"><b>Description</b></td>
+    <td align="center" valign="top"><b>Required</b></td>
+  </tr>
+  <tr>
+    <td valign="top">permissions</td>
+    <td valign="top">The permissions to set as comma separated list of
+    names
+    of <a href="http://docs.oracle.com/javase/8/docs/api/java/nio/file/attribute/PosixFilePermission.html">PosixFilePermission</a>
+    values.</td>
+    <td valign="top" align="center">No</td>
+  </tr>
+  <tr>
+    <td valign="top">mode</td>
+    <td valign="top">The permissions to set as tradional Unix
+      three-digit octal number.</td>
+    <td valign="top" align="center">No</td>
+  </tr>
+  <tr>
+    <td valign="top">nonPosixMode</td>
+    <td valign="top">What to do if changing the permissions of a file
+      is not possible because the file-system doesn't support POSIX
+      file permissions. Possible options are <code>fail</code> (fail
+      the build), <code>pass</code> (just log an
+      error), <code>tryDosOrFail</code> (at least try to set the
+      read-only flag on DOS file systems, fail if that isn't possible
+      either) and <code>tryDosOrPass</code> (at least try to set the
+      read-only flag on DOS file systems, just log an error if that
+      isn't possible either).</td>
+    <td valign="top" align="center">No, defaults to <code>fail</code></td>
+  </tr>
+  <tr>
+    <td valign="top">failonerror</td>
+    <td valign="top">Whether to stop the build if setting permissions
+      fails.</td>
+    <td valign="top" align="center">No, defaults to true</td>
+  </tr>
+</table>
+<h3>Parameters specified as nested elements</h3>
+
+<h4>any resource collection</h4>
+<p><a href="../Types/resources.html#collection">Resource
+Collection</a>s are used to select groups of resources.</p>
+<h3>Examples</h3>
+  <blockquote><pre>
+&lt;setpermissions mode=&quot;755&quot;&gt;
+  &lt;file file=&quot;${dist}/start.sh&quot;/&gt;
+&lt;/setpermissions&gt;
+  </pre></blockquote>
+<p>makes the &quot;start.sh&quot; file readable and executable for
+  anyone and in addition writable by the owner.</p>
+  <blockquote><pre>
+&lt;setpermissions permissions=&quot;OWNER_READ,OWNER_WRITE,OWNER_EXECUTE,OTHERS_READ,OTHERS_EXECUTE,GROUP_READ,GROUP_EXECUTE&quot;&gt;
+  &lt;file file=&quot;${dist}/start.sh&quot;/&gt;
+&lt;/setpermissions&gt;
+  </pre></blockquote>
+<p>makes the &quot;start.sh&quot; file readable and executable for
+  anyone and in addition writable by the owner.</p>
+</body>
+</html>
diff --git a/manual/Types/selectors.html b/manual/Types/selectors.html
index 560b416..153a252 100644
--- a/manual/Types/selectors.html
+++ b/manual/Types/selectors.html
@@ -92,6 +92,12 @@
         Select files if they are readable.</li>
       <li><a href="#writable"><code>&lt;writable&gt;</code></a> -
         Select files if they are writable.</li>
+      <li><a href="#executable"><code>&lt;executable&gt;</code></a> -
+        Select files if they are executable.</li>
+      <li><a href="#symlink"><code>&lt;symlink&gt;</code></a> -
+        Select files if they are symlink.</li>
+      <li><a href="#ownedBy"><code>&lt;ownedBy&gt;</code></a> -
+        Select files if they are owned by a given user.</li>
     </ul>
 
     <h4><a name="containsselect">Contains Selector</a></h4>
@@ -1017,6 +1023,49 @@
         but the Java VM cannot detect this state, this selector will
         still select the file.</p>
 
+      <h4><a name="executable">Executable Selector</a></h4>
+
+      <p>The <code>&lt;executable&gt;</code> selector selects only files
+        that are executable.  Ant only invokes
+        <code>java.nio.file.Files#isExecutable</code> so if a file is not executable
+        but the Java VM cannot detect this state, this selector will
+        still select the file.</p>
+
+      <p><em>Since Ant 1.10.0</em></p>
+
+      <h4><a name="symlink">Symlink Selector</a></h4>
+
+      <p>The <code>&lt;symlink&gt;</code> selector selects only files
+        that are symbolic links.  Ant only invokes
+        <code>java.nio.file.Files#isSymbolicLink</code> so if a file
+        is a symbolic link but the Java VM cannot detect this state,
+        this selector will not select the file.</p>
+
+      <p><em>Since Ant 1.10.0</em></p>
+
+      <h4><a name="ownedBy">OwnedBy Selector</a></h4>
+
+      <p>The <code>&lt;ownedBy&gt;</code> selector selects only files
+        that are owned by the given user.  Ant only invokes
+        <code>java.nio.file.Files#getOwner</code> so if a file system
+        doesn't support the operation this selector will not select
+        the file.</p>
+
+      <p><em>Since Ant 1.10.0</em></p>
+
+      <table border="1" cellpadding="2" cellspacing="0">
+        <tr>
+          <td valign="top"><b>Attribute</b></td>
+          <td valign="top"><b>Description</b></td>
+          <td align="center" valign="top"><b>Required</b></td>
+        </tr>
+        <tr>
+          <td valign="top">owner</td>
+          <td valign="top">Username of the expected owner</td>
+          <td valign="top" align="center">yes</td>
+        </tr>
+      </table>
+
       <h4><a name="scriptselector">Script Selector</a></h4>
 
       <p>
diff --git a/manual/cover.html b/manual/cover.html
index 92d83fe..59b8e43 100644
--- a/manual/cover.html
+++ b/manual/cover.html
@@ -19,14 +19,14 @@
 <head>
 <meta http-equiv="Content-Language" content="en-us">
 <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
-<title>Apache Ant 1.9.8 User Manual</title>
+<title>Apache Ant 1.10.0 User Manual</title>
 </head>
 
 <body bgcolor="#FFFFFF">
 <div align="center"> 
   <h1><img src="images/ant_logo_large.gif" width="190" height="120"></h1>
-  <h1>Apache Ant&trade; 1.9.8 Manual</h1>
-  <p align="left">This is the manual for version 1.9.8 of
+  <h1>Apache Ant&trade; 1.10.0 Manual</h1>
+  <p align="left">This is the manual for version 1.10.0 of
   <a target="_top" href="http://ant.apache.org/index.html">Apache Ant</a>. 
     If your version 
     of Ant (as verified with <tt>ant -version</tt>) is older or newer than this 
diff --git a/manual/credits.html b/manual/credits.html
index 55b508f..d895dfd 100644
--- a/manual/credits.html
+++ b/manual/credits.html
@@ -62,7 +62,7 @@
 </ul>
 
 <center>
-<p>Version: 1.9.8</p>
+<p>Version: 1.10.0</p>
 </center>
 
 
diff --git a/manual/tasklist.html b/manual/tasklist.html
index 6578e55..b57c851 100644
--- a/manual/tasklist.html
+++ b/manual/tasklist.html
@@ -40,7 +40,6 @@
 <li><a href="Tasks/antstructure.html">AntStructure</a></li>
 <li><a href="Tasks/antversion.html">AntVersion</a></li>
 <li><a href="Tasks/apply.html">Apply/<i>ExecOn</i></a></li>
-<li><a href="Tasks/apt.html">Apt</a></li>
 <li><a href="Tasks/attrib.html">Attrib</a></li>
 <li><a href="Tasks/augment.html">Augment</a></li>
 <li><a href="Tasks/available.html">Available</a></li>
@@ -148,6 +147,7 @@
 <li><a href="Tasks/rexec.html">RExec</a></li>
 <li><a href="Tasks/rmic.html">Rmic</a></li>
 <li><a href="Tasks/rpm.html">Rpm</a></li>
+<li><a href="Tasks/setpermissions.html">SetPermissions</a></li>
 <li><a href="Tasks/schemavalidate.html">SchemaValidate</a></li>
 <li><a href="Tasks/scp.html">Scp</a></li>
 <li><a href="Tasks/script.html">Script</a></li>
diff --git a/manual/tasksoverview.html b/manual/tasksoverview.html
index 99aa11b..d04fb4f 100644
--- a/manual/tasksoverview.html
+++ b/manual/tasksoverview.html
@@ -232,12 +232,6 @@
   </tr>
 
   <tr valign="top">
-    <td nowrap><a href="Tasks/apt.html">Apt</a></td>
-    <td><p>Runs the annotation processor tool (apt), and then optionally compiles
-   the original code, and any generated source code.</p></td>
-  </tr>
-
-  <tr valign="top">
     <td nowrap><a href="Tasks/jspc.html">JspC</a></td>
     <td><p>Runs the JSP compiler. It can be used to precompile JSP pages
      for fast initial invocation of JSP pages, deployment on a server without
@@ -582,6 +576,11 @@
   </tr>
 
   <tr valign="top">
+    <td nowrap><a href="Tasks/setpermissions.html">SetPermissions</a></td>
+    <td><p>Changes the permissions of a collection of resources.</p></td>
+  </tr>
+
+  <tr valign="top">
     <td nowrap><a href="Tasks/sync.html">Sync</a></td>
     <td><p>Synchronize two directory trees.</p></td>
   </tr>
diff --git a/release/ivy.xml b/release/ivy.xml
index 4ba758c..f8e13c1 100644
--- a/release/ivy.xml
+++ b/release/ivy.xml
@@ -20,7 +20,7 @@
             xsi:noNamespaceSchemaLocation=
 	    "http://ant.apache.org/ivy/schemas/ivy.xsd">
   <info organisation="org/apache"
-        module="ant" revision="1.9.8"/>
+        module="ant" revision="1.10.0"/>
   <publications xmlns:e="urn:ant.apache.org:ivy-extras">  
     <artifact name="ant-parent" type="pom" ext="pom"/>
     <artifact name="ant-parent" type="pom.asc" ext="pom.asc"/>
diff --git a/src/etc/poms/ant-antlr/pom.xml b/src/etc/poms/ant-antlr/pom.xml
index 06be8e5..186191c 100644
--- a/src/etc/poms/ant-antlr/pom.xml
+++ b/src/etc/poms/ant-antlr/pom.xml
@@ -27,13 +27,13 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-antlr</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant + ANTLR</name>
   <description>antlr specific task.
     The implementation forks a java process, therefore the antlr jar file is only needed at runtime</description>
@@ -41,7 +41,7 @@
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <optional>true</optional>
       <scope>compile</scope>
     </dependency>
diff --git a/src/etc/poms/ant-apache-bcel/pom.xml b/src/etc/poms/ant-apache-bcel/pom.xml
index e335083..610a387 100644
--- a/src/etc/poms/ant-apache-bcel/pom.xml
+++ b/src/etc/poms/ant-apache-bcel/pom.xml
@@ -27,19 +27,19 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-apache-bcel</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant + BCEL</name>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
diff --git a/src/etc/poms/ant-apache-bsf/pom.xml b/src/etc/poms/ant-apache-bsf/pom.xml
index d2d0471..b757de0 100644
--- a/src/etc/poms/ant-apache-bsf/pom.xml
+++ b/src/etc/poms/ant-apache-bsf/pom.xml
@@ -27,19 +27,19 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-apache-bsf</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant + BSF</name>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
diff --git a/src/etc/poms/ant-apache-log4j/pom.xml b/src/etc/poms/ant-apache-log4j/pom.xml
index a1edd89..4b48e2b 100644
--- a/src/etc/poms/ant-apache-log4j/pom.xml
+++ b/src/etc/poms/ant-apache-log4j/pom.xml
@@ -26,19 +26,19 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>  
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-apache-log4j</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant + Log4J</name>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
diff --git a/src/etc/poms/ant-apache-oro/pom.xml b/src/etc/poms/ant-apache-oro/pom.xml
index ddad252..30569e1 100644
--- a/src/etc/poms/ant-apache-oro/pom.xml
+++ b/src/etc/poms/ant-apache-oro/pom.xml
@@ -27,19 +27,19 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-apache-oro</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant + Apache Oro</name>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
diff --git a/src/etc/poms/ant-apache-regexp/pom.xml b/src/etc/poms/ant-apache-regexp/pom.xml
index fccc397..9fcafc8 100644
--- a/src/etc/poms/ant-apache-regexp/pom.xml
+++ b/src/etc/poms/ant-apache-regexp/pom.xml
@@ -26,19 +26,19 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-apache-regexp</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant + Apache Regexp</name>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
diff --git a/src/etc/poms/ant-apache-resolver/pom.xml b/src/etc/poms/ant-apache-resolver/pom.xml
index 36d87c5..03c017c 100644
--- a/src/etc/poms/ant-apache-resolver/pom.xml
+++ b/src/etc/poms/ant-apache-resolver/pom.xml
@@ -26,19 +26,19 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-apache-resolver</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant + Apache Resolver</name>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
diff --git a/src/etc/poms/ant-apache-xalan2/pom.xml b/src/etc/poms/ant-apache-xalan2/pom.xml
index dc8f9e8..3e49f1d 100644
--- a/src/etc/poms/ant-apache-xalan2/pom.xml
+++ b/src/etc/poms/ant-apache-xalan2/pom.xml
@@ -26,20 +26,20 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>  
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-apache-xalan2</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant + Xalan 2</name>
   <description>contains Xalan2-specific features</description>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
diff --git a/src/etc/poms/ant-commons-logging/pom.xml b/src/etc/poms/ant-commons-logging/pom.xml
index 9245dea..51ce038 100644
--- a/src/etc/poms/ant-commons-logging/pom.xml
+++ b/src/etc/poms/ant-commons-logging/pom.xml
@@ -26,20 +26,20 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-commons-logging</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant + Commons Logging</name>
   <description>Ant Listener based on commons-logging</description>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
diff --git a/src/etc/poms/ant-commons-net/pom.xml b/src/etc/poms/ant-commons-net/pom.xml
index fc7e945..8e08ec5 100644
--- a/src/etc/poms/ant-commons-net/pom.xml
+++ b/src/etc/poms/ant-commons-net/pom.xml
@@ -26,20 +26,20 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-commons-net</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant + Commons Net</name>
   <description>ftp, rexec and telnet tasks</description>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
diff --git a/src/etc/poms/ant-jai/pom.xml b/src/etc/poms/ant-jai/pom.xml
index e3c1595..7d3d9f3 100644
--- a/src/etc/poms/ant-jai/pom.xml
+++ b/src/etc/poms/ant-jai/pom.xml
@@ -27,13 +27,13 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-jai</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant + JAI</name>
   <description>image task and corresponding types.
   </description>
@@ -41,7 +41,7 @@
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
diff --git a/src/etc/poms/ant-javamail/pom.xml b/src/etc/poms/ant-javamail/pom.xml
index 08cfc90..ac36479 100644
--- a/src/etc/poms/ant-javamail/pom.xml
+++ b/src/etc/poms/ant-javamail/pom.xml
@@ -26,13 +26,13 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>  
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-javamail</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant + JavaMail</name>
   <description>implementation of the mail task based on javamail.
     Required to send emails to SMTP servers using user/password combinations
@@ -41,7 +41,7 @@
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
diff --git a/src/etc/poms/ant-jdepend/pom.xml b/src/etc/poms/ant-jdepend/pom.xml
index 719be49..2f35da3 100644
--- a/src/etc/poms/ant-jdepend/pom.xml
+++ b/src/etc/poms/ant-jdepend/pom.xml
@@ -27,13 +27,13 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>  
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-jdepend</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant + JDepend</name>
   <description>task jdepend invoking the jdepend parser. There is also a version 2.9.1 of the
     jdepend parser available on the maven repository</description>
@@ -41,7 +41,7 @@
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
diff --git a/src/etc/poms/ant-jmf/pom.xml b/src/etc/poms/ant-jmf/pom.xml
index c492a29..d040c22 100644
--- a/src/etc/poms/ant-jmf/pom.xml
+++ b/src/etc/poms/ant-jmf/pom.xml
@@ -26,13 +26,13 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>  
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-jmf</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant + JMF</name>
   <description>contains the sound task and a soundplayer listener
     download the dependency from http://java.sun.com/products/java-media/jmf/</description>
@@ -40,7 +40,7 @@
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
   </dependencies>
diff --git a/src/etc/poms/ant-jsch/pom.xml b/src/etc/poms/ant-jsch/pom.xml
index abee077..1273d87 100644
--- a/src/etc/poms/ant-jsch/pom.xml
+++ b/src/etc/poms/ant-jsch/pom.xml
@@ -26,13 +26,13 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>  
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-jsch</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant + JSch</name>
   <description>contains the sshexec and scp tasks
   </description>
@@ -40,7 +40,7 @@
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
diff --git a/src/etc/poms/ant-junit/pom.xml b/src/etc/poms/ant-junit/pom.xml
index eb2b270..7ba833e 100644
--- a/src/etc/poms/ant-junit/pom.xml
+++ b/src/etc/poms/ant-junit/pom.xml
@@ -26,20 +26,20 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>  
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-junit</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant + JUnit</name>
   <description>contains the junit and junirreport tasks</description>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
diff --git a/src/etc/poms/ant-junit4/pom.xml b/src/etc/poms/ant-junit4/pom.xml
index ba0b65d..7e66219 100644
--- a/src/etc/poms/ant-junit4/pom.xml
+++ b/src/etc/poms/ant-junit4/pom.xml
@@ -26,20 +26,20 @@
         <groupId>org.apache.ant</groupId>
         <artifactId>ant-parent</artifactId>
         <relativePath>../pom.xml</relativePath>
-        <version>1.9.8-SNAPSHOT</version>
+        <version>1.10.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <url>http://ant.apache.org/</url>
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-junit4</artifactId>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
     <name>Apache Ant + JUnit 4</name>
     <description>contains JUnit 4.x support</description>
     <dependencies>
         <dependency>
             <groupId>org.apache.ant</groupId>
             <artifactId>ant</artifactId>
-            <version>1.9.8-SNAPSHOT</version>
+            <version>1.10.0-SNAPSHOT</version>
             <scope>compile</scope>
         </dependency>
         <dependency>
diff --git a/src/etc/poms/ant-launcher/pom.xml b/src/etc/poms/ant-launcher/pom.xml
index 67df991..8f95569 100644
--- a/src/etc/poms/ant-launcher/pom.xml
+++ b/src/etc/poms/ant-launcher/pom.xml
@@ -27,13 +27,13 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-launcher</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant Launcher</name>
   <build>
     <plugins>
diff --git a/src/etc/poms/ant-netrexx/pom.xml b/src/etc/poms/ant-netrexx/pom.xml
index 3c8a924..502dbe3 100644
--- a/src/etc/poms/ant-netrexx/pom.xml
+++ b/src/etc/poms/ant-netrexx/pom.xml
@@ -26,13 +26,13 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>  
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-netrexx</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant + NetRexx</name>
   <description>NetRexxC task
     dependency can be downloaded from http://www.ibm.com/software/awdtools/netrexx/download.html</description>
@@ -40,7 +40,7 @@
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <!-- Processed too early, before maven-antrun-plugin gets a chance to work:
diff --git a/src/etc/poms/ant-swing/pom.xml b/src/etc/poms/ant-swing/pom.xml
index e7ea852..f41c055 100644
--- a/src/etc/poms/ant-swing/pom.xml
+++ b/src/etc/poms/ant-swing/pom.xml
@@ -27,20 +27,20 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>  
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-swing</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant + Swing</name>
   <description>a listener and a splash task based on Swing</description>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
   </dependencies>
diff --git a/src/etc/poms/ant-testutil/pom.xml b/src/etc/poms/ant-testutil/pom.xml
index 5fc918c..c362df2 100644
--- a/src/etc/poms/ant-testutil/pom.xml
+++ b/src/etc/poms/ant-testutil/pom.xml
@@ -27,20 +27,20 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>  
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-testutil</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant Test Utilities</name>
   <description>test utility classes</description>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
      <dependency>
diff --git a/src/etc/poms/ant/pom.xml b/src/etc/poms/ant/pom.xml
index 9900ae9..e6e4325 100644
--- a/src/etc/poms/ant/pom.xml
+++ b/src/etc/poms/ant/pom.xml
@@ -27,19 +27,19 @@
     <groupId>org.apache.ant</groupId>
     <artifactId>ant-parent</artifactId>
     <relativePath>../pom.xml</relativePath>
-    <version>1.9.8-SNAPSHOT</version>
+    <version>1.10.0-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <url>http://ant.apache.org/</url>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <name>Apache Ant Core</name>
   <dependencies>
     <dependency>
       <groupId>org.apache.ant</groupId>
       <artifactId>ant-launcher</artifactId>
-      <version>1.9.8-SNAPSHOT</version>
+      <version>1.10.0-SNAPSHOT</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
diff --git a/src/etc/poms/pom.xml b/src/etc/poms/pom.xml
index bc96b8d..c1964cf 100644
--- a/src/etc/poms/pom.xml
+++ b/src/etc/poms/pom.xml
@@ -25,7 +25,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>org.apache.ant</groupId>
   <artifactId>ant-parent</artifactId>
-  <version>1.9.8-SNAPSHOT</version>
+  <version>1.10.0-SNAPSHOT</version>
   <packaging>pom</packaging>
   <description>master POM</description>
   <licenses>
@@ -123,8 +123,8 @@
           <artifactId>maven-compiler-plugin</artifactId>
           <version>2.3.2</version>
           <configuration>
-            <source>1.5</source>
-            <target>1.5</target>
+            <source>1.8</source>
+            <target>1.8</target>
           </configuration>
         </plugin>
         <plugin>
diff --git a/src/etc/testcases/core/antclassloader.xml b/src/etc/testcases/core/antclassloader.xml
index cafc823..045428d 100644
--- a/src/etc/testcases/core/antclassloader.xml
+++ b/src/etc/testcases/core/antclassloader.xml
@@ -56,11 +56,7 @@
 package org.example;
 public class Foo {}
 ]]></echo>
-      <available property="jdk1.6+" classname="java.net.CookieStore"/>
-      <condition property="source" value="6">
-        <isset property="jdk1.6+"/>
-      </condition>
-      <property name="source" value="1.4"/>
+      <property name="source" value="8"/>
       <javac srcdir="${tmp.dir.nonascii}"
              destdir="${tmp.dir.nonascii}" source="${source}"/>
       <tempfile property="test.jar" destdir="${tmp.dir}" suffix="test" prefix=".jar" deleteonexit="true"/>
diff --git a/src/etc/testcases/taskdefs/conditions/antversion.xml b/src/etc/testcases/taskdefs/conditions/antversion.xml
index 33918e4..5dd97c7 100644
--- a/src/etc/testcases/taskdefs/conditions/antversion.xml
+++ b/src/etc/testcases/taskdefs/conditions/antversion.xml
@@ -32,11 +32,10 @@
                 <fail>
                         <condition>
                                 <not>
-                                        <antversion exactly="1.9.8" />
+                                        <antversion exactly="1.10.0" />
                                 </not>
                         </condition>
-                        Should be exactly 1.9.8
-
+                        Should be exactly 1.10.0
                 </fail>
         </target>
 
diff --git a/src/etc/testcases/taskdefs/optional/junit.xml b/src/etc/testcases/taskdefs/optional/junit.xml
index cc66e20..314ba87 100644
--- a/src/etc/testcases/taskdefs/optional/junit.xml
+++ b/src/etc/testcases/taskdefs/optional/junit.xml
@@ -339,11 +339,7 @@
       public void bad() {
       throw new RuntimeException("failed");}
       }</echo>
-    <available property="jdk1.6+" classname="java.net.CookieStore"/>
-    <condition property="source" value="6">
-      <isset property="jdk1.6+"/>
-    </condition>
-    <property name="source" value="5"/>
+    <property name="source" value="8"/>
     <javac srcdir="${tmp.dir}" destdir="${tmp.dir}" includes="T1.java,T2.java"
            source="${source}">
 
diff --git a/src/etc/testcases/taskdefs/rmic/rmic.xml b/src/etc/testcases/taskdefs/rmic/rmic.xml
index 4670f43..1ef900d 100644
--- a/src/etc/testcases/taskdefs/rmic/rmic.xml
+++ b/src/etc/testcases/taskdefs/rmic/rmic.xml
@@ -212,12 +212,6 @@
     </condition>
     <property name="rmic.compiler" value="sun"/>
     <available property="wlrmic.present" classname="weblogic.rmic"/>
-    <condition property="rmic6.present">
-      <and>
-        <isset property="rmic.present"/>
-        <available classname="java.util.ServiceLoader"/>
-      </and>
-    </condition>
   </target>
 
   <target name="testDefault" depends="init">
@@ -435,23 +429,6 @@
     <assertBaseCompiled/>
   </target>
 
-  <!--
-  This test stamps on the XML parser settings on java6, so it is disabled.
-  -->
-  <target name="testXnew" if="rmic.present" unless="rmic6.present" depends="init">
-    <base-rmic compiler="${rmic.compiler}">
-      <compilerarg value="-Xnew"/>
-    </base-rmic>
-    <assertBaseCompiled/>
-  </target>
-
-  <target name="testXnewDest" if="rmic.present" unless="rmic6.present" depends="init">
-    <dest-rmic compiler="${rmic.compiler}">
-      <compilerarg value="-Xnew"/>
-    </dest-rmic>
-    <assertBaseCompiledInDest/>
-  </target>
-
   <target name="testXnewForked" if="rmic.present" depends="init">
     <base-rmic compiler="forking">
       <compilerarg value="-Xnew"/>
diff --git a/src/etc/testcases/types/assertions.xml b/src/etc/testcases/types/assertions.xml
index dee7ce7..a849a0b 100644
--- a/src/etc/testcases/types/assertions.xml
+++ b/src/etc/testcases/types/assertions.xml
@@ -21,11 +21,7 @@
   <import file="../buildfiletest-base.xml"/>
 
   <target name="setUp">
-    <available property="jdk1.6+" classname="java.net.CookieStore"/>
-    <condition property="source" value="6">
-      <isset property="jdk1.6+"/>
-    </condition>
-    <property name="source" value="1.4"/>
+    <property name="source" value="8"/>
     <mkdir dir="${output}"/>
     <javac srcdir="${src.dir}"
            includes="*.java"
diff --git a/src/main/org/apache/tools/ant/AntClassLoader.java b/src/main/org/apache/tools/ant/AntClassLoader.java
index 96b92fc..44f7b2d 100644
--- a/src/main/org/apache/tools/ant/AntClassLoader.java
+++ b/src/main/org/apache/tools/ant/AntClassLoader.java
@@ -490,19 +490,13 @@
                 + pathComponent.lastModified() + "-" + pathComponent.length();
         String classpath = pathMap.get(absPathPlusTimeAndLength);
         if (classpath == null) {
-            JarFile jarFile = null;
-            try {
-                jarFile = new JarFile(pathComponent);
+            try (JarFile jarFile = new JarFile(pathComponent)) {
                 final Manifest manifest = jarFile.getManifest();
                 if (manifest == null) {
                     return;
                 }
                 classpath = manifest.getMainAttributes()
                     .getValue(Attributes.Name.CLASS_PATH);
-            } finally {
-                if (jarFile != null) {
-                    jarFile.close();
-                }
             }
             if (classpath == null) {
                 classpath = "";
@@ -1410,12 +1404,7 @@
      */
     public synchronized void cleanup() {
         for (final Enumeration<JarFile> e = jarFiles.elements(); e.hasMoreElements();) {
-            final JarFile jarFile = e.nextElement();
-            try {
-                jarFile.close();
-            } catch (final IOException ioe) {
-                // ignore
-            }
+            FileUtils.close(e.nextElement());
         }
         jarFiles = new Hashtable<File, JarFile>();
         if (project != null) {
@@ -1585,8 +1574,7 @@
     }
 
     private static boolean readFully(final File f, final byte[] b) throws IOException {
-        final FileInputStream fis = new FileInputStream(f);
-        try {
+        try (FileInputStream fis = new FileInputStream(f)) {
             final int len = b.length;
             int count = 0, x = 0;
             while (count != len) {
@@ -1597,8 +1585,6 @@
                 count += x;
             }
             return count == len;
-        } finally {
-            fis.close();
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/Diagnostics.java b/src/main/org/apache/tools/ant/Diagnostics.java
index 6389f6e..fe20764 100644
--- a/src/main/org/apache/tools/ant/Diagnostics.java
+++ b/src/main/org/apache/tools/ant/Diagnostics.java
@@ -42,6 +42,7 @@
 import org.apache.tools.ant.util.JAXPUtils;
 import org.apache.tools.ant.util.JavaEnvUtils;
 import org.apache.tools.ant.util.ProxySetup;
+import org.apache.tools.ant.util.java15.ProxyDiagnostics;
 import org.xml.sax.XMLReader;
 
 /**
@@ -691,25 +692,10 @@
         printProperty(out, ProxySetup.SOCKS_PROXY_USERNAME);
         printProperty(out, ProxySetup.SOCKS_PROXY_PASSWORD);
 
-        if (JavaEnvUtils.getJavaVersionNumber() < JAVA_1_5_NUMBER) {
-            return;
-        }
         printProperty(out, ProxySetup.USE_SYSTEM_PROXIES);
-        final String proxyDiagClassname = "org.apache.tools.ant.util.java15.ProxyDiagnostics";
-        try {
-            Class<?> proxyDiagClass = Class.forName(proxyDiagClassname);
-            Object instance = proxyDiagClass.newInstance();
-            out.println("Java1.5+ proxy settings:");
-            out.println(instance.toString());
-        } catch (ClassNotFoundException e) {
-            //not included, do nothing
-        } catch (IllegalAccessException e) {
-            //not included, do nothing
-        } catch (InstantiationException e) {
-            //not included, do nothing
-        } catch (NoClassDefFoundError e) {
-            // not included, to nothing
-        }
+        ProxyDiagnostics proxyDiag = new ProxyDiagnostics();
+        out.println("Java1.5+ proxy settings:");
+        out.println(proxyDiag.toString());
     }
 
 }
diff --git a/src/main/org/apache/tools/ant/Project.java b/src/main/org/apache/tools/ant/Project.java
index e916002..89dad39 100644
--- a/src/main/org/apache/tools/ant/Project.java
+++ b/src/main/org/apache/tools/ant/Project.java
@@ -930,8 +930,8 @@
         setPropertyInternal(MagicNames.ANT_JAVA_VERSION, javaVersion);
 
         // sanity check
-        if (!JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_1_5))  {
-            throw new BuildException("Ant cannot work on Java prior to 1.5");
+        if (!JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_1_8))  {
+            throw new BuildException("Ant cannot work on Java prior to 1.8");
         }
         log("Detected Java version: " + javaVersion + " in: "
             + System.getProperty("java.home"), MSG_VERBOSE);
diff --git a/src/main/org/apache/tools/ant/filters/Native2AsciiFilter.java b/src/main/org/apache/tools/ant/filters/Native2AsciiFilter.java
index 2e764ae..5631534 100644
--- a/src/main/org/apache/tools/ant/filters/Native2AsciiFilter.java
+++ b/src/main/org/apache/tools/ant/filters/Native2AsciiFilter.java
@@ -39,6 +39,7 @@
         this.reverse = reverse;
     }
 
+    @Override
     public String filter(String line) {
         return reverse
             ? Native2AsciiUtils.ascii2native(line)
diff --git a/src/main/org/apache/tools/ant/launch/Locator.java b/src/main/org/apache/tools/ant/launch/Locator.java
index 4640e70..2e8c37d 100644
--- a/src/main/org/apache/tools/ant/launch/Locator.java
+++ b/src/main/org/apache/tools/ant/launch/Locator.java
@@ -23,6 +23,7 @@
 import java.io.UnsupportedEncodingException;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.nio.charset.StandardCharsets;
 import java.text.CharacterIterator;
 import java.text.StringCharacterIterator;
 import java.util.Locale;
@@ -59,10 +60,6 @@
     private static final int SPACE = 0x20;
     private static final int DEL = 0x7F;
 
-    /**
-     * encoding used to represent URIs
-     */
-    public static final String URI_ENCODING = "UTF-8";
     // stolen from org.apache.xerces.impl.XMLEntityManager#getUserDir()
     // of the Xerces-J team
     // which ASCII characters need to be escaped
@@ -315,11 +312,11 @@
             } else if (c >= 0x0000 && c < 0x0080) {
                 sb.write(c);
             } else { // #50543
-                byte[] bytes = String.valueOf(c).getBytes(URI_ENCODING);
+                byte[] bytes = String.valueOf(c).getBytes(StandardCharsets.UTF_8);
                 sb.write(bytes, 0, bytes.length);
             }
         }
-        return sb.toString(URI_ENCODING);
+        return sb.toString(StandardCharsets.UTF_8.name());
     }
 
     /**
@@ -327,10 +324,9 @@
      * The URI is escaped
      * @param path String to encode.
      * @return The encoded string, according to URI norms
-     * @throws UnsupportedEncodingException if UTF-8 is not available
      * @since Ant 1.7
      */
-    public static String encodeURI(String path) throws UnsupportedEncodingException {
+    public static String encodeURI(String path) {
         int i = 0;
         int len = path.length();
         int ch = 0;
@@ -362,7 +358,7 @@
             // get UTF-8 bytes for the remaining sub-string
             byte[] bytes = null;
             byte b;
-            bytes = path.substring(i).getBytes(URI_ENCODING);
+            bytes = path.substring(i).getBytes(StandardCharsets.UTF_8);
             len = bytes.length;
 
             // for each byte
diff --git a/src/main/org/apache/tools/ant/taskdefs/Apt.java b/src/main/org/apache/tools/ant/taskdefs/Apt.java
deleted file mode 100644
index 52154a8..0000000
--- a/src/main/org/apache/tools/ant/taskdefs/Apt.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You 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.
- *
- */
-package org.apache.tools.ant.taskdefs;
-
-import java.io.File;
-import java.util.Vector;
-
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.Project;
-import org.apache.tools.ant.taskdefs.compilers.AptExternalCompilerAdapter;
-import org.apache.tools.ant.types.Path;
-import org.apache.tools.ant.types.Reference;
-import org.apache.tools.ant.util.JavaEnvUtils;
-
-/**
- * Apt Task for running the Annotation processing tool for JDK 1.5.  It derives
- * from the existing Javac task, and forces the compiler based on whether we're
- * executing internally, or externally.
- *
- * @since Ant 1.7
- */
-
-
-public class Apt
-        extends Javac {
-    private boolean compile = true;
-    private String factory;
-    private Path factoryPath;
-    private Vector<Option> options = new Vector<Option>();
-    private File preprocessDir;
-    /** The name of the apt tool. */
-    public static final String EXECUTABLE_NAME = "apt";
-    /** An warning message when ignoring compiler attribute. */
-    public static final String ERROR_IGNORING_COMPILER_OPTION
-        = "Ignoring compiler attribute for the APT task, as it is fixed";
-    /** A warning message if used with java &lt; 1.5. */
-    public static final String ERROR_WRONG_JAVA_VERSION
-        = "Apt task requires Java 1.5+";
-
-    /**
-     * exposed for debug messages
-     */
-    public static final String WARNING_IGNORING_FORK =
-        "Apt only runs in its own JVM; fork=false option ignored";
-
-    /**
-     * The nested option element.
-     */
-    public static final class Option {
-        private String name;
-        private String value;
-
-        /** Constructor for Option */
-        public Option() {
-            //default
-        }
-
-        /**
-         * Get the name attribute.
-         * @return the name attribute.
-         */
-        public String getName() {
-            return name;
-        }
-
-        /**
-         * Set the name attribute.
-         * @param name the name of the option.
-         */
-        public void setName(String name) {
-            this.name = name;
-        }
-
-        /**
-         * Get the value attribute.
-         * @return the value attribute.
-         */
-        public String getValue() {
-            return value;
-        }
-
-        /**
-         * Set the value attribute.
-         * @param value the value of the option.
-         */
-        public void setValue(String value) {
-            this.value = value;
-        }
-    }
-
-    /**
-     * Constructor for Apt task.
-     * This sets the apt compiler adapter as the compiler in the super class.
-     */
-    public Apt() {
-        super();
-        super.setCompiler(AptExternalCompilerAdapter.class.getName());
-        super.setFork(true);
-    }
-
-    /**
-     * Get the name of the apt executable.
-     *
-     * @return the name of the executable.
-     */
-    public String getAptExecutable() {
-        String exe = getExecutable();
-        return exe != null ? exe :
-            JavaEnvUtils.getJdkExecutable(EXECUTABLE_NAME);
-    }
-
-    /**
-     * Set the compiler.
-     * This is not allowed and a warning log message is made.
-     * @param compiler not used.
-     */
-    public void setCompiler(String compiler) {
-        log(ERROR_IGNORING_COMPILER_OPTION, Project.MSG_WARN);
-    }
-
-    /**
-     * Set the fork attribute.
-     * Non-forking APT is highly classpath dependent and appears to be too
-     * brittle to work. The sole reason this attribute is retained
-     * is the superclass does it
-     * @param fork if false; warn the option is ignored.
-     */
-    public void setFork(boolean fork) {
-        if (!fork) {
-            log(WARNING_IGNORING_FORK, Project.MSG_WARN);
-        }
-    }
-
-    /**
-     * Get the compiler class name.
-     * @return the compiler class name.
-     */
-    public String getCompiler() {
-        return super.getCompiler();
-    }
-
-    /**
-     * Get the compile option for the apt compiler.
-     * If this is false the "-nocompile" argument will be used.
-     * @return the value of the compile option.
-     */
-    public boolean isCompile() {
-        return compile;
-    }
-
-    /**
-     * Set the compile option for the apt compiler.
-     * Default value is true.
-     * @param compile if true set the compile option.
-     */
-    public void setCompile(boolean compile) {
-        this.compile = compile;
-    }
-
-    /**
-     * Get the factory option for the apt compiler.
-     * If this is non-null the "-factory" argument will be used.
-     * @return the value of the factory option.
-     */
-    public String getFactory() {
-        return factory;
-    }
-
-    /**
-     * Set the factory option for the apt compiler.
-     * Default value is null.
-     * @param factory the classname of the factory.
-     */
-    public void setFactory(String factory) {
-        this.factory = factory;
-    }
-
-    /**
-     * Add a reference to a path to the factoryPath attribute.
-     * @param ref a reference to a path.
-     */
-    public void setFactoryPathRef(Reference ref) {
-        createFactoryPath().setRefid(ref);
-    }
-
-    /**
-     * Add a path to the factoryPath attribute.
-     * @return a path to be configured.
-     */
-    public Path createFactoryPath() {
-        if (factoryPath == null) {
-            factoryPath = new Path(getProject());
-        }
-        return factoryPath.createPath();
-    }
-
-    /**
-     * Get the factory path attribute.
-     * If this is not null, the "-factorypath" argument will be used.
-     * The default value is null.
-     * @return the factory path attribute.
-     */
-    public Path getFactoryPath() {
-        return factoryPath;
-    }
-
-    /**
-     * Create a nested option.
-     * @return an option to be configured.
-     */
-    public Option createOption() {
-        Option opt = new Option();
-        options.add(opt);
-        return opt;
-    }
-
-    /**
-     * Get the options to the compiler.
-     * Each option will use '"-E" name ["=" value]' argument.
-     * @return the options.
-     */
-    public Vector<Option> getOptions() {
-        return options;
-    }
-
-    /**
-     * Get the preprocessdir attribute.
-     * This corresponds to the "-s" argument.
-     * The default value is null.
-     * @return the preprocessdir attribute.
-     */
-    public File getPreprocessDir() {
-        return preprocessDir;
-    }
-
-    /**
-     * Set the preprocessdir attribute.
-     * @param preprocessDir where to place processor generated source files.
-     */
-    public void setPreprocessDir(File preprocessDir) {
-        this.preprocessDir = preprocessDir;
-    }
-
-    /**
-     * Do the compilation.
-     * @throws BuildException on error.
-     */
-    public void execute()
-            throws BuildException {
-        if (JavaEnvUtils.getJavaVersionNumber() >= 18) {
-           throw new BuildException("apt does not exist under Java 1.8 and higher");
-        }
-        super.execute();
-    }
-}
diff --git a/src/main/org/apache/tools/ant/taskdefs/Jar.java b/src/main/org/apache/tools/ant/taskdefs/Jar.java
index a0337e1..5b20239 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Jar.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Jar.java
@@ -349,13 +349,7 @@
             }
             return null;
         } finally {
-            if (zf != null) {
-                try {
-                    zf.close();
-                } catch (IOException e) {
-                    // TODO - log an error?  throw an exception?
-                }
-            }
+            FileUtils.close(zf);
         }
     }
 
@@ -388,13 +382,7 @@
             }
             return false;
         } finally {
-            if (zf != null) {
-                try {
-                    zf.close();
-                } catch (IOException e) {
-                    // TODO - log an error?  throw an exception?
-                }
-            }
+            FileUtils.close(zf);
         }
     }
 
@@ -1143,9 +1131,7 @@
     protected static void grabFilesAndDirs(String file, List<String> dirs,
                                                  List<String> files)
         throws IOException {
-        org.apache.tools.zip.ZipFile zf = null;
-        try {
-            zf = new org.apache.tools.zip.ZipFile(file, "utf-8");
+        try (org.apache.tools.zip.ZipFile zf = new org.apache.tools.zip.ZipFile(file, "utf-8")) {
             Enumeration<org.apache.tools.zip.ZipEntry> entries = zf.getEntries();
             HashSet<String> dirSet = new HashSet<String>();
             while (entries.hasMoreElements()) {
@@ -1165,10 +1151,6 @@
                 }
             }
             dirs.addAll(dirSet);
-        } finally {
-            if (zf != null) {
-                zf.close();
-            }
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/Javac.java b/src/main/org/apache/tools/ant/taskdefs/Javac.java
index 892c0f1..1eef467 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Javac.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Javac.java
@@ -1422,8 +1422,7 @@
                 continue;
             }
             log("Creating empty " + pkgInfoClass);
-            final OutputStream os = new FileOutputStream(pkgInfoClass);
-            try {
+            try (OutputStream os = new FileOutputStream(pkgInfoClass)) {
                 os.write(PACKAGE_INFO_CLASS_HEADER);
                 final byte[] name = pkg.getBytes("UTF-8");
                 final int length = name.length + /* "/package-info" */ 13;
@@ -1431,8 +1430,6 @@
                 os.write((byte) length % 256);
                 os.write(name);
                 os.write(PACKAGE_INFO_CLASS_FOOTER);
-            } finally {
-                os.close();
             }
         }
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/LogStreamHandler.java b/src/main/org/apache/tools/ant/taskdefs/LogStreamHandler.java
index ed16cf3..bc69c06 100644
--- a/src/main/org/apache/tools/ant/taskdefs/LogStreamHandler.java
+++ b/src/main/org/apache/tools/ant/taskdefs/LogStreamHandler.java
@@ -23,6 +23,7 @@
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.ProjectComponent;
 import org.apache.tools.ant.Task;
+import org.apache.tools.ant.util.FileUtils;
 
 /**
  * Logs standard output and error of a subprocess to the log system of ant.
@@ -59,12 +60,7 @@
      */
     public void stop() {
         super.stop();
-        try {
-            getErr().close();
-            getOut().close();
-        } catch (IOException e) {
-            // plain impossible
-            throw new BuildException(e);
-        }
+        FileUtils.close(getErr());
+        FileUtils.close(getOut());
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/ManifestClassPath.java b/src/main/org/apache/tools/ant/taskdefs/ManifestClassPath.java
index 4a4f231..f605bd5 100644
--- a/src/main/org/apache/tools/ant/taskdefs/ManifestClassPath.java
+++ b/src/main/org/apache/tools/ant/taskdefs/ManifestClassPath.java
@@ -115,11 +115,8 @@
             if (pathEntry.isDirectory() && !relPath.endsWith("/")) {
                 relPath = relPath + '/';
             }
-            try {
-                relPath = Locator.encodeURI(relPath);
-            } catch (UnsupportedEncodingException exc) {
-                throw new BuildException(exc);
-            }
+            relPath = Locator.encodeURI(relPath);
+
             // Manifest's ClassPath: attribute always uses forward
             // slashes '/', and is space-separated. Ant will properly
             // format it on 72 columns with proper line continuation
diff --git a/src/main/org/apache/tools/ant/taskdefs/Pack.java b/src/main/org/apache/tools/ant/taskdefs/Pack.java
index daabd6b..59a998f 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Pack.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Pack.java
@@ -177,11 +177,8 @@
      */
     protected void zipResource(Resource resource, OutputStream zOut)
         throws IOException {
-        InputStream rIn = resource.getInputStream();
-        try {
+        try (InputStream rIn = resource.getInputStream()) {
             zipFile(rIn, zOut);
-        } finally {
-            rIn.close();
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/Property.java b/src/main/org/apache/tools/ant/taskdefs/Property.java
index ccfb356..db2d9d4 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Property.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Property.java
@@ -533,13 +533,8 @@
         Properties props = new Properties();
         log("Loading " + url, Project.MSG_VERBOSE);
         try {
-            InputStream is = url.openStream();
-            try {
+            try (InputStream is = url.openStream()) {
                 loadProperties(props, is, url.getFile().endsWith(".xml"));
-            } finally {
-                if (is != null) {
-                    is.close();
-                }
             }
             addProperties(props);
         } catch (IOException ex) {
diff --git a/src/main/org/apache/tools/ant/taskdefs/Replace.java b/src/main/org/apache/tools/ant/taskdefs/Replace.java
index 4b68198..1b6cb37 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Replace.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Replace.java
@@ -354,7 +354,7 @@
      * a StringBuffer. Compatible with the Replacefilter.
      * @since 1.7
      */
-    private class FileInput /* JDK 5: implements Closeable */ {
+    private class FileInput implements AutoCloseable {
         private StringBuffer outputBuffer;
         private final InputStream is;
         private Reader reader;
@@ -418,7 +418,7 @@
      * Replacefilter.
      * @since 1.7
      */
-    private class FileOutput /* JDK 5: implements Closeable */ {
+    private class FileOutput implements AutoCloseable {
         private StringBuffer inputBuffer;
         private final OutputStream os;
         private Writer writer;
@@ -667,26 +667,19 @@
             File temp = FILE_UTILS.createTempFile("rep", ".tmp",
                     src.getParentFile(), false, true);
             try {
-                FileInput in = new FileInput(src);
-                try {
-                    FileOutput out = new FileOutput(temp);
-                    try {
-                        out.setInputBuffer(buildFilterChain(in.getOutputBuffer()));
+                try (FileInput in = new FileInput(src);
+                     FileOutput out = new FileOutput(temp)) {
+                    out.setInputBuffer(buildFilterChain(in.getOutputBuffer()));
 
-                        while (in.readChunk()) {
-                            if (processFilterChain()) {
-                                out.process();
-                            }
+                    while (in.readChunk()) {
+                        if (processFilterChain()) {
+                            out.process();
                         }
-
-                        flushFilterChain();
-
-                        out.flush();
-                    } finally {
-                        out.close();
                     }
-                } finally {
-                    in.close();
+
+                    flushFilterChain();
+
+                    out.flush();
                 }
                 boolean changes = (replaceCount != repCountStart);
                 if (changes) {
diff --git a/src/main/org/apache/tools/ant/taskdefs/SQLExec.java b/src/main/org/apache/tools/ant/taskdefs/SQLExec.java
index 6d1e514..c4076bc 100644
--- a/src/main/org/apache/tools/ant/taskdefs/SQLExec.java
+++ b/src/main/org/apache/tools/ant/taskdefs/SQLExec.java
@@ -692,19 +692,11 @@
                 }
             } finally {
                 try {
-                    if (getStatement() != null) {
-                        getStatement().close();
-                    }
+                    FileUtils.close(getStatement());
                 } catch (SQLException ex) {
                     // ignore
                 }
-                try {
-                    if (getConnection() != null) {
-                        getConnection().close();
-                    }
-                } catch (SQLException ex) {
-                    // ignore
-                }
+                FileUtils.close(getConnection());
             }
 
             log(goodSql + " of " + totalSql + " SQL statements executed successfully");
@@ -834,13 +826,7 @@
                 throw e;
             }
         } finally {
-            if (resultSet != null) {
-                try {
-                    resultSet.close();
-                } catch (SQLException e) {
-                    //ignore
-                }
-            }
+            FileUtils.close(resultSet);
         }
     }
 
@@ -854,13 +840,8 @@
      */
     @Deprecated
     protected void printResults(PrintStream out) throws SQLException {
-        ResultSet rs = getStatement().getResultSet();
-        try {
+        try (ResultSet rs = getStatement().getResultSet()) {
             printResults(rs, out);
-        } finally {
-            if (rs != null) {
-                rs.close();
-            }
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/SetPermissions.java b/src/main/org/apache/tools/ant/taskdefs/SetPermissions.java
new file mode 100644
index 0000000..7518077
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/SetPermissions.java
@@ -0,0 +1,231 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.
+ *
+ */
+
+package org.apache.tools.ant.taskdefs;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.DosFileAttributeView;
+import java.nio.file.attribute.PosixFilePermission;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.Set;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Resource;
+import org.apache.tools.ant.types.ResourceCollection;
+import org.apache.tools.ant.types.resources.Resources;
+import org.apache.tools.ant.util.PermissionUtils;
+import org.apache.tools.ant.util.StringUtils;
+
+/**
+ * Sets {@link PosixFilePermission}s for resources.
+ *
+ * <p>This task provides a subset of {@link Chmod}'s and {@link
+ * org.apache.tools.ant.taskdefs.optional.windows.Attrib}'s abilities
+ * in less platform dependent way.</p>
+ *
+ * <p>It requires a file system that supports PosixFilePermissions for
+ * its full potential. It can optionally fall back to
+ * DosFilePermissions (only changing the readonly state) on file
+ * systems that don't support POSIX permissions. See {@link
+ * SetPermissions.NonPosixMode}</p>
+ *
+ * @since Ant 1.10.0
+ */
+public class SetPermissions extends Task {
+    private final Set<PosixFilePermission> permissions =
+        EnumSet.noneOf(PosixFilePermission.class);
+    private Resources resources = null;
+    private boolean failonerror = true;
+    private NonPosixMode nonPosixMode = NonPosixMode.fail;
+
+    /**
+     * Options for dealing with file systems that don't support POSIX
+     * permissions.
+     */
+    public enum NonPosixMode {
+        /** Fail the build. */
+        fail,
+        /** Log an error and go on. */
+        pass,
+        /**
+         * Try DosFilePermissions - setting the read-only flag - and
+         * fail the build if that fails as well.
+         */
+        tryDosOrFail,
+        /**
+         * Try DosFilePermissions - setting the read-only flag - and
+         * log an error and go on if that fails as well.
+         */
+        tryDosOrPass;
+    }
+
+    /**
+     * Adds permissions as a comma separated list.
+     * @param perms comma separated list of names of {@link PosixFilePermission}s.
+     */
+    public void setPermissions(String perms) {
+        if (perms != null) {
+            Arrays.stream(perms.split(","))
+                .map(String::trim)
+                .filter(s -> !s.isEmpty())
+                .map(s -> Enum.valueOf(PosixFilePermission.class, s))
+                .forEach(permissions::add);
+        }
+    }
+
+    /**
+     * A 3 digit octal string, specify the user, group and
+     * other modes in the standard Unix fashion;
+     * @param octalString a <code>String</code> value
+     */
+    public void setMode(String octalString) {
+        int mode = Integer.parseInt(octalString, 8);
+        permissions.addAll(PermissionUtils.permissionsFromMode(mode));
+    }
+
+    /**
+     * Set whether to fail when errors are encountered. If false, note errors
+     * to the output but keep going. Default is true.
+     * <p>Only applies to IO and SecurityExceptions, see {@link
+     * #setNonPosixMode} for ways to deal with file-systems that don't
+     * support PosixPermissions.</p>
+     * @param failonerror true or false.
+     */
+    public void setFailOnError(final boolean failonerror) {
+        this.failonerror = failonerror;
+    }
+
+    /**
+     * Set what to do if changing the permissions of a file is not
+     * possible because the file-system doesn't support POSIX file
+     * permissions.
+     * <p>The default is {@link NonPosixMode#fail}.</p>
+     * @param m what to do if changing the permissions of a file is not possible
+     */
+    public void setNonPosixMode(NonPosixMode m) {
+        this.nonPosixMode = m;
+    }
+
+    /**
+     * Adds a collection of resources to set permissions on.
+     * @param rc a resource collection
+     */
+    public void add(ResourceCollection rc) {
+        if (resources == null) {
+            resources = new Resources();
+        }
+        resources.add(rc);
+    }
+
+    public void execute() {
+        if (resources == null) {
+            throw new BuildException("At least one resource-collection is required");
+        }
+        Resource currentResource = null;
+        try {
+            for (Resource r : resources) {
+                currentResource = r;
+                try {
+                    PermissionUtils.setPermissions(r, permissions, this::posixPermissionsNotSupported);
+                } catch (IOException ioe) {
+                    maybeThrowException(ioe, "Failed to set permissions on '%s' due to %s", r, ioe.getMessage());
+                }
+            }
+        } catch (ClassCastException cce) {
+            maybeThrowException(null, 
+                "some specified permissions are not of type PosixFilePermission: %s", 
+                StringUtils.join(permissions, ", "));
+        } catch (SecurityException se) {
+            maybeThrowException(null, 
+                "the SecurityManager denies role accessUserInformation or write access for SecurityManager.checkWrite for resource '%s'",
+                currentResource);
+        } catch (BuildException be) {
+            // maybe thrown by callback method this::posixPermissionsNotSupported.
+            maybeThrowException(be, be.getMessage());
+        }
+    }
+
+    private void maybeThrowException(Exception exc, String msgFormat, Object... msgArgs) {
+        String msg = String.format(msgFormat, msgArgs);
+        if (failonerror) {
+            if (exc instanceof BuildException) {
+                throw (BuildException)exc;
+            } else {
+                throw new BuildException(msg, exc);
+            }              
+        } else {
+            log("Warning: " + msg, Project.MSG_ERR);
+        }
+    }
+
+    private void posixPermissionsNotSupported(Path p) {
+        String msg = String.format("the associated path '%s' does"
+                                   + " not support the PosixFileAttributeView", p);
+        switch (nonPosixMode) {
+        case fail:
+            throw new BuildException(msg);
+        case pass:
+            log("Warning: " + msg, Project.MSG_ERR);
+            break;
+        case tryDosOrFail:
+            tryDos(p, true);
+            break;
+        case tryDosOrPass:
+            tryDos(p, false);
+            break;
+        }
+    }
+
+    private void tryDos(Path p, boolean failIfDosIsNotSupported) {
+        log("Falling back to DosFileAttributeView");
+        boolean readOnly = !isWritable();
+        DosFileAttributeView view = Files.getFileAttributeView(p, DosFileAttributeView.class);
+        if (view != null) {
+            try {
+                view.setReadOnly(readOnly);
+            } catch (IOException ioe) {
+                maybeThrowException(ioe, "Failed to set permissions on '%s' due to %s",
+                                    p, ioe.getMessage());
+            } catch (SecurityException uoe) {
+                maybeThrowException(null, "the SecurityManager denies role "
+                                    + "accessUserInformation or write access for "
+                                    + "SecurityManager.checkWrite for resource '%s'",
+                                    p);
+            }
+        } else {
+            String msg = String.format("the associated path '%s' does"
+                                       + " not support the DosFileAttributeView", p);
+            if (failIfDosIsNotSupported) {
+                throw new BuildException(msg);
+            } else {
+                log("Warning: " + msg, Project.MSG_ERR);
+            }
+        }
+    }
+
+    private boolean isWritable() {
+        return permissions.contains(PosixFilePermission.OWNER_WRITE)
+            || permissions.contains(PosixFilePermission.GROUP_WRITE)
+            || permissions.contains(PosixFilePermission.OTHERS_WRITE);
+    }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/WhichResource.java b/src/main/org/apache/tools/ant/taskdefs/WhichResource.java
index 3f315a8..d19918a 100644
--- a/src/main/org/apache/tools/ant/taskdefs/WhichResource.java
+++ b/src/main/org/apache/tools/ant/taskdefs/WhichResource.java
@@ -135,11 +135,10 @@
             getProject().log("using system classpath: " + classpath,
                              Project.MSG_DEBUG);
         }
-        AntClassLoader loader = null;
-        try {
-            loader = AntClassLoader.newAntClassLoader(getProject().getCoreLoader(),
-                                                      getProject(),
-                                                      classpath, false);
+        try (AntClassLoader loader =
+             AntClassLoader.newAntClassLoader(getProject().getCoreLoader(),
+                                              getProject(),
+                                              classpath, false)) {
             String loc = null;
             if (classname != null) {
                 //convert a class name into a resource
@@ -162,10 +161,6 @@
                 loc = url.toExternalForm();
                 getProject().setNewProperty(property, loc);
             }
-        } finally {
-            if (loader != null) {
-                loader.cleanup();
-            }
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/Zip.java b/src/main/org/apache/tools/ant/taskdefs/Zip.java
index 5d68b2f..580176f 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Zip.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Zip.java
@@ -1915,14 +1915,11 @@
                                      getLocation());
         }
 
-        final FileInputStream fIn = new FileInputStream(file);
-        try {
+        try (FileInputStream fIn = new FileInputStream(file)) {
             // ZIPs store time with a granularity of 2 seconds, round up
             zipFile(fIn, zOut, vPath,
                     file.lastModified() + (roundUp ? ROUNDUP_MILLIS : 0),
                     null, mode);
-        } finally {
-            fIn.close();
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/AptCompilerAdapter.java b/src/main/org/apache/tools/ant/taskdefs/compilers/AptCompilerAdapter.java
deleted file mode 100644
index 9503ac0..0000000
--- a/src/main/org/apache/tools/ant/taskdefs/compilers/AptCompilerAdapter.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You 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.
- *
- */
-
-package org.apache.tools.ant.taskdefs.compilers;
-
-import java.io.File;
-import java.lang.reflect.Method;
-import java.util.Enumeration;
-import java.util.Vector;
-
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.Project;
-import org.apache.tools.ant.taskdefs.Apt;
-import org.apache.tools.ant.types.Commandline;
-import org.apache.tools.ant.types.Path;
-
-
-/**
- * <p>The implementation of the apt compiler for JDK 1.5.</p>
- *
- * <p>As usual, the low level entry points for Java tools are neither documented or
- * stable; this entry point may change from that of 1.5.0_01-b08 without any
- * warning at all. The IDE decompile of the tool entry points is as follows:</p>
- * <pre>
- * public class Main {
- * public Main() ;
- *
- * public static transient void main(String... strings);
- *
- * public static transient int process(String... strings);
- *
- * public static transient int process(PrintWriter printWriter,
- *      String... strings);
- * public static transient int process(
- *      AnnotationProcessorFactory annotationProcessorFactory,
- *      String... strings);
- *
- * public static transient int process(
- *      AnnotationProcessorFactory annotationProcessorFactory,
- *      PrintWriter printWriter,
- *      String... strings);
- * private static transient int processing(
- *      AnnotationProcessorFactory annotationProcessorFactory,
- *      PrintWriter printWriter,
- *      String... strings) ;
- * }
- * </pre>
- *
- * This Adapter is designed to run Apt in-JVM, an option that is not actually
- * exposed to end-users, because it was too brittle during beta testing; classpath
- * problems being the core issue.
- *
- * @since Ant 1.7
- */
-public class AptCompilerAdapter extends DefaultCompilerAdapter {
-
-    /**
-     * Integer returned by the Apt compiler to indicate success.
-     */
-    private static final int APT_COMPILER_SUCCESS = 0;
-    /**
-     * class in tools.jar that implements APT
-     */
-    public static final String APT_ENTRY_POINT = "com.sun.tools.apt.Main";
-
-    /**
-     * method used to compile.
-     */
-    public static final String APT_METHOD_NAME = "process";
-
-    /**
-     * Get the facade task that fronts this adapter
-     *
-     * @return task instance
-     * @see DefaultCompilerAdapter#getJavac()
-     */
-    protected Apt getApt() {
-        return (Apt) getJavac();
-    }
-
-    /**
-     * Using the front end arguments, set up the command line to run Apt
-     *
-     * @param apt task
-     * @param cmd command that is set up with the various switches from the task
-     *            options
-     */
-    static void setAptCommandlineSwitches(final Apt apt, final Commandline cmd) {
-
-        if (!apt.isCompile()) {
-            cmd.createArgument().setValue("-nocompile");
-        }
-
-        // Process the factory class
-        final String factory = apt.getFactory();
-        if (factory != null) {
-            cmd.createArgument().setValue("-factory");
-            cmd.createArgument().setValue(factory);
-        }
-
-        // Process the factory path
-        final Path factoryPath = apt.getFactoryPath();
-        if (factoryPath != null) {
-            cmd.createArgument().setValue("-factorypath");
-            cmd.createArgument().setPath(factoryPath);
-        }
-
-        final File preprocessDir = apt.getPreprocessDir();
-        if (preprocessDir != null) {
-            cmd.createArgument().setValue("-s");
-            cmd.createArgument().setFile(preprocessDir);
-        }
-
-        // Process the processor options
-        final Vector options = apt.getOptions();
-        final Enumeration elements = options.elements();
-        Apt.Option opt;
-        StringBuffer arg = null;
-        while (elements.hasMoreElements()) {
-            opt = (Apt.Option) elements.nextElement();
-            arg = new StringBuffer();
-            arg.append("-A").append(opt.getName());
-            if (opt.getValue() != null) {
-                arg.append("=").append(opt.getValue());
-            }
-            cmd.createArgument().setValue(arg.toString());
-        }
-    }
-
-    /**
-     * using our front end task, set up the command line switches
-     *
-     * @param cmd command line to set up
-     */
-    protected void setAptCommandlineSwitches(final Commandline cmd) {
-        final Apt apt = getApt();
-        setAptCommandlineSwitches(apt, cmd);
-    }
-
-    /**
-     * Run the compilation.
-     * @return true on success.
-     * @throws BuildException if the compilation has problems.
-     */
-    public boolean execute() throws BuildException {
-        attributes.log("Using apt compiler", Project.MSG_VERBOSE);
-        //set up the javac options
-        final Commandline cmd = setupModernJavacCommand();
-        //then add the Apt options
-        setAptCommandlineSwitches(cmd);
-
-        //finally invoke APT
-        // Use reflection to be able to build on all JDKs:
-        try {
-            final Class c = Class.forName(APT_ENTRY_POINT);
-            final Object compiler = c.newInstance();
-            final Method compile = c.getMethod(APT_METHOD_NAME,
-                    new Class[]{(new String[]{}).getClass()});
-            final int result = ((Integer) compile.invoke
-                    (compiler, new Object[]{cmd.getArguments()}))
-                    .intValue();
-            return (result == APT_COMPILER_SUCCESS);
-        } catch (final BuildException be) {
-            //rethrow build exceptions
-            throw be;
-        } catch (final Exception ex) {
-            //cast everything else to a build exception
-            throw new BuildException("Error starting apt compiler",
-                    ex, location);
-        }
-    }
-}
diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/AptExternalCompilerAdapter.java b/src/main/org/apache/tools/ant/taskdefs/compilers/AptExternalCompilerAdapter.java
deleted file mode 100644
index dadb55b..0000000
--- a/src/main/org/apache/tools/ant/taskdefs/compilers/AptExternalCompilerAdapter.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You 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.
- *
- */
-
-package org.apache.tools.ant.taskdefs.compilers;
-
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.Project;
-import org.apache.tools.ant.taskdefs.Apt;
-import org.apache.tools.ant.types.Commandline;
-
-/**
- * The implementation of the apt compiler for JDK 1.5 using an external process
- *
- * @since Ant 1.7
- */
-public class AptExternalCompilerAdapter extends DefaultCompilerAdapter {
-
-
-    /**
-     * Get the facade task that fronts this adapter
-     *
-     * @return task instance
-     * @see DefaultCompilerAdapter#getJavac()
-     */
-    protected Apt getApt() {
-        return (Apt) getJavac();
-    }
-
-    /**
-     * Performs a compile using the Javac externally.
-     * @return true  the compilation was successful.
-     * @throws BuildException if there is a problem.
-     */
-    public boolean execute() throws BuildException {
-        attributes.log("Using external apt compiler", Project.MSG_VERBOSE);
-
-
-        // Setup the apt executable
-        Apt apt = getApt();
-        Commandline cmd = new Commandline();
-        cmd.setExecutable(apt.getAptExecutable());
-        setupModernJavacCommandlineSwitches(cmd);
-        AptCompilerAdapter.setAptCommandlineSwitches(apt, cmd);
-        int firstFileName = cmd.size();
-        //add the files
-        logAndAddFilesToCompile(cmd);
-
-        //run
-        return 0 == executeExternalCompile(cmd.getCommandline(),
-                firstFileName,
-                true);
-
-    }
-
-}
-
diff --git a/src/main/org/apache/tools/ant/taskdefs/condition/Socket.java b/src/main/org/apache/tools/ant/taskdefs/condition/Socket.java
index d6a69ec..43a40e0 100644
--- a/src/main/org/apache/tools/ant/taskdefs/condition/Socket.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/Socket.java
@@ -23,6 +23,7 @@
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.ProjectComponent;
+import org.apache.tools.ant.util.FileUtils;
 
 /**
  * Condition to wait for a TCP/IP socket to have a listener. Its attributes are:
@@ -73,13 +74,7 @@
         } catch (IOException e) {
             return false;
         } finally {
-          if (s != null) {
-            try {
-              s.close();
-            } catch (IOException ioe) {
-              // Intentionally left blank
-            }
-          }
+            FileUtils.close(s);
         }
         return true;
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/RedirectingStreamHandler.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/RedirectingStreamHandler.java
index 713de0c..e9b755d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/cvslib/RedirectingStreamHandler.java
+++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/RedirectingStreamHandler.java
@@ -22,6 +22,7 @@
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.taskdefs.PumpStreamHandler;
+import org.apache.tools.ant.util.FileUtils;
 
 /**
  * A dummy stream handler that just passes stuff to the parser.
@@ -49,13 +50,8 @@
 
     public void stop() {
         super.stop();
-        try {
-            getErr().close();
-            getOut().close();
-        } catch (final IOException e) {
-            // plain impossible
-            throw new BuildException(e);
-        }
+        FileUtils.close(getErr());
+        FileUtils.close(getOut());
     }
 }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/defaults.properties b/src/main/org/apache/tools/ant/taskdefs/defaults.properties
index 9cf1499..06507a3 100644
--- a/src/main/org/apache/tools/ant/taskdefs/defaults.properties
+++ b/src/main/org/apache/tools/ant/taskdefs/defaults.properties
@@ -19,7 +19,6 @@
 antstructure=org.apache.tools.ant.taskdefs.AntStructure
 antversion=org.apache.tools.ant.taskdefs.condition.AntVersion
 apply=org.apache.tools.ant.taskdefs.Transform
-apt=org.apache.tools.ant.taskdefs.Apt
 attributenamespacedef=org.apache.tools.ant.taskdefs.AttributeNamespaceDef
 augment=org.apache.tools.ant.taskdefs.AugmentReference
 available=org.apache.tools.ant.taskdefs.Available
@@ -92,6 +91,7 @@
 resourcecount=org.apache.tools.ant.taskdefs.ResourceCount
 retry=org.apache.tools.ant.taskdefs.Retry
 rmic=org.apache.tools.ant.taskdefs.Rmic
+setpermissions=org.apache.tools.ant.taskdefs.SetPermissions
 sequential=org.apache.tools.ant.taskdefs.Sequential
 signjar=org.apache.tools.ant.taskdefs.SignJar
 sleep=org.apache.tools.ant.taskdefs.Sleep
diff --git a/src/main/org/apache/tools/ant/taskdefs/email/Message.java b/src/main/org/apache/tools/ant/taskdefs/email/Message.java
index c121f5d..a73fdfa 100644
--- a/src/main/org/apache/tools/ant/taskdefs/email/Message.java
+++ b/src/main/org/apache/tools/ant/taskdefs/email/Message.java
@@ -126,17 +126,13 @@
                 : new BufferedWriter(new OutputStreamWriter(ps));
             if (messageSource != null) {
                 // Read message from a file
-                Reader freader = getReader(messageSource);
-
-                try {
-                    BufferedReader in = new BufferedReader(freader);
+                try (Reader freader = getReader(messageSource);
+                     BufferedReader in = new BufferedReader(freader)) {
                     String line = null;
                     while ((line = in.readLine()) != null) {
                         out.write(getProject().replaceProperties(line));
                         out.newLine();
                     }
-                } finally {
-                    freader.close();
                 }
             } else {
                 out.write(getProject().replaceProperties(buffer.substring(0)));
diff --git a/src/main/org/apache/tools/ant/taskdefs/email/PlainMailer.java b/src/main/org/apache/tools/ant/taskdefs/email/PlainMailer.java
index 20524ac..3b1f95b 100644
--- a/src/main/org/apache/tools/ant/taskdefs/email/PlainMailer.java
+++ b/src/main/org/apache/tools/ant/taskdefs/email/PlainMailer.java
@@ -147,16 +147,13 @@
         int length;
         final int maxBuf = 1024;
         byte[] buf = new byte[maxBuf];
-        FileInputStream finstr = new FileInputStream(file);
 
-        try {
-            BufferedInputStream in = new BufferedInputStream(finstr, buf.length);
+        try (FileInputStream finstr = new FileInputStream(file);
+             BufferedInputStream in = new BufferedInputStream(finstr, buf.length)) {
 
             while ((length = in.read(buf)) != -1) {
                 out.write(buf, 0, length);
             }
-        } finally {
-            finstr.close();
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/email/UUMailer.java b/src/main/org/apache/tools/ant/taskdefs/email/UUMailer.java
index d6542be..03af678 100644
--- a/src/main/org/apache/tools/ant/taskdefs/email/UUMailer.java
+++ b/src/main/org/apache/tools/ant/taskdefs/email/UUMailer.java
@@ -40,16 +40,11 @@
                  + "readable.");
         }
 
-        FileInputStream finstr = new FileInputStream(file);
-
-        try {
-            BufferedInputStream in = new BufferedInputStream(finstr);
+        try (FileInputStream finstr = new FileInputStream(file);
+             BufferedInputStream in = new BufferedInputStream(finstr)) {
             UUEncoder encoder = new UUEncoder(file.getName());
 
             encoder.encode(in, out);
-
-        } finally {
-            finstr.close();
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ANTLR.java b/src/main/org/apache/tools/ant/taskdefs/optional/ANTLR.java
index 605b336..2ed40e5 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ANTLR.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ANTLR.java
@@ -422,17 +422,12 @@
      * @since Ant 1.6
      */
     protected boolean is272() {
-        AntClassLoader l = null;
-        try {
-            l = getProject().createClassLoader(commandline.getClasspath());
+        try (AntClassLoader l =
+             getProject().createClassLoader(commandline.getClasspath())) {
             l.loadClass("antlr.Version");
             return true;
         } catch (ClassNotFoundException e) {
             return false;
-        } finally {
-            if (l != null) {
-                l.cleanup();
-            }
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/PropertyFile.java b/src/main/org/apache/tools/ant/taskdefs/optional/PropertyFile.java
index 162cab1..1c9f665 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/PropertyFile.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/PropertyFile.java
@@ -192,27 +192,16 @@
             if (propertyfile.exists()) {
                 log("Updating property file: "
                     + propertyfile.getAbsolutePath());
-                FileInputStream fis = null;
-                try {
-                    fis = new FileInputStream(propertyfile);
-                    BufferedInputStream bis = new BufferedInputStream(fis);
+                try (FileInputStream fis = new FileInputStream(propertyfile);
+                     BufferedInputStream bis = new BufferedInputStream(fis)) {
                     properties.load(bis);
-                } finally {
-                    if (fis != null) {
-                        fis.close();
-                    }
                 }
             } else {
                 log("Creating new property file: "
                     + propertyfile.getAbsolutePath());
-                FileOutputStream out = null;
-                try {
-                    out = new FileOutputStream(propertyfile.getAbsolutePath());
+                try (FileOutputStream out =
+                     new FileOutputStream(propertyfile.getAbsolutePath())) {
                     out.flush();
-                } finally {
-                    if (out != null) {
-                        out.close();
-                    }
                 }
             }
         } catch (IOException ioe) {
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ReplaceRegExp.java b/src/main/org/apache/tools/ant/taskdefs/optional/ReplaceRegExp.java
index d088096..40b7b5d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ReplaceRegExp.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ReplaceRegExp.java
@@ -356,13 +356,13 @@
         try {
             boolean changes = false;
 
-            InputStream is = new FileInputStream(f);
-            try {
-                Reader r = encoding != null ? new InputStreamReader(is, encoding) : new InputStreamReader(is);
-                OutputStream os = new FileOutputStream(temp);
+            try (InputStream is = new FileInputStream(f);
+                 OutputStream os = new FileOutputStream(temp)) {
+                Reader r = null;
+                Writer w = null;
                 try {
-                    Writer w = encoding != null ? new OutputStreamWriter(os, encoding) : new OutputStreamWriter(os);
-
+                    r = encoding != null ? new InputStreamReader(is, encoding) : new InputStreamReader(is);
+                    w = encoding != null ? new OutputStreamWriter(os, encoding) : new OutputStreamWriter(os);
                     log("Replacing pattern '" + regex.getPattern(getProject())
                         + "' with '" + subs.getExpression(getProject())
                         + "' in '" + f.getPath() + "'" + (byline ? " by line" : "")
@@ -426,15 +426,10 @@
                     } else {
                         changes = multilineReplace(r, w, options);
                     }
-
-                    r.close();
-                    w.close();
-
                 } finally {
-                    os.close();
+                    FileUtils.close(r);
+                    FileUtils.close(w);
                 }
-            } finally {
-                is.close();
             }
             if (changes) {
                 log("File has changed; saving the updated file", Project.MSG_VERBOSE);
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/TraXLiaison.java b/src/main/org/apache/tools/ant/taskdefs/optional/TraXLiaison.java
index 8d9a44a..a497bf7 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/TraXLiaison.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/TraXLiaison.java
@@ -293,17 +293,11 @@
         // and avoid keeping the handle until the object is garbaged.
         // (always keep control), otherwise you won't be able to delete
         // the file quickly on windows.
-        InputStream xslStream = null;
-        try {
-            xslStream
-                = new BufferedInputStream(stylesheet.getInputStream());
+        try (InputStream xslStream =
+             new BufferedInputStream(stylesheet.getInputStream())) {
             templatesModTime = stylesheet.getLastModified();
             final Source src = getSource(xslStream, stylesheet);
             templates = getFactory().newTemplates(src);
-        } finally {
-            if (xslStream != null) {
-                xslStream.close();
-            }
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java
index 05c043d..26b49a2 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/XMLValidateTask.java
@@ -287,42 +287,40 @@
      */
     public void execute() throws BuildException {
         try {
-        int fileProcessed = 0;
-        if (file == null && (filesets.size() == 0)) {
-            throw new BuildException(
-                "Specify at least one source - " + "a file or a fileset.");
-        }
+            int fileProcessed = 0;
+            if (file == null && (filesets.size() == 0)) {
+                throw new BuildException(
+                    "Specify at least one source - " + "a file or a fileset.");
+            }
 
-
-
-        if (file != null) {
-            if (file.exists() && file.canRead() && file.isFile()) {
-                doValidate(file);
-                fileProcessed++;
-            } else {
-                String errorMsg = "File " + file + " cannot be read";
-                if (failOnError) {
-                    throw new BuildException(errorMsg);
+            if (file != null) {
+                if (file.exists() && file.canRead() && file.isFile()) {
+                    doValidate(file);
+                    fileProcessed++;
                 } else {
-                    log(errorMsg, Project.MSG_ERR);
+                    String errorMsg = "File " + file + " cannot be read";
+                    if (failOnError) {
+                        throw new BuildException(errorMsg);
+                    } else {
+                        log(errorMsg, Project.MSG_ERR);
+                    }
                 }
             }
-        }
 
-        final int size = filesets.size();
-        for (int i = 0; i < size; i++) {
+            final int size = filesets.size();
+            for (int i = 0; i < size; i++) {
 
-            FileSet fs = (FileSet) filesets.elementAt(i);
-            DirectoryScanner ds = fs.getDirectoryScanner(getProject());
-            String[] files = ds.getIncludedFiles();
+                FileSet fs = (FileSet) filesets.elementAt(i);
+                DirectoryScanner ds = fs.getDirectoryScanner(getProject());
+                String[] files = ds.getIncludedFiles();
 
-            for (int j = 0; j < files.length; j++) {
-                File srcFile = new File(fs.getDir(getProject()), files[j]);
-                doValidate(srcFile);
-                fileProcessed++;
+                for (int j = 0; j < files.length; j++) {
+                    File srcFile = new File(fs.getDir(getProject()), files[j]);
+                    doValidate(srcFile);
+                    fileProcessed++;
+                }
             }
-        }
-        onSuccessfulValidation(fileProcessed);
+            onSuccessfulValidation(fileProcessed);
         } finally {
             cleanup();
         }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/AntAnalyzer.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/AntAnalyzer.java
index 341f670..d490955 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/AntAnalyzer.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/AntAnalyzer.java
@@ -96,9 +96,7 @@
                         }
                     } finally {
                         FileUtils.close(inStream);
-                        if (zipFile != null) {
-                            zipFile.close();
-                        }
+                        FileUtils.close(zipFile);
                     }
                 } catch (IOException ioe) {
                     // ignore
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/depend/Depend.java b/src/main/org/apache/tools/ant/taskdefs/optional/depend/Depend.java
index cc65129..ae62afe 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/depend/Depend.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/depend/Depend.java
@@ -379,9 +379,7 @@
         if (checkPath != null) {
             // now determine which jars each class depends upon
             classpathDependencies = new Hashtable();
-            AntClassLoader loader = null;
-            try {
-                loader = getProject().createClassLoader(checkPath);
+            try (AntClassLoader loader = getProject().createClassLoader(checkPath)) {
 
                 Hashtable classpathFileCache = new Hashtable();
                 Object nullFileMarker = new Object();
@@ -443,10 +441,6 @@
                         }
                     }
                 }
-            } finally {
-                if (loader != null) {
-                    loader.cleanup();
-                }
             }
         } else {
             log("No classpath to check", Project.MSG_DEBUG);
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/JonasDeploymentTool.java b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/JonasDeploymentTool.java
index 81fe805..00fd180 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/JonasDeploymentTool.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/JonasDeploymentTool.java
@@ -681,10 +681,7 @@
         log("Looking for GenIC class in classpath: "
             + classpath.toString(), Project.MSG_VERBOSE);
 
-        AntClassLoader cl = null;
-
-        try {
-            cl = classpath.getProject().createClassLoader(classpath);
+        try (AntClassLoader cl = classpath.getProject().createClassLoader(classpath)) {
 
             try {
                 cl.loadClass(JonasDeploymentTool.GENIC_CLASS);
@@ -723,10 +720,6 @@
                     + "' not found in classpath.",
                     Project.MSG_VERBOSE);
             }
-        } finally {
-            if (cl != null) {
-                cl.cleanup();
-            }
         }
         return null;
     }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/WeblogicDeploymentTool.java b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/WeblogicDeploymentTool.java
index 7fae8b3..6495e97 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/WeblogicDeploymentTool.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/WeblogicDeploymentTool.java
@@ -866,24 +866,10 @@
 
             throw new BuildException(msg, ioe);
         } finally {
-            // need to close files and perhaps rename output
-            if (genericJar != null) {
-                try {
-                    genericJar.close();
-                } catch (IOException closeException) {
-                    // empty
-                }
-            }
-
-            if (wlJar != null) {
-                try {
-                    wlJar.close();
-                } catch (IOException closeException) {
-                    // empty
-                }
-            }
-
+            FileUtils.close(genericJar);
+            FileUtils.close(wlJar);
             FileUtils.close(newJarStream);
+
             if (newJarStream != null) {
                 try {
                     FILE_UTILS.rename(newWLJarFile, weblogicJarFile);
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/WebsphereDeploymentTool.java b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/WebsphereDeploymentTool.java
index 7114610..da84f24 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ejb/WebsphereDeploymentTool.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ejb/WebsphereDeploymentTool.java
@@ -832,23 +832,10 @@
             throw new BuildException(msg, ioe);
         } finally {
             // need to close files and perhaps rename output
-            if (genericJar != null) {
-                try {
-                    genericJar.close();
-                } catch (IOException closeException) {
-                    // Ignore
-                }
-            }
-
-            if (wasJar != null) {
-                try {
-                    wasJar.close();
-                } catch (IOException closeException) {
-                    // Ignore
-                }
-            }
-
+            FileUtils.close(genericJar);
+            FileUtils.close(wasJar);
             FileUtils.close(newJarStream);
+
             if (newJarStream != null) {
                 try {
                     FILE_UTILS.rename(newwasJarFile, websphereJarFile);
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/javacc/JavaCC.java b/src/main/org/apache/tools/ant/taskdefs/optional/javacc/JavaCC.java
index 219cc9c..bd7aba5 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/javacc/JavaCC.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/javacc/JavaCC.java
@@ -425,12 +425,11 @@
         String packagePrefix = null;
         String mainClass = null;
 
-        AntClassLoader l = null;
-        try {
-            l = AntClassLoader.newAntClassLoader(null, null,
-                                                 path
-                                                 .concatSystemClasspath("ignore"),
-                                                 true);
+        try (AntClassLoader l =
+             AntClassLoader.newAntClassLoader(null, null,
+                                              path
+                                              .concatSystemClasspath("ignore"),
+                                              true)) {
             String javaccClass = COM_PACKAGE + COM_JAVACC_CLASS;
             InputStream is = l.getResourceAsStream(javaccClass.replace('.', '/')
                                                    + ".class");
@@ -498,10 +497,6 @@
                 throw new BuildException("unknown task type " + type);
             }
             return packagePrefix + mainClass;
-        } finally {
-            if (l != null) {
-                l.cleanup();
-            }
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspC.java b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspC.java
index 4274bf0..9832e3e 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspC.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/JspC.java
@@ -439,13 +439,10 @@
 
         File dest = getActualDestDir();
 
-        AntClassLoader al = null;
-        try {
+        try (AntClassLoader al = getProject().createClassLoader(compilerClasspath)) {
             //bind to a compiler
             JspCompilerAdapter compiler =
-                JspCompilerAdapterFactory
-                .getCompiler(compilerName, this,
-                             al = getProject().createClassLoader(compilerClasspath));
+                JspCompilerAdapterFactory.getCompiler(compilerName, this, al);
 
             //if we are a webapp, hand off to the compiler, which had
             //better handle it
@@ -514,10 +511,6 @@
                     log("all files are up to date", Project.MSG_VERBOSE);
                 }
             }
-        } finally {
-            if (al != null) {
-                al.cleanup();
-            }
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/JasperC.java b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/JasperC.java
index f0becac..80ed601 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/JasperC.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/jsp/compilers/JasperC.java
@@ -166,17 +166,11 @@
      * @since Ant 1.6.2
      */
     private boolean isTomcat5x() {
-        AntClassLoader l = null;
-        try {
-            l = getProject().createClassLoader(getClasspath());
+        try (AntClassLoader l = getProject().createClassLoader(getClasspath())) {
             l.loadClass("org.apache.jasper.tagplugins.jstl.If");
             return true;
         } catch (ClassNotFoundException e) {
             return false;
-        } finally {
-            if (l != null) {
-                l.cleanup();
-            }
         }
     }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/AggregateTransformer.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/AggregateTransformer.java
index ec3506d..800c213 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/AggregateTransformer.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/AggregateTransformer.java
@@ -168,12 +168,9 @@
     protected void setXmlfile(File xmlfile) throws BuildException {
         try {
             DocumentBuilder builder = privateDBFactory.newDocumentBuilder();
-            InputStream in = new FileInputStream(xmlfile);
-            try {
+            try (InputStream in = new FileInputStream(xmlfile)) {
                 Document doc = builder.parse(in);
                 setXmlDocument(doc);
-            } finally {
-                in.close();
             }
         } catch (Exception e) {
             throw new BuildException("Error while parsing document: " + xmlfile, e);
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
index 459bd3d..2d98d42 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
@@ -38,6 +38,7 @@
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Vector;
@@ -511,6 +512,26 @@
     }
 
     /**
+     * Add a path to the modulepath.
+     *
+     * @return created modulepath.
+     * @since 1.10.0
+     */
+    public Path createModulepath() {
+        return getCommandline().createModulepath(getProject()).createPath();
+    }
+
+    /**
+     * Add a path to the upgrademodulepath.
+     *
+     * @return created upgrademodulepath.
+     * @since 1.10.0
+     */
+    public Path createUpgrademodulepath() {
+        return getCommandline().createUpgrademodulepath(getProject()).createPath();
+    }
+
+    /**
      * Adds an environment variable; used when forking.
      *
      * <p>Will be ignored if we are not forking a new VM.</p>
@@ -749,7 +770,7 @@
             loader.loadClass("junit.framework.Test"); // sanity check
         } catch (final ClassNotFoundException e) {
             throw new BuildException(
-                    "The <classpath> for <junit> must include junit.jar "
+                    "The <classpath> or <modulepath> for <junit> must include junit.jar "
                     + "if not in Ant's own classpath",
                     e, task.getLocation());
         }
@@ -777,10 +798,14 @@
         if (splitJUnit) {
             final Path path = new Path(getProject());
             path.add(antRuntimeClasses);
-            final Path extra = getCommandline().getClasspath();
+            Path extra = getCommandline().getClasspath();
             if (extra != null) {
                 path.add(extra);
             }
+            extra = getCommandline().getModulepath();
+            if (extra != null && !hasJunit(path)) {
+                path.add(expandModulePath(extra));
+            }
             mirrorLoader = (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
                 public Object run() {
                     return new SplitClassLoader(myLoader, path, getProject(),
@@ -818,7 +843,7 @@
     @Override
     public void execute() throws BuildException {
         checkMethodLists();
-
+        checkModules();
         setupJUnitDelegate();
 
         final List<List> testLists = new ArrayList<List>();
@@ -1360,12 +1385,10 @@
         if (!cmd.haveClasspath()) {
             return;
         }
-        AntClassLoader loader = null;
-        try {
-            loader =
-                AntClassLoader.newAntClassLoader(null, getProject(),
-                                                 cmd.createClasspath(getProject()),
-                                                 true);
+        try (AntClassLoader loader =
+             AntClassLoader.newAntClassLoader(null, getProject(),
+                                              cmd.createClasspath(getProject()),
+                                              true)) {
             final String projectResourceName =
                 LoaderUtils.classNameToResource(Project.class.getName());
             URL previous = null;
@@ -1386,10 +1409,6 @@
             } catch (final Exception ex) {
                 // Ignore exception
             }
-        } finally {
-            if (loader != null) {
-                loader.cleanup();
-            }
         }
     }
 
@@ -1698,6 +1717,75 @@
     }
 
     /**
+     * Checks a validity of module specific options.
+     * @since 1.10.0
+     */
+    private void checkModules() {
+        if (hasPath(getCommandline().getModulepath()) ||
+            hasPath(getCommandline().getUpgrademodulepath())) {
+            for (int i = 0, count = batchTests.size(); i < count; i++) {
+                if(!batchTests.elementAt(i).getFork()) {
+                    throw new BuildException("The module path requires fork attribute to be set to true.");
+                }
+            }
+            for (int i = 0, count = tests.size(); i < count; i++) {
+                if (!tests.elementAt(i).getFork()) {
+                    throw new BuildException("The module path requires fork attribute to be set to true.");
+                }
+            }
+        }
+    }
+
+    /**
+     * Checks is a junit is on given path.
+     * @param path the {@link Path} to check
+     * @return true when given {@link Path} contains junit
+     * @since 1.10.0
+     */
+    private boolean hasJunit(final Path path) {
+        try (AntClassLoader loader = AntClassLoader.newAntClassLoader(
+                null,
+                getProject(),
+                path,
+                true)) {
+            try {
+                loader.loadClass("junit.framework.Test");
+                return true;
+            } catch (final Exception ex) {
+                return false;
+            }
+        }
+    }
+
+    /**
+     * Expands a module path to flat path of jars and root folders usable by classloader.
+     * @param modulePath to be expanded
+     * @return the expanded path
+     * @since 1.10.0
+     */
+    private Path expandModulePath(Path modulePath) {
+        final Path expanded = new Path(getProject());
+        for (String path : modulePath.list()) {
+            final File modulePathEntry = getProject().resolveFile(path);
+            if (modulePathEntry.isDirectory() && !hasModuleInfo(modulePathEntry)) {
+                final File[] modules = modulePathEntry.listFiles((dir,name)->name.toLowerCase(Locale.ENGLISH).endsWith(".jar"));
+                if (modules != null) {
+                    for (File module : modules) {
+                        expanded.add(new Path(getProject(), String.format(
+                                "%s%s%s",   //NOI18N
+                                path,
+                                File.separator,
+                                module.getName())));
+                    }
+                }
+            } else {
+                expanded.add(new Path(getProject(), path));
+            }
+        }
+        return expanded;
+    }
+
+    /**
      * return an enumeration listing each test, then each batchtest
      * @return enumeration
      * @since Ant 1.3
@@ -1892,16 +1980,23 @@
      */
     private void createClassLoader() {
         final Path userClasspath = getCommandline().getClasspath();
-        if (userClasspath != null) {
+        final Path userModulepath = getCommandline().getModulepath();
+        if (userClasspath != null || userModulepath != null) {
             if (reloading || classLoader == null) {
                 deleteClassLoader();
-                final Path classpath = (Path) userClasspath.clone();
+                final Path path = new Path(getProject());
+                if (userClasspath != null) {
+                    path.add((Path) userClasspath.clone());
+                }
+                if (userModulepath != null && !hasJunit(path)) {
+                    path.add(expandModulePath(userModulepath));
+                }
                 if (includeAntRuntime) {
                     log("Implicitly adding " + antRuntimeClasses
                         + " to CLASSPATH", Project.MSG_VERBOSE);
-                    classpath.append(antRuntimeClasses);
+                    path.append(antRuntimeClasses);
                 }
-                classLoader = getProject().createClassLoader(classpath);
+                classLoader = getProject().createClassLoader(path);
                 if (getClass().getClassLoader() != null
                     && getClass().getClassLoader() != Project.class.getClassLoader()) {
                     classLoader.setParent(getClass().getClassLoader());
@@ -2280,4 +2375,24 @@
         w.newLine();
         s.println(text);
     }
+
+    /**
+     * Checks if a path exists and is non empty.
+     * @param path to be checked
+     * @return true if the path is non <code>null</code> and non empty.
+     * @since 1.10.0
+     */
+    private static boolean hasPath(final Path path) {
+        return path != null && path.size() > 0;
+    }
+
+    /**
+     * Checks if a given folder is an unpacked module.
+     * @param root the fodler to be checked
+     * @return true if the root is an unpacked module
+     * @since 1.10.0
+     */
+    private static boolean hasModuleInfo(final File root) {
+        return new File(root, "module-info.class").exists();    //NOI18N
+    }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregator.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregator.java
index 4f76c96..97e2647 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregator.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregator.java
@@ -213,9 +213,8 @@
      * @throws IOException thrown if there is an error while writing the content.
      */
     protected void writeDOMTree(Document doc, File file) throws IOException {
-        OutputStream os = new FileOutputStream(file);
-        try {
-            PrintWriter wri = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(os), "UTF8"));
+        try (OutputStream os = new FileOutputStream(file);
+             PrintWriter wri = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(os), "UTF8"))) {
             wri.write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
             (new DOMElementWriter()).write(doc.getDocumentElement(), wri, 0, "  ");
             wri.flush();
@@ -223,8 +222,6 @@
             if (wri.checkError()) {
                 throw new IOException("Error while writing DOM content");
             }
-        } finally {
-            os.close();
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/BuiltinNative2Ascii.java b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/BuiltinNative2Ascii.java
index db91a26..36e46c3 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/BuiltinNative2Ascii.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/BuiltinNative2Ascii.java
@@ -31,7 +31,6 @@
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.taskdefs.optional.Native2Ascii;
-import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.Native2AsciiUtils;
 import org.apache.tools.ant.util.StringUtils;
 
@@ -44,23 +43,14 @@
 
     static final String IMPLEMENTATION_NAME = "builtin";
 
+    @Override
     public final boolean convert(Native2Ascii args, File srcFile,
                                  File destFile) throws BuildException {
         boolean reverse = args.getReverse();
         String encoding = args.getEncoding();
-        BufferedReader input = null;
-        try {
-            input = getReader(srcFile, encoding, reverse);
-            try {
-                Writer output = getWriter(destFile, encoding, reverse);
-                try {
-                    translate(input, output, reverse);
-                } finally {
-                    FileUtils.close(output);
-                }
-            } finally {
-                FileUtils.close(input);
-            }
+        try (BufferedReader input = getReader(srcFile, encoding, reverse);
+             Writer output = getWriter(destFile, encoding, reverse)) {
+            translate(input, output, reverse);
             return true;
         } catch (IOException ex) {
             throw new BuildException("Exception trying to translate data", ex);
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapterFactory.java b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapterFactory.java
index e8bd74d..74bb323 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapterFactory.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapterFactory.java
@@ -43,9 +43,6 @@
         if (shouldUseKaffee()) {
             return KaffeNative2Ascii.IMPLEMENTATION_NAME;
         }
-        if (shouldUseSun()) {
-            return SunNative2Ascii.IMPLEMENTATION_NAME;
-        }
         return BuiltinNative2Ascii.IMPLEMENTATION_NAME;
     }
 
@@ -85,8 +82,7 @@
         if ((shouldUseKaffee() && choice == null)
             || KaffeNative2Ascii.IMPLEMENTATION_NAME.equals(choice)) {
             return new KaffeNative2Ascii();
-        } else if ((shouldUseSun() && choice == null)
-                   || SunNative2Ascii.IMPLEMENTATION_NAME.equals(choice)) {
+        } else if (SunNative2Ascii.IMPLEMENTATION_NAME.equals(choice)) {
             return new SunNative2Ascii();
         } else if (BuiltinNative2Ascii.IMPLEMENTATION_NAME.equals(choice)) {
             return new BuiltinNative2Ascii();
@@ -121,11 +117,4 @@
     private static final boolean shouldUseKaffee() {
         return JavaEnvUtils.isKaffe() || JavaEnvUtils.isClasspathBased();
     }
-
-    private static final boolean shouldUseSun() {
-        return JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_5)
-            || JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_6)
-            || JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_7)
-            || JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_8);
-    }
 }
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/SSHExec.java b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/SSHExec.java
index a04dfef..7d49709 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/ssh/SSHExec.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/ssh/SSHExec.java
@@ -495,9 +495,7 @@
      */
     private void writeToFile(final String from, final boolean append, final File to)
         throws IOException {
-        FileWriter out = null;
-        try {
-            out = new FileWriter(to.getAbsolutePath(), append);
+        try (FileWriter out = new FileWriter(to.getAbsolutePath(), append)) {
             final StringReader in = new StringReader(from);
             final char[] buffer = new char[BUFFER_SIZE];
             int bytesRead;
@@ -509,10 +507,6 @@
                 out.write(buffer, 0, bytesRead);
             }
             out.flush();
-        } finally {
-            if (out != null) {
-                out.close();
-            }
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/types/AbstractFileSet.java b/src/main/org/apache/tools/ant/types/AbstractFileSet.java
index e3b8aa8..92d5ace 100644
--- a/src/main/org/apache/tools/ant/types/AbstractFileSet.java
+++ b/src/main/org/apache/tools/ant/types/AbstractFileSet.java
@@ -36,18 +36,21 @@
 import org.apache.tools.ant.types.selectors.DepthSelector;
 import org.apache.tools.ant.types.selectors.DifferentSelector;
 import org.apache.tools.ant.types.selectors.ExtendSelector;
+import org.apache.tools.ant.types.selectors.ExecutableSelector;
 import org.apache.tools.ant.types.selectors.FileSelector;
 import org.apache.tools.ant.types.selectors.FilenameSelector;
 import org.apache.tools.ant.types.selectors.MajoritySelector;
 import org.apache.tools.ant.types.selectors.NoneSelector;
 import org.apache.tools.ant.types.selectors.NotSelector;
 import org.apache.tools.ant.types.selectors.OrSelector;
+import org.apache.tools.ant.types.selectors.OwnedBySelector;
 import org.apache.tools.ant.types.selectors.PresentSelector;
 import org.apache.tools.ant.types.selectors.ReadableSelector;
 import org.apache.tools.ant.types.selectors.SelectSelector;
 import org.apache.tools.ant.types.selectors.SelectorContainer;
 import org.apache.tools.ant.types.selectors.SelectorScanner;
 import org.apache.tools.ant.types.selectors.SizeSelector;
+import org.apache.tools.ant.types.selectors.SymlinkSelector;
 import org.apache.tools.ant.types.selectors.TypeSelector;
 import org.apache.tools.ant.types.selectors.WritableSelector;
 import org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector;
@@ -806,6 +809,27 @@
     }
 
     /**
+     * @since 1.10.0
+     */
+    public void addExecutable(ExecutableSelector e) {
+        appendSelector(e);
+    }
+
+    /**
+     * @since 1.10.0
+     */
+    public void addSymlink(SymlinkSelector e) {
+        appendSelector(e);
+    }
+
+    /**
+     * @since 1.10.0
+     */
+    public void addOwnedBy(OwnedBySelector o) {
+        appendSelector(o);
+    }
+
+    /**
      * Add an arbitrary selector.
      * @param selector the <code>FileSelector</code> to add.
      * @since Ant 1.6
diff --git a/src/main/org/apache/tools/ant/types/selectors/AbstractSelectorContainer.java b/src/main/org/apache/tools/ant/types/selectors/AbstractSelectorContainer.java
index b80816d..3039d48 100644
--- a/src/main/org/apache/tools/ant/types/selectors/AbstractSelectorContainer.java
+++ b/src/main/org/apache/tools/ant/types/selectors/AbstractSelectorContainer.java
@@ -313,6 +313,27 @@
     }
 
     /**
+     * @since 1.10.0
+     */
+    public void addExecutable(ExecutableSelector e) {
+        appendSelector(e);
+    }
+
+    /**
+     * @since 1.10.0
+     */
+    public void addSymlink(SymlinkSelector e) {
+        appendSelector(e);
+    }
+
+    /**
+     * @since 1.10.0
+     */
+    public void addOwnedBy(OwnedBySelector o) {
+        appendSelector(o);
+    }
+
+    /**
      * add an arbitrary selector
      * @param selector the selector to add
      * @since Ant 1.6
diff --git a/src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java b/src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java
index 1edf085..3fcccd7 100644
--- a/src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java
+++ b/src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java
@@ -316,6 +316,27 @@
     }
 
     /**
+     * @since 1.10.0
+     */
+    public void addExecutable(ExecutableSelector e) {
+        appendSelector(e);
+    }
+
+    /**
+     * @since 1.10.0
+     */
+    public void addSymlink(SymlinkSelector e) {
+        appendSelector(e);
+    }
+
+    /**
+     * @since 1.10.0
+     */
+    public void addOwnedBy(OwnedBySelector o) {
+        appendSelector(o);
+    }
+
+    /**
      * add an arbitrary selector
      * @param selector the selector to add
      * @since Ant 1.6
diff --git a/src/main/org/apache/tools/ant/types/selectors/ExecutableSelector.java b/src/main/org/apache/tools/ant/types/selectors/ExecutableSelector.java
new file mode 100644
index 0000000..891b795
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/selectors/ExecutableSelector.java
@@ -0,0 +1,51 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.
+ *
+ */
+
+package org.apache.tools.ant.types.selectors;
+
+import java.nio.file.Files;
+import java.io.File;
+
+import org.apache.tools.ant.types.Resource;
+import org.apache.tools.ant.types.resources.FileProvider;
+import org.apache.tools.ant.types.resources.selectors.ResourceSelector;
+
+/**
+ * A selector that selects executable files.
+ *
+ * <p>Executable is defined in terms of {@link
+ * java.nio.file.Files#isExecutable}, this means the selector will
+ * accept any file that exists and is executable by the
+ * application.</p>
+ *
+ * @since Ant 1.10.0
+ */
+public class ExecutableSelector implements FileSelector, ResourceSelector {
+
+    public boolean isSelected(File basedir, String filename, File file) {
+        return file != null && Files.isExecutable(file.toPath());
+    }
+
+    public boolean isSelected(Resource r) {
+        FileProvider fp = r.as(FileProvider.class);
+        if (fp != null) {
+            return isSelected(null, null, fp.getFile());
+        }
+        return false;
+    }
+}
diff --git a/src/main/org/apache/tools/ant/types/selectors/OwnedBySelector.java b/src/main/org/apache/tools/ant/types/selectors/OwnedBySelector.java
new file mode 100644
index 0000000..32aaa8d
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/selectors/OwnedBySelector.java
@@ -0,0 +1,78 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.
+ *
+ */
+
+package org.apache.tools.ant.types.selectors;
+
+import java.nio.file.Files;
+import java.nio.file.attribute.UserPrincipal;
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.Resource;
+import org.apache.tools.ant.types.resources.FileProvider;
+import org.apache.tools.ant.types.resources.selectors.ResourceSelector;
+
+/**
+ * A selector that selects files based on their owner.
+ *
+ * <p>Owner is defined in terms of {@link
+ * java.nio.file.Files#getOwner}, this means the selector will accept
+ * any file that exists and is owned by the given user. If the {@code
+ * getOwner} method throws an {@code UnsupportedOperattionException}
+ * the file in question is not included.</p>
+ *
+ * @since Ant 1.10.0
+ */
+public class OwnedBySelector implements FileSelector, ResourceSelector {
+
+    private String owner;
+
+    /**
+     * Sets the User-Name to look for.
+     * @param owner the user name
+     */
+    public void setOwner(String owner) {
+        this.owner = owner;
+    }
+
+    @Override
+    public boolean isSelected(File basedir, String filename, File file) {
+        if (owner == null) {
+            throw new BuildException("the owner attribute is required");
+        }
+        if (file != null) {
+            try {
+                UserPrincipal user = Files.getOwner(file.toPath());
+                return user != null && owner.equals(user.getName());
+            } catch (UnsupportedOperationException | IOException ex) {
+                // => not the expected owner
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean isSelected(Resource r) {
+        FileProvider fp = r.as(FileProvider.class);
+        if (fp != null) {
+            return isSelected(null, null, fp.getFile());
+        }
+        return false;
+    }
+}
diff --git a/src/main/org/apache/tools/ant/types/selectors/SymlinkSelector.java b/src/main/org/apache/tools/ant/types/selectors/SymlinkSelector.java
new file mode 100644
index 0000000..28c3bcb
--- /dev/null
+++ b/src/main/org/apache/tools/ant/types/selectors/SymlinkSelector.java
@@ -0,0 +1,50 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.
+ *
+ */
+
+package org.apache.tools.ant.types.selectors;
+
+import java.nio.file.Files;
+import java.io.File;
+
+import org.apache.tools.ant.types.Resource;
+import org.apache.tools.ant.types.resources.FileProvider;
+import org.apache.tools.ant.types.resources.selectors.ResourceSelector;
+
+/**
+ * A selector that selects symbolic links.
+ *
+ * <p>Executable is defined in terms of {@link
+ * java.nio.file.Files#isSymbolicLink}, this means the selector will
+ * accept any file that exists and is a symbolic link.</p>
+ *
+ * @since Ant 1.10.0
+ */
+public class SymlinkSelector implements FileSelector, ResourceSelector {
+
+    public boolean isSelected(File basedir, String filename, File file) {
+        return file != null && Files.isSymbolicLink(file.toPath());
+    }
+
+    public boolean isSelected(Resource r) {
+        FileProvider fp = r.as(FileProvider.class);
+        if (fp != null) {
+            return isSelected(null, null, fp.getFile());
+        }
+        return false;
+    }
+}
diff --git a/src/main/org/apache/tools/ant/util/FileUtils.java b/src/main/org/apache/tools/ant/util/FileUtils.java
index bcef5ec..891dafe 100644
--- a/src/main/org/apache/tools/ant/util/FileUtils.java
+++ b/src/main/org/apache/tools/ant/util/FileUtils.java
@@ -1445,13 +1445,7 @@
      * @param device output writer, can be null.
      */
     public static void close(Writer device) {
-        if (null != device) {
-            try {
-                device.close();
-            } catch (IOException e) {
-                //ignore
-            }
-        }
+        close((AutoCloseable) device);
     }
 
     /**
@@ -1461,13 +1455,7 @@
      * @param device Reader, can be null.
      */
     public static void close(Reader device) {
-        if (null != device) {
-            try {
-                device.close();
-            } catch (IOException e) {
-                //ignore
-            }
-        }
+        close((AutoCloseable) device);
     }
 
     /**
@@ -1477,13 +1465,7 @@
      * @param device stream, can be null.
      */
     public static void close(OutputStream device) {
-        if (null != device) {
-            try {
-                device.close();
-            } catch (IOException e) {
-                //ignore
-            }
-        }
+        close((AutoCloseable) device);
     }
 
     /**
@@ -1493,13 +1475,7 @@
      * @param device stream, can be null.
      */
     public static void close(InputStream device) {
-        if (null != device) {
-            try {
-                device.close();
-            } catch (IOException e) {
-                //ignore
-            }
-        }
+        close((AutoCloseable) device);
     }
 
     /**
@@ -1510,13 +1486,7 @@
      * @since Ant 1.8.0
      */
     public static void close(Channel device) {
-        if (null != device) {
-            try {
-                device.close();
-            } catch (IOException e) {
-                //ignore
-            }
-        }
+        close((AutoCloseable) device);
     }
 
     /**
@@ -1544,6 +1514,24 @@
     }
 
     /**
+     * Close an {@link AutoCloseable} without throwing any exception
+     * if something went wrong.  Do not attempt to close it if the
+     * argument is null.
+     *
+     * @param ac AutoCloseable, can be null.
+     * @since Ant 1.10.0
+     */
+    public static void close(AutoCloseable ac) {
+        if (null != ac) {
+            try {
+                ac.close();
+            } catch (Exception e) {
+                //ignore
+            }
+        }
+    }
+
+    /**
      * Delete the file with {@link File#delete()} if the argument is not null.
      * Do nothing on a null argument.
      * @param file file to delete.
diff --git a/src/main/org/apache/tools/ant/util/JavaEnvUtils.java b/src/main/org/apache/tools/ant/util/JavaEnvUtils.java
index a551c0f..84e82fd 100644
--- a/src/main/org/apache/tools/ant/util/JavaEnvUtils.java
+++ b/src/main/org/apache/tools/ant/util/JavaEnvUtils.java
@@ -258,8 +258,8 @@
      * Compares the current Java version to the passed in String -
      * assumes the argument is one of the constants defined in this
      * class.
-     * Note that Ant now requires JDK 1.5+ so {@link #JAVA_1_0} through
-     * {@link #JAVA_1_4} need no longer be tested for.
+     * Note that Ant now requires JDK 1.8+ so {@link #JAVA_1_0} through
+     * {@link #JAVA_1_7} need no longer be tested for.
      * @param version the version to check against the current version.
      * @return true if the version of Java is the same as the given version.
      * @since Ant 1.5
@@ -273,8 +273,8 @@
      * Compares the current Java version to the passed in String -
      * assumes the argument is one of the constants defined in this
      * class.
-     * Note that Ant now requires JDK 1.5+ so {@link #JAVA_1_0} through
-     * {@link #JAVA_1_4} need no longer be tested for.
+     * Note that Ant now requires JDK 1.8+ so {@link #JAVA_1_0} through
+     * {@link #JAVA_1_7} need no longer be tested for.
      * @param version the version to check against the current version.
      * @return true if the version of Java is the same or higher than the
      * given version.
diff --git a/src/main/org/apache/tools/ant/util/PermissionUtils.java b/src/main/org/apache/tools/ant/util/PermissionUtils.java
new file mode 100644
index 0000000..ad363f0
--- /dev/null
+++ b/src/main/org/apache/tools/ant/util/PermissionUtils.java
@@ -0,0 +1,237 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.
+ *
+ */
+package org.apache.tools.ant.util;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.PosixFileAttributeView;
+import java.nio.file.attribute.PosixFilePermission;
+import java.util.EnumSet;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import org.apache.tools.ant.types.Resource;
+import org.apache.tools.ant.types.resources.ArchiveResource;
+import org.apache.tools.ant.types.resources.FileProvider;
+
+/**
+ * Contains helper methods for dealing with {@link
+ * PosixFilePermission} or the traditional Unix mode representation of
+ * permissions.
+ *
+ * @since Ant 1.10.0
+ */
+public class PermissionUtils {
+
+    private PermissionUtils() { }
+
+    /**
+     * Translates a set of permissons into a Unix stat(2) {@code
+     * st_mode} result.
+     * @param permissions the permissions
+     * @param type the file type
+     * @return the "mode"
+     */
+    public static int modeFromPermissions(Set<PosixFilePermission> permissions,
+                                          FileType type) {
+        int mode;
+        switch (type) {
+        case SYMLINK:
+            mode = 012;
+            break;
+        case REGULAR_FILE:
+            mode = 010;
+            break;
+        case DIR:
+            mode = 004;
+            break;
+        default:
+            // OTHER could be a character or block device, a socket or a FIFO - so don't set anything
+            mode = 0;
+            break;
+        }
+        mode <<= 3;
+        mode <<= 3; // we don't support sticky, setuid, setgid
+        mode |= modeFromPermissions(permissions, "OWNER");
+        mode <<= 3;
+        mode |= modeFromPermissions(permissions, "GROUP");
+        mode <<= 3;
+        mode |= modeFromPermissions(permissions, "OTHERS");
+        return mode;
+    }
+
+    /**
+     * Translates a Unix stat(2) {@code st_mode} compatible value into
+     * a set of permissions.
+     * @param mode the "mode"
+     * @return set of permissions
+     */
+    public static Set<PosixFilePermission> permissionsFromMode(int mode) {
+        Set<PosixFilePermission> permissions = EnumSet.noneOf(PosixFilePermission.class);
+        addPermissions(permissions, "OTHERS", mode);
+        addPermissions(permissions, "GROUP", mode >> 3);
+        addPermissions(permissions, "OWNER", mode >> 6);
+        return permissions;
+    }
+
+    /**
+     * Sets permissions on a {@link Resource} - doesn't do anything
+     * for unsupported resource types.
+     *
+     * <p>Supported types are:</p>
+     * <ul>
+     *  <li>any {@link FileProvider}</li>
+     *  <li>{@link ArchiveResource}</li>
+     * </ul>
+     *
+     * @param resource the resource to set permissions for
+     * @param permissions the permissions
+     * @param posixNotSupportedCallback optional callback that is
+     * invoked for a file provider resource if the file-system holding
+     * the file doesn't support PosixFilePermissions. The Path
+     * corresponding to the file is passed to the callback.
+     */
+    public static void setPermissions(Resource r, Set<PosixFilePermission> permissions,
+                                      Consumer<Path> posixNotSupportedCallback)
+        throws IOException {
+        FileProvider f = r.as(FileProvider.class);
+        if (f != null) {
+            Path p = f.getFile().toPath();
+            PosixFileAttributeView view =
+                Files.getFileAttributeView(p, PosixFileAttributeView.class);
+            if (view != null) {
+                view.setPermissions(permissions);
+            } else if (posixNotSupportedCallback != null) {
+                posixNotSupportedCallback.accept(p);
+            }
+        } else if (r instanceof ArchiveResource) {
+            ((ArchiveResource) r).setMode(modeFromPermissions(permissions,
+                                                              FileType.of(r)));
+        }
+    }
+
+    /**
+     * Sets permissions of a {@link Resource} - returns an empty set
+     * for unsupported resource types or file systems that don't
+     * support PosixFilePermissions and no fallback has been
+     * provided..
+     *
+     * <p>Supported types are:</p>
+     * <ul>
+     *  <li>any {@link FileProvider}</li>
+     *  <li>{@link ArchiveResource}</li>
+     * </ul>
+     *
+     * @param resource the resource to read permissions from
+     * @param posixNotSupportedFallback optional fallback function to provide
+     * permissions for file system that don't support
+     * PosixFilePermissions. The Path corresponding to the file is
+     * passed to the callback.
+     * @return the permissions
+     */
+    public static Set<PosixFilePermission> getPermissions(Resource r,
+            Function<Path, Set<PosixFilePermission>> posixNotSupportedFallback)
+        throws IOException {
+        FileProvider f = r.as(FileProvider.class);
+        if (f != null) {
+            Path p = f.getFile().toPath();
+            PosixFileAttributeView view =
+                Files.getFileAttributeView(p, PosixFileAttributeView.class);
+            if (view != null) {
+                return view.readAttributes().permissions();
+            } else if (posixNotSupportedFallback != null) {
+                return posixNotSupportedFallback.apply(p);
+            }
+        } else if (r instanceof ArchiveResource) {
+            return permissionsFromMode(((ArchiveResource) r).getMode());
+        }
+        return EnumSet.noneOf(PosixFilePermission.class);
+    }
+
+    private static long modeFromPermissions(Set<PosixFilePermission> permissions,
+                                            String prefix) {
+        long mode = 0;
+        if (permissions.contains(PosixFilePermission.valueOf(prefix + "_READ"))) {
+            mode |= 4;
+        }
+        if (permissions.contains(PosixFilePermission.valueOf(prefix + "_WRITE"))) {
+            mode |= 2;
+        }
+        if (permissions.contains(PosixFilePermission.valueOf(prefix + "_EXECUTE"))) {
+            mode |= 1;
+        }
+        return mode;
+    }
+
+    private static void addPermissions(Set<PosixFilePermission> permissions,
+                                       String prefix, long mode) {
+        if ((mode & 1) == 1) {
+            permissions.add(PosixFilePermission.valueOf(prefix + "_EXECUTE"));
+        }
+        if ((mode & 2) == 2) {
+            permissions.add(PosixFilePermission.valueOf(prefix + "_WRITE"));
+        }
+        if ((mode & 4) == 4) {
+            permissions.add(PosixFilePermission.valueOf(prefix + "_READ"));
+        }
+    }
+
+    /**
+     * The supported types of files, maps to the {@code isFoo} methods
+     * in {@link java.nio.file.attribute.BasicFileAttributes}.
+     */
+    public enum FileType {
+        /** A regular file. */
+        REGULAR_FILE,
+        /** A directory. */
+        DIR,
+        /** A symbolic link. */
+        SYMLINK,
+        /** Something that is neither a regular file nor a directory nor a symbolic link. */
+        OTHER;
+
+        /**
+         * Determines the file type of a {@link Path}.
+         */
+        public static FileType of(Path p) throws IOException {
+            BasicFileAttributes attrs =
+                Files.readAttributes(p, BasicFileAttributes.class);
+            if (attrs.isRegularFile()) {
+                return FileType.REGULAR_FILE;
+            } else if (attrs.isDirectory()) {
+                return FileType.DIR;
+            } else if (attrs.isSymbolicLink()) {
+                return FileType.SYMLINK;
+            }
+            return FileType.OTHER;
+        }
+
+        /**
+         * Determines the file type of a {@link Resource}.
+         */
+        public static FileType of(Resource r) {
+            if (r.isDirectory()) {
+                return FileType.DIR;
+            }
+            return FileType.REGULAR_FILE;
+        }
+    }
+}
diff --git a/src/main/org/apache/tools/ant/util/StringUtils.java b/src/main/org/apache/tools/ant/util/StringUtils.java
index 626fb22..1576a09 100644
--- a/src/main/org/apache/tools/ant/util/StringUtils.java
+++ b/src/main/org/apache/tools/ant/util/StringUtils.java
@@ -19,7 +19,11 @@
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Vector;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
 
 import org.apache.tools.ant.BuildException;
 
@@ -270,4 +274,36 @@
             return string;
         }
     }
+    
+    /**
+     * Joins the string representation of the elements of a collection to 
+     * a joined string with a given separator.
+     * @param collection Collection of the data to be joined (may be null)
+     * @param separator Separator between elements (may be null)
+     * @return the joined string
+     */
+    public static String join(Collection<?> collection, CharSequence separator) {
+        if (collection == null) {
+            return "";
+        }
+        return collection.stream().map( o -> String.valueOf(o) ).collect(joining(separator));
+    }
+
+    /**
+     * Joins the string representation of the elements of an array to 
+     * a joined string with a given separator.
+     * @param array Array of the data to be joined (may be null)
+     * @param separator Separator between elements (may be null)
+     * @return the joined string
+     */
+    public static String join(Object[] array, CharSequence separator) {
+        if (array == null) {
+            return "";
+        }
+        return join(Arrays.asList(array), separator);
+    }
+
+    private static Collector<CharSequence,?,String> joining(CharSequence separator) {
+        return separator == null ? Collectors.joining() : Collectors.joining(separator);
+    }
 }
diff --git a/src/main/org/apache/tools/ant/util/depend/AbstractAnalyzer.java b/src/main/org/apache/tools/ant/util/depend/AbstractAnalyzer.java
index 5c95d75..eb5f97a 100644
--- a/src/main/org/apache/tools/ant/util/depend/AbstractAnalyzer.java
+++ b/src/main/org/apache/tools/ant/util/depend/AbstractAnalyzer.java
@@ -267,16 +267,10 @@
                 }
             } else {
                 // must be a zip of some sort
-                ZipFile zipFile = null;
-                try {
-                    zipFile = new ZipFile(element);
+                try (ZipFile zipFile = new ZipFile(element)) {
                     if (zipFile.getEntry(resourceLocation) != null) {
                         return element;
                     }
-                } finally {
-                    if (zipFile != null) {
-                        zipFile.close();
-                    }
                 }
             }
         }
diff --git a/src/tests/antunit/antunit-base.xml b/src/tests/antunit/antunit-base.xml
index 9863f3f..e8b3529 100644
--- a/src/tests/antunit/antunit-base.xml
+++ b/src/tests/antunit/antunit-base.xml
@@ -28,10 +28,6 @@
   <property name="test4.jar" location="${antunit.tmpdir}/test4.jar"/>
   <property name="test5.jar" location="${antunit.tmpdir}/test5.jar"/>
   <available property="jdk9+" classname="java.lang.module.ModuleDescriptor"/>
-  <available property="jdk1.8+" classname="java.lang.reflect.Executable"/>
-  <available property="jdk1.7+" classname="java.nio.file.FileSystem"/>
-  <available property="jdk1.6+" classname="java.net.CookieStore"/>
-  <available property="jdk1.5+" classname="java.net.Proxy"/>
   <condition property="build.sysclasspath.only">
     <equals arg1="${build.sysclasspath}" arg2="only"/>
   </condition>
diff --git a/src/tests/antunit/taskdefs/apt-test.xml b/src/tests/antunit/taskdefs/apt-test.xml
deleted file mode 100644
index 9b24001..0000000
--- a/src/tests/antunit/taskdefs/apt-test.xml
+++ /dev/null
@@ -1,158 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  Licensed to the Apache Software Foundation (ASF) under one or more
-  contributor license agreements.  See the NOTICE file distributed with
-  this work for additional information regarding copyright ownership.
-  The ASF licenses this file to You 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 default="antunit" xmlns:au="antlib:org.apache.ant.antunit">
-  <import file="../antunit-base.xml" />
-  <!-- apt tests -->
-
-  <property name="build.dir" location="aptbuild" />
-  <property name="classes.dir" location="${build.dir}/classes" />
-  <property name="classes2.dir" location="${build.dir}/classes2" />
-  <property name="preprocess.dir" location="${build.dir}/source" />
-  <property name="src" location="apt" />
-
-  <property name="AptExample.class" location="${classes.dir}/AptExample.class" />
-
-  <macrodef name="assertCompiled">
-    <attribute name="file" />
-    <sequential >
-      <fail  message="not found: @{file}">
-        <condition>
-          <not>
-            <available file="@{file}" />
-          </not>
-        </condition>
-      </fail>
-    </sequential>
-  </macrodef>
-
-  <macrodef name="assertProcessed">
-    <sequential>
-      <au:assertLogContains text="DistributedAnnotationProcessor-is-go"/>
-      <au:assertLogContains text="[-Abuild.dir="/>
-      <au:assertLogContains text="visiting DistributedAnnotationFactory"/>
-    </sequential>
-  </macrodef>
-
-  <presetdef name="assertAptExampleCompiled">
-    <assertCompiled file="${AptExample.class}"/>
-  </presetdef>
-
-  <target name="tearDown" depends="antunit-base.tearDown">
-    <delete dir="${build.dir}"/>
-  </target>
-
-  <target name="setUp">
-    <mkdir dir="${classes.dir}"/>
-    <mkdir dir="${classes2.dir}"/>
-    <mkdir dir="${preprocess.dir}"/>
-  </target>
-
-  <target name="testApt" depends="setUp" unless="jdk1.8+">
-    <apt srcdir="${src}"
-         destdir="${classes.dir}"
-         debug="on"
-         compile="true"
-         preprocessdir="${preprocess.dir}">
-    </apt>
-    <assertAptExampleCompiled />
-  </target>
-
-  <target name="testAptFork" depends="setUp" unless="jdk1.8+">
-    <apt srcdir="${src}"
-         destdir="${classes.dir}"
-         debug="on"
-         compile="true"
-         fork="true"
-         preprocessdir="${preprocess.dir}">
-    </apt>
-    <assertAptExampleCompiled />
-  </target>
-
-  <target name="testAptForkFalse" depends="setUp" unless="jdk1.8+">
-    <apt srcdir="${src}"
-         destdir="${classes.dir}"
-         debug="on"
-         compile="true"
-         fork="false"
-         preprocessdir="${preprocess.dir}">
-    </apt>
-    <assertAptExampleCompiled />
-    <au:assertLogContains text="Apt only runs in its own JVM; fork=false option ignored"/>
-
-  </target>
-
-  <target name="testListAnnotationTypes" depends="setUp" unless="jdk1.8+">
-    <apt srcdir="${src}"
-         destdir="${classes.dir}"
-         debug="on"
-         compile="true"
-         preprocessdir="${preprocess.dir}">
-         <compilerarg value="-XListAnnotationTypes" />
-         <compilerarg value="-Xlint:deprecation" /> 
-    </apt>
-  
-    <assertAptExampleCompiled />
-    <au:assertLogContains text="Set of annotations found:"/>
-    <au:assertLogContains text="Distributed"/>
-  </target>
-
-
-  <!-- use the factory we compiled. To avoid trouble
-    we deliver into a version in a new classpath, otherwise
-    the dependency logic will not run Apt-->
-  <target name="testAptNewFactory" depends="testApt" unless="jdk1.8+">
-    <apt srcdir="${src}"
-         destdir="${classes2.dir}"
-         debug="on"
-         compile="true"
-         factory="DistributedAnnotationFactory"
-         preprocessdir="${preprocess.dir}">
-         <factorypath path="${classes.dir}" />
-         <option name="build.dir" value="${build.dir}" />
-    </apt>
-    <assertAptExampleCompiled />
-    <assertProcessed />
-  </target>
-
-  <target name="testAptNewFactoryFork" depends="testApt" unless="jdk1.8+">
-    <apt srcdir="${src}"
-         destdir="${classes2.dir}"
-         debug="on"
-         compile="true"
-         fork="true"
-         factory="DistributedAnnotationFactory"
-         preprocessdir="${preprocess.dir}">
-         <factorypath path="${classes.dir}" />
-         <option name="build.dir" value="${build.dir}" />
-    </apt>
-    <assertAptExampleCompiled />
-    <assertProcessed />
-  </target>
-
-  <target name="testAptUnderJDK18" if="jdk1.8+">
-    <au:expectfailure expectedMessage="apt does not exist under Java 1.8 and higher">
-      <apt srcdir="${src}"
-           destdir="${classes.dir}"
-           debug="on"
-           compile="true"
-           fork="true"
-           preprocessdir="${preprocess.dir}">
-      </apt>
-    </au:expectfailure>
-  </target>
-</project>
\ No newline at end of file
diff --git a/src/tests/antunit/taskdefs/apt/AptExample.java b/src/tests/antunit/taskdefs/apt/AptExample.java
deleted file mode 100644
index 9d6fcba..0000000
--- a/src/tests/antunit/taskdefs/apt/AptExample.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You 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.
- *
- */
-/**
- */
-@Distributed(
-        protocol="CORBA",
-        distribution=Distributed.DistributionTypes.FEDERATED
-        )
-public class AptExample {
-}
diff --git a/src/tests/antunit/taskdefs/apt/Distributed.java b/src/tests/antunit/taskdefs/apt/Distributed.java
deleted file mode 100644
index ebc3467..0000000
--- a/src/tests/antunit/taskdefs/apt/Distributed.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You 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.
- *
- */
-import java.lang.annotation.Annotation;
-import java.lang.annotation.Target;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- */
-@Documented
-@Retention(value = RetentionPolicy.RUNTIME)
-@Target(value = ElementType.TYPE)
-public @interface Distributed  {
-
-    public DistributionTypes distribution() default DistributionTypes.LOCAL;
-
-    public String protocol() default "RMI";
-
-    public enum DistributionTypes { SINGLETON, LOCAL, FAULT_TOLERANT, FEDERATED, MOBILE};
-
-
-}
diff --git a/src/tests/antunit/taskdefs/apt/DistributedAnnotationFactory.java b/src/tests/antunit/taskdefs/apt/DistributedAnnotationFactory.java
deleted file mode 100644
index a8fb633..0000000
--- a/src/tests/antunit/taskdefs/apt/DistributedAnnotationFactory.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You 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.
- *
- */
-import com.sun.mirror.apt.AnnotationProcessorFactory;
-import com.sun.mirror.apt.AnnotationProcessor;
-import com.sun.mirror.apt.AnnotationProcessorEnvironment;
-
-import java.util.Collection;
-import java.util.Set;
-import java.util.Arrays;
-import java.util.Collections;
-
-
-/**
- * This was the first piece of Java1.5 code in the source tree.
- * @since 20050-03-09T21:29:25Z
- */
-public class DistributedAnnotationFactory implements AnnotationProcessorFactory {
-
-    private static final Collection<String> supportedAnnotations
-            = Collections.unmodifiableCollection(Arrays.asList("*"));
-
-    public Collection<String> supportedOptions() {
-        return Collections.emptySet();
-    }
-
-    public Collection<String> supportedAnnotationTypes() {
-        return supportedAnnotations;
-    }
-
-    public AnnotationProcessor getProcessorFor(
-            Set<com.sun.mirror.declaration.AnnotationTypeDeclaration> annotationTypeDeclarations,
-            AnnotationProcessorEnvironment env) {
-        return new DistributedAnnotationProcessor(env);
-    }
-}
diff --git a/src/tests/antunit/taskdefs/apt/DistributedAnnotationProcessor.java b/src/tests/antunit/taskdefs/apt/DistributedAnnotationProcessor.java
deleted file mode 100644
index f94ff7f..0000000
--- a/src/tests/antunit/taskdefs/apt/DistributedAnnotationProcessor.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You 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.
- *
- */
-
-//found in tools.jar, not the JRE runtime.
-import com.sun.mirror.apt.AnnotationProcessor;
-import com.sun.mirror.apt.AnnotationProcessorEnvironment;
-import com.sun.mirror.declaration.TypeDeclaration;
-import com.sun.mirror.declaration.ClassDeclaration;
-import com.sun.mirror.util.SimpleDeclarationVisitor;
-import static com.sun.mirror.util.DeclarationVisitors.*;
-
-import java.util.Map;
-
-/**
- * Annotation processor outputs stuff
- */
-
-public class DistributedAnnotationProcessor implements AnnotationProcessor {
-
-    public AnnotationProcessorEnvironment env;
-
-    public DistributedAnnotationProcessor(AnnotationProcessorEnvironment env) {
-        this.env = env;
-    }
-
-    public void echo(String text) {
-        env.getMessager().printNotice(text);
-    }
-
-    public void process() {
-        echo("DistributedAnnotationProcessor-is-go");
-
-        Map<String, String> options=env.getOptions();
-        for(String key:options.keySet()) {
-            echo("Option ["+key+"] = "+options.get(key));
-        }
-
-        //work time
-        for (TypeDeclaration typeDecl : env.getSpecifiedTypeDeclarations()) {
-            typeDecl.accept(getDeclarationScanner(new ClassVisitor(),
-                    NO_OP));
-        }
-    }
-
-    private class ClassVisitor extends SimpleDeclarationVisitor {
-        public void visitClassDeclaration(ClassDeclaration d) {
-            echo("visiting "+ d.getQualifiedName());
-        }
-    }
-}
diff --git a/src/tests/antunit/taskdefs/copy-test.xml b/src/tests/antunit/taskdefs/copy-test.xml
index 51c6277..9b0148b 100644
--- a/src/tests/antunit/taskdefs/copy-test.xml
+++ b/src/tests/antunit/taskdefs/copy-test.xml
@@ -312,13 +312,10 @@
     <mkdir dir="${input}"/>
     <touch file="${output}/${file}"/>
   </target>
-  <target name="makeFileUnwritable"
-          depends="createTestdir,makeFileUnwritable-Unix,makeFileUnwritable-Windows"/>
-  <target name="makeFileUnwritable-Unix" id="unix">
-    <chmod file="${output}/${file}" perm="444"/>
-  </target>
-  <target name="makeFileUnwritable-Windows" unless="unix">
-    <attrib file="${output}/${file}" readonly="true"/>
+  <target name="makeFileUnwritable" depends="createTestdir">
+    <setpermissions mode="444" nonPosixMode="tryDosOrFail">
+      <file file="${output}/${file}"/>
+    </setpermissions>
   </target>
 
   <target name="testCopyOverReadOnlyFile" depends="makeFileUnwritable">
@@ -453,14 +450,9 @@
     <mkdir dir="${output}"/>
     <touch file="${input}/somefile"/>
     <touch file="${output}/somefile"/>
-    <exec executable="chmod" osfamily="unix">
-      <arg value="-w"/>
-      <arg file="${output}/somefile"/>
-    </exec>
-    <exec executable="attrib" osfamily="dos">
-      <arg value="+r"/>
-      <arg file="${output}/somefile"/>
-    </exec>
+    <setpermissions mode="444" nonPosixMode="tryDosOrFail">
+      <file file="${output}/somefile"/>
+    </setpermissions>
     <au:expectfailure>
       <copy todir="${output}" file="${input}/somefile"
             overwrite="true"/>
diff --git a/src/tests/antunit/taskdefs/javac-test.xml b/src/tests/antunit/taskdefs/javac-test.xml
index de193ea..a3ffc82 100644
--- a/src/tests/antunit/taskdefs/javac-test.xml
+++ b/src/tests/antunit/taskdefs/javac-test.xml
@@ -220,28 +220,7 @@
       <mkdir dir="${javac-dir}/classes"/>
     </sequential>
     
-    <sequential unless:set="jdk9+">
-      <echo>JDK 1.5+</echo>
-      <testJavac source="1.5"/>
-      <delete dir="${javac-dir}/classes"/>
-      <mkdir dir="${javac-dir}/classes"/>
-    </sequential>
-    
-    <sequential if:set="jdk1.6+">
-      <echo>JDK 1.6+</echo>
-      <testJavac source="1.6"/>
-      <delete dir="${javac-dir}/classes"/>
-      <mkdir dir="${javac-dir}/classes"/>
-    </sequential>
-  		
-    <sequential if:set="jdk1.7+">
-      <echo>JDK 1.7+</echo>
-      <testJavac source="1.7"/>
-      <delete dir="${javac-dir}/classes"/>
-      <mkdir dir="${javac-dir}/classes"/>
-    </sequential>
-    
-    <sequential if:set="jdk1.8+">
+    <sequential unless:set="jdk1.9+">
       <echo>JDK 1.8+</echo>
       <testJavac source="1.8"/>
       <delete dir="${javac-dir}/classes"/>
@@ -272,34 +251,6 @@
     </au:expectfailure>
 
     <sequential unless:set="jdk9+">
-      <echo>JDK 1.4+</echo>
-      <testJavac source="1.4" target="1.4"/>
-      <delete dir="${javac-dir}/classes"/>
-      <mkdir dir="${javac-dir}/classes"/>
-    </sequential>
-
-    <sequential unless:set="jdk9+">
-      <echo>JDK 1.5+</echo>
-      <testJavac source="1.5" target="1.5"/>
-      <delete dir="${javac-dir}/classes"/>
-      <mkdir dir="${javac-dir}/classes"/>
-    </sequential>
-    
-    <sequential if:set="jdk1.6+">
-      <echo>JDK 1.6+</echo>
-      <testJavac source="1.6" target="1.6"/>
-      <delete dir="${javac-dir}/classes"/>
-      <mkdir dir="${javac-dir}/classes"/>
-    </sequential>
-        
-    <sequential if:set="jdk1.7+">
-      <echo>JDK 1.7+</echo>
-      <testJavac source="1.7" target="1.7"/>
-      <delete dir="${javac-dir}/classes"/>
-      <mkdir dir="${javac-dir}/classes"/>
-    </sequential>
-    
-    <sequential if:set="jdk1.8+">
       <echo>JDK 1.8+</echo>
       <testJavac source="1.8" target="1.8"/>
       <delete dir="${javac-dir}/classes"/>
diff --git a/src/tests/antunit/taskdefs/move-test.xml b/src/tests/antunit/taskdefs/move-test.xml
index 9acac74..3584f9b 100644
--- a/src/tests/antunit/taskdefs/move-test.xml
+++ b/src/tests/antunit/taskdefs/move-test.xml
@@ -134,13 +134,10 @@
     <mkdir dir="${input}"/>
     <touch file="${output}/${file}"/>
   </target>
-  <target name="makeFileUnwritable"
-          depends="createTestdir,makeFileUnwritable-Unix,makeFileUnwritable-Windows"/>
-  <target name="makeFileUnwritable-Unix" id="unix">
-    <chmod file="${output}/${file}" perm="444"/>
-  </target>
-  <target name="makeFileUnwritable-Windows" unless="unix">
-    <attrib file="${output}/${file}" readonly="true"/>
+  <target name="makeFileUnwritable" depends="createTestdir">
+    <setpermissions mode="444" nonPosixMode="tryDosOrFail">
+      <file file="${output}/${file}"/>
+    </setpermissions>
   </target>
 
   <target name="testMoveOverReadOnlyFile" depends="makeFileUnwritable">
diff --git a/src/tests/antunit/taskdefs/optional/junit/junit-test.xml b/src/tests/antunit/taskdefs/optional/junit/junit-test.xml
index e6aa794..d93b96e 100644
--- a/src/tests/antunit/taskdefs/optional/junit/junit-test.xml
+++ b/src/tests/antunit/taskdefs/optional/junit/junit-test.xml
@@ -317,10 +317,7 @@
   </target>
 
   <target name="testTestMethods">
-    <condition property="source" value="6">
-      <isset property="jdk1.6+"/>
-    </condition>
-    <property name="source" value="5"/>
+    <property name="source" value="8"/>
     <echo file="${input}/T1.java">public class T1 extends
 			junit.framework.TestCase {
 			public void testOK() {}
diff --git a/src/tests/antunit/taskdefs/secure-input.xml b/src/tests/antunit/taskdefs/secure-input.xml
index 8311ce9..ae0675e 100644
--- a/src/tests/antunit/taskdefs/secure-input.xml
+++ b/src/tests/antunit/taskdefs/secure-input.xml
@@ -22,7 +22,7 @@
   <target name="setUp">
   </target>
 
-  <target name="test-secure-input" if="jdk1.6+">
+  <target name="test-secure-input">
     <input message="secure-input:>" addproperty="the.password">
       <handler classname="org.apache.tools.ant.input.SecureInputHandler" />
     </input>
diff --git a/src/tests/antunit/taskdefs/setpermissions-test.xml b/src/tests/antunit/taskdefs/setpermissions-test.xml
new file mode 100644
index 0000000..99b90e0
--- /dev/null
+++ b/src/tests/antunit/taskdefs/setpermissions-test.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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 xmlns:au="antlib:org.apache.ant.antunit" default="antunit">
+
+  <import file="../antunit-base.xml" />
+
+  <target name="setUp">
+    <mkdir dir="${input}"/>
+    <property name="file" location="${input}/file"/>
+    <touch file="${file}"/>
+  </target>
+
+  <target name="testRequiresNestedResources" depends="setUp">
+    <au:expectfailure expectedMessage="At least one resource-collection is required">
+      <setpermissions mode="644" />
+    </au:expectfailure>
+  </target>
+
+  <target name="testPermissionsSetViaPermissionsAttribute"
+          depends="setUp">
+    <setpermissions permissions="OWNER_READ,GROUP_READ,OTHERS_READ"
+                    nonPosixMode="tryDosOrFail">
+      <file file="${file}"/>
+    </setpermissions>
+    <au:assertFalse>
+      <isfileselected file="${file}">
+        <writable/>
+      </isfileselected>
+    </au:assertFalse>
+    <au:assertTrue>
+      <isfileselected file="${file}">
+        <readable/>
+      </isfileselected>
+    </au:assertTrue>
+  </target>
+
+  <target name="testPermissionsSetViaModeAttribute"
+          depends="setUp">
+    <setpermissions mode="444" nonPosixMode="tryDosOrFail">
+      <file file="${file}"/>
+    </setpermissions>
+    <au:assertFalse>
+      <isfileselected file="${file}">
+        <writable/>
+      </isfileselected>
+    </au:assertFalse>
+    <au:assertTrue>
+      <isfileselected file="${file}">
+        <readable/>
+      </isfileselected>
+    </au:assertTrue>
+  </target>
+</project>
diff --git a/src/tests/antunit/taskdefs/taskdef-antlib-test.xml b/src/tests/antunit/taskdefs/taskdef-antlib-test.xml
index 58d01f0..72f21ae 100644
--- a/src/tests/antunit/taskdefs/taskdef-antlib-test.xml
+++ b/src/tests/antunit/taskdefs/taskdef-antlib-test.xml
@@ -18,9 +18,7 @@
 <project default="antunit" xmlns:au="antlib:org.apache.ant.antunit">
     <import file="../antunit-base.xml" />
 
-    <!-- Java5 has some trouble with the recursive Antlib lookup -->
-
-    <target name="setUp" if="jdk1.6+">
+    <target name="setUp">
         <mkdir dir="${input}/org/example" />
         <property name="tmpdir" location="../../../../build/ant-unit/taskdef" />
         <mkdir dir="${tmpdir}" />
@@ -46,14 +44,14 @@
         <sleep seconds="1"/>
     </target>
 
-    <target name="testAntlib" depends="setUp" if="jdk1.6+">
+    <target name="testAntlib" depends="setUp">
         <taskdef classpath="${test.jar}" uri="antlib:org.example"
                  loaderref="loader1"/>
         <echoooo xmlns="antlib:org.example" message="exemple" />
         <au:assertLogContains text="exempleexempleexempleexemple" />
     </target>
 
-    <target name="testURI" depends="setUp" if="jdk1.6+">
+    <target name="testURI" depends="setUp">
         <taskdef classpath="${test.jar}" uri="urn:my:exemple"
                  loaderref="loader2"
                  resource="org/example/antlib.xml" />
diff --git a/src/tests/antunit/taskdefs/taskdef-test.xml b/src/tests/antunit/taskdefs/taskdef-test.xml
index 9574508..1da8e9f 100644
--- a/src/tests/antunit/taskdefs/taskdef-test.xml
+++ b/src/tests/antunit/taskdefs/taskdef-test.xml
@@ -41,7 +41,7 @@
     <au:assertLogContains text="Hello"/>
   </target>
 
-  <target name="testDirWithPling" depends="setUp" if="jdk1.6+"
+  <target name="testDirWithPling" depends="setUp"
           description="https://issues.apache.org/bugzilla/show_bug.cgi?id=50007">
     <property name="dir" location="${tmpdir}/pl!ng"/>
     <mkdir dir="${dir}"/>
diff --git a/src/tests/antunit/taskdefs/xslt-test.xml b/src/tests/antunit/taskdefs/xslt-test.xml
index d6f6d66..b327c7b 100644
--- a/src/tests/antunit/taskdefs/xslt-test.xml
+++ b/src/tests/antunit/taskdefs/xslt-test.xml
@@ -187,18 +187,7 @@
     </xslt>
   </target>
 
-
-  <target name="testTraceJdk14" unless="jdk1.5+" depends="setUp">
-    <xslt in="${legacy.dir}/data.xml"
-          out="${output}/out.xml"
-          style="${legacy.dir}/printParams.xsl">
-      <param name="set" expression="myvalue"/>
-      <trace templates="true"/>
-    </xslt>
-    <au:assertLogContains text="Failed to enable tracing" level="warning"/>
-  </target>
-
-  <target name="testTraceJdk15+" if="jdk1.5+" depends="setUp">
+  <target name="testTrace" depends="setUp">
     <xslt in="${legacy.dir}/data.xml"
           out="${output}/out.xml"
           style="${legacy.dir}/printParams.xsl">
diff --git a/src/tests/antunit/types/resources/selectors/readwrite-test.xml b/src/tests/antunit/types/resources/selectors/readwrite-test.xml
index 6a0301b..4247875 100644
--- a/src/tests/antunit/types/resources/selectors/readwrite-test.xml
+++ b/src/tests/antunit/types/resources/selectors/readwrite-test.xml
@@ -70,13 +70,10 @@
     </au:assertTrue>
   </target>
 
-  <target name="makeFileUnwritable"
-          depends="createTestdir,makeFileUnwritable-Unix,makeFileUnwritable-Windows"/>
-  <target name="makeFileUnwritable-Unix" id="unix">
-    <chmod file="${output}/${file}" perm="444"/>
-  </target>
-  <target name="makeFileUnwritable-Windows" unless="unix">
-    <attrib file="${output}/${file}" readonly="true"/>
+  <target name="makeFileUnwritable" depends="createTestdir">
+    <setpermissions mode="444" nonPosixMode="tryDosOrFail">
+      <file file="${output}/${file}"/>
+    </setpermissions>
   </target>
 
   <target name="testUnwritable" depends="makeFileUnwritable">
diff --git a/src/tests/antunit/types/selectors/executable-test.xml b/src/tests/antunit/types/selectors/executable-test.xml
new file mode 100644
index 0000000..45cbeeb
--- /dev/null
+++ b/src/tests/antunit/types/selectors/executable-test.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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 xmlns:au="antlib:org.apache.ant.antunit" default="antunit">
+
+  <import file="../../antunit-base.xml" />
+
+  <property name="file" value="testfile"/>
+
+  <condition property="unix">
+    <os family="unix"/>
+  </condition>
+
+  <target name="createTestdir">
+    <mkdir dir="${output}"/>
+    <touch file="${output}/${file}"/>
+  </target>
+
+  <target name="testExecutable" depends="makeFileExecutable" if="unix">
+    <au:assertTrue>
+      <resourcecount when="equal" count="1">
+        <fileset dir="${output}">
+          <executable/>
+        </fileset>
+      </resourcecount>
+    </au:assertTrue>
+    <au:assertTrue>
+      <resourcecount when="equal" count="0">
+        <fileset dir="${output}" excludes="${file}">
+          <executable/>
+        </fileset>
+      </resourcecount>
+    </au:assertTrue>
+  </target>
+
+  <target name="makeFileExecutable" depends="createTestdir">
+    <setpermissions mode="755" nonPosixMode="pass">
+      <file file="${output}/${file}"/>
+    </setpermissions>
+  </target>
+
+  <target name="testNotexecutable" depends="createTestdir" if="unix">
+    <au:assertTrue>
+      <resourcecount when="equal" count="0">
+        <fileset dir="${output}">
+          <executable/>
+        </fileset>
+      </resourcecount>
+    </au:assertTrue>
+  </target>
+
+  <target name="testAsFalseConditions" depends="createTestdir" if="unix">
+    <au:assertFalse>
+      <isfileselected file="${output}/${file}">
+        <executable/>
+      </isfileselected>
+    </au:assertFalse>
+  </target>
+
+  <target name="testAsTrueConditions" depends="makeFileExecutable" if="unix">
+    <au:assertTrue>
+      <isfileselected file="${output}/${file}">
+        <executable/>
+      </isfileselected>
+    </au:assertTrue>
+  </target>
+
+</project>
diff --git a/src/tests/antunit/types/selectors/ownedby-test.xml b/src/tests/antunit/types/selectors/ownedby-test.xml
new file mode 100644
index 0000000..5ec4381
--- /dev/null
+++ b/src/tests/antunit/types/selectors/ownedby-test.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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 xmlns:au="antlib:org.apache.ant.antunit" default="antunit">
+
+  <import file="../../antunit-base.xml" />
+
+  <property name="file" value="testfile"/>
+
+  <condition property="unix">
+    <os family="unix"/>
+  </condition>
+
+  <target name="createTestdir">
+    <mkdir dir="${output}"/>
+    <touch file="${output}/${file}"/>
+  </target>
+
+  <target name="testRequiresOwner" depends="createTestdir">
+    <au:expectfailure expectedMessage="the owner attribute is required">
+      <au:assertTrue>
+        <isfileselected file="${output}/${file}">
+          <ownedBy/>
+        </isfileselected>
+      </au:assertTrue>
+    </au:expectfailure>
+  </target>
+
+  <!-- at least on Jenkins the file is owned by BUILTIN\Administrators -->
+  <target name="testOwnedBy" depends="createTestdir" if="unix">
+    <au:assertTrue>
+      <resourcecount when="equal" count="1">
+        <fileset dir="${output}">
+          <ownedBy owner="${user.name}"/>
+        </fileset>
+      </resourcecount>
+    </au:assertTrue>
+    <au:assertTrue>
+      <resourcecount when="equal" count="0">
+        <fileset dir="${output}" excludes="${file}">
+          <ownedBy owner="${user.name}"/>
+        </fileset>
+      </resourcecount>
+    </au:assertTrue>
+  </target>
+
+  <target name="testAsTrueConditions" depends="createTestdir" if="unix">
+    <au:assertTrue>
+      <isfileselected file="${output}/${file}">
+        <ownedBy owner="${user.name}"/>
+      </isfileselected>
+    </au:assertTrue>
+  </target>
+
+</project>
diff --git a/src/tests/antunit/types/selectors/readwrite-test.xml b/src/tests/antunit/types/selectors/readwrite-test.xml
index bd4ac8d..62dc052 100644
--- a/src/tests/antunit/types/selectors/readwrite-test.xml
+++ b/src/tests/antunit/types/selectors/readwrite-test.xml
@@ -64,13 +64,10 @@
     </au:assertTrue>
   </target>
 
-  <target name="makeFileUnwritable"
-          depends="createTestdir,makeFileUnwritable-Unix,makeFileUnwritable-Windows"/>
-  <target name="makeFileUnwritable-Unix" id="unix">
-    <chmod file="${output}/${file}" perm="444"/>
-  </target>
-  <target name="makeFileUnwritable-Windows" unless="unix">
-    <attrib file="${output}/${file}" readonly="true"/>
+  <target name="makeFileUnwritable" depends="createTestdir">
+    <setpermissions mode="444" nonPosixMode="tryDosOrFail">
+      <file file="${output}/${file}"/>
+    </setpermissions>
   </target>
 
   <target name="testUnwritable" depends="makeFileUnwritable">
diff --git a/src/tests/antunit/types/selectors/symlink-test.xml b/src/tests/antunit/types/selectors/symlink-test.xml
new file mode 100644
index 0000000..0c47326
--- /dev/null
+++ b/src/tests/antunit/types/selectors/symlink-test.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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 xmlns:au="antlib:org.apache.ant.antunit" default="antunit">
+
+  <import file="../../antunit-base.xml" />
+
+  <property name="file" value="testfile"/>
+  <property name="link" value="testlink"/>
+
+  <condition property="unix">
+    <os family="unix"/>
+  </condition>
+
+  <target name="createTestdir">
+    <mkdir dir="${output}"/>
+    <touch file="${output}/${file}"/>
+  </target>
+
+  <target name="testSymlink" depends="makeSymlink" if="unix">
+    <au:assertTrue>
+      <resourcecount when="equal" count="1">
+        <fileset dir="${output}">
+          <symlink/>
+        </fileset>
+      </resourcecount>
+    </au:assertTrue>
+    <au:assertTrue>
+      <resourcecount when="equal" count="0">
+        <fileset dir="${output}" excludes="${link}">
+          <symlink/>
+        </fileset>
+      </resourcecount>
+    </au:assertTrue>
+  </target>
+
+  <target name="makeSymlink"
+          depends="createTestdir,makeSymlink-Unix,makeSymlink-Windows"/>
+  <target name="makeSymlink-Unix" if="unix">
+    <symlink link="${output}/${link}" resource="${output}/${file}"/>
+  </target>
+  <target name="makeSymlink-Windows" unless="unix">
+    <!-- no idea how to do this -->
+  </target>
+
+  <target name="testNoSymlink" depends="createTestdir">
+    <au:assertTrue>
+      <resourcecount when="equal" count="0">
+        <fileset dir="${output}">
+          <symlink/>
+        </fileset>
+      </resourcecount>
+    </au:assertTrue>
+  </target>
+
+  <target name="testAsFalseConditions" depends="createTestdir">
+    <au:assertFalse>
+      <isfileselected file="${output}/${link}">
+        <symlink/>
+      </isfileselected>
+    </au:assertFalse>
+  </target>
+
+  <target name="testAsTrueConditions" depends="makeSymlink" if="unix">
+    <au:assertTrue>
+      <isfileselected file="${output}/${link}">
+        <symlink/>
+      </isfileselected>
+    </au:assertTrue>
+  </target>
+
+</project>
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/JavacTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/JavacTest.java
index 67e31e9..364a50e 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/JavacTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/JavacTest.java
@@ -35,7 +35,6 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 /**
  * Testcase for <javac>.
@@ -249,46 +248,31 @@
         assertEquals("1.5", javac.getTarget());
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void testModulesourcepathOrSrcDirRequired() {
-        try {
-            javac.checkParameters();
-            fail("Build exception should have been thrown - neither srcDir nor modulesourcepath");
-        } catch (BuildException e) {
-            //pass
-        }
+        javac.checkParameters();
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void testModulesourcepathAndSrcDirForbidden() {
-        try {
-            javac.checkParameters();
-            final Path p = new Path(project);
-            p.setPath("src");
-            javac.setSrcdir(p);
-            final Path mp = new Path(project);
-            p.setPath("modsrc");
-            javac.setModulesourcepath(mp);
-            fail("Build exception should have been thrown - neither srcDir nor modulesourcepath");
-        } catch (BuildException e) {
-            //pass
-        }
+        javac.checkParameters();
+        final Path p = new Path(project);
+        p.setPath("src");
+        javac.setSrcdir(p);
+        final Path mp = new Path(project);
+        p.setPath("modsrc");
+        javac.setModulesourcepath(mp);
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void testModulesourcepathAndSourcepathForbidden() {
-        try {
-            javac.checkParameters();
-            final Path p = new Path(project);
-            p.setPath("src");
-            javac.setSourcepath(p);
-            final Path mp = new Path(project);
-            p.setPath("modsrc");
-            javac.setModulesourcepath(mp);
-            fail("Build exception should have been thrown - neither srcDir nor modulesourcepath");
-        } catch (BuildException e) {
-            //pass
-        }
+        javac.checkParameters();
+        final Path p = new Path(project);
+        p.setPath("src");
+        javac.setSourcepath(p);
+        final Path mp = new Path(project);
+        p.setPath("modsrc");
+        javac.setModulesourcepath(mp);
     }
 
     @Test
@@ -317,16 +301,11 @@
         }
     }
 
-    @Test
+    @Test(expected = BuildException.class)
     public void testModulesourcepathRequiresDestdir() {
-        try {
-            final Path p = new Path(project);
-            p.setPath("src");
-            javac.setModulesourcepath(p);
-            javac.checkParameters();
-            fail("Build exception should have been thrown - modulesourcepath requires destdir");
-        } catch (BuildException e) {
-            //pass
-        }
+        final Path p = new Path(project);
+        p.setPath("src");
+        javac.setModulesourcepath(p);
+        javac.checkParameters();
     }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/RmicAdvancedTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/RmicAdvancedTest.java
index 3753b68..f2f1861 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/RmicAdvancedTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/RmicAdvancedTest.java
@@ -348,28 +348,6 @@
     }
 
     /**
-     * test that passes -Xnew to sun's rmic.
-     *
-     * @throws Exception
-     */
-    @Test
-    public void testXnew() throws Exception {
-        // skipped via unless attribute for JDK > 6
-        buildRule.executeTarget("testXnew");
-    }
-
-    /**
-     * test that passes -Xnew to sun's rmic.
-     *
-     * @throws Exception
-     */
-    @Test
-    public void testXnewDest() throws Exception {
-        // skipped via unless attribute for JDK > 6
-        buildRule.executeTarget("testXnewDest");
-    }
-
-    /**
      * test that passes -Xnew to sun's rmic running in a different VM.
      *
      * @throws Exception
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/SignJarTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/SignJarTest.java
index 95585fd..93d5e78 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/SignJarTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/SignJarTest.java
@@ -106,7 +106,6 @@
 
     @Test
     public void testTsaLocalhost() {
-        Assume.assumeTrue("Only runs on Java 1.5+", JavaEnvUtils.getJavaVersionNumber()>=15);
         try {
             buildRule.executeTarget("testTsaLocalhost");
             fail("Should have thrown exception - no TSA at localhost:0");
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapterTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapterTest.java
index 3064876..4292806 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapterTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/compilers/DefaultCompilerAdapterTest.java
@@ -232,6 +232,7 @@
             javac.setProject(prj);
             final Commandline[] cmd = new Commandline[1];
             final DefaultCompilerAdapter impl = new DefaultCompilerAdapter() {
+                @Override
                 public boolean execute() throws BuildException {
                     cmd[0] = setupModernJavacCommand();
                     return true;
@@ -288,6 +289,7 @@
             javac.setProject(prj);
             final Commandline[] cmd = new Commandline[1];
             final DefaultCompilerAdapter impl = new DefaultCompilerAdapter() {
+                @Override
                 public boolean execute() throws BuildException {
                     cmd[0] = setupModernJavacCommand();
                     return true;
@@ -351,6 +353,7 @@
             final LogCapturingJavac javac = new LogCapturingJavac();
             javac.setProject(prj);
             final DefaultCompilerAdapter impl = new DefaultCompilerAdapter() {
+                @Override
                 public boolean execute() throws BuildException {
                     setupModernJavacCommand();
                     return true;
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskTest.java
index 33fd3b0..5284d56 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskTest.java
@@ -1,398 +1,602 @@
-/*

- *  Licensed to the Apache Software Foundation (ASF) under one or more

- *  contributor license agreements.  See the NOTICE file distributed with

- *  this work for additional information regarding copyright ownership.

- *  The ASF licenses this file to You 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.

- *

- */

-package org.apache.tools.ant.taskdefs.optional.junit;

-

-import static org.junit.Assert.assertEquals;

-import static org.junit.Assert.assertFalse;

-import static org.junit.Assert.assertNotNull;

-import static org.junit.Assert.assertNull;

-import static org.junit.Assert.assertTrue;

-

-import static org.apache.tools.ant.AntAssert.assertNotContains;

-import static org.apache.tools.ant.AntAssert.assertContains;

-

-import java.io.BufferedReader;

-import java.io.File;

-import java.io.FileReader;

-import java.io.IOException;

-

-import javax.xml.parsers.DocumentBuilder;

-import javax.xml.parsers.DocumentBuilderFactory;

-import javax.xml.xpath.XPath;

-import javax.xml.xpath.XPathConstants;

-import javax.xml.xpath.XPathFactory;

-

-import org.apache.tools.ant.BuildFileRule;

-import org.apache.tools.ant.util.JavaEnvUtils;

-import org.junit.Assume;

-import org.junit.Before;

-import org.junit.Rule;

-import org.junit.Test;

-import org.w3c.dom.Document;

-import org.w3c.dom.Node;

-

-public class JUnitTaskTest {

-

-	@Rule

-	public BuildFileRule buildRule = new BuildFileRule();

-	

-    /**

-     * The JUnit setup method.

-     */

-	@Before

-    public void setUp() {

-        buildRule.configureProject("src/etc/testcases/taskdefs/optional/junit.xml");

-    }

-

-	@Test

-    public void testCrash() {

-    	buildRule.executeTarget("crash");

-    	assertEquals("true", buildRule.getProject().getProperty("crashed"));

-    }

-

-	@Test

-    public void testNoCrash() {

-    	buildRule.executeTarget("nocrash");

-    	assertNull(buildRule.getProject().getProperty("crashed"));

-    }

-

-	@Test

-    public void testTimeout() {

-    	buildRule.executeTarget("timeout");

-    	assertEquals("true", buildRule.getProject().getProperty("timeout"));

-    }

-

-    @Test

-    public void testNoTimeout() {

-       buildRule.executeTarget("notimeout");

-   	   assertNull(buildRule.getProject().getProperty("timeout"));

-    }

-

-    @Test

-    public void testNonForkedCapture() throws IOException {

-        buildRule.executeTarget("capture");

-        assertNoPrint(buildRule.getLog(), "log");

-        assertNoPrint(buildRule.getFullLog(), "debug log");

-    }

-

-    @Test

-    public void testForkedCapture() throws IOException {

-        buildRule.getProject().setProperty("fork", "true");

-        testNonForkedCapture();

-        // those would fail because of the way BuildFileRule captures output

-        assertNoPrint(buildRule.getOutput(), "output");

-        assertNoPrint(buildRule.getError(), "error output");

-        assertOutput();

-    }

-

-    @Test

-    public void testBatchTestForkOnceToDir() {

-        assertResultFilesExist("testBatchTestForkOnceToDir", ".xml");

-    }

-

-    /** Bugzilla Report 32973 */

-    @Test

-    public void testBatchTestForkOnceExtension() {

-        assertResultFilesExist("testBatchTestForkOnceExtension", ".foo");

-    }

-

-

-    /* Bugzilla Report 42984 */

-    //TODO This scenario works from command line, but not from JUnit ...

-    //     Running these steps from the junit.xml-directory work

-    //     $ ant -f junit.xml failureRecorder.prepare

-    //     $ ant -f junit.xml failureRecorder.runtest

-    //     $ ant -f junit.xml failureRecorder.runtest

-    //     $ ant -f junit.xml failureRecorder.fixing

-    //     $ ant -f junit.xml failureRecorder.runtest

-    //     $ ant -f junit.xml failureRecorder.runtest

-    //     But running the JUnit testcase fails in 4th run.

-    @Test

-    public void testFailureRecorder() {

-        if (JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_1_5)) {

-            try {

-            	Class<?> clazz =Class.forName("junit.framework.JUnit4TestAdapter");

-                Assume.assumeFalse("Skipping test since it fails with JUnit 4", clazz != null);

-            } catch (ClassNotFoundException e) {

-                // OK, this is JUnit3, can run test

-            }

-        }

-

-        File testDir = new File(buildRule.getOutputDir(), "out");

-        File collectorFile = new File(buildRule.getOutputDir(),

-                "out/FailedTests.java");

-

-        // ensure that there is a clean test environment

-        assertFalse("Test directory '" + testDir.getAbsolutePath()

-                    + "' must not exist before the test preparation.", 

-                    testDir.exists());

-        assertFalse("The collector file '"

-                    + collectorFile.getAbsolutePath()

-                    + "'must not exist before the test preparation.", 

-                    collectorFile.exists());

-

-    

-        // prepare the test environment

-        buildRule.executeTarget("failureRecorder.prepare");

-        assertTrue("Test directory '" + testDir.getAbsolutePath()

-                   + "' was not created.", testDir.exists());

-        assertTrue("There should be one class.",

-                   (new File(testDir, "A.class")).exists());

-        assertFalse("The collector file '"

-                    + collectorFile.getAbsolutePath() 

-                    + "' should not exist before the 1st run.",

-                    collectorFile.exists());

-    

-    

-        // 1st junit run: should do all tests - failing and not failing tests

-        buildRule.executeTarget("failureRecorder.runtest");

-        assertTrue("The collector file '" + collectorFile.getAbsolutePath() 

-                   + "' should exist after the 1st run.",

-                   collectorFile.exists());

-        // the passing test cases

-        buildRule.executeTarget("A.test01");

-        assertContains("1st run: should run A.test01", buildRule.getOutput());

-        buildRule.executeTarget("B.test05");

-        assertContains("1st run: should run B.test05", buildRule.getOutput());

-        buildRule.executeTarget("B.test06");

-        assertContains("1st run: should run B.test06", buildRule.getOutput());

-        buildRule.executeTarget("C.test07");

-        assertContains("1st run: should run C.test07", buildRule.getOutput());

-        buildRule.executeTarget("C.test08");

-        assertContains("1st run: should run C.test08", buildRule.getOutput());

-        buildRule.executeTarget("C.test09");

-        assertContains("1st run: should run C.test09", buildRule.getOutput());

-        // the failing test cases

-        buildRule.executeTarget("A.test02");

-        assertContains("1st run: should run A.test02", buildRule.getOutput());

-        buildRule.executeTarget("A.test03");

-        assertContains("1st run: should run A.test03", buildRule.getOutput());

-        buildRule.executeTarget("B.test04");

-        assertContains("1st run: should run B.test04", buildRule.getOutput());

-        buildRule.executeTarget("D.test10");

-        assertContains("1st run: should run D.test10", buildRule.getOutput());

-

-    

-        // 2nd junit run: should do only failing tests

-        buildRule.executeTarget("failureRecorder.runtest");

-        assertTrue("The collector file '" + collectorFile.getAbsolutePath() 

-                   + "' should exist after the 2nd run.",

-                   collectorFile.exists());

-        // the passing test cases

-        buildRule.executeTarget("A.test01");

-        assertNotContains("2nd run: should not run A.test01", buildRule.getOutput());

-        buildRule.executeTarget("B.test05");

-        assertNotContains("2nd run: should not run A.test05", buildRule.getOutput());

-        buildRule.executeTarget("B.test06");

-        assertNotContains("2nd run: should not run B.test06", buildRule.getOutput());

-        buildRule.executeTarget("C.test07");

-        assertNotContains("2nd run: should not run C.test07", buildRule.getOutput());

-        buildRule.executeTarget("C.test08");

-        assertNotContains("2nd run: should not run C.test08", buildRule.getOutput());

-        buildRule.executeTarget("C.test09");

-        assertNotContains("2nd run: should not run C.test09", buildRule.getOutput());

-        // the failing test cases

-        buildRule.executeTarget("A.test02");

-        assertContains("2nd run: should run A.test02", buildRule.getOutput());

-        buildRule.executeTarget("A.test03");

-        assertContains("2nd run: should run A.test03", buildRule.getOutput());

-        buildRule.executeTarget("B.test04");

-        assertContains("2nd run: should run B.test04", buildRule.getOutput());

-        buildRule.executeTarget("D.test10");

-        assertContains("2nd run: should run D.test10", buildRule.getOutput());

-    

-    

-        // "fix" errors in class A

-        buildRule.executeTarget("failureRecorder.fixing");

-    

-        // 3rd run: four running tests with two errors

-        buildRule.executeTarget("failureRecorder.runtest");

-        assertTrue("The collector file '" + collectorFile.getAbsolutePath() 

-                   + "' should exist after the 3rd run.",

-                   collectorFile.exists());

-        buildRule.executeTarget("A.test02");

-        assertContains("3rd run: should run A.test02", buildRule.getOutput());

-        buildRule.executeTarget("A.test03");

-        assertContains("3rd run: should run A.test03", buildRule.getOutput());

-        buildRule.executeTarget("B.test04");

-        assertContains("3rd run: should run B.test04", buildRule.getOutput());

-        buildRule.executeTarget("D.test10");

-        assertContains("3rd run: should run D.test10", buildRule.getOutput());

-    

-    

-        // 4rd run: two running tests with errors

-        buildRule.executeTarget("failureRecorder.runtest");

-        assertTrue("The collector file '" + collectorFile.getAbsolutePath() 

-                   + "' should exist after the 4th run.",

-                   collectorFile.exists());

-        //TODO: these two statements fail

-        //buildRule.executeTarget("A.test02");assertNotContains("4th run: should not run A.test02", buildRule.getOutput());

-        //buildRule.executeTarget("A.test03");assertNotContains("4th run: should not run A.test03", buildRule.getOutput());

-        buildRule.executeTarget("B.test04");

-        assertContains("4th run: should run B.test04", buildRule.getOutput());

-        buildRule.executeTarget("D.test10");

-        assertContains("4th run: should run D.test10", buildRule.getOutput());

-

-    }

-

-    @Test

-    public void testBatchTestForkOnceCustomFormatter() {

-        assertResultFilesExist("testBatchTestForkOnceCustomFormatter", "foo");

-    }

-

-    // Bugzilla Issue 45411

-    @Test

-    public void testMultilineAssertsNoFork() {

-        buildRule.executeTarget("testMultilineAssertsNoFork");

-        assertNotContains("messaged up", buildRule.getLog());

-        assertNotContains("crashed)", buildRule.getLog());

-    }

-

-    // Bugzilla Issue 45411

-    @Test

-    public void testMultilineAssertsFork() {

-        buildRule.executeTarget("testMultilineAssertsFork");

-        assertNotContains("messaged up", buildRule.getLog());

-        assertNotContains("crashed)", buildRule.getLog());

-    }

-

-    private void assertResultFilesExist(String target, String extension) {

-        buildRule.executeTarget(target);

-        assertResultFileExists("JUnitClassLoader", extension);

-        assertResultFileExists("JUnitTestRunner", extension);

-        assertResultFileExists("JUnitVersionHelper", extension);

-    }

-

-    private void assertResultFileExists(String classNameFragment, String ext) {

-        assertTrue("result for " + classNameFragment + "Test" + ext + " exists",

-

-                   new File(buildRule.getOutputDir(), "TEST-org.apache.tools.ant."

-                                            + "taskdefs.optional.junit."

-                                            + classNameFragment + "Test" + ext)

-                   .exists());

-    }

-

-    private void assertNoPrint(String result, String where) {

-        assertNotContains(where + " '" + result + "' must not contain print statement",

-                   "print to System.", result);

-    }

-

-    private void assertOutput() throws IOException {

-        FileReader inner = new FileReader(new File(buildRule.getOutputDir(),

-                                          "testlog.txt"));

-        BufferedReader reader = new BufferedReader(inner);

-        try {

-            String line = reader.readLine();

-            assertEquals("Testsuite: org.apache.tools.ant.taskdefs.optional.junit.Printer",

-                         line);

-            line = reader.readLine();

-            assertNotNull(line);

-            assertTrue(line.startsWith("Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed:"));

-            line = reader.readLine();

-            assertEquals("------------- Standard Output ---------------",

-                         line);

-            assertPrint(reader.readLine(), "static", "out");

-            assertPrint(reader.readLine(), "constructor", "out");

-            assertPrint(reader.readLine(), "method", "out");

-            line = reader.readLine();

-            assertEquals("------------- ---------------- ---------------",

-                         line);

-            line = reader.readLine();

-            assertEquals("------------- Standard Error -----------------",

-                         line);

-            assertPrint(reader.readLine(), "static", "err");

-            assertPrint(reader.readLine(), "constructor", "err");

-            assertPrint(reader.readLine(), "method", "err");

-            line = reader.readLine();

-            assertEquals("------------- ---------------- ---------------",

-                         line);

-            line = reader.readLine();

-            assertEquals("", line);

-            line = reader.readLine();

-            assertNotNull(line);

-            assertTrue(line.startsWith("Testcase: testNoCrash took "));

-        } finally {

-            inner.close();

-        }

-    }

-

-    private void assertPrint(String line, String from, String to) {

-        String search = from + " print to System." + to;

-        assertEquals(search, line);

-    }

-

-    @Test

-    public void testJUnit4Skip() throws Exception {

-        buildRule.executeTarget("testSkippableTests");

-

-        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();

-        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();

-        Document doc = dBuilder.parse(new File(buildRule.getOutputDir(), "TEST-org.example.junit.JUnit4Skippable.xml"));

-

-        assertEquals("Incorrect number of nodes created", 8, doc.getElementsByTagName("testcase").getLength());

-

-        XPathFactory factory = XPathFactory.newInstance();

-        XPath xpath = factory.newXPath();

-

-        assertEquals("Incorrect number of skipped tests in header", 4, Integer.parseInt(xpath.compile("//testsuite/@skipped").evaluate(doc)));

-        assertEquals("Incorrect number of error tests in header", 1, Integer.parseInt(xpath.compile("//testsuite/@errors").evaluate(doc)));

-        assertEquals("Incorrect number of failure tests in header", 2, Integer.parseInt(xpath.compile("//testsuite/@failures").evaluate(doc)));

-        assertEquals("Incorrect number of tests in header", 8, Integer.parseInt(xpath.compile("//testsuite/@tests").evaluate(doc)));

-

-

-        assertEquals("Incorrect ignore message on explicit ignored test", "Please don't ignore me!", xpath.compile("//testsuite/testcase[@name='explicitIgnoreTest']/skipped/@message").evaluate(doc));

-        assertEquals("No message should be set on Ignored tests with no Ignore annotation text", 0, ((Node)xpath.compile("//testsuite/testcase[@name='explicitlyIgnoreTestNoMessage']/skipped").evaluate(doc, XPathConstants.NODE)).getAttributes().getLength());

-        assertEquals("Incorrect ignore message on implicit ignored test", "This test will be ignored", xpath.compile("//testsuite/testcase[@name='implicitlyIgnoreTest']/skipped/@message").evaluate(doc));

-        assertNotNull("Implicit ignore test should have an ignore element", xpath.compile("//testsuite/testcase[@name='implicitlyIgnoreTestNoMessage']/skipped").evaluate(doc, XPathConstants.NODE));

-

-    }

-

-    @Test

-    public void testTestMethods() throws Exception {

-        buildRule.executeTarget("testTestMethods");

-    }

-

-    @Test

-    public void testNonTestsSkipped() throws Exception {

-

-        buildRule.executeTarget("testNonTests");

-        assertFalse("Test result should not exist as test was skipped - TEST-org.example.junit.NonTestMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.NonTestMissed.xml").exists());

-        assertFalse("Test result should not exist as test was skipped - TEST-org.example.junit.JUnit3NonTestMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.JUnit3TestMissed.xml").exists());

-        assertFalse("Test result should not exist as test was skipped - TEST-org.example.junit.AbstractTestMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.AbstractTestMissed.xml").exists());

-        assertFalse("Test result should not exist as test was skipped - TEST-org.example.junit.AbstractJUnit3TestMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.AbstractJUnit3TestMissed.xml").exists());

-        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.AbstractTestNotMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.AbstractTestNotMissed.xml").exists());

-        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.AbstractJUnit3TestNotMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.AbstractJUnit3TestNotMissed.xml").exists());

-        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.TestNotMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.TestNotMissed.xml").exists());

-        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.JUnit3TestNotMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.JUnit3TestNotMissed.xml").exists());

-        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.TestWithSuiteNotMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.TestWithSuiteNotMissed.xml").exists());

-

-        buildRule.executeTarget("testNonTestsRun");

-        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.NonTestMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.NonTestMissed.xml").exists());

-        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.JUnit3NonTestMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.JUnit3NonTestMissed.xml").exists());

-        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.TestNotMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.TestNotMissed.xml").exists());

-        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.JUnit3TestNotMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.JUnit3TestNotMissed.xml").exists());

-        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.AbstractTestMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.AbstractTestMissed.xml").exists());

-        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.AbstractTestNotMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.AbstractTestNotMissed.xml").exists());

-        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.AbstractJUnit3TestMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.AbstractJUnit3TestMissed.xml").exists());

-        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.JUnit3NonTestMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.JUnit3NonTestMissed.xml").exists());

-        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.TestWithSuiteNotMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.TestWithSuiteNotMissed.xml").exists());

-

-

-    }

-

-}

+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.
+ *
+ */
+package org.apache.tools.ant.taskdefs.optional.junit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import static org.apache.tools.ant.AntAssert.assertNotContains;
+import static org.apache.tools.ant.AntAssert.assertContains;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+import org.apache.tools.ant.BuildException;
+
+import org.apache.tools.ant.BuildFileRule;
+import org.apache.tools.ant.MagicNames;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.launcher.CommandLauncher;
+import org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.ForkMode;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.JavaEnvUtils;
+import org.apache.tools.ant.util.LoaderUtils;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+public class JUnitTaskTest {
+
+	@Rule
+	public BuildFileRule buildRule = new BuildFileRule();
+	
+    /**
+     * The JUnit setup method.
+     */
+	@Before
+    public void setUp() {
+        buildRule.configureProject("src/etc/testcases/taskdefs/optional/junit.xml");
+    }
+
+	@Test
+    public void testCrash() {
+    	buildRule.executeTarget("crash");
+    	assertEquals("true", buildRule.getProject().getProperty("crashed"));
+    }
+
+	@Test
+    public void testNoCrash() {
+    	buildRule.executeTarget("nocrash");
+    	assertNull(buildRule.getProject().getProperty("crashed"));
+    }
+
+	@Test
+    public void testTimeout() {
+    	buildRule.executeTarget("timeout");
+    	assertEquals("true", buildRule.getProject().getProperty("timeout"));
+    }
+
+    @Test
+    public void testNoTimeout() {
+       buildRule.executeTarget("notimeout");
+   	   assertNull(buildRule.getProject().getProperty("timeout"));
+    }
+
+    @Test
+    public void testNonForkedCapture() throws IOException {
+        buildRule.executeTarget("capture");
+        assertNoPrint(buildRule.getLog(), "log");
+        assertNoPrint(buildRule.getFullLog(), "debug log");
+    }
+
+    @Test
+    public void testForkedCapture() throws IOException {
+        buildRule.getProject().setProperty("fork", "true");
+        testNonForkedCapture();
+        // those would fail because of the way BuildFileRule captures output
+        assertNoPrint(buildRule.getOutput(), "output");
+        assertNoPrint(buildRule.getError(), "error output");
+        assertOutput();
+    }
+
+    @Test
+    public void testBatchTestForkOnceToDir() {
+        assertResultFilesExist("testBatchTestForkOnceToDir", ".xml");
+    }
+
+    /** Bugzilla Report 32973 */
+    @Test
+    public void testBatchTestForkOnceExtension() {
+        assertResultFilesExist("testBatchTestForkOnceExtension", ".foo");
+    }
+
+
+    /* Bugzilla Report 42984 */
+    //TODO This scenario works from command line, but not from JUnit ...
+    //     Running these steps from the junit.xml-directory work
+    //     $ ant -f junit.xml failureRecorder.prepare
+    //     $ ant -f junit.xml failureRecorder.runtest
+    //     $ ant -f junit.xml failureRecorder.runtest
+    //     $ ant -f junit.xml failureRecorder.fixing
+    //     $ ant -f junit.xml failureRecorder.runtest
+    //     $ ant -f junit.xml failureRecorder.runtest
+    //     But running the JUnit testcase fails in 4th run.
+    @Test
+    public void testFailureRecorder() {
+        if (JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_1_5)) {
+            try {
+            	Class<?> clazz =Class.forName("junit.framework.JUnit4TestAdapter");
+                Assume.assumeFalse("Skipping test since it fails with JUnit 4", clazz != null);
+            } catch (ClassNotFoundException e) {
+                // OK, this is JUnit3, can run test
+            }
+        }
+
+        File testDir = new File(buildRule.getOutputDir(), "out");
+        File collectorFile = new File(buildRule.getOutputDir(),
+                "out/FailedTests.java");
+
+        // ensure that there is a clean test environment
+        assertFalse("Test directory '" + testDir.getAbsolutePath()
+                    + "' must not exist before the test preparation.", 
+                    testDir.exists());
+        assertFalse("The collector file '"
+                    + collectorFile.getAbsolutePath()
+                    + "'must not exist before the test preparation.", 
+                    collectorFile.exists());
+
+    
+        // prepare the test environment
+        buildRule.executeTarget("failureRecorder.prepare");
+        assertTrue("Test directory '" + testDir.getAbsolutePath()
+                   + "' was not created.", testDir.exists());
+        assertTrue("There should be one class.",
+                   (new File(testDir, "A.class")).exists());
+        assertFalse("The collector file '"
+                    + collectorFile.getAbsolutePath() 
+                    + "' should not exist before the 1st run.",
+                    collectorFile.exists());
+    
+    
+        // 1st junit run: should do all tests - failing and not failing tests
+        buildRule.executeTarget("failureRecorder.runtest");
+        assertTrue("The collector file '" + collectorFile.getAbsolutePath() 
+                   + "' should exist after the 1st run.",
+                   collectorFile.exists());
+        // the passing test cases
+        buildRule.executeTarget("A.test01");
+        assertContains("1st run: should run A.test01", buildRule.getOutput());
+        buildRule.executeTarget("B.test05");
+        assertContains("1st run: should run B.test05", buildRule.getOutput());
+        buildRule.executeTarget("B.test06");
+        assertContains("1st run: should run B.test06", buildRule.getOutput());
+        buildRule.executeTarget("C.test07");
+        assertContains("1st run: should run C.test07", buildRule.getOutput());
+        buildRule.executeTarget("C.test08");
+        assertContains("1st run: should run C.test08", buildRule.getOutput());
+        buildRule.executeTarget("C.test09");
+        assertContains("1st run: should run C.test09", buildRule.getOutput());
+        // the failing test cases
+        buildRule.executeTarget("A.test02");
+        assertContains("1st run: should run A.test02", buildRule.getOutput());
+        buildRule.executeTarget("A.test03");
+        assertContains("1st run: should run A.test03", buildRule.getOutput());
+        buildRule.executeTarget("B.test04");
+        assertContains("1st run: should run B.test04", buildRule.getOutput());
+        buildRule.executeTarget("D.test10");
+        assertContains("1st run: should run D.test10", buildRule.getOutput());
+
+    
+        // 2nd junit run: should do only failing tests
+        buildRule.executeTarget("failureRecorder.runtest");
+        assertTrue("The collector file '" + collectorFile.getAbsolutePath() 
+                   + "' should exist after the 2nd run.",
+                   collectorFile.exists());
+        // the passing test cases
+        buildRule.executeTarget("A.test01");
+        assertNotContains("2nd run: should not run A.test01", buildRule.getOutput());
+        buildRule.executeTarget("B.test05");
+        assertNotContains("2nd run: should not run A.test05", buildRule.getOutput());
+        buildRule.executeTarget("B.test06");
+        assertNotContains("2nd run: should not run B.test06", buildRule.getOutput());
+        buildRule.executeTarget("C.test07");
+        assertNotContains("2nd run: should not run C.test07", buildRule.getOutput());
+        buildRule.executeTarget("C.test08");
+        assertNotContains("2nd run: should not run C.test08", buildRule.getOutput());
+        buildRule.executeTarget("C.test09");
+        assertNotContains("2nd run: should not run C.test09", buildRule.getOutput());
+        // the failing test cases
+        buildRule.executeTarget("A.test02");
+        assertContains("2nd run: should run A.test02", buildRule.getOutput());
+        buildRule.executeTarget("A.test03");
+        assertContains("2nd run: should run A.test03", buildRule.getOutput());
+        buildRule.executeTarget("B.test04");
+        assertContains("2nd run: should run B.test04", buildRule.getOutput());
+        buildRule.executeTarget("D.test10");
+        assertContains("2nd run: should run D.test10", buildRule.getOutput());
+    
+    
+        // "fix" errors in class A
+        buildRule.executeTarget("failureRecorder.fixing");
+    
+        // 3rd run: four running tests with two errors
+        buildRule.executeTarget("failureRecorder.runtest");
+        assertTrue("The collector file '" + collectorFile.getAbsolutePath() 
+                   + "' should exist after the 3rd run.",
+                   collectorFile.exists());
+        buildRule.executeTarget("A.test02");
+        assertContains("3rd run: should run A.test02", buildRule.getOutput());
+        buildRule.executeTarget("A.test03");
+        assertContains("3rd run: should run A.test03", buildRule.getOutput());
+        buildRule.executeTarget("B.test04");
+        assertContains("3rd run: should run B.test04", buildRule.getOutput());
+        buildRule.executeTarget("D.test10");
+        assertContains("3rd run: should run D.test10", buildRule.getOutput());
+    
+    
+        // 4rd run: two running tests with errors
+        buildRule.executeTarget("failureRecorder.runtest");
+        assertTrue("The collector file '" + collectorFile.getAbsolutePath() 
+                   + "' should exist after the 4th run.",
+                   collectorFile.exists());
+        //TODO: these two statements fail
+        //buildRule.executeTarget("A.test02");assertNotContains("4th run: should not run A.test02", buildRule.getOutput());
+        //buildRule.executeTarget("A.test03");assertNotContains("4th run: should not run A.test03", buildRule.getOutput());
+        buildRule.executeTarget("B.test04");
+        assertContains("4th run: should run B.test04", buildRule.getOutput());
+        buildRule.executeTarget("D.test10");
+        assertContains("4th run: should run D.test10", buildRule.getOutput());
+
+    }
+
+    @Test
+    public void testBatchTestForkOnceCustomFormatter() {
+        assertResultFilesExist("testBatchTestForkOnceCustomFormatter", "foo");
+    }
+
+    // Bugzilla Issue 45411
+    @Test
+    public void testMultilineAssertsNoFork() {
+        buildRule.executeTarget("testMultilineAssertsNoFork");
+        assertNotContains("messaged up", buildRule.getLog());
+        assertNotContains("crashed)", buildRule.getLog());
+    }
+
+    // Bugzilla Issue 45411
+    @Test
+    public void testMultilineAssertsFork() {
+        buildRule.executeTarget("testMultilineAssertsFork");
+        assertNotContains("messaged up", buildRule.getLog());
+        assertNotContains("crashed)", buildRule.getLog());
+    }
+
+    private void assertResultFilesExist(String target, String extension) {
+        buildRule.executeTarget(target);
+        assertResultFileExists("JUnitClassLoader", extension);
+        assertResultFileExists("JUnitTestRunner", extension);
+        assertResultFileExists("JUnitVersionHelper", extension);
+    }
+
+    private void assertResultFileExists(String classNameFragment, String ext) {
+        assertTrue("result for " + classNameFragment + "Test" + ext + " exists",
+
+                   new File(buildRule.getOutputDir(), "TEST-org.apache.tools.ant."
+                                            + "taskdefs.optional.junit."
+                                            + classNameFragment + "Test" + ext)
+                   .exists());
+    }
+
+    private void assertNoPrint(String result, String where) {
+        assertNotContains(where + " '" + result + "' must not contain print statement",
+                   "print to System.", result);
+    }
+
+    private void assertOutput() throws IOException {
+        FileReader inner = new FileReader(new File(buildRule.getOutputDir(),
+                                          "testlog.txt"));
+        BufferedReader reader = new BufferedReader(inner);
+        try {
+            String line = reader.readLine();
+            assertEquals("Testsuite: org.apache.tools.ant.taskdefs.optional.junit.Printer",
+                         line);
+            line = reader.readLine();
+            assertNotNull(line);
+            assertTrue(line.startsWith("Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed:"));
+            line = reader.readLine();
+            assertEquals("------------- Standard Output ---------------",
+                         line);
+            assertPrint(reader.readLine(), "static", "out");
+            assertPrint(reader.readLine(), "constructor", "out");
+            assertPrint(reader.readLine(), "method", "out");
+            line = reader.readLine();
+            assertEquals("------------- ---------------- ---------------",
+                         line);
+            line = reader.readLine();
+            assertEquals("------------- Standard Error -----------------",
+                         line);
+            assertPrint(reader.readLine(), "static", "err");
+            assertPrint(reader.readLine(), "constructor", "err");
+            assertPrint(reader.readLine(), "method", "err");
+            line = reader.readLine();
+            assertEquals("------------- ---------------- ---------------",
+                         line);
+            line = reader.readLine();
+            assertEquals("", line);
+            line = reader.readLine();
+            assertNotNull(line);
+            assertTrue(line.startsWith("Testcase: testNoCrash took "));
+        } finally {
+            inner.close();
+        }
+    }
+
+    private void assertPrint(String line, String from, String to) {
+        String search = from + " print to System." + to;
+        assertEquals(search, line);
+    }
+
+    @Test
+    public void testJUnit4Skip() throws Exception {
+        buildRule.executeTarget("testSkippableTests");
+
+        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
+        Document doc = dBuilder.parse(new File(buildRule.getOutputDir(), "TEST-org.example.junit.JUnit4Skippable.xml"));
+
+        assertEquals("Incorrect number of nodes created", 8, doc.getElementsByTagName("testcase").getLength());
+
+        XPathFactory factory = XPathFactory.newInstance();
+        XPath xpath = factory.newXPath();
+
+        assertEquals("Incorrect number of skipped tests in header", 4, Integer.parseInt(xpath.compile("//testsuite/@skipped").evaluate(doc)));
+        assertEquals("Incorrect number of error tests in header", 1, Integer.parseInt(xpath.compile("//testsuite/@errors").evaluate(doc)));
+        assertEquals("Incorrect number of failure tests in header", 2, Integer.parseInt(xpath.compile("//testsuite/@failures").evaluate(doc)));
+        assertEquals("Incorrect number of tests in header", 8, Integer.parseInt(xpath.compile("//testsuite/@tests").evaluate(doc)));
+
+
+        assertEquals("Incorrect ignore message on explicit ignored test", "Please don't ignore me!", xpath.compile("//testsuite/testcase[@name='explicitIgnoreTest']/skipped/@message").evaluate(doc));
+        assertEquals("No message should be set on Ignored tests with no Ignore annotation text", 0, ((Node)xpath.compile("//testsuite/testcase[@name='explicitlyIgnoreTestNoMessage']/skipped").evaluate(doc, XPathConstants.NODE)).getAttributes().getLength());
+        assertEquals("Incorrect ignore message on implicit ignored test", "This test will be ignored", xpath.compile("//testsuite/testcase[@name='implicitlyIgnoreTest']/skipped/@message").evaluate(doc));
+        assertNotNull("Implicit ignore test should have an ignore element", xpath.compile("//testsuite/testcase[@name='implicitlyIgnoreTestNoMessage']/skipped").evaluate(doc, XPathConstants.NODE));
+
+    }
+
+    @Test
+    public void testTestMethods() throws Exception {
+        buildRule.executeTarget("testTestMethods");
+    }
+
+    @Test
+    public void testNonTestsSkipped() throws Exception {
+
+        buildRule.executeTarget("testNonTests");
+        assertFalse("Test result should not exist as test was skipped - TEST-org.example.junit.NonTestMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.NonTestMissed.xml").exists());
+        assertFalse("Test result should not exist as test was skipped - TEST-org.example.junit.JUnit3NonTestMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.JUnit3TestMissed.xml").exists());
+        assertFalse("Test result should not exist as test was skipped - TEST-org.example.junit.AbstractTestMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.AbstractTestMissed.xml").exists());
+        assertFalse("Test result should not exist as test was skipped - TEST-org.example.junit.AbstractJUnit3TestMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.AbstractJUnit3TestMissed.xml").exists());
+        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.AbstractTestNotMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.AbstractTestNotMissed.xml").exists());
+        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.AbstractJUnit3TestNotMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.AbstractJUnit3TestNotMissed.xml").exists());
+        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.TestNotMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.TestNotMissed.xml").exists());
+        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.JUnit3TestNotMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.JUnit3TestNotMissed.xml").exists());
+        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.TestWithSuiteNotMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.TestWithSuiteNotMissed.xml").exists());
+
+        buildRule.executeTarget("testNonTestsRun");
+        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.NonTestMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.NonTestMissed.xml").exists());
+        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.JUnit3NonTestMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.JUnit3NonTestMissed.xml").exists());
+        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.TestNotMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.TestNotMissed.xml").exists());
+        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.JUnit3TestNotMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.JUnit3TestNotMissed.xml").exists());
+        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.AbstractTestMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.AbstractTestMissed.xml").exists());
+        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.AbstractTestNotMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.AbstractTestNotMissed.xml").exists());
+        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.AbstractJUnit3TestMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.AbstractJUnit3TestMissed.xml").exists());
+        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.JUnit3NonTestMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.JUnit3NonTestMissed.xml").exists());
+        assertTrue("Test result should exist as test was not skipped - TEST-org.example.junit.TestWithSuiteNotMissed.xml", new File(buildRule.getOutputDir(), "TEST-org.example.junit.TestWithSuiteNotMissed.xml").exists());
+
+
+    }
+
+    @Test(expected = BuildException.class)
+    public void testModulePathNeedsFork() throws Exception {
+        final Project project = new Project();
+        project.init();
+        JUnitTask task = new JUnitTask();
+        task.setProject(project);
+        final Path p = new Path(project);
+        p.setPath("modules");
+        task.createModulepath().add(p);
+        task.addTest(new JUnitTest("org.apache.tools.ant.taskdefs.optional.junit.TestTest"));
+        task.execute();
+    }
+
+    @Test(expected = BuildException.class)
+    public void testUpgradeModulePathNeedsFork() throws Exception {
+        final Project project = new Project();
+        project.init();
+        JUnitTask task = new JUnitTask();
+        task.setProject(project);
+        final Path p = new Path(project);
+        p.setPath("modules");
+        task.createUpgrademodulepath().add(p);
+        task.addTest(new JUnitTest("org.apache.tools.ant.taskdefs.optional.junit.TestTest"));
+        task.execute();
+    }
+
+    @Test
+    public void testJunitOnCpArguments() throws Exception {
+        final File tmp = new File(System.getProperty("java.io.tmpdir"));    //NOI18N
+        final File workDir = new File(tmp, String.format("%s_testJCP%d",    //NOI18N
+                getClass().getName(),
+                System.currentTimeMillis()/1000));
+        workDir.mkdirs();
+        try {
+            final File modulesDir = new File(workDir,"modules");    //NOI18N
+            modulesDir.mkdirs();
+
+            final Project project = new Project();
+            project.init();
+            project.setBaseDir(workDir);
+            final MockCommandLauncher mockProcLauncher = new MockCommandLauncher();
+            project.addReference(
+                    MagicNames.ANT_VM_LAUNCHER_REF_ID,
+                    mockProcLauncher);
+            JUnitTask task = new JUnitTask();
+            task.setDir(workDir);
+            task.setFork(true);
+            task.setProject(project);
+            final File junit = LoaderUtils.getResourceSource(
+                    JUnitTask.class.getClassLoader(),
+                    "junit/framework/Test.class");    //NOI18N
+            final Path cp = new Path(project);
+            cp.setPath(junit.getAbsolutePath());
+            task.createClasspath().add(cp);
+            final Path mp = new Path(project);
+            mp.setPath(modulesDir.getName());
+            task.createModulepath().add(mp);
+            task.addTest(new JUnitTest("org.apache.tools.ant.taskdefs.optional.junit.TestTest"));
+            task.execute();
+            assertNotNull(mockProcLauncher.cmd);
+            String resCp = null;
+            String resMp = null;
+            Set<String> resExports = new TreeSet<>();
+            for (int i = 1; i< mockProcLauncher.cmd.length; i++) {
+                if ("-classpath".equals(mockProcLauncher.cmd[i])) { //NOI18N
+                    resCp = mockProcLauncher.cmd[++i];
+                } else if ("-modulepath".equals(mockProcLauncher.cmd[i])) { //NOI18N
+                    resMp = mockProcLauncher.cmd[++i];
+                } else if (mockProcLauncher.cmd[i].startsWith("-XaddExports:")) {   //NOI18N
+                    resExports.add(mockProcLauncher.cmd[i]);
+                } else if (JUnitTestRunner.class.getName().equals(mockProcLauncher.cmd[i])) {
+                    break;
+                }
+            }
+            assertTrue("No exports", resExports.isEmpty());
+            assertEquals("Expected classpath", cp.toString(), resCp);
+            assertEquals("Expected modulepath", mp.toString(), resMp);
+        } finally {
+            delete(workDir);
+        }
+    }
+
+    @Test
+    public void testJunitOnMpArguments() throws Exception {
+        final File tmp = new File(System.getProperty("java.io.tmpdir"));    //NOI18N
+        final File workDir = new File(tmp, String.format("%s_testJMP%d",    //NOI18N
+                getClass().getName(),
+                System.currentTimeMillis()/1000));
+        workDir.mkdirs();
+        try {
+            final File modulesDir = new File(workDir,"modules");    //NOI18N
+            modulesDir.mkdirs();
+
+            final Project project = new Project();
+            project.init();
+            project.setBaseDir(workDir);
+            final MockCommandLauncher mockProcLauncher = new MockCommandLauncher();
+            project.addReference(
+                    MagicNames.ANT_VM_LAUNCHER_REF_ID,
+                    mockProcLauncher);
+            JUnitTask task = new JUnitTask();
+            task.setDir(workDir);
+            task.setFork(true);
+            task.setProject(project);
+            final File junit = LoaderUtils.getResourceSource(
+                    JUnitTask.class.getClassLoader(),
+                    "junit/framework/Test.class");    //NOI18N
+            final Path mp = new Path(project);
+            mp.add(new Path(project, junit.getAbsolutePath()));
+            mp.add(new Path(project, modulesDir.getName()));
+            task.createModulepath().add(mp);
+            task.addTest(new JUnitTest("org.apache.tools.ant.taskdefs.optional.junit.TestTest"));       //NOI18N
+            task.execute();
+            assertNotNull(mockProcLauncher.cmd);
+            String resCp = null;
+            String resMp = null;
+            Set<String> resExports = new TreeSet<>();
+            for (int i = 1; i< mockProcLauncher.cmd.length; i++) {
+                if ("-classpath".equals(mockProcLauncher.cmd[i])) { //NOI18N
+                    resCp = mockProcLauncher.cmd[++i];
+                } else if ("-modulepath".equals(mockProcLauncher.cmd[i])) { //NOI18N
+                    resMp = mockProcLauncher.cmd[++i];
+                } else if (mockProcLauncher.cmd[i].startsWith("-XaddExports:")) {   //NOI18N
+                    resExports.add(mockProcLauncher.cmd[i]);
+                } else if (JUnitTestRunner.class.getName().equals(mockProcLauncher.cmd[i])) {
+                    break;
+                }
+            }
+            assertTrue("No exports", resExports.isEmpty());
+            assertNull("No classpath", resCp);
+            assertEquals("Expected modulepath", mp.toString(), resMp);
+        } finally {
+            delete(workDir);
+        }
+    }
+
+    private void delete(File f) {
+        if (f.isDirectory()) {
+            final File[] clds = f.listFiles();
+            if (clds != null) {
+                for (File cld : clds) {
+                    delete(cld);
+                }
+            }
+        }
+        f.delete();
+    }
+
+    private static final class MockCommandLauncher extends CommandLauncher {
+        private String[] cmd;
+
+        @Override
+        public Process exec(Project project, String[] cmd, String[] env, File workingDir) throws IOException {
+            this.cmd = Arrays.copyOf(cmd, cmd.length);
+            return new MockProcess();
+        }
+
+        private static class MockProcess extends Process {
+
+            @Override
+            public OutputStream getOutputStream() {
+                return new ByteArrayOutputStream();
+            }
+
+            @Override
+            public InputStream getInputStream() {
+                return new ByteArrayInputStream(new byte[0]);
+            }
+
+            @Override
+            public InputStream getErrorStream() {
+                return new ByteArrayInputStream(new byte[0]);
+            }
+
+            @Override
+            public int waitFor() throws InterruptedException {
+                return exitValue();
+            }
+
+            @Override
+            public int exitValue() {
+                return 0;
+            }
+
+            @Override
+            public void destroy() {
+            }
+        }
+    }
+}
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/OwnedBySelectorTest.java b/src/tests/junit/org/apache/tools/ant/types/selectors/OwnedBySelectorTest.java
new file mode 100644
index 0000000..389923f
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/OwnedBySelectorTest.java
@@ -0,0 +1,53 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.
+ *
+ */
+
+package org.apache.tools.ant.types.selectors;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.attribute.UserPrincipal;
+
+import org.apache.tools.ant.taskdefs.condition.Os;
+import org.junit.Assume;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+public class OwnedBySelectorTest {
+
+    @Rule
+    public TemporaryFolder folder = new TemporaryFolder();
+
+    @Test
+    public void ownedByIsTrueForSelf() throws Exception {
+        // at least on Jenkins the file is owned by "BUILTIN\Administrators"
+        Assume.assumeFalse(Os.isFamily("windows"));
+        String self = System.getProperty("user.name");
+        File file = folder.newFile("f.txt");
+        UserPrincipal user = Files.getOwner(file.toPath());
+        assertEquals(self, user.getName());
+
+        OwnedBySelector s = new OwnedBySelector();
+        s.setOwner(self);
+        assertTrue(s.isSelected(null, null, file));
+    }
+
+}
diff --git a/src/tests/junit/org/apache/tools/ant/util/JavaEnvUtilsTest.java b/src/tests/junit/org/apache/tools/ant/util/JavaEnvUtilsTest.java
index 80a92a9..e27cc4d 100644
--- a/src/tests/junit/org/apache/tools/ant/util/JavaEnvUtilsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/JavaEnvUtilsTest.java
@@ -116,12 +116,11 @@
         assertTrue(j+" is normalized and in the JDK dir",
                    j.startsWith(javaHomeParent));
 
-        if ((Os.isFamily("mac") && JavaEnvUtils.getJavaVersionNumber() <= JavaEnvUtils.VERSION_1_6)
-            || JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9)) {
-            assertTrue(j+" is normalized and in the JRE dir",
+        if (JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9)) {
+            assertTrue(j + " is normalized and in the JRE dir",
                        j.startsWith(javaHome));
         } else {
-            assertTrue(j+" is normalized and not in the JRE dir",
+            assertTrue(j + " is normalized and not in the JRE dir",
                        !j.startsWith(javaHome));
         }
 
@@ -145,5 +144,4 @@
         assertTrue("JAVA_1_9 is not considered equal to JAVA_9",
                 JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_9));
     }
-
 }
diff --git a/src/tests/junit/org/apache/tools/ant/util/PermissionUtilsTest.java b/src/tests/junit/org/apache/tools/ant/util/PermissionUtilsTest.java
new file mode 100644
index 0000000..c4dd8fc
--- /dev/null
+++ b/src/tests/junit/org/apache/tools/ant/util/PermissionUtilsTest.java
@@ -0,0 +1,160 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.
+ *
+ */
+
+package org.apache.tools.ant.util;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.attribute.PosixFileAttributeView;
+import java.nio.file.attribute.PosixFilePermission;
+import java.util.EnumSet;
+import java.util.Set;
+
+import org.apache.tools.ant.types.resources.FileResource;
+import org.apache.tools.ant.types.resources.TarResource;
+import org.apache.tools.ant.types.resources.ZipResource;
+import org.apache.tools.tar.TarEntry;
+import org.apache.tools.tar.TarOutputStream;
+import org.apache.tools.zip.ZipEntry;
+import org.apache.tools.zip.ZipOutputStream;
+import org.junit.Assume;
+import org.junit.Test;
+
+public class PermissionUtilsTest {
+
+    @Test
+    public void modeFromPermissionsReturnsExpectedResult() {
+        int mode = PermissionUtils.modeFromPermissions(EnumSet.of(PosixFilePermission.OWNER_READ,
+                                                                  PosixFilePermission.OWNER_WRITE,
+                                                                  PosixFilePermission.OWNER_EXECUTE),
+                                                       PermissionUtils.FileType.REGULAR_FILE);
+        assertEquals("100700", Integer.toString(mode, 8));
+    }
+
+    @Test
+    public void permissionsFromModeReturnsExpectedResult() {
+        Set<PosixFilePermission> s = PermissionUtils.permissionsFromMode(0100753);
+        assertEquals(EnumSet.of(PosixFilePermission.OWNER_READ,
+                                PosixFilePermission.OWNER_WRITE,
+                                PosixFilePermission.OWNER_EXECUTE,
+                                PosixFilePermission.GROUP_READ,
+                                PosixFilePermission.GROUP_EXECUTE,
+                                PosixFilePermission.OTHERS_WRITE,
+                                PosixFilePermission.OTHERS_EXECUTE),
+                     s);
+    }
+
+    @Test
+    public void detectsFileTypeOfRegularFileFromPath() throws IOException {
+        File f = File.createTempFile("ant", ".tst");
+        f.deleteOnExit();
+        assertEquals(PermissionUtils.FileType.REGULAR_FILE,
+                     PermissionUtils.FileType.of(f.toPath()));
+    }
+
+    @Test
+    public void detectsFileTypeOfRegularFileFromResource() throws IOException {
+        File f = File.createTempFile("ant", ".tst");
+        f.deleteOnExit();
+        assertEquals(PermissionUtils.FileType.REGULAR_FILE,
+                     PermissionUtils.FileType.of(new FileResource(f)));
+    }
+
+    @Test
+    public void detectsFileTypeOfDirectoryFromPath() throws IOException {
+        File f = File.createTempFile("ant", ".dir");
+        f.delete();
+        f.mkdirs();
+        f.deleteOnExit();
+        assertEquals(PermissionUtils.FileType.DIR,
+                     PermissionUtils.FileType.of(f.toPath()));
+    }
+
+    @Test
+    public void detectsFileTypeOfDirectoryFromResource() throws IOException {
+        File f = File.createTempFile("ant", ".tst");
+        f.delete();
+        f.mkdirs();
+        f.deleteOnExit();
+        assertEquals(PermissionUtils.FileType.DIR,
+                     PermissionUtils.FileType.of(new FileResource(f)));
+    }
+
+    @Test
+    public void getSetPermissionsWorksForFiles() throws IOException {
+        File f = File.createTempFile("ant", ".tst");
+        f.deleteOnExit();
+        Assume.assumeNotNull(Files.getFileAttributeView(f.toPath(),
+                                                        PosixFileAttributeView.class));
+        Set<PosixFilePermission> s =
+            EnumSet.of(PosixFilePermission.OWNER_READ,
+                       PosixFilePermission.OWNER_WRITE,
+                       PosixFilePermission.OWNER_EXECUTE,
+                       PosixFilePermission.GROUP_READ);
+        PermissionUtils.setPermissions(new FileResource(f), s, null);
+        assertEquals(s, PermissionUtils.getPermissions(new FileResource(f), null));
+    }
+
+    @Test
+    public void getSetPermissionsWorksForZipResources() throws IOException {
+        File f = File.createTempFile("ant", ".zip");
+        f.deleteOnExit();
+        try (ZipOutputStream os = new ZipOutputStream(f)) {
+            ZipEntry e = new ZipEntry("foo");
+            os.putNextEntry(e);
+            os.closeEntry();
+        }
+
+        ZipResource r = new ZipResource();
+        r.setName("foo");
+        r.setArchive(f);
+        Set<PosixFilePermission> s =
+            EnumSet.of(PosixFilePermission.OWNER_READ,
+                       PosixFilePermission.OWNER_WRITE,
+                       PosixFilePermission.OWNER_EXECUTE,
+                       PosixFilePermission.GROUP_READ);
+        PermissionUtils.setPermissions(r, s, null);
+        assertEquals(s, PermissionUtils.getPermissions(r, null));
+    }
+
+    @Test
+    public void getSetPermissionsWorksForTarResources() throws IOException {
+        File f = File.createTempFile("ant", ".zip");
+        f.deleteOnExit();
+        try (TarOutputStream os = new TarOutputStream(new FileOutputStream(f))) {
+            TarEntry e = new TarEntry("foo");
+            os.putNextEntry(e);
+            os.closeEntry();
+        }
+
+        TarResource r = new TarResource();
+        r.setName("foo");
+        r.setArchive(f);
+        Set<PosixFilePermission> s =
+            EnumSet.of(PosixFilePermission.OWNER_READ,
+                       PosixFilePermission.OWNER_WRITE,
+                       PosixFilePermission.OWNER_EXECUTE,
+                       PosixFilePermission.GROUP_READ);
+        PermissionUtils.setPermissions(r, s, null);
+        assertEquals(s, PermissionUtils.getPermissions(r, null));
+    }
+}
diff --git a/src/tests/junit/org/apache/tools/ant/util/StringUtilsTest.java b/src/tests/junit/org/apache/tools/ant/util/StringUtilsTest.java
index 4dc43ee..d2187c4 100644
--- a/src/tests/junit/org/apache/tools/ant/util/StringUtilsTest.java
+++ b/src/tests/junit/org/apache/tools/ant/util/StringUtilsTest.java
@@ -1,170 +1,199 @@
-/*

- *  Licensed to the Apache Software Foundation (ASF) under one or more

- *  contributor license agreements.  See the NOTICE file distributed with

- *  this work for additional information regarding copyright ownership.

- *  The ASF licenses this file to You 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.

- *

- */

-package org.apache.tools.ant.util;

-

-import java.util.Vector;

-

-import org.junit.Test;

-

-import static org.junit.Assert.assertEquals;

-import static org.junit.Assert.assertFalse;

-import static org.junit.Assert.assertTrue;

-

-/**

- * Test for StringUtils

- */

-public class StringUtilsTest {

-

-    @Test

-    public void testSplit(){

-        final String data = "a,b,,";

-        Vector res = StringUtils.split(data, ',');

-        assertEquals(4, res.size());

-        assertEquals("a", res.elementAt(0));

-        assertEquals("b", res.elementAt(1));

-        assertEquals("", res.elementAt(2));

-        assertEquals("", res.elementAt(3));

-    }

-

-    @Test

-    public void testSplitLines(){

-        final String data = "a\r\nb\nc\nd\ne";

-        Vector res = StringUtils.lineSplit(data);

-        assertEquals(5, res.size());

-        assertEquals("a\r", res.elementAt(0));

-        assertEquals("b", res.elementAt(1));

-        assertEquals("c", res.elementAt(2));

-        assertEquals("d", res.elementAt(3));

-        assertEquals("e", res.elementAt(4));

-    }

-

-    @Test

-    public void testReplace() {

-        final String data = "abcabcabca";

-        String res = StringUtils.replace(data, "a", "");

-        assertEquals("bcbcbc", res);

-    }

-

-    @Test

-    public void testEndsWithBothEmpty() {

-        assertTrue( StringUtils.endsWith( new StringBuffer(), "") );

-    }

-

-    @Test

-    public void testEndsWithEmptyString() {

-        assertTrue( StringUtils.endsWith( new StringBuffer("12234545"), "") );

-    }

-

-    @Test

-    public void testEndsWithShorterString() {

-        assertTrue( StringUtils.endsWith( new StringBuffer("12345678"), "78"));

-    }

-

-    @Test

-    public void testEndsWithSameString() {

-        assertTrue( StringUtils.endsWith( new StringBuffer("123"), "123"));

-    }

-

-    @Test

-    public void testEndsWithLongerString() {

-        assertFalse( StringUtils.endsWith( new StringBuffer("12"), "1245"));

-    }

-

-    @Test

-    public void testEndsWithNoMatch() {

-        assertFalse( StringUtils.endsWith( new StringBuffer("12345678"), "789"));

-    }

-

-    @Test

-    public void testEndsWithEmptyBuffer() {

-        assertFalse( StringUtils.endsWith( new StringBuffer(""), "12345667") );

-    }

-

-    @Test

-    public void testEndsWithJDKPerf() {

-        StringBuffer buf = getFilledBuffer(1024*300, 'a');

-        for (int i = 0; i < 1000; i++) {

-            assertTrue(buf.toString().endsWith("aa"));

-        }

-    }

-

-    @Test

-    public void testEndsWithPerf() {

-        StringBuffer buf = getFilledBuffer(1024*300, 'a');

-        for (int i = 0; i < 1000; i++) {

-            assertTrue(StringUtils.endsWith(buf, "aa"));

-        }

-    }

-

-    private StringBuffer getFilledBuffer(int size, char ch) {

-        StringBuffer buf = new StringBuffer(size);

-        for (int i = 0; i < size; i++) { buf.append(ch); };

-        return buf;

-    }

-

-    @Test

-    public void testParseHumanSizes() throws Exception {

-    	final long KILOBYTE = 1024;

-    	final long MEGABYTE = KILOBYTE * 1024;

-    	final long GIGABYTE = MEGABYTE * 1024;

-    	final long TERABYTE = GIGABYTE * 1024;

-    	final long PETABYTE = TERABYTE * 1024;

-    	assertEquals(StringUtils.parseHumanSizes("1K"), KILOBYTE);

-    	assertEquals(StringUtils.parseHumanSizes("1M"), MEGABYTE);

-    	assertEquals(StringUtils.parseHumanSizes("1G"), GIGABYTE);

-    	assertEquals(StringUtils.parseHumanSizes("1T"), TERABYTE);

-    	assertEquals(StringUtils.parseHumanSizes("1P"), PETABYTE);

-    	assertEquals(StringUtils.parseHumanSizes("1"), 1L);

-    }

-

-    @Test

-    public void testRemoveSuffix() {

-        String prefix = "Prefix";

-        String name = "Name";

-        String suffix = "Suffix";

-        String input = prefix + name + suffix;

-        assertEquals(

-            "Does not remove the suffix right.",    

-            prefix + name, 

-            StringUtils.removeSuffix(input, suffix)

-        );

-        assertEquals(

-            "Should leave the string unattended.",    

-            prefix + name + suffix, 

-            StringUtils.removeSuffix(input, "bla")

-        );

-    }

-

-    @Test

-    public void testRemovePrefix() {

-        String prefix = "Prefix";

-        String name = "Name";

-        String suffix = "Suffix";

-        String input = prefix + name + suffix;

-        assertEquals(

-            "Does not remove the prefix right.",    

-            name + suffix, 

-            StringUtils.removePrefix(input, prefix)

-        );

-        assertEquals(

-            "Should leave the string unattended.",    

-            prefix + name + suffix, 

-            StringUtils.removePrefix(input, "bla")

-        );

-    }    

-}

+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.
+ *
+ */
+package org.apache.tools.ant.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Vector;
+
+import org.junit.Test;
+
+/**
+ * Test for StringUtils
+ */
+public class StringUtilsTest {
+
+    @Test
+    public void testSplit(){
+        final String data = "a,b,,";
+        Vector<String> res = StringUtils.split(data, ',');
+        assertEquals(4, res.size());
+        assertEquals("a", res.elementAt(0));
+        assertEquals("b", res.elementAt(1));
+        assertEquals("", res.elementAt(2));
+        assertEquals("", res.elementAt(3));
+    }
+
+    @Test
+    public void testSplitLines(){
+        final String data = "a\r\nb\nc\nd\ne";
+        Vector<String> res = StringUtils.lineSplit(data);
+        assertEquals(5, res.size());
+        assertEquals("a\r", res.elementAt(0));
+        assertEquals("b", res.elementAt(1));
+        assertEquals("c", res.elementAt(2));
+        assertEquals("d", res.elementAt(3));
+        assertEquals("e", res.elementAt(4));
+    }
+
+    @SuppressWarnings("deprecation")
+        @Test
+    public void testReplace() {
+        final String data = "abcabcabca";
+        String res = StringUtils.replace(data, "a", "");
+        assertEquals("bcbcbc", res);
+    }
+
+    @Test
+    public void testEndsWithBothEmpty() {
+        assertTrue( StringUtils.endsWith( new StringBuffer(), "") );
+    }
+
+    @Test
+    public void testEndsWithEmptyString() {
+        assertTrue( StringUtils.endsWith( new StringBuffer("12234545"), "") );
+    }
+
+    @Test
+    public void testEndsWithShorterString() {
+        assertTrue( StringUtils.endsWith( new StringBuffer("12345678"), "78"));
+    }
+
+    @Test
+    public void testEndsWithSameString() {
+        assertTrue( StringUtils.endsWith( new StringBuffer("123"), "123"));
+    }
+
+    @Test
+    public void testEndsWithLongerString() {
+        assertFalse( StringUtils.endsWith( new StringBuffer("12"), "1245"));
+    }
+
+    @Test
+    public void testEndsWithNoMatch() {
+        assertFalse( StringUtils.endsWith( new StringBuffer("12345678"), "789"));
+    }
+
+    @Test
+    public void testEndsWithEmptyBuffer() {
+        assertFalse( StringUtils.endsWith( new StringBuffer(""), "12345667") );
+    }
+
+    @Test
+    public void testEndsWithJDKPerf() {
+        StringBuffer buf = getFilledBuffer(1024*300, 'a');
+        for (int i = 0; i < 1000; i++) {
+            assertTrue(buf.toString().endsWith("aa"));
+        }
+    }
+
+    @Test
+    public void testEndsWithPerf() {
+        StringBuffer buf = getFilledBuffer(1024*300, 'a');
+        for (int i = 0; i < 1000; i++) {
+            assertTrue(StringUtils.endsWith(buf, "aa"));
+        }
+    }
+
+    private StringBuffer getFilledBuffer(int size, char ch) {
+        StringBuffer buf = new StringBuffer(size);
+        for (int i = 0; i < size; i++) { buf.append(ch); };
+        return buf;
+    }
+
+    @Test
+    public void testParseHumanSizes() throws Exception {
+        final long KILOBYTE = 1024;
+        final long MEGABYTE = KILOBYTE * 1024;
+        final long GIGABYTE = MEGABYTE * 1024;
+        final long TERABYTE = GIGABYTE * 1024;
+        final long PETABYTE = TERABYTE * 1024;
+        assertEquals(StringUtils.parseHumanSizes("1K"), KILOBYTE);
+        assertEquals(StringUtils.parseHumanSizes("1M"), MEGABYTE);
+        assertEquals(StringUtils.parseHumanSizes("1G"), GIGABYTE);
+        assertEquals(StringUtils.parseHumanSizes("1T"), TERABYTE);
+        assertEquals(StringUtils.parseHumanSizes("1P"), PETABYTE);
+        assertEquals(StringUtils.parseHumanSizes("1"), 1L);
+    }
+
+    @Test
+    public void testRemoveSuffix() {
+        String prefix = "Prefix";
+        String name = "Name";
+        String suffix = "Suffix";
+        String input = prefix + name + suffix;
+        assertEquals(
+            "Does not remove the suffix right.",    
+            prefix + name, 
+            StringUtils.removeSuffix(input, suffix)
+        );
+        assertEquals(
+            "Should leave the string unattended.",    
+            prefix + name + suffix, 
+            StringUtils.removeSuffix(input, "bla")
+        );
+    }
+
+    @Test
+    public void testRemovePrefix() {
+        String prefix = "Prefix";
+        String name = "Name";
+        String suffix = "Suffix";
+        String input = prefix + name + suffix;
+        assertEquals(
+            "Does not remove the prefix right.",    
+            name + suffix, 
+            StringUtils.removePrefix(input, prefix)
+        );
+        assertEquals(
+            "Should leave the string unattended.",    
+            prefix + name + suffix, 
+            StringUtils.removePrefix(input, "bla")
+        );
+    }
+    
+    @Test
+    public void testJoin() {
+        assertEquals("a, b, c", StringUtils.join(Arrays.asList("a", "b", "c"), ", "));
+    }
+    
+    @Test
+    public void testJoinEmptyArray() {
+        assertEquals("", StringUtils.join(new String[]{}, ", "));
+    }
+    
+    @Test
+    public void testJoinNullCollection() {
+        assertEquals("", StringUtils.join((Collection<String>)null, ", "));
+    }
+
+    @Test
+    public void testJoinNullArray() {
+        assertEquals("", StringUtils.join((String[])null, ", "));
+    }
+
+    @Test
+    public void testJoinNullSeparator() {
+        assertEquals("abc", StringUtils.join(Arrays.asList("a", "b", "c"), null));
+    }
+    
+}